Capture what you did, when you did it โ without ever leaving the shell.
Contents
- Why devlog?
- Features
- Install
- Usage
- How your data is stored
- Project layout
- Building from source
- Roadmap
- Contributing
- License
Why devlog?
Standups, retros, performance reviews, and "wait, what did I actually ship last
Tuesday?" all want the same thing: a timestamped trail of your work. devlog
gives you that with two commands and zero ceremony. It is local-first, has
no network calls, and keeps everything in a single SQLite file you own.
$ devlog add "Refactored the store layer"
Added item "Refactored the store layer"!
That is the whole ritual. Type the note, hit enter, get back to work.
Features
| ๐ Frictionless capture | One short command โ devlog add "โฆ" โ and the thought is saved. |
| ๐ Full history at a glance | devlog list groups every entry by day, most recent day first. |
| โ Track each entry's state | Move items between in_progress, done, and cancelled with devlog set-status. |
| ๐๏ธ Local-first SQLite | Your journal lives in ~/.devlog/entries.sqlite. No cloud, no account. |
| ๐ Time-ordered UUID v7 | IDs encode creation time, so entries sort naturally by when they happened. |
| ๐ Honest timestamps | Stored in UTC (RFC 3339), shown in your local time when you list. |
| ๐ฆ One small binary | SQLite is bundled at build time โ nothing to install alongside it. |
| ๐ Quiet by design | No telemetry, no background process, no network. |
Install
From crates.io
The crate is published as
d3vlog, but it installs a binary nameddevlog.
From source
Requirements: a Rust toolchain new enough for the 2024 edition (Rust 1.85+)
and a C compiler โ rusqlite compiles a
bundled copy of SQLite, so you do not need SQLite installed on your system.
Usage
$ devlog --help
A tiny developer journal for the terminal
Usage: devlog <COMMAND>
Commands:
add Add a new journal entry
list List journal entries
set-status Set status of entry
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
| Command | What it does | Example |
|---|---|---|
devlog add <message> |
Append a new entry, stamped with the current UTC time. | devlog add "Cut the v0.2 release" |
devlog list |
Print every entry, grouped by day (newest day first). | devlog list |
devlog set-status <id> <status> |
Set an entry's status to in_progress, done, or cancelled. |
devlog set-status <id> done |
devlog --version |
Show the installed version. | devlog --version |
devlog --help |
Show help (works on subcommands too). | devlog add --help |
A typical session
$ devlog add "Ship the new auth flow"
Added item "Ship the new auth flow"!
$ devlog add "Fix flaky test in store.rs"
Added item "Fix flaky test in store.rs"!
$ devlog list
Wednesday, 2026-06-24 ยท 2 entries
[~] 09:14 Ship the new auth flow
id: 019efa5e-5f23-70b3-b4d3-f5f1643764a3
[~] 11:02 Fix flaky test in store.rs
id: 019efa5e-5f2a-7eb0-9ed7-9980495715a5
$ devlog set-status 019efa5e-5f23-70b3-b4d3-f5f1643764a3 done
Set status of item 019efa5e-5f23-70b3-b4d3-f5f1643764a3 to be Done
$ devlog list
Wednesday, 2026-06-24 ยท 2 entries
[โ] 09:14 Ship the new auth flow
id: 019efa5e-5f23-70b3-b4d3-f5f1643764a3
[~] 11:02 Fix flaky test in store.rs
id: 019efa5e-5f2a-7eb0-9ed7-9980495715a5
Entries are grouped under a day header โ <weekday>, <YYYY-MM-DD> ยท <count> โ
with the most recent day first. Within a day, each entry shows a status marker,
its local HH:MM time, and the message, followed by the full UUID on an
indented id: line:
[~]โ in progress (the state every new entry starts in)[โ]โ done[x]โ cancelled
Move an entry between states with devlog set-status <id> <status>, passing the
full id from the list output and one of in_progress, done, or cancelled.
How your data is stored
Everything lives in one SQLite database, created on first run:
~/.devlog/entries.sqlite
The schema is a single table:
(
id TEXT PRIMARY KEY NOT NULL,
created_at TEXT NOT NULL CHECK (datetime(created_at) IS NOT NULL),
message TEXT NOT NULL CHECK (length(trim(message)) > 0),
status TEXT NOT NULL DEFAULT 'in_progress'
CHECK (status IN ('in_progress', 'done', 'cancelled'))
);
| Column | Type | Notes |
|---|---|---|
id |
TEXT |
UUID v7 โ time-ordered, generated per entry. |
created_at |
TEXT |
UTC timestamp in RFC 3339; the CHECK rejects anything SQLite can't parse as a datetime. |
message |
TEXT |
The note. Must be non-empty after trimming whitespace. |
status |
TEXT |
Lifecycle state โ one of in_progress (the default for new entries), done, or cancelled. |
The schema is versioned (via SQLite's PRAGMA user_version), so existing
journals are migrated in place when you upgrade devlog โ the status column
was added this way.
Because it is plain SQLite, you can always inspect or back up your journal with ordinary tools:
Project layout
devlog/
โโโ Cargo.toml # crate: d3vlog ยท binary: devlog
โโโ src/
โโโ main.rs # entry point โ parse args, dispatch commands
โโโ cli.rs # clap definitions for `add`, `list`, and `set-status`
โโโ store.rs # SQLite connection, schema migrations, reads & writes
โโโ data.rs # data module root
โโโ data/
โโโ entry.rs # DevLogEntry model + display formatting
โโโ status.rs # DevLogEntryStatus enum + parsing & rendering
The dependencies are intentionally few:
clapโ argument parsing (derive API)rusqliteโ SQLite access (bundled)chronoโ UTC timestampsuuidโ UUID v7 identifiers
Building from source
# Run without installing
# Optimized build
Roadmap
Ideas under consideration โ not yet implemented:
-
devlog search <term>โ filter entries by text -
devlog rm/devlog editโ remove or amend entries - Date filters (
--since,--today,--week) - Tags / projects per entry
- Export to Markdown or JSON
- A scrollable TUI view
Have a different itch? Open an issue.
Contributing
Issues and pull requests are welcome.
Please keep changes small and focused, and run cargo fmt and cargo clippy
before opening a PR.
License
Licensed under the Apache License, Version 2.0. See LICENSE or
https://www.apache.org/licenses/LICENSE-2.0 for the full text.