Guide / From the first decision onward
Give your next session
a memory of why.
Start with one real choice. Keep the reason and the rejected alternative. Then let the next session pick up where you left off.
Install dira
Homebrew is the quickest path on Apple Silicon Macs, Intel Macs, and Linux AMD64.
brew install kazi-org/tap/dira
dira --versionFor Linux ARM64, or to install without Homebrew, download the matching archive from GitHub Releases. Each release includes macOS and Linux builds for ARM64 and AMD64, plus a checksums.txt file.
Build from source
Use the Go toolchain specified in go.mod.
git clone https://github.com/kazi-org/dira.git
cd dira
go build ./cmd/dira
./dira --helpA plain source build reports dev. Release binaries carry their release version. Put the binary on your PATH before configuring hooks.
Record your first decision
In your project directory, seed a ledger with a short interview. Choose workspace, then supply an intent, a constraint, and an open question. The interview writes all answers together; an incomplete interview leaves no partial ledger.
dira init --interviewRecord a choice, the option you rejected, and the reason. This example creates dec-0001 in a fresh ledger:
dira log --kind decision --title "Use SQLite for local storage" \
--alternative "PostgreSQL" \
--why-not "Local storage must work offline without a database server" \
--revisit-if "Multiple users need concurrent remote writes"Now retrieve it and try a plan that repeats the rejected choice.
dira why SQLite
dira check "use PostgreSQL for local storage"✗ conflicts with dec-0001
rejected alternative: "PostgreSQL"
why_not: Local storage must work offline without a database server
revisit_if: Multiple users need concurrent remote writes
→ supersede dec-0001, or revise the planOutput above is abridged. check exits with 2 for the conflict. Commit .dira/ alongside your code; its cache is derived data.
Matching is lexical. A result with no conflict means the matcher found none; it is not a proof that a plan has no semantic contradictions.
Connect your coding agent
The bundled integration targets Claude Code. Install its hooks and capture skill once:
dira install-hooks
dira install-skillThe hooks merge into ~/.claude/settings.json, preserving existing registrations. The skill is written under ~/.claude/skills/dira/. Start a new session in the repository to receive the brief.
| Event | What happens |
|---|---|
| SessionStart | brief --context --chain supplies decision context. |
| Stop | sniff --stage --quiet stages candidate decisions. |
| PreCompact | sniff --deep --stage --all preserves candidates before compaction. |
Review is a separate step
dira distillIn an interactive terminal, confirm, ignore, edit, or undo a capture. Regex capture never invents a reason or accepts a decision. Confirmation marks a capture for semantic extraction; the entry stays staged until the session agent supplies its reasoning.
The PreCompact hook captures candidates, but its output alone does not guarantee completed semantic extraction. Check pending captures with distill. The hook configuration documents the delivery constraints.
For another agent, invoke the CLI directly and arrange for dira brief at session start and dira check before planning. The CLI has no model client; semantic work belongs to your agent session.
Recall the reasoning
dira brief
dira why SQLite
dira uibrief summarizes blockers, active intents, and recent decisions in at most 1,500 tokens. why resolves an entry by ID, title, or tags and follows the reasoning chain. Search by the decision’s title, not just the name of a rejected alternative.
ui serves a read-only browser on localhost. See the same renderer in action in Dira’s own ledger.
Use check in your workflow
Run plans through dira check "your proposed plan" explicitly. The bundled capture hooks do not automatically gate plans.
| check exit code | Meaning |
|---|---|
0 | No conflict detected. |
2 | A conflict with a settled decision. |
1 | The check failed to run, including invalid arguments. Never treat this as a clean verdict. |
Other commands generally use exit 2 for usage errors. Consult the command reference for each command’s contract.
Change direction without losing history
Decisions are allowed to change. First record a replacement with its own reasoning, then supersede the old decision. Use the IDs returned by your ledger:
dira supersede dec-0001 --with dec-0002 \
--note "Requirements have changed"The replacement gains a supersedes relationship and the old entry becomes superseded. Future checks consult the replacement. Both sides of the change remain in Git.
Bring existing ADRs
dira import docs/adrDira reports how many documents contain a rejected option with a reason before asking to write. Confirm interactively or pass --yes. Imported decisions are staged and carry the source filename and content hash.
If the corpus contains no reasoned rejections, dira offers to index it in the cache instead. It does not invent alternatives or turn every document into an enforceable decision.
Your files are the record
.dira/
├── config.toml # Configuration
├── entries/ # Markdown + YAML frontmatter
│ ├── int-0001.md
│ └── dec-0001.md
└── cache/ # Derived SQLite; rebuildableThere are five entry kinds. Rejected alternatives are part of a decision, rather than a separate kind.
| Kind | What it records |
|---|---|
| Intent | What you are trying to make true. |
| Decision | A choice, its rejected alternatives, and their reasons. |
| Question | Something unresolved that may block work. |
| Constraint | A rule the work must respect. |
| Note | Supporting context. |
Relationships connect entries. For example, a decision can derive_from an intent. See the exact edge names and validation rules in the entry schema.
dira reindexThe cache can be rebuilt from the entry files. Read, review, and diff the source with ordinary Git tools.
Connect context across projects
Declare parent ledgers in .dira/config.toml to organize personal, workspace, and repository context. dira brief --chain surfaces parent context; namespaced references connect entries across ledgers.
Parent context is read at runtime. Follow the tier and privacy rules when combining private context with public repositories.
Direction and execution
kazi checks whether a declared goal satisfies its acceptance predicates. Dira preserves why the goal matters and the choices behind it. Both work independently.
dira mapThe map groups active intents and accepted decisions and reads execution status through kazi’s public JSON interface. If kazi is unavailable, the ledger groups still render with an explanation. Execution status is never stored in the ledger.
When something doesn’t look right
The hook cannot find dira
Verify dira --version in your shell and ensure the binary is on the PATH available to Claude Code. Start a new session after installing hooks.
A capture stays staged
Confirmation is not acceptance. The agent still needs to supply semantic reasoning. Review the queue with dira distill and consult the capture skill.
why cannot find my search
Try the entry’s exact ID, a word from its title, or a tag. The quick-start example uses dira why SQLite.
The command list differs
This website follows the source tree. Run dira --help for your installed binary and check release notes before upgrading.
Help make the record better
Dira is open source under the Apache License 2.0. Read the design document, explore the project’s decisions, or report a reproducible issue on GitHub.
sh hooks/install.sh
go test ./...Run these from the source checkout before contributing. The tests include validation of Dira’s own ledger against its schema.