The forge project uses a well-structured markdown-based task tracking system
(docs/tasks/), with ~4100 lines across 10 files, an inbox, topic trackers,
and a prioritized next.md. The system works well for detailed planning with
AI agents, but has friction points:
- No unified view — status is scattered across files; "what's in flight?" requires reading multiple documents
- Manual triage — promoting items from inbox → trackers → next is manual copy-paste
- No queryability — can't filter by status, priority, or tag across trackers
- Large files —
tui-polish.mdis 1353 lines; hard to scan
| Priority | Requirement |
|---|---|
| #1 | AI-readable — Copilot/Claude can read and update tasks during sessions |
| #2 | Queryable — "show me all in-progress items" in one command |
| #3 | General-purpose — works across all projects, not just forge |
| Rust — single binary, consistent with forge ecosystem |
| Decision | Choice | Rationale |
|---|---|---|
| Storage engine | rusqlite (C SQLite via FFI) + refinery for migrations |
Battle-tested, production-grade, sync API ideal for CLI. Refinery provides versioned SQL migrations embedded at compile time (crates/track-db/migrations/). |
| Storage model | SQLite-first — central DB, markdown is an export | Simplest model. No sync logic. AI agents interact via CLI (--json). Markdown export (track render) is a future read-only view for git repos. |
| DB location | ~/.track/track.db (global, central) |
Single DB for all projects. Cross-project queries are trivial. Projects are scoped inside the DB, not by file location. |
| Repo structure | New standalone repo (~/workspace/track) |
General-purpose tool, not coupled to forge. Own release cycle, cargo install friendly. |
| Markdown in repos | Repos keep their own plan/doc markdown files | The tracker doesn't own or sync repo markdown. track render (future) can export a snapshot, but repos manage their own docs independently. |
Human / AI agent
│
▼
track CLI ──→ track-api ──→ track-db ──→ ~/.track/track.db
│ (central SQLite via rusqlite)
▼ (future)
track render ──→ docs/tasks/*.md (read-only export)
Future frontends slot in at the same level as the CLI:
track-cli ─────┐
track-tui ─────┤ (future, ratatui)
track-web ─────┤ (future, axum/REST)
track-mcp ─────┘ (future, MCP server)
│
▼
track-api (business logic, sync)
│
▼
track-db (rusqlite, schema, migrations, sync)
│
▼
track-core (pure types, enums, no IO)
track/
├── Cargo.toml # workspace (edition 2024, MSRV 1.86)
├── justfile # test, lint, check, build recipes
├── AGENTS.md # AI agent instructions
├── crates/
│ ├── track-core/ # Pure types: Item, Note, Status, Priority enums
│ ├── track-db/ # rusqlite storage, refinery migrations, queries
│ │ └── migrations/ # V1__initial_schema.sql, V2__... (embedded at compile time)
│ ├── track-api/ # Business logic: list, add, transition, validate
│ └── track-cli/ # clap CLI, terminal formatting, --json output
| Crate | Responsibility | Depends on | Async? |
|---|---|---|---|
track-core |
Pure types, enums, error types, no IO | nothing | sync |
track-db |
SQLite schema, queries, migrations | track-core, rusqlite, refinery |
sync |
track-api |
Business logic, validation, filtering | track-core, track-db |
sync |
track-cli |
Arg parsing, terminal formatting, --json |
track-core, track-api, clap |
sync |
Key rules:
- Frontends (
cli, futuretui/web/mcp) depend ontrack-api, never ontrack-dbdirectly track-corehas zero dependencies on IO — can be used anywhere- Everything is sync — rusqlite is sync, no network IO, no streaming
- Future async frontends (TUI, web, MCP) wrap sync API calls with
spawn_blocking
| Pattern | Description |
|---|---|
| Core = pure types, no IO | track-core mirrors forge-core — portable, testable |
thiserror in libs, anyhow in CLI |
Clean error separation |
clap derive for CLI args |
Declarative arg parsing |
tracing for logging |
Structured, not println! |
Workspace [workspace.dependencies] |
Dep version deduplication |
justfile recipes |
just test, just lint, just check |
AGENTS.md at repo root |
Self-documenting for AI agents |
| Edition 2024, MSRV 1.86 | Modern stable Rust |
| Pattern | Why not |
|---|---|
| Async/tokio throughout | No streaming, no network IO in core path |
| Channels/worker separation | No concurrent workers |
| Provider abstraction | Single storage backend (SQLite) |
| Session recording | Not relevant |
Project
├── Tracker (≈ epic / milestone)
│ └── Item (≈ issue / work item)
└── Note (≈ decision log / cross-session knowledge)
Coding agents (Copilot CLI, Claude Code, etc.) each have native planning modes
that are already good at in-session planning. track does NOT compete with that.
Instead, it is the persistent system of record that agents write to and read
from — capturing what agents genuinely can't do: remember across sessions and
answer "what's the status?" at any time.
Designed for LLM efficiency: Level 1 fields are always returned (scan 50 items
in ~2K tokens). Level 2 is only returned by track item show (full context when
working on a specific item).
Level 1 — Triage / routing (returned by track item list):
| Column | Type | Description |
|---|---|---|
id |
TEXT PK | Per-tracker prefixed ID: "T04", "M03" |
title |
TEXT | Short name: "CLI subprocess smoke tests" |
summary |
TEXT | 1-2 sentence "what and why" for quick scanning |
status |
TEXT | open, in_progress, done, blocked, deferred, wont_do |
priority |
TEXT | high, medium, low, none |
effort |
TEXT | small, medium, large (optional) |
tags |
junction table | Labels via item_tags table: "testing", "cli", "ci" |
scope |
TEXT | Area/crate/component (optional): "forge-cli" |
tracker_id |
TEXT FK | Which tracker this belongs to |
project_id |
TEXT FK | Which project this belongs to |
created_at |
TEXT | ISO 8601 timestamp |
updated_at |
TEXT | ISO 8601 timestamp |
Level 2 — Full detail (returned by track item show):
| Column | Type | Description |
|---|---|---|
description |
TEXT | Full markdown: problem, solution, tables, code, implementation notes |
Notes capture decisions, context, and knowledge that should survive across sessions and across different AI tools. They are the "institutional memory" that no single agent session retains.
| Column | Type | Description |
|---|---|---|
id |
INTEGER PK | Auto-increment |
content |
TEXT | The note/decision text |
tags |
junction table | Labels via note_tags table: "decision", "storage", "data-model" |
project_id |
TEXT FK | Which project (optional — can be global) |
created_at |
TEXT | ISO 8601 timestamp |
Typical usage by agents:
# Agent persists a decision at end of planning session
track note add "Chose rusqlite over Limbo — battle-tested, sync API, swap later" --tags decision,storage
# Next session (possibly different tool), agent recovers context
track note list --tag decision # What did we decide?
track note list --project forge # All notes for forge| Table | Description |
|---|---|
projects |
id, name, path (e.g., ~/workspace/forge) |
trackers |
id, name, prefix, project_id (e.g., "testing", prefix "T") |
items |
All Level 1 + Level 2 columns above |
item_tags |
item_id, tag (junction table for item labels) |
dependencies |
item_id, depends_on (item-to-item) |
notes |
Cross-session decisions and knowledge |
note_tags |
note_id, tag (junction table for note labels) |
Key concepts:
- Project — a directory (e.g.,
~/workspace/forge). Auto-detected from cwd. - Tracker — a named group of related items (≈ current task files like
testing.md,tui-polish.md) - Item — a single work item with structured metadata + rich markdown description
- Note — a persistent decision/context snippet that survives across sessions and tools
- Inbox — special tracker for quick capture (no template required)
# Project management
track init # Initialize tracking (shorthand)
track init --name api # Initialize with custom name
track project init # Initialize tracking (explicit form)
track project list # List all tracked projects
# Quick capture (inbox)
track item add "Fix SSE reconnect logic" # Add to inbox (current project)
track item add -t testing "Mock provider needs ThinkingDelta" # Add to specific tracker
# Querying (the killer feature)
track item list # All open items in current project
track item list --all # All open items across ALL projects
track item list -s in_progress # Filter by status
track item list -t testing # Filter by tracker
track item list -p high # Filter by priority
track item list --tags rust,tui # Filter by tags
track item next # Show prioritized next items
# Status updates (validated — invalid transitions are rejected)
track item start T01 # Mark in_progress
track item done T01 # Mark done
track item block T01 # Mark blocked
track item defer T01 # Mark deferred
track item reopen T01 # Re-open a done/blocked/deferred item
# Editing items
track item edit T01 --title "New title" # Update title
track item edit T01 -p high --tags api # Update priority and tags
track item edit T01 --effort small # Set effort estimate
# Deleting
track item delete T01 # Remove an item permanently
track note delete 1 # Remove a note permanently
# Notes (cross-session knowledge)
track note add "Chose rusqlite over Limbo" --tags decision,storage
track note list # All notes for current project
track note list --tag decision # Filter by tag
track note list --all # Cross-project
track note show 1 # Full detail for a single note
# Trackers
track tracker add testing T # Add a named tracker
track tracker list # List trackers with item counts
# Triage (future)
track triage # Interactive inbox review
track promote I42 -t testing # Move item to a tracker
# Rendering (future)
track render # Generate/update markdown files in docs/tasks/
track render -t testing # Render single tracker
# Import (migration from existing markdown)
track import docs/tasks/ # Parse existing markdown trackers into DB- Workspace scaffold with four crates (
track-core,track-db,track-api,track-cli) -
track-core: Item, Note, Status, Priority, Effort enums + error types -
track-db: SQLite schema + migrations (projects, trackers, items, notes, dependencies) -
track-api: CRUD operations — create/read/update items, notes; filter/query logic -
track-cli: clap args,track project init,track item add,track item list,track item show -
track-cli:track item start/done/block/defer/reopen— validated status transitions -
track-cli:track item next— prioritized view -
track-cli:track item edit— update title, summary, priority, effort, tags, description -
track-cli:track item delete/track note delete— remove items and notes -
track-cli:track note show— full detail for a single note -
track-cli:track initshorthand fortrack project init -
track-cli:track tracker list— shows item counts per tracker -
track-cli:--jsonoutput mode for all commands - justfile with
test,lint,check,buildrecipes - AGENTS.md with usage instructions for AI agents
-
track render— generate markdown from DB (per-tracker files) - Output format matches current forge conventions (frontmatter, tables, sections)
-
track render --watch— re-render on changes (for AI sessions)
-
track import— parse existingdocs/tasks/*.mdinto DB - Handle current conventions: frontmatter, status markers (✅, 🔶), IDs (Txx, Mxx)
- Preserve item descriptions and notes
-
track item list --all— cross-project queries -
track triage— interactive inbox review (TUI or prompt-based) -
track promote— move items between trackers - Shell completions (bash, zsh, fish)
-
track stats— summary statistics
- Machine-readable output (
--json,--tsv) for AI agents to parse -
AGENTS.md/ context file conventions for AI to discover track CLI - Optionally: MCP server mode for direct tool integration
New standalone repo at ~/workspace/track — general-purpose tool, own release
cycle, installable via cargo install.
- Name —
trackis the working name. Alternatives:tasks,wk(work),ti(task items)? - Should
track renderwrite to a configurable path (defaultdocs/tasks/)? - Bi-directional markdown sync — future consideration. For now, AI uses CLI exclusively.