Non-Interactive Mode
With the -p (--prompt) flag, pw code runs a single prompt to completion and exits (these docs also call this a one-shot run): no full-screen interface, no follow-up questions. This is the mode to use in scripts, CI jobs, and anywhere you want the agent's answer as program output.
pw code -p "find all TODO comments" owner:provider-name/model-namePass a model as the positional argument or with -m. Without one, the run uses the custom agent's model when --agent names one, and otherwise your saved default model (see Which Choices Persist); with none of these, the run fails. Organization provider models also need an allocation: --allocation, or your saved default allocation (there is no picker to fall back to). List available model IDs with pw ai models ls.
Press Ctrl+C to cancel a run in flight.
What Goes to stdout vs. stderr
In the default text output, the streams are separated so the result stays clean:
- stdout carries only the model's answer, streamed as it is generated.
- stderr carries everything else: tool activity as it happens (a
● ToolName(...)line per call with a condensed result line beneath it), notices, the final usage summary, and the session/resume hint.
That means command substitution and pipes capture just the answer:
RESULT=$(pw code -p "summarize the changes in HEAD in one sentence" owner:provider-name/model-name)
echo "$RESULT"Add 2>/dev/null to silence the progress output entirely, or 2>progress.log to keep it. Progress lines are colorized only when stderr is a terminal, so redirected logs never contain escape codes.
JSON Output
Pass -o json to get a single structured result object on stdout instead of streamed text (no progress is printed for the answer itself in this mode):
pw code -p "list the Go files in this repo" -o json owner:provider-name/model-name{
"message": "The repository contains ...",
"model": "owner:provider-name/model-name",
"session_id": "20260719-153045-a1b2c3d4",
"iterations": 4,
"usage": {
"input_tokens": 18000,
"output_tokens": 1200,
"total_tokens": 19200
},
"estimated_cost": "$0.0480"
}| Field | Description |
|---|---|
message | The model's final answer. |
model | The model ID the run used. |
session_id | The local session ID, usable with pw code -r. |
iterations | How many model requests the agent loop made to finish the prompt. |
activated_skills | Names of the skills the run activated. Omitted when none were. |
usage.input_tokens | Total input (prompt) tokens across the run. |
usage.output_tokens | Total output (completion) tokens across the run. |
usage.total_tokens | Input plus output tokens. |
estimated_cost | Estimated cost as a dollar string, e.g. "$0.0480", based on platform-configured model rates. |
blocked_by_hook | The reason a hook rejected the prompt. Omitted unless one did. |
Extract fields with jq:
pw code -p "how many source files are in src/?" -o json owner:provider-name/model-name \
| jq -r '.message, .estimated_cost'Exit Status
A run that completes exits 0. It exits non-zero when:
- A hook rejects the prompt. With
-o json, the result object is still printed, with the reason inblocked_by_hook. - The model request fails partway through. The error goes to stderr and no JSON object is printed.
Permissions in One-Shot Runs
One-shot runs use the same permission modes as interactive sessions, but there is no one to answer a prompt: any action that would normally ask for approval is denied automatically (it fails closed). The agent sees the denial and continues, working around the restriction or reporting it in its answer. Questions the agent asks you get an empty answer.
The same applies to workspace configuration: a one-shot run never prompts to approve a workspace's settings, MCP servers, commands, or agent definitions, so unapproved files are ignored with a notice on stderr. Launch pw code interactively once to approve them. See Workspace Trust.
For scripting, that means:
--permission-mode read-onlyis the safe choice for analysis and question-answering runs.- The default
accept-editsmode auto-approves file edits inside the workspace, but shell commands that would normally prompt are denied unless pre-approved. --allowedToolspre-approves specific tools or commands, e.g.--allowedTools 'Bash(git status:*)',ReadFile.--permission-mode bypass-permissionsruns every tool without prompting.--permission-mode planhas the agent research and write a plan. Approving the plan is denied, so nothing is changed; stderr ends withPlan saved to <path>.
bypass-permissions runs everything
bypass-permissions gives the agent unrestricted tool access, including arbitrary shell commands. Use it only in environments where that is acceptable, such as a disposable CI container.
MCP Servers and Custom Agents
When the workspace configures MCP servers, the run waits up to 30 seconds for them to connect before sending the prompt, so their tools are available. A server that fails to connect is reported on stderr.
With --agent, a custom agent's initialPrompt is placed before your -p prompt.
Running a Goal
A -p prompt of /goal <condition> runs a goal loop to completion: the agent keeps taking turns until the condition is met, and the run follows every turn. Goal progress lines go to stderr; the model's answers go to stdout.
pw code -p "/goal go test ./... passes, or stop after 15 turns" \
--permission-mode bypass-permissions owner:provider-name/model-namePress Ctrl+C to stop: the current turn is interrupted and the goal is paused, so it does not keep running after the command exits. /goal with no condition, or with clear, prints the result and exits. Resuming a session with -r whose goal is still active follows that goal's turns too.
Skills and custom commands also work as -p prompts, for example pw code -p "/fix-issue 123".
Subagents in One-Shot Runs
The agent may delegate parts of the prompt to subagents. In non-interactive mode, subagents always run inline: requests to run a task in the background are forced to block until the task finishes, so no work is lost when the process exits.
- Progress on stderr is coarse: one
● Task(...)-style start line naming the subagent and its task, and one condensed result line when it completes. The subagent's individual tool calls are not streamed. - Permission-gated commands a subagent runs fail closed, just like the main agent's.
- The JSON output contains only aggregate usage: subagent tokens and cost roll up into the run's
usageandestimated_costtotals, and there is no per-subagent breakdown field.
Resuming a One-Shot Session
Every one-shot run is saved as a local session. In text mode, stderr ends with the session ID and a ready-to-run resume command:
Session: 20260719-153045-a1b2c3d4
Resume: pw code -r 20260719-153045-a1b2c3d4 -m owner:provider-name/model-nameRun that command to reopen the conversation interactively, with the one-shot exchange as history. The reverse also works: combine -r with -p to continue a saved session with another non-interactive prompt, or use -r latest for the most recent session. See Sessions & Resume.
The Daemon in CI
One-shot runs are hosted by the same background daemon as interactive sessions, which pw code starts if needed. The daemon keeps running after the run exits. At the end of a CI job, stop it so the job does not leave a process behind:
pw code -p "run the tests and fix any failures" --permission-mode bypass-permissions owner:provider-name/model-name
pw code daemon stopRelated Documentation
- pw code Overview: Feature overview and quick start
- Permissions: Permission modes and allow rules
- Models & Allocations: Model IDs and the
--allocationflag - Plans, Goals & Checkpoints: Plan mode and
/goal - Sessions & Resume: Resuming one-shot sessions
- Subagents: How delegated tasks behave
- Hooks: Blocking or rewriting prompts
- Usage & Costs: What the usage and cost figures mean
- pw code command reference: Full CLI reference