sara-tasks 2.7.6

Sara — folder-aware task manager
sara-tasks-2.7.6 is not a library.

Sara — task memory for AI agents

Sara is what plan mode would be if it kept its memory. She's built primarily as a tool for an LLM agent, not the human at the keyboard: instead of a plan that disappears when the conversation ends, an agent can persist it in Sara and pick up where it left off in the next session. She knows which Git project the agent is standing in, ranks work with a transparent urgency model, tracks time, and links tasks to branches. She's LLM-agnostic — any agent can drive her through a plain local CLI, and a human can still poke around by hand.

Task data lives in a single SQLite database in your home directory — nothing is ever written into your repositories.

     ID  PRI   PROJECT      DUE           URG  DEPS             DESCRIPTION
──────────────────────────────────────────────────────────────────────────────
⛓    1  H     web-app      2026-07-01   28.0  blocks 1 task    Design the auth flow
     2  M     web-app      -             5.9                   Wire up the login form
⊘    3  M     web-app      -             0.9  blocked by 1     Write auth integration tests

Table of contents


Highlights

  • Persistent memory — tasks, steps, notes, decisions, and history all live in a local SQLite database and survive across chat sessions and machine reboots.
  • Knowledge memory — sara learn / sara recall let agents save and retrieve free-form findings (decisions, gotchas, context) that outlive any single task.
  • Project-aware — sara auto-detects the current project (a Git repo, or any folder you run sara init in) and scopes sara list to it by default.
  • Transparent urgency — a Taskwarrior-style scoring model decides ordering; sara info shows the exact breakdown.
  • Interactive TUI — a ratatui review form for adding/editing, and a rich detail view for everything else.
  • Dependencies — block tasks on each other, with cycle detection and an at-a-glance DEPS column.
  • Time tracking — a task's clock starts automatically the first time you act on it and accumulates into time spent, with optional estimates.
  • Git integration — tie a task to a branch.
  • Full history — every change (field edits, deps, files, checklist, links, comments, timer) is recorded.
  • Single SQLite file — easy to back up, and nothing is written into your repos.

What Sara remembers

The core promise: an agent that uses Sara can always pick up exactly where it left off, even after the conversation ends, the shell closes, or the machine reboots.

Sara has two scopes of memory — project-wide and file-level — sitting on top of a full change history and a cross-task search index.

Project-wide memory (sara init)

Running sara init in a repo records the project's goal, stack, conventions, and setup/test/lint commands. Any agent (or human) that opens that project later can read this profile — it's the "what is this project and how do I work in it" context that would otherwise live only in a system prompt.

sara init --goal "Auth service for web-app" --stack "Rust, SQLite" \
  --conventions "snake_case, no unwrap" --notes "run cargo test before PR"

Use sara init (without flags) to reopen the profile and edit it. The profile travels with the project name, so every agent that touches the same repo reads the same shared context.

File-level memory (sara attach)

Individual tasks can carry code anchors — durable pointers into the codebase — so an agent resuming work knows exactly where to look:

sara attach 1 src/auth/login.rs                            # whole file
sara attach 1 src/auth/login.rs --symbol "validate_token"  # specific function
sara attach 1 src/auth/login.rs --lines "42-67"            # line range
sara attach 1 src/auth/login.rs --reason "JWT logic lives here"

Each anchor records the file path, an optional symbol or line range, a reason (why it matters to the task), and a source fragment (a snapshot of the code at attach time). This means the agent can later ask "what files does this task touch?" and get a precise, annotated answer — not a guess.

Task memory

Every task is a durable record with description, priority, due date, tags, estimate, recurrence, status, and a full set of attached context:

Attachment What it holds
Steps The ordered sub-tasks to execute; each step can carry its own intent, verify command, and result
Acceptance criteria The conditions that must be true before done
Annotations / comments Free-form notes, decisions, findings, open questions
Links URLs (GitHub PRs/issues get auto-labelled)
File attachments Code anchors — file path, symbol, lines, source fragment
Assignment The originating prompt / what to build
Rationale Why this task exists
Branch tie The git branch this task lives on

None of this requires the agent to be running. Open the task later — in any session, on any client — and the full context is there.

Change history

Every mutation to a task is recorded: field edits, timer events, dependency changes, step completions, comment additions, file attachments, and branch ties. Additions show +, removals show −, and value changes show old → new.

The history panel is visible in sara info and included in --md/--plain output via --history. Nothing is ever silently overwritten.

Cross-task search (sara recall)

sara recall "auth"          # full-text search across all tasks in the current project
sara recall "migration" -a  # search across all projects

When the agent needs to know "have I seen this before?" or "what did I decide about X?", recall searches descriptions, annotations, steps, and links across every task — making the database a queryable long-term memory, not just a todo list.


Memory system (sara learn / sara recall / sara memories)

Sara has a persistent knowledge store that is separate from tasks. While tasks track what to do, memories capture what you've learned — decisions, gotchas, architectural context, and session findings that future agents (and future you) can surface in seconds.

Every memory carries tags for quick lookup, optional file associations so a memory surfaces whenever an agent touches a related path, and a strength score that rises automatically when the memory is frequently recalled.

Learning (sara learn)

Save a finding as a memory after finishing meaningful work:

sara learn --tag auth -p web-app "JWT refresh tokens must be stored httpOnly; localStorage is XSS-vulnerable."

# tie to the file you just edited
sara learn --tag auth --file src/auth/login.rs "validate_token() returns Err on clock skew > 30s — callers must handle."

# auto-attach all files changed since last commit
sara learn --auto-files --tag migration "Running diesel migrations in tests requires a separate test database URL."

# correct a stale memory atomically
sara learn --supersedes m7 --tag codeql "Sanitiser is LogSanitizer.escape(), not String::replace()."

Rules of thumb:

  • One idea per memory — don't dump an entire conversation. A paragraph that stands alone is the target.
  • Tags are the primary lookup key — always include at least one.
  • Use --file (repeatable) to bind a memory to the file it describes; recall will surface it whenever an agent revisits that file.
  • --auto-files reads git diff --name-only HEAD and attaches every changed file automatically — ideal at the end of a work session.
  • Memories over 4 000 chars (configurable via SARA_MEMORY_CHAR_LIMIT) or containing secret-like patterns are rejected by default; pass --force only when the content is legitimately safe.

Recalling (sara recall)

Before starting any new feature or investigation, always recall:

sara recall                             # no args → most recent memories ("what do I know?")
sara recall --tag auth -p web-app       # tag-scoped lookup (fast, reliable)
sara recall "refresh token"             # full-text keyword search
sara recall --file src/auth/login.rs    # everything linked to a specific file
sara recall --file src/ --top 5         # most recent memories for any file under src/
sara recall --semantic "auth bug"       # also match by meaning (embeddings), not just keywords
sara recall --task 3f2a91c0 "retry"     # record the hits as used by this task (MCP: `task`)

Pass --task (MCP: task) when you recall while working on a task. Direct hits are recorded as recalled and associative hits as surfaced by that task, so the memories that helped can be credited when it succeeds. An unknown task id is an error. Without it, recall records no use.

recall searches both memories and tasks in one pass — memory hits are prefixed [item_memory]. If a memory was superseded by a newer one, recall shows a [superseded by: mN] warning so you don't act on stale knowledge. When a canonical memory and the memories derived from it all match, recall shows only one representative and names the best-matching hidden sibling (— nearest mN; JSON: cluster.nearest) so you can open it directly.

Stale file anchors. When a memory is bound to files (--file/--auto-files), sara stores a small fingerprint of each file's lines. If an anchored file has since been rewritten (≥ 40 % of its fingerprinted lines gone) or deleted, recall marks the memory ⚠ may be stale — re-validate: <file> (62% changed) (JSON: stale[]). Re-check it against the code, then sara relearn mN … to update it — that re-fingerprints its files and clears the flag. sara doctor lists every memory with a stale anchor. The fingerprint ignores git history, so the commit or squash-merge that lands the work a memory describes never counts as drift.

Semantic recall (--semantic). By default recall is lexical (FTS5), so a paraphrase with no shared keyword is missed. sara recall --semantic also ranks memories by embedding cosine using a small model bundled into the binary — no daemon, no network, no runtime download — so conceptually-similar memories surface (marked *). It's off by default; enable it permanently in config.toml:

[recall]
semantic = true            # default false
semantic_threshold = 0.30  # minimum cosine to surface a semantic hit
semantic_top_k = 5         # max semantic hits merged per recall

Run sara reindex-embeddings once after enabling it to embed existing memories (new memories are indexed automatically on sara learn while semantic is on).

Overlap warnings: when sara learn detects an existing memory with the same tag or file association, it prints an overlap warning. Always resolve it before moving on — run sara dream <label> to read the old memory in full, then either sara relearn <label> to correct it in place, sara learn --supersedes <label> to mark it superseded, or sara learn --force if the two memories genuinely cover different concerns.

Browsing & managing memories

sara memories           # all memories newest-first, with Strong / Linked / Weak labels
sara tags               # all tags with counts — check before learning to avoid drift
sara dream m7           # full body + bond graph for a single memory
sara dream              # whole-brain constellation (all memories + links)
sara forget m7          # archive a stale memory
sara relearn m7 --tag auth "corrected text"   # edit in place — keeps label, links, dates
sara promote m14        # accept a provisional auto-memory as permanent
sara prune-memories --dry-run   # preview low-value memories eligible for archival
sara prune-memories --apply     # actually archive them
sara doctor             # health report: embeddings, orphaned links, duplicates, backlog, decay, stale anchors

Knowledge reuse: sara doctor ends with Sara's headline measure: the share of verified tasks (completed with a validated commit in the last 30 days) that cited or recalled a memory created before the task began, plus the stricter cited-only share. It is shown for the current project and for all projects, and reads "insufficient data" until 5 verified tasks qualify. In --json it is the knowledge_reuse object. It does not affect healthy or --strict. Memory uses are only recorded from 2.1.0 onwards, so earlier tasks count as not reusing.

Strength labels:

  • Strong — frequently recalled; the most trusted memories.
  • Linked — tied to tasks or files; reliable context.
  • Weak — saved but rarely used; candidates for pruning after 90 days.

Provisional memories: sara done automatically synthesises a memory from the completed task's steps, results, and annotations. These are marked [provisional] in sara memories. Read each one with sara dream <label>, then either promote it (sara promote <label>), correct it (sara relearn <label> "fixed text"), or discard it (sara forget <label> -y). Don't let provisionals accumulate — they dilute recall precision.


Installation

The fastest paths use prebuilt packages and need no Rust toolchain. Prefer one of these; the from-source build further down is for development.

Quick install (Linux & macOS)

curl -fsSL https://raw.githubusercontent.com/Abarbesgaard/Sara/main/scripts/install.sh | sh

Downloads the right binary from the latest GitHub Release into ~/.local/bin (override with SARA_INSTALL_DIR).

crates.io

Published as sara-tasks (sara and sara-cli were taken); the installed binary is still sara.

cargo install sara-tasks          # compiles from source
cargo binstall sara-tasks         # or grabs the prebuilt binary, no compile

Debian / Ubuntu (apt)

One-off .deb from a release:

curl -fsSLO https://github.com/Abarbesgaard/Sara/releases/latest/download/sara_amd64.deb
sudo apt install ./sara_amd64.deb

Or add the apt repository so sudo apt install sara and future upgrades work:

echo "deb [trusted=yes] https://abarbesgaard.github.io/Sara/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/sara.list
sudo apt update
sudo apt install sara

Build from source

1 — Prerequisites

Rust (if not already installed):

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Restart your shell, or:
source "$HOME/.cargo/env"

2 — Build & install

git clone https://github.com/Abarbesgaard/Sara
cd Sara
cargo install --path .

This compiles the binary and places it at ~/.cargo/bin/sara. Make sure ~/.cargo/bin is on your PATH (the Rust installer usually handles this):

echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.zshrc   # or ~/.bashrc
source ~/.zshrc
sara --version

Anonymous usage telemetry is on by default. Sara records the command or MCP tool name, duration, ok/error and version — never arguments, paths, task text or memory content — and sends it to the maintainer's collector over HTTPS. When a task is completed, it also records an outcome event with two values: n, how many memories that existed before the task it cited or recalled, and verified, whether it closed with a validated commit. These are counts, never labels or ids, and they measure whether Sara's memory helps across installs. sara telemetry --show prints exactly what is queued. Turn it off with sara telemetry off or SARA_NO_TELEMETRY=1, or build without it entirely: cargo install --path . --no-default-features.

Benchmarks

Criterion.rs benchmarks in benches/ time the real sara binary (list, recall by query/tag/file, add, begin) against two seeded, isolated temp homes: 200 tasks/100 memories and 1000 tasks/1000 memories. Run them with cargo bench (seeding the large home takes a couple of minutes); HTML reports land in target/criterion/.

Mutation testing

cargo-mutants checks that the tests actually catch bugs: it injects small changes (flip a >, return an empty value, skip a body) and reports each one no test noticed as MISSED. CI runs it on each PR's diff, once the tests pass; a full run takes hours. Interactive TUI drawing is excluded in .cargo/mutants.toml.

cargo install --locked cargo-mutants
cargo mutants -f src/commands/recall/mod.rs     # one file
git diff main > /tmp/sara.diff && cargo mutants --in-diff /tmp/sara.diff  # your changes

Results land in mutants.out/ (missed.txt lists the gaps).

Dependency policy

cargo-deny checks dependencies for RustSec advisories, licenses outside the allow-list, wildcard versions and crates from unknown sources. CI runs it on every push and PR.

cargo install --locked cargo-deny
cargo deny check

PR titles

A PR title is a conventional commit, and squash merges make it the commit on main. Following Impatient Programming's Rule 9, fix: is only for a defect in released code and needs the bug label; anything else that changes sara is refine:, which gets the refine label. .github/workflows/pr-title.yml checks both.

Similar code

This is the exhale half of IMP's "breathe in, breathe out": a PR folds what it learned into what already exists instead of leaving a copy behind. similarity-rs finds functions in src/ that are at least 87% similar; tests are left out, because tests stay DAMP, not DRY. On PRs, CI compares the branch with the merge base and labels each pair:

Label Meaning Gate
introduced The PR touched a side and the pair didn't match at the base fails
shifted Neither side was touched, yet the pair is new fails
already there The pair matched at the base too warns
declared scripts/similar-code.allow keeps it, with its reason warns

The report also lists the pairs the PR contracted. File renames are followed, so moving code is not a new pair. To fix a failure, reuse the existing function or extract a shared helper, or declare the pair in scripts/similar-code.allow with the reason the two should stay separate.

cargo install --locked similarity-rs
scripts/similar-code.sh               # every similar pair in src/
scripts/similar-code.sh origin/main   # label every pair against your branch's base

Contract

contract/ writes down what sara promises as numbered obligations, each proved by a tagged test in tests/contract/. impish's cargo impish check fails when an obligation has no test, or a contract test names no obligation. Only Contract tests live in tests/contract/; integration tests no obligation claims yet live in tests/behaviour/. See contract/README.md.

Kill matrix

A test earns its place by catching a bug no other test catches. scripts/kill-matrix.sh runs every mutant against the whole suite, records which tests fail ("kill" it), and lists tests that kill nothing or only mutants other tests also kill. It only suggests: contract tests are spec, so keep them unless the spec changed.

A full sweep takes over a day, so a nightly job runs one of 128 small shards and adds it to the results on the kill-matrix-data branch. Once every shard has run, it files an issue labelled kill-matrix per suspect test, at most 3 a night. Close the issue to keep the test.

scripts/kill-matrix.sh 'src/domain/**'                       # sweep files, print the report
scripts/kill-matrix.sh --test contract/undo::undo_reverts_the_last_command \
                       'src/main.rs'                         # is this one test needed?

Quick start

# Initialize the current folder as a Sara project.
# A git repo becomes its own project (named after the repo root); any other
# folder is initialized in place (named after the folder).
cd ~/web-app
sara init

# Add a task (opens the interactive review form)
sara add "add password reset flow"

# Add quickly, no form, with an inline priority token
sara add "fix logout redirect" pri:H --yes

# See what to work on (current project, ranked by urgency)
sara list

# Inspect / edit a task interactively
sara info 1

# Complete it
sara done 1

Core concepts

Projects. Every task belongs to a project. Inside a Git repo, sara uses the repo as the project (run sara init once to record its goal/stack). In any other folder, sara init registers that folder as the project, named after the directory. The configurable default_project (inbox) is only used as a last-resort fallback when a folder has no usable name.

IDs vs UUIDs. Each task has a small, recycled display ID (the 1, 2, 3 you type) and a stable UUID that never changes. Most commands accept either the ID or a UUID prefix. When a task is completed, pending IDs are repacked to stay small — so today's 4 may be tomorrow's 3.

Urgency. Tasks are ordered by a computed urgency score (see The urgency model). It rewards priority, due dates, active timers, tags, and tasks that block others — and penalizes blocked tasks.


The task list

sara list prints the pending tasks for the current project, highest urgency first.

sara list                      # current project
sara list -a                   # all projects
sara list -p web-app           # a specific project from anywhere (`--project` also works)

Each row has a small marker gutter, columns, and a dependency column:

⛓    1  H     web-app      2026-07-01   28.0  blocks 1 task    Design the auth flow

Gutter markers (left edge):

Marker Meaning
● Timer is running (task is active)
♺ Recurring task
⊘ Blocked — waiting on an unfinished task
⛓ Blocking — other tasks depend on this one

Columns: ID, PRI (H/M/L, color-coded), PROJECT, DUE (red overdue, yellow soon), URG (urgency score), DEPS, and DESCRIPTION. A PR or ↗ badge appears before the description when the task has a linked pull request or URL.

The DEPS column spells out the relationship the gutter hints at: blocked by 3 (red) or blocks 2 tasks (gray).

Tip: set NO_COLOR=1 to disable colors (e.g. for piping or screenshots).

Finding a task by uuid fragment (sara find)

When you only hold a piece of a uuid — from a log line, a PR body, a commit, telemetry or another agent's output — sara find lists every task whose uuid contains it. Unlike targeting a task by id or a unique prefix (which must be exact), find is a case-insensitive substring search and returns all matches.

sara find 4c449b0e              # every task whose uuid contains this fragment
sara find 4c44-9b0e             # hyphens are optional — same result as above
sara find 88 --status pending   # restrict to a status (pending | completed | all)
sara find 88 -a                 # search every project, not just the current one
sara find 88 --limit 50         # cap the result set (default 20)
sara find 88 --json             # machine-readable {"matches": [...]}

Behaviour:

  • Substring, hyphen-agnostic: both the fragment and each stored uuid are lowercased and have hyphens stripped before matching, so 4c449b0e matches …-4c44-9b0e-….
  • Literal wildcards: %, _ and \ in the fragment are matched literally, never as SQL wildcards.
  • All statuses by default (--status pending|completed|all); deleted tasks are never returned.
  • Current project by default, -a/--all searches every project.
  • Minimum 4 characters (hyphens don't count) — shorter fragments are rejected with a clear message, so a fragment can't match nearly everything.
  • Sorted pending first, then most recently modified, capped at --limit (default 20).

find is strictly read-only: it never resolves to a single task, so it can't be used to target a mutation — commands that change a task still require an exact id or unique prefix.


The detail view (sara info)

sara info <id> opens a full-screen, interactive view of a single task: its title and timing, an anchor block, a details grid, notes, dependencies, the memory ledger, links, files, a checklist, verification, AI activity, related tasks and feedback. A side panel holds the task tree, the tied git branch and the history log (below the body on narrow terminals).

It's also where you edit a task inline.

A one-row header bar of bracketed badges sits on top: status ([○ PENDING], [● ACTIVE]), guide freshness ([✓ VALID @<commit>], [⚠ STALE @<commit> · HEAD <head>] or [· NOT VALIDATED]), the tied branch, open feedback ([! 2 FEEDBACK · ⟳ 1 REVISE]), and the display id with the short uuid. The body opens with the task title, a single meta line (status when not pending, time spent against the estimate, urgency, created and modified) and the anchor — assignment and why — as a quoted block. Fields sit in a two-column Details grid on wide terminals; priority shows as ▲ High / ■ Medium / ▼ Low and tags as #tag. Every section starts with a ▌ TITLE rule, and long lines wrap with a hanging indent.

In the checklist, the step sara next would return is marked ◉ … ← next with its intent; steps and acceptance progress show as ▰▱ bars, and every acceptance item shows its $ verify command and last result inline. The Memory ledger lists each memory surfaced, recalled or cited for the task (Enter opens it in sara dream), and AI activity shows token usage per run with a Σ total. The footer lists only the keys that apply to the selected item.

Every section below the fields — Memory ledger, Links, files, Checklist, Verification, AI activity, Related tasks and Feedback — is collapsible. Its header shows ▾/▸ and an item count; select it and press Enter or Space to fold it. Checklist and Feedback start open, the rest folded, and your choice is remembered across sessions (stored under the tui.info.open meta key). Adding a step opens the Checklist.

Keys

Key Action
↑ / ↓ (or k / j) Move between fields and items
Enter / e Edit the selected field, open the selected file/link, open the selected memory in sara dream, or fold/unfold the selected section
← / → Cycle priority (when Priority is selected)
Space Toggle the selected checklist item, or fold/unfold the selected section
a Add a new checklist step (Enter saves, Esc cancels)
⇧↑ / ⇧↓ (or K / J) Reorder the selected checklist step within its kind
PgUp / PgDn Scroll
Esc Cancel an edit
q / Esc Close the view

Editable fields: Description, Project, Priority, Due, Tags, Estimate, Recur, and Depends on.

To change dependencies, select Depends on, press Enter, and type the task IDs it should wait on (space- or comma-separated), e.g. 7 9. sara reconciles the set — adding and removing edges — and rejects self-references and cycles with an inline error. The change is reflected immediately in the "Blocked by" section and the History panel.

Non-interactive & agent-friendly output

sara info detects whether stdout is a terminal: in a TTY it opens the interactive view; when piped it prints a readable plain-text digest instead. You can force a specific format regardless of TTY:

Flag Output
--md Markdown digest — LLM-native: ## headings and - [ ]/- [x] checkboxes for steps & acceptance. Ideal for agent context or a PR body.
--plain The readable plain-text digest, forced (no TUI).
--json The full structured guide (every field) for scripts.
--history Include the full History log in --plain/--md (collapsed to a one-line summary by default to keep output lean).
sara info 7 --md                 # paste-ready Markdown for an agent / PR
sara info 7 --md --history       # …including the full change log
sara info 7 --plain              # readable text, History collapsed
sara info 7 --json | jq .steps   # structured access

The Markdown digest is the recommended way to feed a task to an AI agent: it's stable, omits the unbounded History log by default, and needs no reshaping.


The board (sara board)

sara board groups the project's tasks under the GitHub issue they link to. Every task is a two-line card: the row (ID, priority, age, PR/issue badge, description), then a strip of state you can read at a glance:

▶ ├─  1   H  0m       PR   wire the theme
  │                        ★ NEXT  ⚠ stale  ☐ 1/2  ! 1 feedback  ◷ due 3d  ⎇ feat/theme  ▸ Pin the palette

The strip always shows guide validation (✓ valid / ⚠ stale / · unvalidated), acceptance criteria met (☐ n/m) and open feedback (! n, with ⟳ n revise when a revision is requested). Blockers (⊘ blocked #4), the due date (◷), the tied branch (⎇) and the current step (▸) appear when present. ★ marks the most urgent pending task, the one the Next: label names. Issue headers carry a ▰▱ progress bar.

Key Action
/ Filter by text, or +tag for an exact tag; terms are ANDed. Enter keeps the filter, Esc clears it
p Toggle a preview pane (terminals ≥ 110 columns) that shows the selected task with the info widgets
h / l Collapse / expand an issue
Enter Open the task in sara info

Following agents live (sara follow)

sara follow is a live, read-only view of agents working through tasks. It refreshes as soon as anything writes to the database, so you can keep it open in a side pane while an agent works.

sara follow                # mission control: every open task in every project, most recently active first
sara follow 782d04d7       # follow one task: step rail, current step, flow timeline
sara follow -m             # minimal: step rails, active step and an event feed, grouped by project
sara follow -m -p          # tie the view to this folder's project
sara follow -p pling       # tie the view to a named project
sara follow --stall 5      # flag tasks as STALLED after 5 quiet minutes (default 10)
  • Mission control lists every open task, most recently active first, with a pulse badge (LIVE with a spinner for activity in the last 2 minutes, STALLED when steps are open but nothing has happened past the stall threshold, otherwise IDLE), its step rail (● done, ◆ current, ○ open), the current step, a one-hour activity sparkline, and what the agent says it is doing. It covers every project unless -p ties it to one: -p alone means the project of the current folder, -p <name> a named project. At 110 columns or wider, a live feed of every visible task's events runs alongside the list.
    • ↑↓ selects a task and ⏎ follows it.
    • o opens the task in sara info, and quitting info returns here.
    • / filters by text (description, project, id, current step or "now doing"), and Esc clears the filter.
    • i hides idle tasks.
    • p switches between all projects and this project.
    • m toggles minimal mode, Space pauses or resumes live updates, ? shows every key, and q quits.
  • Task view shows the full plan: each step with how long it took, measured from the previous step's completion, and done steps with their recorded result. Long plans are windowed around the current step. Below the plan is a timeline of the task's flow: steps added and done, notes, memories recalled or cited, "now doing" lines, and other changes, newest at the bottom.
    • Events from the last 15 seconds are highlighted.
    • j/k, PgUp/PgDn and gg scroll back in time, and G returns to the latest event.
    • While you are scrolled back, new events don't move the view, and the divider counts them (↓ N newer).
  • Minimal mode (-m) shows one step rail per active task with the name of the active step (◆ …) beneath it, grouped under a ── project ── header when several projects are active (most recently active first). Below is a feed of the tasks' events, newest at the top and older further down: steps added and done, notes, memories and "now doing" lines, each prefixed with its age and, when several tasks are active, the task id (and project name when several projects are). It fits in a 24×6 pane and switches on automatically when the terminal is narrower than 40 columns or shorter than 12 rows.

Agents report the "now doing" line with the MCP doing tool, or by passing doing to step_done or annotate. From a shell, use sara doing <id> "running the parser tests". sara keeps only the latest 200 lines per task, and nothing reads them as evidence.


MCP server (sara mcp)

sara mcp runs a Model Context Protocol server over stdio, exposing sara's agent loop as typed tools. Any MCP client (Claude Code / Claude Desktop, OpenAI Codex, GitHub Copilot, Cursor, …) can then drive sara with structured JSON in and out — no flag-ordering, UUID-juggling, or TUI pitfalls. It's a thin adapter over the same code the CLI uses, so there is a single source of truth.

The server exposes forty-one tools — the non-interactive agent loop end to end, from reading and planning a task through to completing it:

Tool Purpose
list Pending tasks for a project (or all)
find Find tasks by a partial uuid (substring, hyphens optional; all statuses by default)
projects List every registered project
move_task Move a task to another project
info Full task guide: steps, acceptance, notes, links, freshness, feedback
resume One-call briefing to pick a task back up: progress, open steps, acceptance, recent notes, links, relevant memories and next_actions (defaults to the project's most recent pending task)
begin Start work: create the task, set assignment/rationale, add an optional acceptance criterion, recall related memories and attach them as a finding
add Create a task (never opens the review form)
next The execution cursor — first not-done step
steps Ordered steps (optionally up to step N)
step_done Mark a step done, recording result + commit (optional doing reports what comes next)
doing Report a one-line "now doing" status, shown live in sara follow
verify Read-only: the verification commands + acceptance criteria (does not run them)
recall Cross-task keyword search + memory lookup
memories Browse saved memories with strength labels (scope = project (default, plus global) / all; limit, default 50)
forget Archive a memory by label
learn Save a knowledge memory (tags, file bindings, task links, typed supersedes / derived_from / similar_to); reports possible_duplicates
relearn Edit a memory in place, keeping its label, links and dates
tags Tag vocabulary with usage counts (scope, prefix, limit)
promote Accept a provisional auto-memory as permanent
link_memory Create (or with remove, delete) a typed edge between two memories (supersedes, similar_to, derived_from, used_in)
annotate Add a comment / finding / decision
denotate Remove an annotation by its id
plan_import Bulk-ingest a task graph from an inline JSON plan
plan_show Dependency-ordered briefing (the task plus everything it is blocked by)
check Add a checklist step or acceptance criterion (with optional intent / verify command)
step_undone Reopen a completed step / acceptance criterion
step_remove Delete step N (remaining items renumber)
dep Manage dependencies — action = on / off / list
link Attach a URL (e.g. a PR) to a task
unlink Remove a link by its id
attach Attach a file or code anchor (reason, symbol, lines, source); a URL becomes a link
modify Set task fields non-interactively, including assignment and rationale (never opens the review form; at least one field required)
validate Run every acceptance criterion's verify command and stamp the guide against git HEAD only if all pass (fails closed)
feedback List a task's open human feedback
resolve Resolve a feedback item by its id
record_run Log an AI/LLM interaction against a task; returns a run_id that resolve can cite
done Complete a task (errors if blocked unless force; validate=true runs validate first; spawns the next recurrence)
finish Close out after the PR: link pr_url once, check the merge (gh, or merged), then validate at HEAD and complete the task
maintain Memory-store maintenance: action = diagnose / consolidate / reflect / prune / reindex
doctor One-call memory-store health report (embeddings, orphaned links, duplicates, superseded, provisional backlog, decay, stale file anchors) with a fix per finding

Every tool carries MCP annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint): the read/report tools are marked read-only and the ones that delete or overwrite (done, forget, step_remove, modify, …) destructive, so clients can auto-approve reads and confirm the rest.

Task-mutating tools (begin, next, step_done, check, link, validate, finish, …) return a next_actions list — {tool, args, why} entries naming the next lifecycle call (finish the open step, tick acceptance, validate, link the PR, finish) — so an agent never has to guess what comes next.

When a tool fails for a domain reason (unknown task id, blocked done, failing validate, …) it returns a normal tool result with isError: true and the reason as text, not a JSON-RPC error, so the model can read the message and correct its call.

Interactive-only surfaces (the bare add/modify review form, board, activity, follow, projects) stay CLI-only by design — the server never opens a TUI or blocks on stdin. So do a few niche/destructive/setup commands (init, move, delete, reset, undo, sync, export/import).

Project awareness: the CLI derives "the project" from the current git folder, but a long-running server has no per-call working directory. So every tool takes an optional project_path — set it to the absolute path of the target repo and the tool operates on that project. Omit it to use the directory the server was launched in.

Client configuration

The server is launched as a subprocess over stdio — every client needs the same two ingredients: command: sara, args: ["mcp"]. If sara isn't on the client's PATH, point command at the absolute path (e.g. ~/.cargo/bin/sara).

Quickest — Claude Code (--scope user makes sara available in every project):

claude mcp add --scope user --transport stdio sara -- sara mcp
# repo-local instead:  claude mcp add --scope project --transport stdio sara -- sara mcp

For any other client, drop in the same command + args:

Claude Desktop (claude_desktop_config.json):

{ "mcpServers": { "sara": { "command": "sara", "args": ["mcp"] } } }

OpenAI Codex (~/.codex/config.toml):

[mcp_servers.sara]
command = "sara"
args = ["mcp"]

GitHub Copilot / VS Code (.vscode/mcp.json):

{ "servers": { "sara": { "type": "stdio", "command": "sara", "args": ["mcp"] } } }

On stdio transport, stdout is the JSON-RPC channel: run sara mcp directly (no wrapper that writes to stdout). Diagnostics go to stderr.

Instructing your agent to use it

Once connected, the tools show up in the client automatically, and the server sends usage instructions on initialize — the project_path model, UUID targeting, the begin → next → step_done → validate execution loop, the recall/learn memory discipline, and the PR/completion rule. Clients like Claude Code surface those to the model, so often no extra prompting is needed.

For stronger, always-on steering, add a short rule to your agent's own persistent instructions (Claude Code's CLAUDE.md, an AGENTS.md, Cursor rules, …):

Use the sara MCP tools for task management (prefer them over the sara CLI). Pass project_path — the absolute path of the repo you're working in — on every call. Target tasks by their 8-char UUID prefix, not the recycled display id. Mirror multi-step work into sara: tick steps with step_done as you finish them, link the PR when you open it, and call done only once that PR has merged.

Keep it short — the tool descriptions and the server's instructions carry the mechanics; your rule just says prefer sara, pass project_path, follow the loop.


Working with tasks

Adding tasks

sara add "write integration tests"            # opens the review form
sara add "write tests" --yes                  # skip the form, save immediately
sara add "write tests" -p web-app --priority H -t testing

By default sara add opens an interactive review form so you can confirm the fields before saving. --yes saves immediately without the form.

The form is laid out in three steps — Task (title, project, priority, due, tags, estimate), Guide (assignment, why, done when, verify) and Relations (links, dependencies, files). Filling any Guide field founds the task exactly like sara begin: assignment (defaulting to the title), rationale, an acceptance criterion with its verify command, and the recall step. While you type the title, a Similar work pane (terminals ≥100 columns) lists related tasks and memories. Invalid fields are flagged inline, and Ctrl+S saves from any field — or jumps to the first problem. See inline tokens for the project: / +tag / pri: shorthand.

Creation output echoes the new task's UUID prefix, so scripts/agents never need a follow-up lookup: Created task 5 [Sara] (3f458474): write tests.

Attach notes, links, checklist steps, and a dependency inline at creation instead of separate follow-up commands (all repeatable except --depends-on, which chains onto an existing task by uuid prefix):

sara add --priority H -t api --annotation "amounts in minor units" \
  --link "https://…/Controller.cs" --check "Add model" --check "Wire route" \
  --depends-on 3f458474 --yes "Implement payment client"
sara modify 2        # edit via the review form (estimate and links too)
# …or set fields non-interactively (no TUI):
sara modify 2 --description "new text" --priority H --due 2026-12-31
sara modify 2 --tag api --tag urgent   # replace tags (--clear-tags / --clear-due to unset)
sara done 1          # mark complete (use --force to complete a blocked task)
sara delete 3        # soft-delete (prompts; -y to skip)

Dependencies

A dependency means "this task is blocked until that task is done." Blocked tasks sink in urgency; blocking tasks rise.

sara dep 4 on 5      # task 4 now depends on (is blocked by) task 5
sara dep 4 off 5     # remove that dependency
sara dep 4 list      # show what 4 is blocked by / blocking
sara dep chain 1 2 3 # wire a linear sequence in one command: 1 → 2 → 3

You can also edit dependencies interactively in the Depends on field of sara info (see above). Dependencies are shown in sara list via the ⊘/⛓ gutter markers and the DEPS column. Cycles are prevented automatically.

Time tracking

A task's clock starts automatically the first time you act on it — the first sara step done (or sara verify --run) on an idle task marks it active (●) and starts the clock. Elapsed time accumulates into "time spent" when you sara done it.

Set an estimate (in the Estimate field of sara info) to see a progress percentage against time spent.

Recurring tasks

sara add "weekly review" --every weekly
sara add "rotate secrets" --recur 2w     # --recur is an alias for --every

Supported intervals: daily, weekly, monthly, yearly, or Nd / Nw / Nm (e.g. 3d, 2w, 1m). Recurring tasks show a ♺ marker in the list.

Checklists

Break a task into sub-steps without creating separate tasks:

sara check 1 "draft the schema"
sara check 1 "write the migration"

sara step done 1 1                  # tick step 1 (records the commit, if any)
sara step done 1 2 --used m12       # …and cite the memory that helped
sara step undone 1 1               # reopen it
sara step remove 1 2              # delete step 2 (alias: sara step rm); later steps shift up

--used <label> (repeatable, on sara step done and sara done; MCP: used) cites the memories that actually helped. Citations are the strongest signal that a memory is useful, and sara info lists them under Cited. Every label must name an active memory, or the command fails and nothing changes.

Each memory then carries a track record: sara recall and sara memories show how many tasks cited it (and how many of those were validated), recalled or surfaced it, and ignored it (completed without citing it), e.g. ✓ cited in 3 verified tasks · cited in 1 task · surfaced in 7 · ignored in 2. The JSON and MCP output carry the counts as provenance. Deleted tasks are not counted.

Add --kind acceptance to any sara step … command to act on the task's acceptance criteria instead of its steps. Toggle items with Space in sara info.

The first sara step done (or sara verify --run/--tick-on-pass) on an idle task auto-starts its timer, so its active state reflects reality. Add --json to sara step done|undone|remove for a structured record (the activated field reports whether that call started the task).

sara check 1 "tests pass" --kind acceptance --verify "cargo test"
sara verify 1 --run            # run every verification command, print pass/fail
sara verify 1 --tick-on-pass   # run each criterion's verify cmd; tick the ones that exit 0

--tick-on-pass collapses "run the check", "read the output", and "tick the box" into one call: each step/acceptance criterion that carries a stored verify command is executed and marked done only when it exits 0, with the pass/fail recorded as that item's execution result.

Notes, comments & links

sara annotate 1 "spoke with design, going with option B"   # alias: sara comment
sara denotate 4                                             # remove comment #4 (alias: uncomment)

sara link 1 https://github.com/org/repo/pull/123           # auto-labels GitHub PRs/issues
sara link 1 https://example.com --label "Spec"
sara unlink 2                                               # remove link #2

sara attach 1 src/auth/login.rs                             # attach a file path (alias: sara pr)

Linked PRs/URLs surface as a badge in sara list and are openable from sara info.

Git branch linkage

sara addbranch 1            # tie task 1 to the *currently checked-out* branch
sara addbranch 1 --clear    # remove the tie

Note: addbranch takes the task ID, not a branch name — the branch is read from the repo you're standing in. The task's project must have been sara init'd inside that repo.

Sharing tasks

Export a task — together with its full dependency closure (the task plus every task it transitively depends on) — to a single copy-pasteable blob, then import it into another user's Sara on a different machine.

sara export 1                     # print a `sara-task-v1:…` blob to stdout
sara export 1 -o task.blob        # …or write it to a file
sara 1 export                     # the usual id-first shorthand

sara import task.blob             # read a blob from a file
sara import "sara-task-v1:…"      # …or pass the blob string directly
pbpaste | sara import             # …or pipe it in on stdin
sara import task.blob -p backlog  # reassign every imported task to a project

What travels: the description, project, status, priority, due date, tags, estimate, recurrence, comments, checklist/steps, links and attached file paths — plus the dependency edges between the exported tasks. On import every task gets a fresh uuid and display id (so importing into a DB that already has the task never collides), dependency edges are remapped within the bundle, the timer is reset and urgency is recomputed. History and time-tracking do not travel.

A bundle carries each task's project name, not the project profile (its goal, stack, conventions and setup/test/lint commands). Importing a task whose project doesn't exist locally is fine — it's created under that name and shows up in sara list/-p and tab-completion straight away; only the profile metadata is absent. Run sara init in that project's folder to attach a profile, or use -p/--project on import to drop everything into an existing local project instead of the bundle's original name.

The blob tolerates being line-wrapped by email or chat clients, so a pasted sara-task-v1:… token still imports even if it picked up newlines.

History & undo

Every mutating action is recorded and shown in the History panel of sara info: field edits (description, project, priority, due, tags, estimate, recur, status), timer start/stop, dependencies, attached files, checklist items, links, comments, and branch ties. Additions show +, removals show −, and value changes show old → new.

sara undo     # revert the most recent command

The urgency model

Urgency is a sum of weighted components, recomputed whenever a task changes. sara info displays the exact breakdown, e.g. 28.0 (pri 6.0 + due 12.0 + blocking 8.0 + age 2.0).

Component Default Applies when…
priority_h 6.0 Priority is High
priority_m 3.9 Priority is Medium
priority_l 1.8 Priority is Low
due 12.0 Scaled by closeness (overdue = full, 7+ days out = 0)
blocking 8.0 The task blocks at least one other task
blocked -5.0 The task is blocked (penalty)
active 4.0 A timer is currently running
has_tags 1.0 The task has any tags
project 1.0 The task is not in the fallback project (inbox)
age 2.0 Scaled by age, capped at age_max days
age_max 365.0 Age in days at which the age bonus maxes out

All coefficients are configurable under [urgency] in the config file.


Configuration

A config file is created with sensible defaults on first run.

OS Path
macOS ~/Library/Application Support/sara/config.toml
Linux ~/.config/sara/config.toml

Full example:

default_project = "inbox"   # last-resort fallback name when a folder has no usable name
date_dialect    = "uk"      # "uk" or "us" — affects "next friday" parsing

[urgency]                   # all optional; defaults shown
priority_h = 6.0
priority_m = 3.9
priority_l = 1.8
due        = 12.0
blocking   = 8.0
blocked    = -5.0
active     = 4.0
has_tags   = 1.0
project    = 1.0
age        = 2.0
age_max    = 365.0

[tui]
theme = "classic"           # see `sara theme` for every palette

TUI palette

Every full-screen view (info, the board, add/modify review, projects, activity, follow) draws from one palette:

  • classic — the familiar terminal colours (default).
  • retro — a phosphor look: pale green text, a cyan-green accent, amber warnings. It uses 24-bit colour when COLORTERM is truecolor/24bit and falls back to the 16 ANSI colours otherwise.
  • Editor themes — dracula, nord, gruvbox, catppuccin (mocha), tokyo-night, solarized-dark, solarized-light, one-dark, rose-pine and high-contrast. They use 24-bit colour on truecolor terminals and the nearest xterm-256 colour otherwise. solarized-light expects a light terminal background.

Switch any time with sara theme <name> (e.g. sara theme nord); plain sara theme lists every palette with a row of colour swatches and marks the active one. The choice is saved as [tui] theme. For a one-off, override it per shell with SARA_THEME=retro. NO_COLOR=1 turns colour off in every palette.

Print the resolved config and database paths:

sara paths

Inline Taskwarrior-style tokens

Leading and trailing tokens on sara add are parsed as attributes:

sara add "fix login bug" project:web-app +auth pri:H
sara add project:api "redesign rate limiting" +backend

Tokens in the middle of a description stay as literal text. Explicit flags are always unambiguous and win over inline tokens:

sara add "fix the project:foo reference in docs" --project web-app
Token Meaning
project:x Set the project
+tag Add a tag
pri:H Set priority (H/M/L)

Due dates

Natural-language dates work in the Due field of the review form and anywhere a date is accepted:

Input Meaning
2026-07-01 ISO date
today Today
tomorrow Tomorrow
friday This coming Friday
next friday Friday next week
+3d 3 days from now
+2w 2 weeks from now

The date_dialect config setting (uk vs us) affects ambiguous phrasing.


Shell completions

Sara ships dynamic completions: once registered, <TAB> completes real pending task ids — annotated with their descriptions — for commands like sara done / info / start, and known project names for --project / -p.

Register by having your shell evaluate COMPLETE=<shell> sara at startup (no fpath/compinit setup needed). Re-run on upgrade so the generated shell glue stays in sync with the binary:

# Bash — ~/.bashrc
echo 'source <(COMPLETE=bash sara)' >> ~/.bashrc

# Zsh — ~/.zshrc
echo 'source <(COMPLETE=zsh sara)' >> ~/.zshrc

# Fish
echo 'COMPLETE=fish sara | source' >> ~/.config/fish/completions/sara.fish

# Elvish
echo 'eval (E:COMPLETE=elvish sara | slurp)' >> ~/.elvish/rc.elv

Restart your shell (or source the file) afterwards. To disable, set COMPLETE= or COMPLETE=0.

Prefer a static completion script (command/flag structure only — no dynamic task-id/project values)? sara completions <shell> still emits one, e.g. sara completions zsh > ~/.zsh/completions/_sara.


File locations

What macOS Linux
Database ~/Library/Application Support/sara/tasks.db ~/.local/share/sara/tasks.db
Config ~/Library/Application Support/sara/config.toml ~/.config/sara/config.toml

Run sara paths to see the exact locations on your machine.


Command reference

Command Description
sara init Initialize/update the current folder as a project (--goal, --stack, --conventions, --notes, -y)
sara begin <desc> Start work: create the task, recall related memories and attach them (-t, --file, --assignment, --why, --check, --verify, --priority, --json)
sara add <desc> [tokens] Add a task (--yes, -p, --priority, -t, --every, --annotation, --link, --check, --depends-on)
sara next <id> Execution cursor: the first step not yet done (--json)
sara steps <id> List the task's ordered steps (--until N, --json)
sara verify <id> Show verify commands and acceptance criteria (--step N; --run executes them, --tick-on-pass ticks the ones that pass)
sara validate <id> Run every acceptance criterion's verify command; stamp the guide only if all pass (--fresh ignores cached passes, --no-run stamps without running)
sara assignment <id> <text> Set what was asked (the originating prompt)
sara rationale <id> <text> Set why the task exists
sara feedback <id> List the task's open human feedback (--json)
sara resolve <feedback-id> Resolve a feedback item (--run <run-id> cites the run that fixed it)
sara record-run <id> --kind <k> Log an AI/LLM interaction on a task (--model, --provider, --prompt, --response)
sara denotate <annotation-id> Remove an annotation (alias uncomment)
sara unlink <link-id> Remove a link from a task
sara move <id> <project> Move a task to another project (alias mv)
sara projects Browse every registered project with open/active/stale/feedback badges
sara board Interactive board of tasks across projects (-p to scope, --finished to include done)
sara plan import <file|-> Bulk-create a task graph from JSON
sara plan show <id> Dependency-ordered briefing for a task and its blockers
sara sync Import GitHub issues assigned to you as tasks (token from GH_TOKEN, GITHUB_TOKEN or gh auth token)
sara diagnose-memories Report unlinked memory pairs that share a file or tag set and are semantically close (--threshold, -p, --limit, --json)
sara reflect Cluster memories recalled together and nominate a canonical (--min-weight, --max-cluster, --apply writes derived_from, --json)
sara consolidate Recompute links between memories recalled together (--window-days, --bucket-secs, --delta, --max-bucket)
sara reindex-embeddings Rebuild the semantic index over all memories
sara telemetry [action] Telemetry controls: on, off, status (default), --show (--json)
sara list List tasks (-a all, -p/--project <name>)
sara find <fragment> Find tasks by partial uuid (substring, hyphens optional; --status, -a, --limit, --json)
sara modify <id> Edit via the review form, or set fields non-interactively (--description, --priority, --due/--clear-due, --tag/--clear-tags)
sara info <id> Open the interactive detail view (--md/--plain/--json, --history)
sara done <id> Complete a task (--force if blocked, --used mN to cite memories)
sara delete <id> Soft-delete a task (-y to skip confirmation)
sara dep <id> on|off|list / sara dep chain <id>... Manage dependencies, or wire a linear chain in one command
sara check <id> <text> Add a checklist item
sara step done|undone|remove <id> <n> Tick / reopen / delete step n (--kind acceptance, --json; done takes --used mN)
sara annotate <id> <text> Add a comment (alias comment); sara denotate <n> removes
sara link <id> <url> Add a link; sara unlink <n> removes
sara attach <id> <path> Attach a file path (alias pr)
sara addbranch <id> Tie the current git branch to a task (--clear)
sara export <id> Export a task + its deps to a portable blob (-o <file>)
sara import [src] Import a task blob (file, arg, or stdin; -p <project>)
sara recall [query] Full-text search across tasks and memories; no args → recent memories (-a all projects, --tag, --file, --top N)
sara learn [FLAGS] "<text>" Save a knowledge memory (--tag, -p, --file, --auto-files, --task, --supersedes, --force; flags before text)
sara memories Browse all saved memories newest-first with Strong / Linked / Weak labels
sara tags List all memory tags with counts
sara dream [label] Inspect a single memory's full body + bond graph (or whole-brain constellation without a label)
sara forget <label> Archive a memory (e.g. sara forget m3 -y)
sara relearn <label> [FLAGS] ["text"] Edit a memory in place — --tag/--file replace the whole set; keeps label + links
sara promote <label> Accept a provisional auto-memory as permanent
sara link-memory <from> <rel> <to> Create a typed edge between memories (supersedes, similar_to, derived_from, used_in)
sara unlink-memory <from> <rel> <to> Remove a typed edge between memories
sara prune-memories Preview (--dry-run, default) or archive (--apply) low-value memories
sara doctor Read-only memory-store health report with the fix for each finding, plus the knowledge-reuse share (--json, --strict exits 1 on warnings)
sara activity Dotted activity heatmap; ↵ drills into a day's tasks (--project, -a)
sara follow [id] Live view of agents working tasks across all projects; -m minimal, -p [project] tie to one project, --stall <min> (details)
sara doing <id> <text> Report what is being done on a task right now (shown in sara follow)
sara mcp Run a stdio MCP server exposing the agent loop as tools (details)
sara undo Revert the most recent command
sara reset Delete a project's tasks and profile (-p, -y)
sara paths Print config and data paths
sara theme [name] Show or switch the TUI palette
sara completions <shell> Generate shell completions

Run sara help or sara <command> --help for full options.


Uninstall

cargo uninstall sara

Remove data and config:

# macOS
rm -rf ~/Library/Application\ Support/sara/

# Linux
rm -rf ~/.config/sara/ ~/.local/share/sara/