{
  "markdown": "<div align=\"center\">\n\n```\n██████╗ ███████╗██╗   ██╗██╗      ██████╗  ██████╗\n██╔══██╗██╔════╝██║   ██║██║     ██╔═══██╗██╔════╝\n██║  ██║█████╗  ██║   ██║██║     ██║   ██║██║  ███╗\n██║  ██║██╔══╝  ╚██╗ ██╔╝██║     ██║   ██║██║   ██║\n██████╔╝███████╗ ╚████╔╝ ███████╗╚██████╔╝╚██████╔╝\n╚═════╝ ╚══════╝  ╚═══╝  ╚══════╝ ╚═════╝  ╚═════╝\n```\n\n### A development blog that writes itself — through the AI agent you already use.\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![Python 3.11+](https://img.shields.io/badge/python-3.11+-3776AB.svg?logo=python&logoColor=white)](https://www.python.org/)\n[![Agents: 27](https://img.shields.io/badge/agents-27-9B59B6.svg)](#supported-agents)\n\n</div>\n\n---\n\nMost developers don't keep a dev log — or they abandon one within a week. But\nAI coding agents already sit in the loop where the work happens. `devlog`\nteaches them, once per project, to narrate that work as they go.\n\nThe result: a time-ordered, portfolio-ready record of your project that\ngrows automatically, in the agent's own voice.\n\n<br>\n\n## Table of contents\n\n- [Why devlog?](#why-devlog)\n- [What you get](#what-you-get)\n- [Quickstart](#quickstart)\n- [What actually happens](#what-actually-happens)\n- [Commands](#commands)\n- [Slash commands (Claude Code, OpenCode)](#slash-commands-claude-code-opencode)\n- [Adaptive convention](#adaptive-convention)\n- [Supported agents](#supported-agents)\n- [How it works](#how-it-works)\n- [Configuration](#configuration)\n- [Upgrading](#upgrading)\n- [Uninstalling](#uninstalling)\n- [License](#license)\n\n<br>\n\n## Why devlog?\n\nA codebase is the *what*. The *why* — the dead ends, the constraint that ruled\nout the obvious design, the reason a function looks wrong but isn't — lives\nsomewhere far more fragile. With an AI agent it lives in a chat transcript\nyou'll close and never reopen. The commit captures the change, never the\nreasoning behind it. Six months later that reasoning is simply gone, and the\nnext person — or the next agent — re-derives it from scratch or breaks it by\naccident.\n\ndevlog's real output isn't a blog. It's a durable, git-versioned,\n**cross-agent record of why the code is the way it is** — written down at the\nmoment the reasoning is fresh, by the agent that did the reasoning. The\nportfolio-ready blog is just the human-facing rendering of that record.\n\nThe premise holds *harder* for agent-written code than for hand-written code:\n\n- **The reasoning never lived in your head.** You didn't write the code — the\n  agent did. The thinking is in a transcript you're about to discard, not in\n  your memory.\n- **Commits carry the *what*, never the *why*.** Reconstructing intent from git\n  metadata after the fact is lossy by design — and capped by how good the\n  commit message was.\n- **Native agent memory can't hold this.** It's private, unversioned, and\n  harness-bound — locked to one vendor's tool. It doesn't travel with the repo,\n  survive a switch from one agent to another, or open up to a collaborator.\n\nA dev log usually dies for one reason: the human is the write-trigger, and\ndiscipline lapses. devlog moves the trigger to the agent that's already in the\nloop where the work happens — so the record gets written because the work got\ndone, not because someone remembered to journal.\n\nCapture is best-effort: the agent follows the convention because it's in its\ncontext — *polite*, not guaranteed. For Claude Code, an optional `Stop` hook\nmakes it far more reliable by nudging the agent before it ends a turn, and\n`devlog status` reports when sessions ended without producing an entry — so the\nblind spot is at least visible.\n\n<br>\n\n## What you get\n\nA `blog/` directory that fills itself in as the agent works — and, underneath\nit, a project memory that outlives any single session, agent, or vendor.\n\n- **A \"why\" record that survives.** Decisions, tradeoffs, and dead ends get\n  captured in git, in the agent's own voice, as they happen — not reconstructed\n  post-hoc from commit messages.\n- **Institutional memory across sessions and agents.** `.devlog/learned.md`\n  accumulates the project's vocabulary, recurring themes, and open threads;\n  `/devlog-catchup` reloads the project arc, recent work, and glossary at the\n  start of a session. Any agent inherits the context — not just the one that\n  wrote it.\n- **Onboarding for humans and agents alike.** A new collaborator, or the next\n  agent to touch the repo, reads the narrative instead of re-deriving the\n  reasoning by hand.\n- **Durable and versioned.** It lives in git and travels with the repo,\n  surviving across agents and harness changes — no vendor, no private store, no\n  lock-in.\n- **A portfolio-ready record as a byproduct.** Time-ordered, narrative, written\n  for whoever evaluates the work next — collaborators, employers, researchers.\n- **Self-maintaining.** The tag vocabulary self-updates, the convention can\n  re-tailor its config to the project's domain, and `/devlog-manicure` audits\n  and prunes stale entries so the record stays trustworthy.\n\nHow it compares:\n\n| Approach | What it produces | The catch |\n| --- | --- | --- |\n| **devlog** | Narrative *why*, written as the work happens | Best-effort capture (firmer with the hook) |\n| Commit-driven journals | Narrative reconstructed from git after the fact | Lossy; quality capped by commit messages |\n| Changelog generators | Structured release notes for upgraders | Not narrative; wrong audience |\n| Manual markdown diaries | Exactly the right narrative | You have to remember to write it — and won't |\n\n<br>\n\n## Quickstart\n\nTwo commands. No install.\n\n```bash\nuvx --from git+https://github.com/b3008/devlog.git devlog init\nuvx --from git+https://github.com/b3008/devlog.git devlog install --ai claude\n```\n\nOr install it as a `uv` tool for repeated use:\n\n```bash\nuv tool install git+https://github.com/b3008/devlog.git\ndevlog init && devlog install --ai claude\n```\n\n### One-time global setup (Claude Code, OpenCode)\n\nInstall once and every project gets a blog — no per-project install needed:\n\n```bash\ndevlog install --ai claude --global --with-hook\n# or, for OpenCode (hooks are claude-only):\ndevlog install --ai opencode --global\n```\n\nThis injects the convention into the agent's global context file\n(`~/.claude/CLAUDE.md` for Claude Code, `~/.config/opencode/AGENTS.md` for\nOpenCode) with self-bootstrapping instructions: the agent creates `blog/`,\n`.devlog/`, and `learned.md` on its first entry in any project. Per-project\ncustomization is still available via `devlog init` + config edits in any repo.\n\nRunning a per-project `devlog install` on top of a global install injects a\n**thin pointer block** instead of duplicating the full convention (which\nwould cost ~1.5k duplicated context tokens per session and let the copies\ndrift). Pass `--full` to force the standalone convention — useful for repos\nwhose collaborators don't have the global install.\n\n<br>\n\n## What actually happens\n\n`devlog install` drops a single, bracketed block into your agent's context\nfile — leaving whatever you already had intact:\n\n```diff\n  # My Project\n  <existing CLAUDE.md content stays untouched>\n+\n+ <!-- DEVLOG:START - Do not edit manually. Remove with: devlog uninstall --ai <key> -->\n+ ## Development Blog (Automatic)\n+ After every session where meaningful progress is made, create or\n+ update a blog entry in `blog/`.\n+ ...triggers, structure, voice, tags, media instructions...\n+ <!-- DEVLOG:END -->\n```\n\nFrom then on, the agent writes entries like this without being asked:\n\n```markdown\n---\ntype: \"Devlog Entry\"\ntitle: \"Tag vocabulary now self-updates\"\ndate: 2026-04-16\ntags: [feature, cli, ux]\ndescription: \"devlog install now folds tags from existing entries into the rendered vocabulary.\"\n---\n\n## What changed\n...\n\n## Why it matters\n...\n\n## How it works\n...\n\n## What's next\n...\n```\n\nEntries are [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf) (OKF) concept documents — plain markdown with YAML frontmatter whose one required field is `type`. The `blog/` directory is an OKF bundle: `blog/index.md` is the reserved bundle index (stamped with `okf_version`), and entries cross-link through ordinary markdown links. That makes a devlog readable by any OKF-aware tool or agent, not just this one. Already have a pre-OKF blog? Run [`devlog migrate`](#commands) — it's automatic on your next `devlog install`.\n\n<br>\n\n## Commands\n\n| Command | What it does |\n| --- | --- |\n| `devlog init [--name NAME]` | Scaffold `.devlog/`, `blog/`, `blog/media/`, `blog/index.md`, and `.devlog/learned.md`. |\n| `devlog install --ai <key>` | Inject the convention into the agent's context file. Auto-runs `init` if needed. |\n| `devlog install --ai <key> --global` | Install into the agent's global config (`~/.claude/CLAUDE.md`, `~/.config/opencode/AGENTS.md`) so the convention applies to every project. Supported: `claude`, `opencode`. |\n| `devlog install --ai <key> --force` | Overwrite locally-edited hooks and slash commands with the shipped templates. Untouched files resync on their own; use this to discard an edit you know is obsolete. Never deletes files. |\n| `devlog uninstall --ai <key>` | Remove the convention section and manifest. |\n| `devlog uninstall --ai <key> --global` | Remove the global convention from the agent's global config dir. |\n| `devlog index` | Regenerate `blog/index.md` from entry frontmatter (newest first). |\n| `devlog migrate` | Bring an existing blog up to [Open Knowledge Format](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf) conformance (adds `type`, renames `summary`→`description`, renames the index to `index.md`, stamps `okf_version`). Idempotent; `--check` previews. Also runs automatically during `devlog install`. |\n| `devlog list` | List all supported agents. |\n| `devlog status` | Show which agents currently have the convention active. |\n| `devlog upgrade` | Upgrade the devlog tool, then resync this repo's convention to it. `--check` previews; `--project-only` / `--tool-only` scope it. |\n| `devlog version` | Print version. |\n\n<br>\n\n## Slash commands (Claude Code, OpenCode)\n\nInstalling for Claude Code also drops four slash commands into\n`.claude/commands/` (or `~/.claude/commands/` for `--global` installs).\nInstalling for OpenCode drops the same four into `.opencode/commands/`\n(globally: `~/.config/opencode/commands/`) — the command format (markdown\nbody, `description` frontmatter, `$ARGUMENTS` placeholder) is shared.\nThey give you direct, on-demand control over the blog from inside any\nsession — no flag needed, they ship by default.\n\nIn a project that hasn't been initialized yet, `/devlog-write` will\nbootstrap the scaffolding (`.devlog/`, `blog/`, `learned.md`) on first\nuse — following the global convention's First-time setup instructions\nor running `devlog init` if it's available. `/devlog-catchup` and\n`/devlog-manicure` are read-only; they report \"no devlog yet\" and exit\ngracefully if the project hasn't been scaffolded.\n\n| Command | What it does |\n| --- | --- |\n| `/devlog-catchup` | Reads `blog/index.md`, the 5 most recent entries, and `.devlog/learned.md`, then returns a structured project briefing — project arc, recent work, open threads, glossary highlights. Use at the start of a session to load context. |\n| `/devlog-write <topic>` | Writes a new entry about the given topic. Computes the next per-day index `NN` and ISO timestamp, derives a kebab-case slug, follows your project's convention (sections, voice, tags from `.devlog/config.yaml`), and updates `blog/index.md`. Refuses vague input rather than fabricating. |\n| `/devlog-manicure [topic]` | Four-phase audit of past entries: categorizes findings (followed-through, revised, discarded, drifted, etc.), writes a recap entry, then proposes wipes or dated blockquote annotations (`> **Update YYYY-MM-DD**: …`) for you to approve before applying. Optional topic argument scopes the manicure to a single thread. |\n| `/devlog-upgrade [flags]` | Upgrades the `devlog` tool to the latest from GitHub, then resyncs this repo's convention to it. A thin driver over the two-layer [`devlog upgrade`](#upgrading) CLI: it previews with `--check`, applies when the install is self-upgradeable, and falls back to the right manual step (e.g. `git pull` for a source checkout) when it isn't. Scope with `--tool-only` / `--project-only`. |\n\nThe first three form a working loop: **catchup** loads the blog into\ncontext, **write** adds new entries, **manicure** audits and prunes\nwhat's already there. **upgrade** is maintenance — it pulls the latest\ndevlog and resyncs the convention to it. Uninstall removes them\nautomatically.\n\n<br>\n\n## Adaptive convention\n\nThe convention isn't a frozen snapshot. Three lightweight mechanisms let it\ngrow with the project:\n\n> **`.devlog/learned.md`** — a shared notebook the agent reads before writing\n> and appends to when durable project knowledge surfaces (domain vocabulary,\n> recurring themes, open threads). It lives outside the injected sentinel\n> block, so accumulation is free and diffable. Humans can edit it too.\n\n> **Self-updating tag vocabulary** — on each `devlog install`, entries in\n> `blog/` are scanned and any tags found in their frontmatter are unioned\n> into the rendered tag list. The agent is told it may introduce new tags\n> when they genuinely fit; the next install folds them into the canonical\n> vocabulary.\n\n> **Self-tailoring config** — if the default triggers or voice don't match\n> the project's domain (say, creative writing rather than a code project),\n> the injected convention instructs the agent to propose edits to\n> `config.yaml` and prompt the user to re-run install. The tool adapts to\n> the project rather than the other way around.\n\nTogether these let the convention absorb what the project has actually been\ndoing — without anyone curating `config.yaml` by hand.\n\n### Optional: runtime enforcement (Claude Code)\n\nThe convention asks the agent to self-check at the end of each turn, but\nagents can interpret rules differently depending on whether the turn\nproduced an artifact. For Claude Code, opt into a hook bundle:\n\n```bash\ndevlog install --ai claude --with-hook\n```\n\nThis installs two small scripts under `.devlog/hooks/` and merges the\nmatching entries into `.claude/settings.json` (preserving any existing\nconfig):\n\n- **`stop.py`** (`Stop`) — injects a one-shot reminder before the agent\n  ends its turn, via the structured block channel (no error styling).\n- **`session_end.py`** (`SessionEnd`) — appends one line per session to\n  `.devlog/sessions.jsonl`, so `devlog status` can report sessions that\n  ended without producing an entry.\n\nReinstalls are idempotent and carry existing hooks forward even without\nthe flag (refreshing stale scripts); locally-customized hook scripts are\ndetected by hash and preserved — including across later template changes,\nsince the manifest records what devlog last wrote separately from what is\non disk. Pass `--force` to discard a local edit you know is obsolete; it\nsays which files it overwrote, and never deletes. When both global and per-project hooks\nare installed, the global instance defers to the project's at runtime —\none reminder, one session record. `devlog uninstall --ai claude` removes\nthe hook entries, deletes the scripts (unless customized), and leaves\nany unrelated settings untouched.\n\n### Is it working?\n\n`devlog status` reports whether entries are actually being produced — not\njust whether the sentinel block is present. If the install is more than a\nday old and no entries have been written, it prints a warning with\nremediation hints. With the SessionEnd hook installed it also reports\nsession coverage — how many sessions ended since the last entry was\nwritten, devlog's blind spot.\n\nInstalls are version-aware: the manifest records the devlog version that\nperformed the install, and the sentinel block carries a version stamp\n(`<!-- DEVLOG:START v<version> ... -->`). `status` flags drift — an\ninstall from an older version, an unstamped convention block, or\nartifacts whose recorded hashes differ from the currently shipped\ntemplates — and points at `devlog install --ai <key>`, which doubles as\nthe upgrade command (customized files are preserved). If the install\nwas made by a *newer* devlog than the one running, it recommends\nupgrading the tool instead, since a resync would downgrade.\n\n```\nBlog: blog/ — 3 entries, most recent 2026-04-15\nSessions: 12 recorded, last 2026-04-17 — 4 since the last entry\n\n                  Installed Conventions\n┏━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━┓\n┃ Agent       ┃ Context File ┃ Status ┃ Version ┃ Installed  ┃\n┡━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━┩\n│ Claude Code │ CLAUDE.md    │ active │ 0.1.0   │ 2026-04-10 │\n└─────────────┴──────────────┴────────┴─────────┴────────────┘\n\nClaude Code: installed by devlog 0.1.0, current is 0.2.0. Run\ndevlog install --ai claude to resync (customized files are preserved).\n```\n\n<br>\n\n## Supported agents\n\nFour agents get first-class integrations:\n\n| Key | Agent | Context file | Extras |\n| --- | --- | --- | --- |\n| `claude` | Claude Code | `CLAUDE.md` | slash commands, `--global`, `--with-hook` |\n| `opencode` | OpenCode | `AGENTS.md` | slash commands, `--global` |\n| `copilot` | GitHub Copilot | `.github/copilot-instructions.md` | — |\n| `gemini` | Gemini CLI | `GEMINI.md` | — |\n\n<details>\n<summary><strong>23 more agents</strong> use the shared <code>AGENTS.md</code> standard — click to expand</summary>\n\n<br>\n\n`codex` · `cursor-agent` · `kimi` · `qwen` · `agy` · `trae` · `roo` ·\n`bob` · `auggie` · `kilocode` · `windsurf` · `codebuddy` · `vibe` ·\n`amp` · `kiro-cli` · `tabnine` · `goose` · `pi` ·\n`forge` · `shai` · `iflow` · `junie` · `qodercli`\n\n</details>\n\nRun `devlog list` for the live registry.\n\n<br>\n\n## How it works\n\n1. **`init`** drops a default `.devlog/config.yaml`, creates the blog\n   skeleton, and scaffolds `.devlog/learned.md`.\n2. **`install`** renders the config into a markdown block and writes it to\n   the agent's context file between sentinel markers. Existing content is\n   preserved; re-installing replaces only the section between the sentinels.\n   A SHA-256 of the resulting file is saved to\n   `.devlog/manifests/<agent>.manifest.json`.\n3. **`uninstall`** strips the sentinel block and removes the manifest.\n\n### Layout after install\n\n```\nyour-project/\n├── .devlog/\n│   ├── config.yaml              # stable convention settings\n│   ├── learned.md               # agent-maintained project notebook\n│   ├── .gitignore               # ignores the runtime session log\n│   ├── hooks/                   # Stop + SessionEnd scripts (--with-hook)\n│   ├── sessions.jsonl           # session coverage log (gitignored)\n│   └── manifests/\n│       └── claude.manifest.json # install tracking\n├── .claude/                     # claude installs (.opencode/ for opencode)\n│   └── commands/                # slash commands\n│       ├── devlog-catchup.md\n│       ├── devlog-write.md\n│       ├── devlog-manicure.md\n│       └── devlog-upgrade.md\n├── blog/                        # OKF bundle\n│   ├── index.md                 # bundle index (okf_version stamp)\n│   ├── 2026-04-16-01-first-entry.md\n│   └── media/\n└── CLAUDE.md                    # convention injected between sentinels\n```\n\n<br>\n\n## Configuration\n\nEdit `.devlog/config.yaml` to customize:\n\n| Key | Purpose |\n| --- | --- |\n| `blog_dir` / `media_dir` / `index_file` | Where entries and media live. |\n| `sections` | Headings each entry should have. |\n| `voice` | Tone and audience guidelines baked into the convention. |\n| `triggers` | When the agent should write an entry. |\n| `tags` | Base tag vocabulary (auto-extended by discovery). |\n| `frontmatter` | YAML frontmatter fields for each entry. |\n| `media` | Supporting-artifact instructions (CLI output, diffs, Mermaid, user-provided screenshots). Set `enabled: false` to skip. |\n\nRe-run `devlog install --ai <key>` after editing to regenerate the injected\nsection.\n\n<br>\n\n## Upgrading\n\nA devlog install has two layers — the **tool** itself and the **convention** it\ndropped into your repo — and they version independently. `devlog upgrade` brings\nboth up to date in one step:\n\n```bash\ndevlog upgrade\n```\n\nIt detects how the tool was installed, runs the matching upgrade (e.g.\n`uv tool upgrade devlog`), then re-invokes the freshly installed binary to\nresync every agent in this repo — convention block, hooks, and slash commands —\npreserving any files you've customized. Preview first with `--check`; scope with\n`--project-only` (resync this repo only) or `--tool-only` (bump the binary only):\n\n```bash\ndevlog upgrade --check          # show what would happen, change nothing\ndevlog upgrade --project-only   # resync this repo to the installed tool\ndevlog upgrade --tool-only      # upgrade the binary, skip the resync\n```\n\nIf devlog is running from a source checkout or an ephemeral `uvx` invocation —\nwhere there's no managed binary to replace — `upgrade` won't guess; it prints\nthe exact command to run and stops.\n\n<details>\n<summary>Prefer to do it by hand?</summary>\n\n<br>\n\n```bash\n# 1. Upgrade the tool\nuv tool upgrade devlog\n#    (or, for a clean reinstall from latest:)\n# uv tool install --force git+https://github.com/b3008/devlog.git\n\n# 2. Resync this repo's convention to the new tool\ndevlog install --ai claude        # add --global if it was a global install\n```\n\n`devlog status` reports the version that performed the install versus the\nrunning tool and flags any drift — and if the repo was last touched by a *newer*\ndevlog than your tool, it tells you to upgrade the tool first rather than\nresyncing (which would downgrade).\n\n</details>\n\n<br>\n\n## Uninstalling\n\n```bash\n# Remove from a specific project\ndevlog uninstall --ai claude\n\n# Remove the global install\ndevlog uninstall --ai claude --global\n```\n\nThis removes the sentinel block from the context file, the Stop hook (if\ninstalled) from `settings.json`, the hook script, and the manifest. Your\nblog entries, `.devlog/config.yaml`, and `.devlog/learned.md` are left\nuntouched — they're your data, not ours.\n\nIf the context file (`CLAUDE.md`, `AGENTS.md`, etc.) is empty after\nremoving the devlog section, it's deleted automatically.\n\n<br>\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n",
  "bytes": 22258,
  "sha": "967530933377a59075ca95d7a6a9ddf4a8f51597d25756fecb2030d3bdad7b63",
  "repo_slug": "b3008/devlog",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/okf_b3008_devlog_blog_index_md_ca3228de/readme"
}