## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents read runtime prompts, tool help, skills, and role instructions. > - Several of these texts tell agents to create child tasks as a normal next step. > - One accepted-plan prompt even forbids work on the current task. > - Task parentage is useful, but it does not need a prompt that encourages task creation. > - This pull request removes those prompts and keeps the task APIs available. ## Linked Issues or Issue Description Refs #10642. This change adjusts prompt wording; it does not add delegation-cycle guards. **Current behavior** Prompts tell agents to create children after plan approval, use children for long work, and create a task just to pass context. Onboarding requires a child even for a single request. **Proposed behavior** Continue work on the current task. Keep explicit assignments, optional task creation, parentage, dependencies, and approval gates. Use the separate-task recipes when the user requests that structure or when continuing existing work. **Reason and benefit** Reduce needless task trees without removing subtask support. Keep the patch limited to wording, existing test expectations, and generated catalog data. ## What Changed - Align accepted-plan prompts and remove direct child-creation advice from runtime and error text. - Make task tool descriptions neutral. Keep their fields, defaults, and handlers. - Update the main skill, onboarding, CEO instructions, company templates, specialist workflows, and matching guides. - Keep historical release snapshots intact. Refresh the explicitly seeded schema fixture's catalog digest; the server still verifies historical release snapshot hashes. - Refresh the affected generated catalogs, capability inventory, semantic contracts, and fixture manifest. ## Verification - Final tested head: `c6e304d0c105cdbfbe0b2ab0a233307fcd91a04b`. - All 66 check runs are complete: 60 pass, one is neutral, and five are skipped by CI conditions. Snyk also passes. No checks fail or remain pending. - [PR CI](https://github.com/paperclipai/paperclip/actions/runs/42846226554) passes typecheck, build, server/general tests, all eight E2E shards, Runner support, Runner Rust, and the aggregate verify gate. [Windows](https://github.com/paperclipai/paperclip/actions/runs/42846226546) and [Docker Runner](https://github.com/paperclipai/paperclip/actions/runs/42846226108) also pass. - [Greptile](https://github.com/paperclipai/paperclip/pull/20362#issuecomment-6751419835) and [Paperclip review](https://github.com/paperclipai/paperclip/pull/20362#issuecomment-6751454010) give this exact head 5/5. All six inline threads are resolved. Neither current summary has findings. - Merged master `bf0220d34a156c81853755c3d1365ddc527037de`. Resolved three generated-file conflicts with the canonical generators. - Local verification passes: 473 focused prompt, continuation, UI, catalog, runtime and native-execution tests; Runner TypeScript build; generated metadata; UI token gates; and diff checks. - The prior head `c22018cb0f` failed three SDK evidence tests because two source hashes were stale. Reproduced all three failures locally. The existing generator refreshed only the hashes for the denial-copy file and its test. All 53 affected evidence/source-pin tests then passed, including private-value rejection. No scanner logic, assertions, or runtime dependency pins changed. Current CI confirms the support suite passes. - A prior commit failed the Rust process reaping test. Its cause remains unproven. No Rust code or assertions changed. Later Rust runs pass; this does not establish the cause of the earlier failure. - Local preflight built shared/plugin SDK packages, then stopped because `cargo` is absent. Current-head CI supplies Rust and full build coverage. `pnpm verify --explain` selects broad required CI; full local suites were not repeated. ## Risks - Wording changes guide the model; they do not enforce a ban on subtasks. - Existing installed skill versions and saved custom instructions need their normal refresh process. This PR does not migrate company configuration. - Existing approved task assignments and approval gates remain in effect. ## Model Used - OpenAI GPT-6, through Codex, with reasoning, tool use, and code execution. The exact routed model ID and context-window size were not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
9.7 KiB
title, summary
| title | summary |
|---|---|
| Claude Code | Claude Code local adapter setup and configuration |
The claude_local adapter runs Anthropic's Claude Code CLI locally. It supports session persistence, skills injection, and structured output parsing.
Quota waits
Claude ACP runs that end with a typed provider-quota error retain the quota
classification and any parsed reset time. Recovery waits until that time, or
uses its existing one-hour quota backoff when no reset time is available.
This includes the Claude bridge's typed “The Claude account has no available
quota.” fallback, which carries no reset timestamp.
The adapter inspects the terminal provider message in memory; the run result
and run log retain only the generic failure message, recovery labels, and reset
timestamp. Context, turn, rate, and configured budget limits are not treated as
subscription quota exhaustion merely because ACP labels them limit.
Prerequisites
- Claude Code CLI installed (
claudecommand available) - Either
ANTHROPIC_API_KEYorCLAUDE_CODE_OAUTH_TOKENin adapter or environment env (or host env), or a Claude Code subscription login available to the execution target
Configuration Fields
| Field | Type | Required | Description |
|---|---|---|---|
cwd |
string | Yes | Working directory for the agent process (absolute path; created automatically if missing when permissions allow) |
model |
string | No | Claude model to use (default: claude-opus-5) |
promptTemplate |
string | No | Prompt used for all runs |
env |
object | No | Environment variables (supports secret refs) |
timeoutSec |
number | No | Process timeout (0 = no timeout) |
graceSec |
number | No | Grace period before force-kill |
maxTurnsPerRun |
number | No | Max agentic turns per heartbeat (defaults to 300) |
dangerouslySkipPermissions |
boolean | No | Skip permission prompts (default: true); required for headless runs where interactive approval is impossible |
On the CLI engine, version and --effort capability probes have a bounded
20-second budget when timeoutSec is zero or unset. A positive run timeout below
20 seconds also limits these probes, with a minimum probe budget of one second.
Default model
An omitted, empty, or whitespace-only model uses Claude Opus 5
(claude-opus-5) on both the CLI and ACP engines. This also applies to existing
agents with an unset model, including agents created through the API and agents
running in sandboxes. No database migration is needed. The editor shows the
Paperclip default and leaves the setting unset until you select a model.
An explicit model takes precedence over ANTHROPIC_MODEL. When only
ANTHROPIC_MODEL is configured, the adapter keeps that override. Bedrock and
Vertex configurations without an explicit model keep their provider-specific
default because those providers use different model IDs. Host environment
settings apply only to local targets when resolving the model.
The default does not change explicitly configured agent models or the separate Paperclip Runner's qualified provider profiles.
Prompt Templates
Templates support {{variable}} substitution:
| Variable | Value |
|---|---|
{{agentId}} |
Agent's ID |
{{companyId}} |
Company ID |
{{runId}} |
Current run ID |
{{agent.name}} |
Agent's name |
{{company.name}} |
Company name |
Session Persistence
The adapter persists Claude Code session IDs between heartbeats. On the next wake, it resumes the existing conversation so the agent retains full context.
Session resume is cwd-aware: if the agent's working directory changed since the last run, a fresh session starts instead.
If resume fails with an unknown session error, the adapter automatically retries with a fresh session.
Poisoned previous_message_id (recovery)
Symptom in logs / issue thread:
API Error: 400 diagnostics.previous_message_id: must be the `id` from a prior /v1/messages response (starts with `msg_`)
What it means: the on-disk Claude Code transcript JSONL for that session contains a malformed (non-msg_-prefixed) previous_message_id. Anthropic's /v1/messages rejects every resume attempt against that transcript with a deterministic 400. Without guards, Paperclip would re-persist the same poisoned session id and the issue is stranded permanently — see RED-976 / RED-978.
What the adapter does automatically:
- Auto-rotate on resume. If a
--resumeattempt returns this 400, the adapter retries once with a fresh session, deletes the poisoned<session>.jsonlfrom the local Claude config dir (best effort), and uses the fresh session id going forward. - Validate-before-persist. A result that carries this 400 never gets its
session_idwritten back to the task session store, even if Claude Code emits one in the result event. The adapter returnssessionId: null,sessionParams: null, anderrorCode: "claude_poisoned_previous_message_id". - Clear-on-error. The adapter sets
clearSession: trueon the result, which causes the heartbeat service to drop any persisted session row for that issue (clearTaskSessions). The next continuation starts from a clean slate.
On-call checklist if you see this in production:
- Confirm
errorCodeisclaude_poisoned_previous_message_idin the run row — that means the guards fired correctly and the issue auto-recovers on the next heartbeat. - If the same issue still loops after one heartbeat, check that
agentTaskSessionsfor that(agentId, taskKey)was cleared. If not, the adapter return value was lost (e.g. a malformed run finalization) — escalate; do not manually edit the row, include the run id in the escalation. - For remote execution targets (sandbox/SSH), the poisoned JSONL is on the remote and the adapter only logs the cleanup intent. The fresh-session retry still succeeds because it uses a new session id, and the server-side
clearSession: trueis authoritative regardless of remote disk state.
Skills Injection
The adapter creates a temporary directory with symlinks to Paperclip skills and passes it via --add-dir. This makes skills discoverable without polluting the agent's working directory.
Remote credential ownership
When no API key or CLAUDE_CODE_OAUTH_TOKEN is configured,
claude_local uses a snapshot-owns-auth topology for managed sandbox execution
targets. When the run uses a sandbox execution target and no explicit
CLAUDE_CONFIG_DIR is configured, Paperclip creates a remote
CLAUDE_CONFIG_DIR under the run's Claude runtime directory. It uploads
sanitized host-side settings such as settings.json and CLAUDE.md, but the
managed seed does not upload host Claude credential files.
After the seed is copied, the remote materialization command checks the
execution target's own $HOME/.claude directory. For each missing credential
file, it copies .credentials.json or credentials.json from that remote home
into the managed CLAUDE_CONFIG_DIR. That means credentials baked into the
sandbox image win for managed remote Claude runs.
Worked example: a sandbox image contains $HOME/.claude/.credentials.json from
its own Claude Code login. Paperclip starts a managed remote claude_local run,
uploads only the sanitized config seed, and sets CLAUDE_CONFIG_DIR to the
remote runtime config path. Because the managed config has no credential file,
the adapter copies the sandbox image's $HOME/.claude/.credentials.json into
that path before invoking Claude. The sandbox snapshot owns the credential for
the run.
This differs from codex_local, where a
Paperclip-managed sandbox run uploads a host-owned CODEX_HOME/auth.json and
therefore shadows any Codex login already present inside the sandbox image.
Sandbox memory limits
A sandbox has a fixed memory limit. When a tool command (for example a type check or a dependency install) uses most of that memory, the kernel kills one process. Without help it can kill the Claude Code process, and the run fails with "The connection to Claude was lost."
For managed sandbox runs, the same materialization step installs a
tool-shell-prefix.sh script in the run's Claude runtime directory and sets
CLAUDE_CODE_SHELL_PREFIX to it. Claude Code runs each Bash tool command and
hook through that script. The script raises the command's oom_score_adj to
1000 and then runs the command in the shell that Claude Code selects. The
kernel then kills the tool command first, and Claude sees a failed command
(exit 137) that it can recover from. Paperclip sets the variable only after the
sandbox confirms the install. An operator CLAUDE_CODE_SHELL_PREFIX in the
adapter env is kept, and no script is installed.
For manual local CLI usage outside heartbeat runs (for example running as claudecoder directly), use:
npx paperclipai agent local-cli claudecoder --company-id <company-id>
This installs Paperclip skills in ~/.claude/skills, creates an agent API key, and prints shell exports to run as that agent.
Environment Test
Use the "Test Environment" button in the UI to validate the adapter config. It checks:
- Claude CLI is installed and accessible
- Working directory is absolute and available (auto-created if missing and permitted)
- API key/auth mode hints (
ANTHROPIC_API_KEYvsCLAUDE_CODE_OAUTH_TOKENvs subscription login) - A live hello probe (
claude --print - --output-format stream-json --verbosewith promptRespond with hello.) to verify CLI readiness
The probe sees the same layered env as a real run: when an environment is
selected, its environment variables (secret refs included) are resolved and
merged under the adapter config's env, so environment-level auth is
reflected in the test result. A secret binding that is missing surfaces as
an environment_env_binding_missing failure instead of a silently passing
probe.