bagit
Markdown-native, git-aware backlog management for humans and AI agents.
bagit keeps your backlog as a directory of markdown files inside .bagit/.
Every item is a single item.md with YAML frontmatter for state, an inline
## Comments log, and a per-item assets/ directory. Git is the history;
the files are the database.
A single binary gives you a scriptable CLI and an interactive terminal UI.
Designed Windows-first for Windows Terminal on Windows 10/11; Linux and macOS
builds are produced as best-effort.
Status: pre-1.0. The on-disk format is stable but the CLI surface may
still shift in small ways before the first tagged release.
Why
Most issue trackers are databases-with-a-web-UI. That's fine for big
organisations and miserable for solo work, agent-driven work, or anything
you'd like to keep alongside the code in git. bagit flips it:
- Markdown is the source of truth — your backlog lives in your repo,
diffs cleanly, and works offline.
- Humans and agents share the same workflow — the CLI is the canonical
surface; agents are taught the schema via a shipped
AGENTS.md skill.
- No vendor lock-in for AI —
bagit doesn't talk to LLM providers. It
shells out to your existing agent CLI (OpenCode, Claude Code, …)
through configurable named actions.
- Soft validation — drift is warned about, never blocked. You can always
open
item.md in $EDITOR and fix things by hand.
Install
Go
go install github.com/douglaswaights/bagit/cmd/bagit@latest
Manual
Grab the latest archive from the releases page
and put bagit (or bagit.exe) on your PATH.
A Scoop bucket is planned for the first tagged release. Until then,
use go install or grab a release archive.
Quick start
Start every repo with bagit init. It creates the .bagit/ backlog shape,
refreshes the repo-root AGENTS.md instructions, updates .gitignore, and on
an interactive first run asks which detected agent harnesses should get bagit
skills installed.
cd path/to/your/repo
bagit init # first-time setup; prompts for detected agent skills
bagit new "Wire up the kanban view" # creates .bagit/items/0001-wire-up-the-kanban-view/item.md
bagit new # on a TTY, launches an interactive scaffold form
bagit new "Login crash" --type bug # use the bug template
bagit new "Quick note" --blank # skip the template body
bagit new "Tweak readme" --edit # create then open in $EDITOR
bagit list # show the backlog
bagit show 1 # render the item preview
bagit start 1 # move to in-progress
bagit comment 1 "started prototyping"
bagit body 1 -m "rewrote the body" # replace body without an editor
bagit attach 1 ./screenshot.png # copy a file into the item's assets/
bagit open 1 # open the item directory in the OS file handler
bagit done 1
bagit i # launch the interactive TUI (alias: bagit interactive)
Useful init variants:
bagit init --yes # non-interactive defaults; auto-detects skills
bagit init --skills opencode # force-install a skill for a harness
bagit init --reconfigure # re-run the first-time prompts later
bagit skills regenerate # refresh detected harness files after upgrading bagit
Run bagit --help for the full command list. Bare bagit always prints
help; the TUI is only launched explicitly via bagit i. Many structured read
commands accept --json for scripting; run <cmd> --help for details.
Command map
| Group |
Commands |
| Items |
new, list, show, rm, mv, start, done, reopen, edit, body, open, path |
| Comments |
comment, comments |
| Assets |
attach, attach rm, assets |
| Tags |
tag list, tag add, tag rm, tag rename, tag set, tag add-to, tag rm-from |
| Search |
search, xref, validate, stats |
| Config |
config get, config set, config show |
| Templates |
templates list, templates eject, templates reset |
| Skills / AI |
skills install, skills regenerate, skills list, ai, ai list |
| TUI |
i, interactive, tui |
Getting started
bagit is designed to live inside a code repository and be edited by
both humans and AI agents in the same session. The mental model is:
- The backlog is a folder, not a service. Every item is a file you
can read, edit, grep, diff, and commit.
bagit is a convenience
layer over that folder; if it ever gets in your way, drop into
$EDITOR and fix the markdown directly.
- The CLI is the canonical surface. Every supported workflow has a
scriptable command. The TUI is a nicer way to drive the same commands
for humans; agents only need the CLI.
- Agents share your workflow.
bagit init teaches whatever agent
is operating in the repo (OpenCode, Claude, Cursor, GitHub Copilot, …)
the schema
and the small command vocabulary it should use, so a human and an
agent can pick up each other's work mid-stream.
First five minutes
Run these once per repo:
cd path/to/your/repo
bagit init # scaffolds .bagit/ (config, tags, items), refreshes
# AGENTS.md, and detects agent tools already
# configured here. On a TTY you'll get a few quick
# questions, including which detected tool skills
# to install. Pass --yes to skip them, or
# --reconfigure to re-ask later.
bagit new "Try out bagit" # creates the first item from the default template
bagit list # confirm it's there
bagit i # browse it in the TUI
git add .bagit AGENTS.md # commit the backlog with your code
git commit -m "chore: adopt bagit"
After that, the day-to-day rhythm is:
- Pick or create an item (
bagit new, or n in the TUI).
- Move it through
new -> in-progress -> done as you work
(bagit start, bagit done, or s / d in the TUI).
- Drop comments and screenshots onto items you're investigating
(
bagit comment, bagit attach, or c in the TUI).
- Commit
.bagit/ alongside the code change that resolves the item.
The backlog ships with the codebase; PR reviewers see exactly which
items a change addresses.
Working as a human
- Stay in the TUI for backlog grooming, triage, and quick edits.
bagit i gives you kanban + list views, inline previews, substring
filter (/), tag filter (f), and link navigation in list preview.
- Reach for the CLI when you're scripting, piping, or batch-editing.
Structured read commands support
--json where useful so you can pipe
into jq, spreadsheet importers, dashboards, etc.
- Edit
item.md files directly whenever the CLI feels heavier than
necessary. As long as the YAML frontmatter stays valid, bagit will
pick up your changes on the next read; bagit validate will warn
about anything that drifted.
- Treat
.bagit/ as part of your code. Branches, PRs, and merges all
apply to the backlog the same way they apply to source.
Working as (or with) an agent
bagit init writes a bagit:start / bagit:end block into the
repo-root AGENTS.md. That block is the agent's contract: it
describes the on-disk schema, the command vocabulary, and the rules
for safe edits (always go through bagit for state changes; never
invent IDs; comments are append-only; etc.).
- On a fresh interactive init, bagit auto-detects supported harnesses that
already have repo markers (
.opencode/, .claude/, .cursor/, Copilot
instruction files, etc.) and prompts which detected tool skills to install.
The selected skills are written immediately. If a tool is not detected, force
it explicitly with bagit init --skills opencode or later with
bagit skills install opencode (also supports claude, cursor, and
copilot).
- OpenCode and Claude get a task-oriented
/backlog command for capturing
follow-up work from the current chat; Cursor and Copilot get equivalent
always-on instructions. bagit skills regenerate refreshes whatever you've
installed after upgrading bagit.
- In command-capable harnesses, use
/backlog <request> or
/backlog bug|feature|idea <request> to ask the agent to summarize the
current chat into a new bagit item. In instruction-only harnesses, say
"add this to the backlog" or "track this later"; the generated guidance
tells the agent to run bagit new and bagit body non-interactively.
- For free-form AI edits on a single item, configure named actions in
.bagit/config.toml (see Agent integration
below) and trigger them from the CLI (bagit ai <action> <id>) or
from the TUI (a on the focused item). bagit shells out to your
existing agent CLI; it never talks to a model directly and never
needs an API key of its own.
- Auditing what an agent did is just
git log .bagit/. Because the
backlog is plain markdown, every state change is a normal commit
diff you can review, revert, or cherry-pick.
A typical mixed session looks like:
# Human triages overnight work
bagit i # browse, reorder, retag
# Agent picks up the next in-progress item
bagit list --status in-progress --json | jq '.[0]'
bagit show 7
bagit comment 7 "investigating the failing test"
# ... agent edits code, runs tests ...
bagit body 7 -f repro.md
bagit done 7
# Human reviews the diff
git diff .bagit/items/0007-*/item.md
On-disk layout
.bagit/
config.toml
tags.yaml
items/
0001-wire-up-the-kanban-view/
item.md
assets/
0002-fix-yaml-roundtrip/
item.md
Each item.md looks like:
---
id: 1
title: Wire up the kanban view
type: feature
status: in-progress
tags: [tui, ui]
created: 2026-04-22T09:14:00-07:00
updated: 2026-04-22T11:02:00-07:00
---
Body in markdown. [Cross-references](../0002-fix-yaml-roundtrip/item.md)
are just relative links. Images live in `assets/` and are referenced the
same way.
## Comments
### 2026-04-22 11:02 — alice
Started prototyping the column layout.
TUI
bagit i (aliases: bagit interactive, bagit tui) launches a Bubble
Tea v2 app:
- Switch between kanban and list-with-preview with
K / L,
or toggle between them with v.
- Vim and arrow keys both work for navigation.
gg / G (and
home / end) jump to the top / bottom of the current list or column.
n creates an item, e edits the body in $EDITOR, m edits the
tag list, c adds a comment, s / d / r start / done / reopen,
D deletes (with confirm), R refreshes from disk.
/ opens an inline filter, f opens a tag filter, and x / Ctrl+L
clears the active filter. p toggles the preview pane in list view.
o opens the selected item's directory in the platform file handler;
a runs a configured AI action against the selected item.
- In list preview,
Tab / Shift+Tab cycle markdown links;
Enter activates them (navigates to bagit items via cross-reference,
or opens external URLs / asset files via the platform default opener);
Ctrl+O walks the navigation history backwards and Ctrl+I walks it
forwards (browser-style).
i toggles inline image previews for selected image links. Rendering uses
Kitty / iTerm / Sixel when the terminal supports it, then chafa if
installed, otherwise a metadata placeholder is shown.
? shows the full key-binding list.
- File-system changes (anything that touches
.bagit/items/) are picked
up live while the TUI is open.
Agent integration
bagit init writes a bagit:start / bagit:end block into the repo-root
AGENTS.md containing the full schema, command reference, and operating
guidelines for any agent. On a fresh interactive init, detected tools are shown
in a prompt and the selected skills are installed immediately. You can also
install or refresh them later:
bagit skills install opencode # writes .opencode/command/backlog.md
bagit skills install claude # writes .claude/commands/backlog.md
bagit skills install cursor # writes .cursor/rules/backlog.mdc
bagit skills install copilot # writes .github/copilot-instructions.md
bagit skills regenerate # refresh detected harness files
bagit skills list # show detected harnesses
OpenCode and Claude command files are designed for prompts like:
/backlog add a follow-up to make the TUI filter menu keyboard searchable
/backlog bug selected kanban items lose focus after moving lanes
/backlog idea explore richer backlog capture templates
The agent should infer a concise title, type, tags, and a markdown body from
the current chat context, then create the item with bagit new ... --yes and
bagit body <id> -m .... Cursor and Copilot receive the same workflow as
standing repo instructions rather than slash commands.
For free-form AI edits on a single item, configure named actions in
.bagit/config.toml:
[ai]
default_action = "opencode"
[ai.actions.opencode]
command = "opencode"
args = ["run", "--file", "{item_path}", "improve this item"]
[ai.actions.claude]
command = "claude"
args = ["--file", "{item_path}", "rewrite for clarity"]
Then:
bagit ai opencode 1 # run the named action against item 1
bagit ai 1 # run the default action
bagit ai list # show available actions
Substitution tokens: {item_path}, {item_dir}, {item_id}, {title}.
Configuration
.bagit/config.toml is seeded by bagit init from the embedded sample.
Inspect or change values via:
bagit config show # print the full effective config
bagit config show --json
bagit config get tui.default_view
bagit config set tui.default_view list
bagit config set editor.command "code --wait"
bagit config set tags.strict true
Keys are addressed by their TOML path (e.g. tui.default_view,
general.default_status, ai.default_action, tags.strict). String
and bool leaves are settable from the CLI; complex values can be edited
directly in .bagit/config.toml.
Defaults bias toward Windows: code --wait if it's on PATH, otherwise
notepad. Override with $VISUAL / $EDITOR or
bagit config set editor.command ....
Templates
Item bodies are seeded from per-type templates. The defaults are embedded
in the binary; eject any of them to override:
bagit templates list # show which templates are embedded vs. ejected
bagit templates eject bug # writes .bagit/templates/bug.md
bagit templates eject --force feature
bagit templates reset bug # delete the override and fall back to embedded
Use bagit new --type <bug|feature|idea> to pick a different per-type
template, or bagit new --blank to skip template insertion entirely.
On a TTY, running bagit new with no title (or with --interactive /
-i) launches a form to pick title, type, status, tags, and optionally
open the new item in $EDITOR. Pass --yes / -y to force the
non-interactive path.
Building from source
git clone https://github.com/douglaswaights/bagit
cd bagit
go build ./cmd/bagit
go test -race ./...
Requires Go 1.25+.
Contribution guidelines for humans and agents live in AGENTS.md.
Releasing
Releases are created by pushing a version tag. Use a v prefix:
git tag v0.1.0
git push origin v0.1.0
GitHub Actions runs GoReleaser and creates a draft release with artifacts.
License
MIT — see LICENSE.