AGENTS.md
What this repo is
- Rust CLI app (
td) for local task tracking aimed at agent workflows. - Storage is SQLite in a per-project
.td/tasks.dbdatabase. - Entry flow is
src/main.rs→yatd::run()(src/lib.rs) →cmd::dispatch()(src/cmd/mod.rs). - We use jj for version control, not git. DO NOT use Conventional Commits. Do use imperative, Linux kernel-style commits.
- JSON mode is not for "agent consumers". It's for wiring things together, whether the wirer is human or LLM.
Essential commands
- Format:
make fmt - Lint (warnings are errors):
cargo clippy --quiet -- -D warnings - Full local gate:
make ci(runs fmt + check + test)
Implementation details
- Initialization requirement: most commands call
require_root()and fail unless.td/exists somewhere in current dir ancestry (db::find_root). Onlyinitandskillavoid this path. - DB schema is created in
src/db.rs(SCHEMA): - Foreign keys are explicitly enabled on each connection (
PRAGMA foreign_keys = ON). - Task IDs:
- top-level: generated short IDs (
td-xxxxxx) viadb::gen_id() - subtasks:
<parent>.<n>generated by counting existing children increate.
- top-level: generated short IDs (
Command/module map
- CLI definition and argument shapes:
src/cli.rs - Dispatch wiring:
src/cmd/mod.rs - Command implementations live in
src/cmd/*.rs(one module per subcommand, includingskill). - Shared DB/domain helpers and structs (
Task,TaskDetail, loaders):src/db.rs
Testing approach
- Integration-style CLI tests in
tests/cli_*.rsusing:assert_cmdfor invokingtdtempfile::TempDirfor isolated workdirspredicatesfor stdout/stderr assertions
- Typical pattern:
- create temp dir
- run
td init - invoke command under test
- assert output and/or inspect
.td/tasks.dbdirectly withrusqlite
- When adding/changing behavior, prefer extending these CLI tests rather than only unit tests.
Conventions and patterns to preserve
- Error handling uses
anyhow::Resultthroughout command functions. - Keep command functions shaped as
run(...) -> Result<()>with argument parsing incli.rsand routing incmd/mod.rs. - JSON structs rely on serde naming alignment (notably
Task.task_typerenamed to"type"). Maintain compatibility for import/export and tests.
Gotchas
- Running most commands outside an initialized tree yields
not initialized. Run 'td init'due to upward root search; tests should setcurrent_dirto initialized temp dirs. Cargo.tomlusesrusqlitewithbundledfeature, so SQLite is vendored; build behavior differs from system-SQLite setups.