AGENTS.md

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.db database.
  • Entry flow is src/main.rsyatd::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. Always check jj st before starting. If there are changes in progress, run jj new ... to create a new working copy describe the pending work. If there are no changes in the working copy, run jj desc ... to describe the pending work.
  • 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). Only init and skill avoid 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) via db::gen_id()
    • subtasks: <parent>.<n> generated by counting existing children in create.

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, including skill).
  • Shared DB/domain helpers and structs (Task, TaskDetail, loaders): src/db.rs

Testing approach

  • Integration-style CLI tests in tests/cli_*.rs using:
    • assert_cmd for invoking td
    • tempfile::TempDir for isolated workdirs
    • predicates for stdout/stderr assertions
  • Typical pattern:
    1. create temp dir
    2. run td init
    3. invoke command under test
    4. assert output and/or inspect .td/tasks.db directly with rusqlite
  • When adding/changing behavior, prefer extending these CLI tests rather than only unit tests.

Conventions and patterns to preserve

  • Error handling uses anyhow::Result throughout command functions.
  • Keep command functions shaped as run(...) -> Result<()> with argument parsing in cli.rs and routing in cmd/mod.rs.
  • JSON structs rely on serde naming alignment (notably Task.task_type renamed 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 set current_dir to initialized temp dirs.
  • Cargo.toml uses rusqlite with bundled feature, so SQLite is vendored; build behavior differs from system-SQLite setups.