Core Concepts
The vocabulary and data model behind every backlog command.
| Concept | What it is |
|---|---|
| Workspace | A directory containing backlog.db, backlog.json, and backlog.config. Created by backlog init. |
| Project | A named grouping of tasks, identified by a short alias. Optionally linked to a repo_path. |
| Task | The unit of work. Has a type, status, priority, and actor. |
| Plan | A versioned markdown document on a task. Every edit creates an immutable version. |
| Comment | A timestamped, actor-attributed note on a task. Append-only. |
| Label | A per-project tag that can be attached to tasks for filtering. |
| Actor | Who performed an action. Format: kind:name where kind is human or ai. |
| Profile | A named pointer to a workspace directory, stored in ~/.config/backlog/config.toml. |
Workspace
A workspace is a directory that contains a backlog.db SQLite file. All data for all projects in that workspace — tasks, plans, docs, comments, memory, labels, attachments, activity — lives in that single file.
Created with backlog init. The three files created:
| File | Purpose |
|---|---|
backlog.db | SQLite database (WAL mode). Contains everything. Commit this to your repo. |
backlog.json | Project manifest. Used by backlog sync to reconcile. Commit this too. |
backlog.config | Local workspace settings (defaults, output format). Do not commit. |
DB resolution order
When you run a command, the database is located by the first match in this chain:
--db <path>flag--profile <name>flag$BACKLOG_DBenvironment variable- Walk up from the current directory looking for
backlog.db - Default profile from
~/.config/backlog/config.toml
$BACKLOG_DB — it bypasses directory walking and makes the path explicit regardless of where the process starts.
Profile
A profile is a named pointer to a workspace directory, registered in ~/.config/backlog/config.toml. Profiles let you switch between workspaces without typing paths.
backlog profile add work --path ~/projects/work/.backlog
backlog profile set-default work # use this workspace by default
backlog task list --profile personal # use a different workspace for one command
backlog profile clear-default # remove the active default
Default workspaces (created by backlog init without --path) are placed at ~/.backlog/<profile-name>/. The default profile name is default.
Project
A project groups tasks within a workspace. It has a human-readable name and a short alias — the alias is what you type in every -p / --project flag.
- Alias constraints: lowercase alphanumeric with optional hyphens, 1–64 characters. E.g.
api,web-frontend,security-2026. - Optional
repo_path: filesystem path to the source repository. - Projects can be archived (hidden from lists) without deleting their tasks.
Set a default project so -p can be omitted:
backlog project set-default api
backlog task list # implicitly uses api
backlog project current # shows the active default
backlog project clear-default
Task
The primary unit of work. Every task belongs to a project and carries:
| Field | Values |
|---|---|
| Ref | TASK-N — per-workspace sequential integer. Also addressable by bare integer or full ULID. |
| Type | task · bug · issue · improvement · feature · vulnerability · chore · spike |
| Status | todo (default) · doing · done |
| Priority | P1–P5. P1 is critical/highest. P3 is default. |
| Actor | kind:name of the creator — attributed at the DB level. |
| Assignee | Optional free-text name of who is responsible. |
| Source | Origin system, e.g. semgrep, pentest-2026. |
| External ref | URL or external ticket ID for cross-referencing. |
Status lifecycle
todo → doing → done
↑___________|
All transitions are valid in any direction. Use backlog task move <id> --status <status>.
Priority scale
| Value | Meaning |
|---|---|
| P1 | Critical — drop everything |
| P2 | High — next sprint |
| P3 | Normal — default |
| P4 | Low — when time permits |
| P5 | Backlog — nice to have |
Plan
A versioned markdown document attached to a task. Plans capture implementation plans, remediation steps, or any structured text that may evolve over time.
The versioning model: every call to backlog plan update creates a new immutable plan_versions row. The plan record tracks the current version number. Old versions are never modified or deleted. backlog plan history <plan-id> returns the full list.
| Ver | Title | Actor | Note |
|---|---|---|---|
| v1 | Initial remediation plan | ai:claude-code | — |
| v2 | Remediation plan (revised) | human:alice | added key rotation step |
| v3 | Remediation plan (final) | human:alice | simplified step 3 per review |
Read a specific version: backlog plan show <plan-id> --version 1.
Actor
An actor is a kind:name pair that attributes every write operation. Kind is either human or ai.
| Example | Meaning |
|---|---|
human:alice | Alice the engineer |
ai:claude-code | Claude Code agent |
ai:semgrep | Semgrep scanner (automated import) |
human:ci | CI system acting on behalf of a human workflow |
Every task, plan version, doc version, comment, memory entry, and activity log event records the actor. This allows filtering: backlog task list --actor-kind ai or backlog task list --actor-name semgrep.
The actor is resolved at runtime from the --as flag, workspace config, global config, or $USER env var — in that order. If none are set it defaults to human:$USER.
Label
A per-project tag that can be attached to tasks. Labels have a name and an optional hex color. They are scoped to a project — a label named security in project api is distinct from one in project web.
backlog label create --project api "security" --color "#e03e3e"
backlog label attach --task TASK-1 security
backlog task list --label security
Doc
A versioned markdown document attached to a project (not a task). Docs are used for longer-form project-level content: architecture overviews, runbooks, design documents, ADRs.
The versioning model is identical to plans: each update creates a new immutable version row. Docs also support an append operation that creates a new version concatenating old content with new content.
backlog web or the API directly.
Memory
A free-form note attached to a project. Unlike docs, memory entries are not versioned — they are mutable records with a body and optional comma-separated tags.
Memory is intended for short-lived context: decisions, assumptions, meeting notes, design rationale. AI agents working on a project can read and write memory entries via the MCP memory_add and memory_list tools.
backlog memory add --project api --body "Auth team decision: JWT TTL = 15min" --tags "decision,auth"
backlog memory list --project api --tag decision
ULID vs TASK-N
Every entity (task, plan, doc, comment, memory, label, attachment) uses a ULID as its primary key — a 26-character lexicographically sortable identifier. Tasks additionally have a human-readable sequential reference.
All three formats are accepted wherever a task ID is expected:
| Format | Example | Notes |
|---|---|---|
| Sequential ref | TASK-5 | Canonical. Use in messages, comments, PRs. |
| Bare integer | 5 | Shorthand. Resolves to the same task. |
| Full ULID | 01KR4JA4754H... | Useful when chaining JSON output between commands. |
| ULID prefix | 01KR4JA4 | The 8-char prefix shown in table output. |
Plan IDs, doc IDs, memory IDs, and attachment IDs are always ULIDs — there is no sequential N form for those entities.
Activity log
An append-only event log that records every write operation across the workspace. Each event stores:
- entity — the kind of entity affected (
task,plan,doc,comment,memory,project,label,attachment) - entity_id — the ULID of the affected entity
- action — the operation performed (
created,updated,status_changed,archived,deleted, etc.) - actor —
kind:nameof who performed the operation - summary — a human-readable description of the change
- project_id — the project the event belongs to
The activity log is never pruned. Query it with backlog activity or view the Activity page in the web UI.