A Rust CLI tool for task management with SQLite storage (via libsql). Built for AI agents and humans to track work items, checklists, and comments.
src/
├── main.rs # Entry point, command dispatch, error handling
├── cli.rs # Clap-based CLI definitions (Commands, subcommands, args)
├── models.rs # Data structures (Agent, Board, Card, ChecklistItem, Comment, Status)
├── db.rs # SQLite database operations (CRUD for all entities)
├── output.rs # Output formatting (table, json, simple)
└── schema.sql # SQLite schema definitions
- Entry point with
main() -> ExitCode run(cli: Cli)dispatches commands to db operationsAgentBoardErrorenum with exit codes (0-6)- Extracts
default_format,quiet,agent_id_resultbefore match to avoid borrow issues
Clistruct with global options (--format,--quiet,--verbose)Commandsenum:Version,Get,List,Create,Update,Delete,Mine,Whoami- Subcommand enums:
ListCommands,CreateCommands,UpdateCommands,DeleteCommands - Uses clap derive macros
Agentstruct: id, name, command, working_directory, description, timestamps, deactivated_atAgentUpdatestruct for agent update operationsStatusenum:Todo,InProgress,PendingReview,Done(serde snake_case)OutputFormatenum:Json,Table,Simple,PrettyCardUpdatestruct for update operations (avoids too-many-args clippy warning)Board,Card,ChecklistItem,CommentstructsCard.checklist: Vec<ChecklistItem>- single checklist per card (simplified model)BoardandCardhavedeleted_at: Option<DateTime<Utc>>for soft deleteAgentBoardDataholds all entities for JSON serialization
Databasestruct withconn: Connection(libsql)load()opens SQLite at~/.agent-board/data.dborAGENT_BOARD_DB_PATH- Auto-initializes schema from
schema.sql - Async CRUD methods for agents, boards, cards, checklist items, comments
generate_id(prefix)creates IDs likeagent_abc123def456,card_abc123def456generate_agent_name()usesnamescrate for random adjective-noun names
- SQLite schema with tables:
agents,boards,cards,card_tags,checklist_items,comments agentstable: id, name (unique), command, working_directory, description, timestamps, deactivated_atboardsandcardstables havedeleted_at TEXTcolumn for soft deletechecklist_itemstable referencescard_iddirectly (simplified - one checklist per card)- Foreign keys with
ON DELETE CASCADE - Indexes for common queries (board_id, status, assigned_to, card_id)
print_agents(),print_agent(),print_agent_whoami()for agent outputprint_cards(),print_card(),print_boards(),print_board(),print_kanban()print_comments(),print_checklist_items()for listing comments/checklist items- Uses
tabledcrate for table output - JSON output via
serde_json::to_string_pretty - Simple output: just IDs, one per line
- Pretty output: visual kanban board with colored columns (board get only)
- Deleted items show
[DELETED]suffix, inactive agents show[INACTIVE]
clap = { version = "4.4", features = ["derive"] } # CLI parsing
serde = { version = "1.0", features = ["derive"] } # Serialization
serde_json = "1.0" # JSON
chrono = { version = "0.4", features = ["serde"] } # Timestamps
uuid = { version = "1.6", features = ["v4"] } # ID generation
dirs = "5.0" # Home directory
tabled = "0.15" # Table output
thiserror = "1.0" # Error handling
libsql = { version = "0.9", features = ["core"] } # SQLite database
tokio = { version = "1.29", features = ["rt", "macros"] } # Async runtime
colored = "2.1" # Terminal colors
names = { version = "0.14.0", default-features = false } # Random name generation# Build
cargo build
cargo build --release
# Run clippy
cargo clippy
# Test manually
./target/debug/agent-board create board "Test" --description "Test board"
./target/debug/agent-board create card board_xxx "Task name"
./target/debug/agent-board --helpAgent identity is tracked via the AGENT_BOARD_AGENT_ID environment variable. Identity must be explicitly registered before using features that require it.
Using --assign-to-me or --status in-progress requires an existing agent identity:
# Register a new agent (auto-generated name)
./target/debug/agent-board create agent
# Register with explicit name
./target/debug/agent-board create agent code-reviewer --command claude --description "Reviews PRs"
# Set identity for session (required before using --assign-to-me or --status in-progress)
export AGENT_BOARD_AGENT_ID=agent_abc123
# Now you can claim cards
./target/debug/agent-board update card card_xxx --status in-progress --assign-to-meIf you try to use --assign-to-me or --status in-progress without setting AGENT_BOARD_AGENT_ID, you'll get an error with setup instructions.
- id: Unique identifier (e.g.,
agent_abc123def456) - name: Human-readable name (unique, auto-generated if not provided)
- command: The CLI command used to invoke the agent (e.g.,
stakpak,claude,aider) - working_directory: Directory where the agent was registered (used for context validation)
- description: Optional description of the agent's purpose
# Show current agent identity
export AGENT_BOARD_AGENT_ID=agent_xxx
./target/debug/agent-board whoami
# List all agents
./target/debug/agent-board list agents
./target/debug/agent-board list agents --include-inactive
# Get agent details (uses top-level get command)
./target/debug/agent-board get <agent_id>
# Update agent
./target/debug/agent-board update agent <agent_id> --name new-name --workdir .
# Delete agent (soft delete)
./target/debug/agent-board delete agent <agent_id>whoami warns if current directory doesn't match registered working directory:
WARNING: Current directory (/tmp) does not match registered working directory
- Add variant to appropriate enum in
cli.rs - Add match arm in
main.rsrun()function - Add db method in
db.rs - Add output function in
output.rsif needed
- Extract values from
clibefore thematch cli.commandblock - Use
cli.format.clone()sinceOutputFormatdoesn't implCopy - Agent ID is fetched before match to avoid partial move issues
- Use
in-progress(hyphen) on CLI, stored asin_progress(underscore) in JSON - Clap's
ValueEnumhandles the conversion
- Default:
~/.agent-board/data.db(SQLite) - Override:
AGENT_BOARD_DB_PATHenv var - Auto-creates parent directories and initializes schema on first run
- Uses libsql for SQLite operations
| Variable | Purpose |
|---|---|
AGENT_BOARD_AGENT_ID |
Current agent identity for mine, whoami, --assign-to-me |
AGENT_BOARD_DB_PATH |
Override default database path |
| Code | Constant | Meaning |
|---|---|---|
| 0 | - | Success |
| 1 | General |
General error |
| 2 | InvalidArgs |
Invalid arguments |
| 4 | NotFound |
Entity not found |
| 5 | PermissionDenied |
Permission denied |
| 6 | SessionConflict |
Session conflict |
Boards, cards, and agents support soft delete - records are marked with deleted_at or deactivated_at timestamp rather than being permanently removed.
# Delete a card (soft delete)
./target/debug/agent-board delete card <card_id>
# Delete a board (soft delete, cascades to all cards in board)
./target/debug/agent-board delete board <board_id>
# Delete an agent (soft delete)
./target/debug/agent-board delete agent <agent_id>
# Delete a comment (hard delete)
./target/debug/agent-board delete comment <comment_id>
# Delete a checklist item (hard delete)
./target/debug/agent-board delete checklist-item <item_id># List boards including deleted ones
./target/debug/agent-board list boards --include-deleted
# List cards including deleted ones (works even on deleted boards)
./target/debug/agent-board list cards <board_id> --include-deleted
# List agents including inactive ones
./target/debug/agent-board list agents --include-inactiveDeleted items display with [DELETED] suffix, inactive agents show [INACTIVE].
- All list/get queries filter
WHERE deleted_at IS NULLorWHERE deactivated_at IS NULLby default - Board deletion cascades: soft-deletes all cards in that board
--include-deleted/--include-inactiveflags bypass the filter to show all records- Data is preserved in DB for potential recovery (restore not yet implemented)
Display a board as a visual kanban with --format pretty:
./target/debug/agent-board get <board_id> --format prettyFeatures:
- 4-column layout: TODO → IN PROGRESS → PENDING REVIEW → DONE
- Color-coded headers and card names by status
- Cards display: title (2 lines), ID, assignee, tags (2 lines), comment count
- Tags shown in blue, IDs and comments dimmed
Example output:
┌───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ My Board - board_abc123 │
├────────────────────────────┬────────────────────────────┬────────────────────────────┬────────────────────────────┤
│ TODO │ IN PROGRESS │ PENDING REVIEW │ DONE │
│ (2 cards) │ (1 cards) │ (0 cards) │ (3 cards) │
├────────────────────────────┼────────────────────────────┼────────────────────────────┼────────────────────────────┤
│ ┌────────────────────────┐ │ ┌────────────────────────┐ │ │ ┌────────────────────────┐ │
│ │ Task name here │ │ │ Another task │ │ │ │ Completed task │ │
│ │ │ │ │ │ │ │ │ │ │
│ │ card_xyz789 │ │ │ card_def456 │ │ │ │ card_ghi012 │ │
│ │ @agent_session_id │ │ │ @agent_session_id │ │ │ │ @agent_session_id │ │
│ │ #tag1 #tag2 │ │ │ #urgent │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ │
│ │ [2 comments] │ │ │ [0 comments] │ │ │ │ [5 comments] │ │
│ └────────────────────────┘ │ └────────────────────────┘ │ │ └────────────────────────┘ │
└────────────────────────────┴────────────────────────────┴────────────────────────────┴────────────────────────────┘
list boards [--include-deleted]
list cards <board_id> [--status STATUS] [--assigned-to ID] [--tag TAG] [--include-deleted]
list agents [--include-inactive]
list comments <card_id>create board <name> [--description DESC]
create card <board_id> <name> [--description DESC] [--status STATUS]
create agent [name] [--command CMD] [--description DESC]
create checklist <card_id> --item "text" [--item "text"...] # adds items to card's checklist
create comment <card_id> <text> | --file PATHupdate board <board_id> [--name NAME] [--description DESC]
update card <card_id> [--name NAME] [--description DESC] [--status STATUS] [--assign ID|--assign-to-me] [--add-tag TAG] [--remove-tag TAG]
update agent <agent_id> [--name NAME] [--command CMD] [--description DESC] [--workdir PATH]
update checklist-item <item_id> --check|--uncheckdelete board <board_id> # soft delete
delete card <card_id> # soft delete
delete agent <agent_id> # soft delete
delete comment <comment_id> # hard delete
delete checklist-item <item_id> # hard delete- Add
--filterfor more flexible queries - Add
delete cardcommand - Add
delete boardcommand - Add
--format prettyfor visual kanban board - Add agent identity system
- Add top-level
getcommand (auto-detects entity type from ID prefix) - Add
versionsubcommand - Simplify CLI to
<action> <entity>pattern (get/list/create/update/delete) - Add
list commentscommand - Add
update boardcommand - Add
delete comment,delete checklist-itemcommands - Simplify checklist model (single checklist per card, items shown when viewing card)
- Add restore commands for soft-deleted entities
- Add shell completions (
clap_complete) - Add
--dry-runfor mutations