Fast, minimal task tracking with plain markdown files — no database required
Minimal task tracker for AI coding agents.
| beads (SQLite) | dots (markdown) | |
|---|---|---|
| Binary | 25 MB | 200 KB (125x smaller) |
| Lines of code | 115,000 | 2,800 (41x less) |
| Dependencies | Go, SQLite/Wasm | None |
| Portability | Rebuild per platform | Copy .dots/ anywhere |
A CLI task tracker with zero dependencies — tasks are plain markdown files with YAML frontmatter in .dots/. No database, no server, no configuration. Copy the folder between machines, commit to git, edit with any tool. Parent-child relationships map to folders. Each task has an ID, title, status, priority, and optional dependencies.
Please open an issue with the details of the feature you want, including the AI prompt if possible, instead of submitting PRs.
brew install joelreymont/tap/dotsgit clone https://github.com/joelreymont/dots.git
cd dots
zig build -Doptimize=ReleaseSmall
cp zig-out/bin/dot ~/.local/bin/dot --version
# Output: dots 0.6.4# Initialize in current directory
dot init
# Creates: .dots/ directory (added to git if in repo)
# Add a task
dot add "Fix the login bug"
# Output: dots-a1b2c3d4e5f6a7b8
# List tasks
dot ls
# Output: [a1b2c3d] o Fix the login bug
# Start working
dot on a1b2c3d
# Output: (none, task marked active)
# Complete task
dot off a1b2c3d -r "Fixed in commit abc123"
# Output: (none, task marked done and archived)dot initCreates .dots/ directory. Runs git add .dots if in a git repository. Safe to run if already exists.
dot add "title" [-p PRIORITY] [-d "description"] [-P PARENT_ID] [-a AFTER_ID] [--json]
dot "title" # shorthand for: dot add "title"Options:
-p N: Priority 0-4 (0 = highest, default 2)-d "text": Long description (markdown body of the file)-P ID: Parent task ID (creates folder hierarchy)-a ID: Blocked by task ID (dependency)--json: Output created task as JSON
Examples:
dot add "Design API" -p 1
# Output: dots-1a2b3c4d5e6f7890
dot add "Implement API" -a dots-1a2b3c4d -d "REST endpoints for user management"
# Output: dots-3c4d5e6f7a8b9012
dot add "Write tests" --json
# Output: {"id":"dots-5e6f7a8b9012cdef","title":"Write tests","status":"open","priority":2,...}dot ls [--status STATUS] [--json]Options:
--status: Filter byopen,active, ordone(default: shows open + active)--json: Output as JSON array
Output format (text):
[1a2b3c4] o Design API # o = open
[3c4d5e6] > Implement API # > = active
[5e6f7a8] x Write tests # x = done
dot on <id> [id2 ...]Marks task(s) as active. Use when you begin working on tasks. Supports short ID prefixes.
dot off <id> [id2 ...] [-r "reason"]Marks task(s) as done and archives them. Optional reason applies to all. Root tasks are moved to .dots/archive/. Child tasks wait for parent to close before moving.
dot show <id>Output:
ID: dots-1a2b3c4d5e6f7890
Title: Design API
Status: open
Priority: 1
Desc: REST endpoints for user management
Created: 2024-12-24T10:30:00Z
dot rm <id> [id2 ...]Permanently deletes task file(s). If removing a parent, children are also deleted.
dot ready [--json]Lists tasks that are open and have no blocking dependencies (or blocker is done).
dot tree [id]Without arguments: shows all open root dots and their children.
With id: shows that specific dot's tree (including closed children).
Output:
[1a2b3c4] o Build auth system
+- [2b3c4d5] o Design schema
+- [3c4d5e6] o Implement endpoints (blocked)
+- [4d5e6f7] o Write tests (blocked)
dot fixPromotes orphaned children to root and removes missing parent folders.
dot find "query"Case-insensitive search across title, description, close-reason, created-at, and closed-at. Shows open dots first, then archived.
dot purgePermanently deletes all archived (completed) tasks from .dots/archive/.
Tasks are stored as markdown files with YAML frontmatter in .dots/:
.dots/
a1b2c3d4e5f6a7b8.md # Root dot (no children)
f9e8d7c6b5a49382/ # Parent with children
f9e8d7c6b5a49382.md # Parent dot file
1a2b3c4d5e6f7890.md # Child dot
archive/ # Closed dots
oldtask12345678.md # Archived root dot
oldparent1234567/ # Archived tree
oldparent1234567.md
oldchild23456789.md
config # ID prefix setting
---
title: Fix the bug
status: open
priority: 2
issue-type: task
assignee: joel
created-at: 2024-12-24T10:30:00Z
blocks:
- a3f2b1c8d9e04a7b
---
Description as markdown body here.IDs have the format {prefix}-{slug}-{hex} where:
prefix: Project prefix from.dots/config(default:dots)slug: URL-safe abbreviation of the title (max 32 chars)hex: 8-character random hex suffix
Example: dots-fix-user-auth-a3f2b1c8
The slug uses common abbreviations (authentication→auth, configuration→config, etc.) and truncates at word boundaries. Run dot slugify to rename existing IDs to include slugs.
Commands accept short prefixes:
dot on a3f2b1 # Matches dots-fix-user-auth-a3f2b1c8
dot show a3f # Error if ambiguous (multiple matches)dot slugifyRenames all issue IDs (including archived) to include slugs based on their titles. Preserves the hex suffix and updates all dependency references.
open -> active -> done (archived)
open: Task created, not startedactive: Currently being worked ondone: Completed, moved to archive
0: Critical1: High2: Normal (default)3: Low4: Backlog
parent (-P): Creates folder hierarchy. Parent folder contains child files.blocks (-a): Stored in frontmatter. Task blocked until all blockers aredone.
When a task is marked done:
- Root tasks: Immediately moved to
.dots/archive/ - Child tasks: Stay in parent folder until parent is closed
- Parent tasks: Only archive when ALL children are closed (moves entire folder)
dots is a pure CLI tool. For Claude Code and Codex integration (session management, auto-continuation, context clearing), use banjo.
If you have existing tasks in .beads/beads.db, use the migration script:
./migrate-dots.shThis exports your tasks from SQLite and imports them as markdown files. The script verifies the migration was successful before prompting you to delete the old .beads/ directory.
Requirements: sqlite3 and jq must be installed.
| Feature | Description |
|---|---|
| Markdown files | Human-readable, git-friendly storage |
| YAML frontmatter | Structured metadata with flexible body |
| Folder hierarchy | Parent-child relationships as directories |
| Short IDs | Type a3f instead of dots-a3f2b1c8d9e04a7b |
| Archive | Completed tasks out of sight, available if needed |
| Zero dependencies | Single binary, no runtime requirements |
MIT