Core Concepts
CarryCtx’s state is a set of related records in a SQLite database. This page defines each one precisely: what it means, what commands create or read it, and (for the two that have a real lifecycle) exactly which state transitions are allowed.
Project
Section titled “Project”A Project corresponds to one Git repository and its lifecycle contract. It’s created with carryctx init, which writes .carryctx/config.toml and creates authoritative state at <git-common-dir>/carryctx/state.sqlite, shared by every worktree.
carryctx init --name my-app --task-prefix CTXEvery other record (task, agent, session, …) belongs to exactly one project.
An Agent is any entity that acts on the project, human or AI. Agents are registered explicitly and referenced by name or ULID everywhere else in the system:
carryctx agent register --name claude-core --provider claude-code --role implementerRegistering an existing name syncs it rather than erroring. carryctx agent current prints whichever agent is active for the invocation (resolved from --agent or the CARRYCTX_AGENT environment variable). carryctx agent deactivate <ref> marks an agent inactive so it can no longer be assigned new tasks or sessions; it does not delete history.
An agent can carry optional kind metadata (commander or subagent), set with --kind at registration. It helps a caller identify roles, but is not a permission boundary.
A Team is a durable, project-scoped roster of agents with an optional commander. Because it lives in the shared state database, it survives new windows, sessions, and linked worktrees.
carryctx team create --name payments-squad --commander commander-1carryctx team member add payments-squad --agent backend-1 --role backendTwo invariants are enforced: a commander must be a member of its own team, and the sitting commander can’t be removed until it’s replaced or explicitly cleared with team commander set <ref> --clear.
Tasks can be associated with a team (task create --team, task team set, task team unset) and can carry an advisory required_role. Neither changes lifecycle, ownership, dependencies, or scopes — association is purely additive labelling, and required_role gates nothing.
The read side is two projections that open the database read-only and write nothing at all: carryctx team status for the roster with per-member active work, and carryctx team context for the full picture a commander or member needs, narrowable with --agent-for and --task.
Session
Section titled “Session”A Session represents one continuous working period for an agent, bound to a task and (optionally) a worktree. Sessions use a 5-state model:
Active ──┬──> Paused ──> Active ├──> Ended (terminal) ├──> Stale ──> Active └──> Abandoned (terminal)carryctx session start --agent claude-core --task CTX-0001creates a session inActivestate.carryctx session pauselogs a sleep/pause transition, movingActive → Paused.carryctx session resumemoves it back toActive(also valid fromStale).carryctx session end --summary "..."cleanly terminates it (Ended, terminal).carryctx session abandon --reason "crashed"force-terminates it without a clean end state (Abandoned, terminal).
Ended and Abandoned are terminal: no further transition is allowed out of them. Stale exists for sessions the runtime has detected as inactive without an explicit pause.
A Task is the basic unit of work, shown with a display ID like CTX-0001. Tasks use a 7-state status model:
| Status | Meaning |
|---|---|
planned |
Recorded but not yet actionable (e.g. waiting on unfinished dependencies) |
ready |
Actionable, unclaimed or claimed but not started |
in_progress |
Actively being worked on |
blocked |
Work is stalled on an external or internal blocker |
review |
Implementation done, awaiting review |
completed |
Done (terminal) |
cancelled |
Abandoned, won’t be done (terminal) |
completed and cancelled are terminal. in_progress, review, and blocked all count as “active” for the purposes of dashboards and task list --mine.
Transitions are driven by named actions, each mapped to a subcommand:
claim → owner is set, status typically becomes readystart → ready → in_progress (also auto-binds the task to the caller)block → in_progress → blocked (requires a reason)unblock → blocked → in_progressreview → in_progress → reviewcomplete→ review/in_progress → completedcancel → any non-terminal → cancelled (requires a reason)reopen → completed/cancelled → in_progressrelease → clears ownership without changing statuscarryctx task create --title "Add streaming CSV export" --priority highcarryctx task claim CTX-0001carryctx task start CTX-0001carryctx task block CTX-0001 --reason "waiting on upstream API schema"carryctx task unblock CTX-0001carryctx task complete CTX-0001A newly created task with no unfinished dependencies starts in ready; one with unfinished dependencies starts in planned (or --status can set it explicitly).
A task can also carry team_id and required_role (an advisory role label). Neither participates in the state machine above.
Checkpoint
Section titled “Checkpoint”A Checkpoint is a persisted snapshot of what an agent has learned about a task’s progress at a point in time: what’s done, what remains, what’s blocking, what risks were identified, and what the next step is, optionally alongside the actual Git diff.
carryctx checkpoint --done "Implemented CSV writer" --remaining "Add streaming for >1M rows" --next "Wire writer into pipeline"By default a checkpoint also runs git add/git commit to capture file changes (--no-git disables that), and --include-diff embeds the uncommitted diff directly into the checkpoint record. carryctx checkpoint list and carryctx checkpoint show <id> read them back; carryctx checkpoint correct <id> rolls project/agent state back to a previous checkpoint.
Progress Item
Section titled “Progress Item”A Progress Item is a smaller, more frequent unit than a checkpoint: a single todo, blocker, risk, or note attached to a task, logged as you go rather than batched at a checkpoint.
carryctx progress todo "Write unit tests for the streaming writer"carryctx progress block "S3 credentials missing in CI"carryctx progress note "Chunked upload caps out at 5MB parts"Progress items can be completed (progress complete <ref>), reopened, edited, removed, or reordered independently of the task’s own status.
Worktree
Section titled “Worktree”A Worktree record binds a Git worktree directory to a task, so that CLI invocations run from inside that directory automatically resolve to the right task without needing --task every time.
carryctx worktree create CTX-0001 --branch feature/csv-exportcarryctx worktree status reports the binding of the current directory; carryctx worktree unbind <ref> removes it.
Handoff
Section titled “Handoff”A Handoff is an explicit request for another agent (or role) to take over a task, distinct from just changing the owner field: it carries a summary and can be accepted or rejected.
carryctx handoff create --target reviewer-bot --task CTX-0001 --summary "Ready for review, tests green"carryctx handoff accept <handoff_ref> --claim-taskDecision
Section titled “Decision”A Decision records an architectural or design choice (an ADR, in effect): the context that prompted it, the decision itself, and its consequences, optionally linked to a task. Decisions can later be marked as superseded by a newer decision.
carryctx decision add --title "Use chunked multipart upload for CSV export" --context "Files exceed 1M rows" --decision "Stream via S3 multipart API"An Event is a single immutable row in the append-only log everything above is ultimately built on: task transitions, session lifecycle changes, checkpoints, and more, each timestamped and attributed to an agent and session.
carryctx event list --task CTX-0001 --limit 20