# Shell tool (`type: "shell"`) — hosted containers and local runtime; legacy `local_shell` **Status:** `shell` DOCUMENTED · LIVE_VERIFIED (2026-09-18, `gpt-5.4-nano`: local environment proposal; hosted `container_auto` with a mounted skill executed `echo OK`). `local_shell` DOCUMENTED · LEGACY · FAILED_VERIFICATION (HTTP 400 "The local_shell tool is no longer supported." on `gpt-5.4-nano`; only `codex-mini-latest` documented). **Sources:** https://developers.openai.com/api/docs/guides/tools-shell · https://developers.openai.com/api/docs/guides/tools-local-shell · https://developers.openai.com/api/docs/pricing#built-in-tools · openapi-master.yaml `FunctionShellToolParam`, `ContainerAutoParam`, `LocalEnvironmentParam`, `ContainerReferenceParam`, `FunctionShellCall`, `FunctionShellCallOutputItemParam`, `LocalShellToolParam`, `LocalShellToolCall` **Last verified:** 2026-09-18 ## Parameters | Parameter | Type / enum | Notes | |---|---|---| | `type` | `shell` | Responses API only (not Chat Completions) | | `environment` | `{type:"container_auto", file_ids[] ≤50, memory_limit: 1g\|4g\|16g\|64g, network_policy: {type:"disabled"} \| {type:"allowlist", allowed_domains[], domain_secrets[]}, skills[] ≤200}` | hosted: OpenAI runs commands, emits `shell_call_output` itself | | | `{type:"container_reference", container_id:"cntr_…"}` | reuse a container (files + mounted skills persist while active) | | | `{type:"local", skills[] {name, description, path}}` | your runtime executes; skills by absolute path | | `allowed_callers` | `["direct"\|"programmatic"]` | programmatic tool calling | `tool_choice: {"type":"shell"}` forces a shell call (verified). Hosted cwd `/mnt/data`; skills mounted at `/home/oai/skills/-`; no TTY; no outbound network unless `network_policy.allowlist` within the org allow-list. ## Items (live shapes) ```json {"id":"sh_…","type":"shell_call","status":"completed","call_id":"call_…","action":{"commands":["echo OK"],"timeout_ms":10000,"max_output_length":null},"environment":null} {"id":"sho_…","type":"shell_call_output","status":"completed","call_id":"call_…","max_output_length":null,"output":[{"stdout":"OK\n","stderr":"","outcome":{"type":"exit","exit_code":0}}]} ``` - Local mode: `environment` is `null` in the item (spec allows `{type:"local"}`); `timeout_ms` was `null` in one run and `10000` in others — treat it as a hint and enforce your own limits. - Hosted mode: `environment: {type:"container_reference", container_id}` on each `shell_call`; the API appends `shell_call_output` items automatically (two call/output pairs observed: `ls`/`cat SKILL.md`, then `echo OK`). - Your `shell_call_output` (local): `{type, call_id, output:[{stdout, stderr, outcome: {type:"exit", exit_code} | {type:"timeout"}}], max_output_length?}`; return partial output + `timeout` outcome on timeouts; preserve non-zero exit codes. ## Streaming (live, local) `response.output_item.added` → `response.shell_call_command.added` (`command_index`, `command: ""`) → `response.shell_call_command.delta` (`delta`) → `response.shell_call_command.done` (`command`) → `response.output_item.done`. Hosted output streaming: `response.shell_call_output_content.delta/.done` (spec). ## Billing Hosted containers: same session pricing as code interpreter (1 GB $0.03 … 64 GB $1.92 per 20-min session). Local: tokens only. ## Models Model pages list `hosted_shell` for gpt-5.2, gpt-5.2-codex, gpt-5.3-codex, gpt-5.4, gpt-5.4-mini, gpt-5.4-nano, gpt-5.5, gpt-5.5-pro, gpt-5.6-*, gpt-6-astra, daybreak-*. ## `local_shell` (legacy) `{"type":"local_shell"}` → `local_shell_call {action:{type:"exec", command[], timeout_ms, working_directory, env, user}}` answered by `local_shell_call_output {id, output}`. Designed for Codex CLI / `codex-mini-latest`. Live on `gpt-5.4-nano`: **400** `invalid_request_error`, `param: tools`, "The local_shell tool is no longer supported." Use `shell` with `environment.type = "local"` instead. ## Security (docs) Local: you execute arbitrary commands — sandbox, resource limits, filter `rm`/`curl`/network, never run untrusted commands. Hosted: allow-listed domains are exfiltration channels under prompt injection; use `domain_secrets` so credentials never enter model context; validate data-residency needs. Examples: `examples/openai/tools/shell/` (local proposal), hosted with skill in `tmp-live/tools/shell_hosted_skill.json` and [skills](skills.md). Test: `test_shell_local_and_apply_patch_proposals`.