Codex-style persisted thread goals for Piclaw.
Requires Piclaw >=2.0.0.
This add-on replaces the older prompt-template goal loop with a high-fidelity port of Codex CLI's goal model: a per-chat/thread goal record, Codex-compatible model tools, /goal user controls, budget accounting, and continuation/budget-limit prompts derived from Codex's upstream logic.
Open Settings → Add-Ons and install goal from the catalog.
chat_jidget_goalcreate_goalgoal_completegoal_stopupdate_goal/goal user controls for summary, create/replace, pause, resume, clear, and statusbudget_limited when the configured token budget is exhausted and emits a Codex-style wrap-up promptupdate_goal({ status: "complete" }) as a first-class completion path while also offering evidence-rich goal_completeplan action=update when available, so multi-step goal turns can keep a live plan currentno_progress/goal command/goal or /goal help — print the command list as a visible table plus the current goal status (also ?, commands)/goal status — show the current goal state/goal <objective> — create a new active goal or immediately replace the current objective/goal pause, /goal off, or /goal stop — pause the current goal/goal resume or /goal on — resume a paused/blocked/usage-limited/budget-limited goal as active and queue continuation/goal reset or /goal clear — clear the saved thread goal (clear is an exact synonym for reset)/goal edit — points to the Settings pane or replacement flowget_goalRead the current thread goal and usage state.
{}Returns:
{
"goal": {
"threadId": "web:default",
"goalId": "...",
"objective": "Ship the feature",
"status": "active",
"tokenBudget": 100000,
"tokensUsed": 1234,
"timeUsedSeconds": 42,
"createdAt": "2026-05-27T...Z",
"updatedAt": "2026-05-27T...Z"
},
"remainingTokens": 98766,
"completionBudgetReport": null,
"terminalGuidance": [
"If the full objective is verified complete, finish the goal by calling goal_complete({ summary, evidence }) when available.",
"Codex-compatible completion path: update_goal({ status: \"complete\", summary, evidence }) also marks the goal complete and should be used if goal_complete is unavailable or not selected."
]
}create_goalCreate a new active goal only when explicitly requested. It fails if a goal already exists.
{
"objective": "Ship the feature",
"token_budget": 100000
}goal_completePreferred completion tool. Use only as the final action when the full objective is verified complete:
{
"summary": "Feature shipped and verified.",
"evidence": ["bun test passed", "commit abc123 pushed", "microVM UI check passed"]
}goal_complete records evidence and marks the goal complete. After it succeeds, the agent should send a concise final answer to the user instead of ending the turn with only the tool call.
goal_stopStop the autonomous loop without marking the goal complete:
{
"reason": "plan_complete_unverified",
"summary": "Plan is checked off but completion evidence is insufficient.",
"evidence": ["all plan items completed", "missing deployment verification"]
}Use this when completion is unverified, progress is stuck, user input is required, or external state blocks progress. It marks the goal stopped; after it succeeds, the agent should explain the stop to the user instead of ending the turn with only the tool call.
update_goalCodex-compatible terminal tool. Use this when following upstream Codex goal policy or when goal_complete is unavailable/not selected:
{
"status": "complete",
"summary": "Verified against tests and PR state.",
"evidence": ["bun test passed", "commit abc123 pushed"]
}{ "status": "blocked", "summary": "The same external service outage blocked three consecutive goal turns." }Prefer goal_complete for verified completion when it is available because it requires evidence explicitly, but update_goal({ "status": "complete" }) is intentionally kept as the Codex-compatible completion fallback. Both completion paths record terminal metadata and end the autonomous goal loop, but they deliberately do not early-terminate the Piclaw turn; the agent still needs to produce a user-facing final answer. update_goal intentionally cannot pause, resume, clear, budget-limit, stop, or usage-limit a goal. Those status transitions are controlled by the user, runtime, or goal_stop.
The add-on uses Codex's status vocabulary:
| Status | Meaning |
|---|---|
active |
goal is live and auto-continuation can proceed |
paused |
user paused the goal |
blocked |
model verified the strict repeated-blocker audit |
usage_limited |
reserved for runtime usage-limit integration |
budget_limited |
token budget was exhausted |
complete |
model verified the objective is achieved |
stopped |
autonomous loop was stopped without verified completion |
Open Settings → Goal to:
The pane uses /agent/addons/api/goal/goal?chat_jid=.... The add-on stores no secrets and does not use the keychain.
The prompt templates are intentionally no longer editable. The add-on embeds Codex's goal prompt policy so behaviour stays faithful to the upstream goal logic.
| What | Where |
|---|---|
| Current thread goal | Extension KV (goal, chat scope, key thread-goal) |
| Settings pane state | Browser state only |
Each goal has a durable lifecycle_generation. Every status transition advances it and clears any prior deadline checkpoint; replacement creates a new goal identity, while ordinary accounting and bookkeeping saves preserve both the current lifecycle identity and checkpoint. This invalidates checkpoints across pause/resume, complete/stop/reactivation, blocked, usage-limited, and budget-limited transitions without preventing an idempotent retry of the same already-claimed successor.
Deadline checkpoint expiry is fail-closed. A checkpoint is valid only while expires_at is strictly later than the current clock; equality is expired. Generated leases live for at least one minute and at most five minutes. Malformed timestamps, deadline values more than five minutes ahead of or behind the current clock, and expiry values more than five minutes ahead are treated as invalid clock skew and suppressed. Persisted checkpoint IDs and ownership counters must also be non-empty bounded IDs and safe integers; malformed evidence is cleared only at an invalidation boundary.
Scheduled and claimed checkpoint evidence survives process restart. The same exact claimed successor may retry within its lifecycle and expiry window, including after a crash. A matching scheduling retry is idempotent and cannot change claimed evidence back to scheduled. Claimed evidence is consumed only after the successor reaches a successful agent_end; hard-error outcomes retain it for retry. Pause, terminal transitions, replacement, expiry, or malformed ownership invalidate it.
Runtime checkpoint state is bounded to 1,024 live leases and exact-turn suppressions. Expired entries are pruned and suppressions also have expiry timers. At capacity, Goal rejects a new checkpoint latch rather than evicting live duplicate-prevention state.
chat_jid).## Active Goal system-prompt block with current status/budget and explicit terminal action guidance. This closes the gap where an agent could achieve a goal on a user-triggered turn but lack the goal context or completion instructions needed to stop.terminate hint. This prevents tool-only turns from completing without user-visible assistant output.stopReason toolUse) is not treated as a failed turn. Only a hard error (stopReason error or an errorMessage) suppresses autonomous continuation.stopReason aborted and the compaction is usually deferred to the next prompt, so no session_compact event fires that turn. Earlier versions tried to detect this via the session_compact event (0.1.34) and then a per-turn tool-activity signal (0.1.35), but both proved unreliable in production: tool-heavy goal turns kept dying on the bare aborted after a turn or a nudge — the main reason long unattended goals appeared to "stop soon after I leave the web UI". As of 0.1.37 the loop continues on any non-errored outcome (clean finish, tool-use finish, or bare aborted); only a hard error stops it. A user stop is rare for an autonomous goal and /goal pause is the intended stop control, and any spurious continuation is bounded by the no_progress auto-stop. An agent_end decision that skips continuation is logged to stderr with a [goal-debug] tag for diagnosis.no_progress auto-stop keys on real tool activity, not just the Plan Sidebar text: substantive tool work (edits, bash, web, etc.) in a turn counts as progress even when the plan checklist is unchanged. Goal-internal tools (get_goal, create_goal, goal_complete, goal_stop, update_goal) do not count as progress.plan action=update when available.agent_end. If every structured plan item is completed, Goal queues a finalization prompt instead of ordinary continuation. If the same completed plan remains unresolved after two probes, Goal marks the loop stopped with reason plan_complete_unverified.stopped with reason no_progress instead of continuing forever.