Project management that lives in your repo. Git isn't just the sync layer — it's the database, the audit log, and the permission system.
DIT stores issues, epics, documents, and changelogs as Markdown files inside a
git repo. A fast local index answers queries; a frontmatter-aware merge driver
merges two people's edits to the same issue field-by-field; one dit binary
serves the browser UI itself. No server to run, no account to create — every
clone is the whole workspace.
Roughly: Jira + Confluence + GitLens, merged, running locally, with git as the database.
v0.1 slice running. The CLI, the merge driver, and the browser UI
work end to end on real workspaces — dogfooding starts now. What is deliberately
not built yet: git hooks, commit-trailer integration, dit validate, the AI
layer, the block editor. See DESIGN.md §10 for the roadmap.
On a Mac, without the terminal afterwards — the DIT app lives in the menu bar, starts and stops DIT, and opens it in your browser:
brew install --cask faridlab/tap/ditThen open DIT from Applications. The first page asks for a name for your
first workspace; nothing else to set up. The cask also puts dit on your
PATH. (DIT is not notarized by Apple yet, so the cask clears macOS's
download quarantine from DIT's own app — see ADR 0029. A zip downloaded from
the releases page in a browser instead needs System Settings → Privacy &
Security → Open Anyway once.)
The command line, any platform. Requires git. The installer downloads a release binary for your platform and falls back to building from source when there isn't one:
curl -fsSL https://raw.githubusercontent.com/faridlab/dit-cli/main/scripts/install.sh | bashFrom source:
git clone https://github.com/faridlab/dit-cli
cd dit-cli
npm ci --prefix apps/web && npm run build --prefix apps/web # embeds the UI
cargo install --path crates/dit-cli --features embed-ui --lockedWithout the npm step the binary still works from the terminal — dit ui just
won't serve pages until it is built with --features embed-ui.
mkdir my-tracker && cd my-tracker # any git repo becomes the workspace
dit init # git init, merge driver, README
dit issue new "Fix the login flow" -P p1 -a budi -l area:auth
dit list "status != done AND assignee = @me"
dit ui # board, detail, DQL search — in the browserEverything you just made is Markdown — issues/, docs/, notes/, changelogs/ at the
root, machinery in .dit/ — one commit per change. Push it, clone it elsewhere, and the
workspace travels with the repo.
Two people edit the same issue on different machines. Both dit sync. The
merge driver reads the frontmatter on all three sides and merges field-by-field:
status moved by one, assignee by the other — both land. Only a genuine edit to
the same field leaves conflict markers, as a state git already knows how to
finish, never a corrupt file.
| Category | Command | What it does |
|---|---|---|
| Workspace | dit init |
Make the current directory a workspace: git init, merge driver, README. |
dit doctor |
Check everything that silently breaks a workspace when wrong. | |
dit status |
Branch, head and working-tree state. | |
dit sync |
Fetch, rebase onto the remote, push. Exits 1 when files need a human. | |
dit reindex |
Rebuild the local index from git. | |
dit install-driver |
Register this binary as the repository's merge driver. | |
dit workspace list | current | new | add | use | remove |
The workspaces on this machine; current names the one a command acts on, -W <name> picks another. |
|
| Issues | dit issue new <title> |
Create — kind, status, priority, assignees, labels, estimate, body. |
dit issue show <ref> |
One issue: fields, body, comments, field history. | |
dit issue set <ref> field=value… |
Change fields, e.g. status=done labels=a,b. |
|
dit issue comment <ref> <text> |
Add a comment. | |
dit list [DQL] |
List issues matching a query; no query = all. | |
dit board |
The board: one column per workflow status. | |
| Coordination | dit ready, dit claim, dit inbox |
What a lane can start, exclusive intent on an issue, and the threads waiting on a lane. |
dit flow [name] |
Orchestration flows: issues sharing a name, as stages. | |
| Documents | dit docs templates |
The kinds of document — BRD, PRD, SRS, FSD, business flow, TSD, data model, API contract, ADR, test plan, release notes. |
dit docs new <kind> <title> |
Make a page from a template, placed in its stage folder. | |
| API scenarios | dit morse check | run | sync | send |
Morse: scenarios pinned to OpenAPI specs — is each still true, and prove it against an environment. |
dit morse import | env |
Bring in cURL or Postman; set this machine's environments. | |
| Code | dit code users <file|symbol> |
Who imports it — in any git repository, no setup (docs/code-map.md). |
dit code uses | path | where | hubs | explain |
What it depends on, how two files connect, which files answer a question. | |
| UI | dit ui [--all] |
Serve this workspace — or, with --all, every workspace on this machine — to the browser. |
| AI agents | dit ai init, dit ai spec [topic] |
Write the agent guide into a workspace, or point a code repository's agents at one (dit -W <name> ai init); print the guide, or one topic of it. |
| Install | dit upgrade [--check] |
Update a binary installed by the script; a Homebrew install updates with brew upgrade --cask dit. |
dit ui serves on 127.0.0.1, authenticates with a per-session token it
prints (and puts in the URL fragment once), and opens the browser. The same
workspace can be worked from the terminal and the browser at once — both go
through one dit-core.
Git already provides, for free, what Jira built from scratch and sells:
| Need | What Jira built | What git already has |
|---|---|---|
| Change history | An activity log table | git log, git blame |
| Who changed what | An audit table | Author + committer + signature |
| Multi-device sync | A server + API | fetch / push |
| Offline work | Nothing | Native |
| Reviewing changes | Approval workflows | Pull requests |
| Permissions | Custom RBAC | Git host permissions + CODEOWNERS |
| Backup | A paid service | Every clone is a full backup |
| File | What it is |
|---|---|
DESIGN.md |
What is being built and why, with a table of contents and glossary. |
ARCHITECTURE.md |
How code is written and changed. Eleven invariants, dependency rules, TDD policy. |
CONTRIBUTING.md |
Setup, the checks, commits and pull requests. Start here to contribute. |
docs/module-map.md |
Where a change belongs, by what it is about. |
docs/adr/ |
The decisions taken so far, by topic. |
CLAUDE.md / AGENTS.md |
Operating instructions for AI coding agents. |
docs/code-map.md |
The code map: how to use dit code, and what it costs against grep and graphify, measured. |
Read ARCHITECTURE.md §1 before your first PR. Eleven invariants are
non-negotiable, and each one is enforced by a test in tests/invariants.rs.
CONTRIBUTING.md has the setup; just check runs every
Rust gate — fmt, clippy, tests, architecture, invariants, wasm — and
just web-test the web app's tests. Open in VS Code and accept the
recommended extensions.
The rich editor's markdown bridge is Rust compiled to WASM (ADR 0011):
the editor in the browser serializes through the exact same code as
dit fmt, so a UI save never produces a formatting diff. The artifact is
gitignored like any build output — after changing dit-parse or dit-wasm,
rebuild it and restart the dev server:
just wasm-build # → apps/web/src/editor/wasm/npm run build and vite dev both fail with instructions when it is
missing, and the bundle gate caps the artifact at 260 KB gzipped.
crates/
dit-model dit-parse dit-query pure core — no I/O, compiles to wasm32
dit-store dit-index dit-vcs dit-ai adapters — touch the outside world
dit-morse dit-code adapters — API scenarios, the code map
dit-core facade — the only public API
dit-cli dit-server dit-wasm delivery
dit-tray delivery — the macOS menu bar app
docs/
adr/ the decisions, one file each
module-map.md where a change belongs
plans/ work in progress across many pull requests
tests/
architecture.rs dependency direction
invariants.rs invariants I1–I11
apps/web/ React + TypeScript UI
scripts/
install.sh the curl | bash installer
build-macos-app.sh assembles DIT.app (CI runs it on release)
packaging/homebrew/dit.rb the cask template for faridlab/homebrew-tap
Apache-2.0