Documentation
¶
Overview ¶
Package autopilot — self-direction backlog primitive that lets a Claude Code agent (the operator's clawtool driver) pull "what to work on next" without requiring the human to re-prompt every turn. The user calls this "devam edebilme yeteneği" — continuation ability / non-stalling.
Pattern: classic single-producer-multi-consumer task queue persisted as TOML. The operator (or the agent itself) appends items via AutopilotAdd; the agent dequeues via AutopilotNext, does the work, marks done via AutopilotDone, then loops. When Claim() returns ok=false the queue is empty and the agent ends the loop.
Why this is NOT BIAM/SendMessage: BIAM is agent-to-agent dispatch (codex / gemini / opencode). Autopilot is self-work — the SAME agent picking up its own backlog. Pre-this primitive an agent that finished a task either (a) stalled waiting for operator input, or (b) re-invented a TODO list in its scratchpad on every session.
Storage: a TOML file at $XDG_CONFIG_HOME/clawtool/autopilot/queue.toml (defaults to ~/.config/clawtool/autopilot/queue.toml). Per-host, not per-repo, so a backlog the operator wrote at lunch is still there when they reopen Claude Code in the evening. Atomic writes via internal/atomicfile so a crashed mid-rewrite never corrupts the queue.
Concurrency: Claim() takes an exclusive lock on the file (load → mutate → save under one rwmu acquisition). Two parallel "next" calls from a fanned-out agent will not return the same item — the tests pin this invariant.
Index ¶
- Variables
- func DefaultPath() string
- type Counts
- type Item
- type ProposeInput
- type Queue
- func (q *Queue) Accept(id, note string) (Item, error)
- func (q *Queue) Add(prompt string, priority int, note string) (Item, error)
- func (q *Queue) Claim() (Item, bool, error)
- func (q *Queue) Complete(id, note string) (Item, error)
- func (q *Queue) List(filter Status) ([]Item, error)
- func (q *Queue) Path() string
- func (q *Queue) Propose(in ProposeInput) (Item, error)
- func (q *Queue) Skip(id, note string) (Item, error)
- func (q *Queue) Status() (Counts, error)
- type Status
Constants ¶
This section is empty.
Variables ¶
var ErrAlreadyAccepted = errors.New("autopilot: item already accepted")
ErrAlreadyAccepted is returned by Accept when the item is already pending or in_progress — i.e. has already passed the operator gate. Callers ignore for idempotency.
var ErrAlreadyTerminal = errors.New("autopilot: item already in terminal state")
ErrAlreadyTerminal is returned by Complete / Skip / Accept when the item is already done or skipped. Callers can ignore for idempotency.
var ErrDuplicateProposal = errors.New("autopilot: duplicate proposal")
ErrDuplicateProposal is returned by Propose when an existing non-terminal item shares the supplied DedupeKey. The Ideator passes through this as a "deduped" tally rather than a real error.
var ErrNotFound = errors.New("autopilot: item not found")
ErrNotFound is returned by Complete / Skip / Accept when no item matches the given id.
Functions ¶
func DefaultPath ¶
func DefaultPath() string
DefaultPath returns the canonical autopilot queue file: $XDG_CONFIG_HOME/clawtool/autopilot/queue.toml.
Types ¶
type Counts ¶
type Counts struct {
Proposed int `json:"proposed"`
Pending int `json:"pending"`
InProgress int `json:"in_progress"`
Done int `json:"done"`
Skipped int `json:"skipped"`
Total int `json:"total"`
}
Counts represents the queue's status histogram. Returned by Status.
type Item ¶
type Item struct {
ID string `toml:"id" json:"id"`
Prompt string `toml:"prompt" json:"prompt"`
Priority int `toml:"priority" json:"priority"`
Status Status `toml:"status" json:"status"`
CreatedAt time.Time `toml:"created_at" json:"created_at"`
ClaimedAt time.Time `toml:"claimed_at,omitempty" json:"claimed_at,omitempty"`
DoneAt time.Time `toml:"done_at,omitempty" json:"done_at,omitempty"`
AcceptedAt time.Time `toml:"accepted_at,omitempty" json:"accepted_at,omitempty"`
Note string `toml:"note,omitempty" json:"note,omitempty"`
Source string `toml:"source,omitempty" json:"source,omitempty"`
Evidence string `toml:"evidence,omitempty" json:"evidence,omitempty"`
DedupeKey string `toml:"dedupe_key,omitempty" json:"dedupe_key,omitempty"`
}
Item is one unit of self-work. Field names map directly to TOML keys; preserve them when adding fields so existing queues survive rolling upgrades.
Source / Evidence / DedupeKey are populated by the Ideator when the item is Proposed; operator-added items leave them empty. They stay attached through Accept so the eventual completion note can reference the originating signal (e.g. "TODO at foo.go:42").
type ProposeInput ¶ added in v0.22.119
type ProposeInput struct {
Prompt string
Priority int
Note string
Source string
Evidence string
DedupeKey string
}
ProposeInput is the wire shape Ideator hands the queue. Fields mirror Item but only the ones a freshly-minted suggestion needs; status is forced to StatusProposed regardless of caller intent so the operator's Accept gate is the only path into pending.
type Queue ¶
type Queue struct {
// contains filtered or unexported fields
}
Queue is a TOML-backed self-direction backlog. Construct with Open or OpenAt. Operations are concurrency-safe via an internal mutex; multiple Queue instances pointing at the same path serialize through the file system (atomicfile rename + every mutation does a fresh load).
func OpenAt ¶
OpenAt returns a Queue rooted at the supplied path. Tests use this to redirect into a tmpdir.
func (*Queue) Accept ¶ added in v0.22.119
Accept flips a proposed item to pending so AutopilotNext can claim it. This is the operator's safety gate — without an explicit Accept no Ideator output ever reaches the agent's working queue.
Errors: ErrNotFound (unknown id); ErrAlreadyTerminal (item is already done/skipped); ErrAlreadyAccepted (item is already pending, in_progress, or terminal — Accept is idempotent only on proposed).
func (*Queue) Add ¶
Add appends a new pending item. id is auto-generated when empty. Returns the persisted Item (with id + created_at filled).
func (*Queue) Claim ¶
Claim returns the highest-priority pending item, marks it in_progress, and persists. ok=false (zero Item, nil err) when the queue has no pending items — the agent's signal to stop the loop.
Selection order: highest Priority first, then earliest CreatedAt. Ties broken by lexicographic ID for determinism in tests.
func (*Queue) Complete ¶
Complete marks the named item done. Idempotent: completing an already-done item returns a typed error so the caller can decide whether to ignore it. Unknown id returns ErrNotFound.
func (*Queue) List ¶
List returns every item filtered by status. Pass empty string to return all. Order: pending first (priority/created), then in_progress, then done/skipped.
func (*Queue) Propose ¶ added in v0.22.119
func (q *Queue) Propose(in ProposeInput) (Item, error)
Propose appends a new proposed item — the Ideator's output. The item is NOT claimable by AutopilotNext until an operator runs Accept (CLI: `clawtool autopilot accept <id>`). Returns ErrDuplicateProposal when DedupeKey collides with an existing non-terminal proposed/pending/in_progress item — callers can ignore for idempotency.
type Status ¶
type Status string
Status enumerates the lifecycle of one backlog Item. The set is closed: anything outside this list is a programmer error.
const ( StatusProposed Status = "proposed" // Ideator-emitted suggestion; needs operator Accept before Claim picks it up StatusPending Status = "pending" // freshly added (or accepted), not yet claimed StatusInProgress Status = "in_progress" // returned by Claim, not yet completed StatusDone Status = "done" // Complete() called StatusSkipped Status = "skipped" // Skip() called — operator told the agent to drop it )