Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion skills/delegation/delegating-to-claude-p/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: delegating-to-claude-p
description: Use when authoring a non-interactive `claude -p` invocation or designing a delegation prompt for autonomous Claude on the consumer side. Provides the empirically-validated flag set, prompt template, steers-vs-needs-naming map, failure-mode catalog, recipe templates, and cost reference distilled from 22 sub-experiments (S1 → S22) in the agentic-harness-lab v0.8.0 dogfood arc. Trigger phrases include "delegate to claude -p", "claude -p flags", "autonomous claude", "one-shot claude", "claude -p prompt", "headless claude". Do NOT use for interactive Claude Code sessions, brainstorming, or genuine multi-turn work - `claude -p` is a one-shot contract; pick interactive Claude for those.
placement: "Domain skill. Lives at `plugins/delegation/skills/delegating-to-claude-p/` in agentic-primitives. NOT in `.claude/skills/`; that scope is for meta skills."
placement: "Domain skill. Lives at `skills/delegation/delegating-to-claude-p/` in agentic-skills; install with `npx skills add AgentParadise/agentic-skills --skill delegating-to-claude-p`. NOT a meta skill."
---

# Delegating to `claude -p`
Expand All @@ -12,6 +12,37 @@ Invoke this skill any time you are about to write a `claude -p` invocation or de

The single guiding finding: **hard gates and explicit prompt verbs are what steer `claude -p`. Soft documentation (CLAUDE.md content, skill indices, advisory rules) is largely inert in non-interactive mode unless the user prompt names it explicitly.**

## Captured workflow delegation

This section applies only inside an Agentic Workspace (for example a
Syntropic137 workflow workspace) whose session-store capability installs the
`syn-delegate` shim and sets `AGENTIC_SESSION_STORE_PROVIDER=local`. Check with
`command -v syn-delegate`. Outside such a workspace the shim does not exist:
skip to the raw `claude -p` recipes below.

When `AGENTIC_SESSION_STORE_PROVIDER=local`, use the installed structured shim:

```sh
syn-delegate claude --prompt="$TASK_PROMPT" --timeout 600
```

Keep the `=` in `--prompt="$TASK_PROMPT"`: a prompt that starts with `-` is
otherwise read as an option and the shim exits 2 without launching. The shim
passes the prompt to the harness after `--`, so it can never become a CLI flag.
`--sandbox` is Codex-only; the shim rejects it for `claude`.

Use `--model` when selecting a model explicitly. Run from the intended working
directory. Existing harness configuration controls permissions; the shim does
not grant permissions. It records intent before launch, binds the delegate's own
native session ID, and preserves its actual exit status even when a caller uses
`|| true` or a pipeline. Claude's shell hook supplies exact parent context;
Codex supplies its native `CODEX_THREAD_ID`. Missing parent context or durable
storage denies launch. Do not fabricate these context values or fall back to a
raw CLI to bypass a capture failure.

The raw CLI examples below describe uncaptured use and underlying harness
options. In captured workflows, use the shim so the run can discover this launch.

## The validated invocation

```sh
Expand Down
113 changes: 95 additions & 18 deletions skills/delegation/delegating-to-codex/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: delegating-to-codex
description: Use when authoring a non-interactive `codex exec` invocation or deciding whether to hand a task from Claude Code to OpenAI Codex CLI. Provides the validated autonomous invocation, the sandbox/approval ladder, the JSON event schema for triage, a when-to-delegate framework, failure modes, and one empirical trial. Trigger phrases include "delegate to codex", "codex exec", "hand this to codex", "run codex", "codex --full-auto", "ask codex", "second opinion from codex", "have codex use a skill", "run a skill in codex", "codex pr-review". Do NOT use for interactive pair-programming in the Codex TUI, or for trivial CRUD/UI/first-attempt tasks where a model handoff adds no value. For autonomous Claude (not Codex), use `delegating-to-claude-p` instead.
placement: "Domain skill. Lives at `plugins/delegation/skills/delegating-to-codex/` in agentic-primitives. NOT in `.claude/skills/`; that scope is for meta skills."
placement: "Domain skill. Lives at `skills/delegation/delegating-to-codex/` in agentic-skills; install with `npx skills add AgentParadise/agentic-skills --skill delegating-to-codex`. NOT a meta skill."
---

# Delegating to `codex exec`
Expand All @@ -19,6 +19,41 @@ The single most important difference from `claude -p`: **Codex has no built-in
cost cap.** `claude -p` enforces `--max-budget-usd`; `codex exec` has no
equivalent. The only hard bound is an external one (see the budget section).

## Captured workflow delegation

This section applies only inside an Agentic Workspace (for example a
Syntropic137 workflow workspace) whose session-store capability installs the
`syn-delegate` shim and sets `AGENTIC_SESSION_STORE_PROVIDER=local`. Check with
`command -v syn-delegate`. Outside such a workspace the shim does not exist:
skip to the raw `codex exec` recipes below, which keep the same sandbox rules.

When `AGENTIC_SESSION_STORE_PROVIDER=local`, use the installed structured shim:

```sh
syn-delegate codex --prompt="$TASK_PROMPT" --timeout 600
```

Keep the `=` in `--prompt="$TASK_PROMPT"`: a prompt that starts with `-` is
otherwise read as an option and the shim exits 2 without launching. The shim
passes the prompt to the harness after `--`, so it can never become a CLI flag.

Use `--model` when selecting a model explicitly. Run from the intended working
directory. The shim always passes Codex an explicit `--sandbox`: `workspace-write`
by default, or `read-only` via `--sandbox read-only` or
`AGENTIC_DELEGATE_CODEX_SANDBOX=read-only`. Any other value is refused before
launch. Before every launch it probes the Codex sandbox live, in the same mode,
directory and environment Codex will get, and launches only if the probe
passes (see the ladder below); otherwise it records `launch_failed` and exits
69. The shim grants no other permissions. It records intent before launch, binds the delegate's own
native session ID, and preserves its actual exit status even when a caller uses
`|| true` or a pipeline. Claude's shell hook supplies exact parent context;
Codex supplies its native `CODEX_THREAD_ID`. Missing parent context or durable
storage denies launch. Do not fabricate these context values or fall back to a
raw CLI to bypass a capture failure.

The raw CLI examples below describe uncaptured use and underlying harness
options. In captured workflows, use the shim so the run can discover this launch.

## The validated invocation

```sh
Expand Down Expand Up @@ -86,14 +121,20 @@ Pick the least privilege that lets the task finish. Granularity Codex exposes:
|---|---|---|
| `-s read-only` | Read files; no writes, no commands | Analysis / review only |
| `-s workspace-write` | Write + run inside the workspace; no network | The default for fmt/test/edit loops |
| `-s danger-full-access` | Writes anywhere, network | Almost never; prefer adding `--add-dir` to widen scope precisely |
| `--dangerously-bypass-approvals-and-sandbox` | No sandbox, no prompts | ONLY when the host is already externally sandboxed (CI container, disposable VM) |

### Inside a container, the bypass flag is the correct choice, not the reckless one
Nothing above `workspace-write` is on the ladder. Modes and flags that switch
Codex's sandbox off are not used by these recipes, and `syn-delegate` refuses
them (`--sandbox` accepts only `read-only` and `workspace-write`). When writes
must reach a directory outside the workspace, pass `--add-dir <dir>` to a raw
`codex exec` instead. `syn-delegate` has no `--add-dir` option; under the shim,
run from a working directory that already contains every path Codex must write.

### Inside a workspace container: keep the sandbox, fix the container

`-s workspace-write` makes Codex sandbox itself with **bubblewrap**, and
bubblewrap needs an unprivileged user namespace. Docker does not grant that by
default, so inside a container every sandboxed operation fails:
bubblewrap needs an unprivileged user namespace. Docker's default seccomp
profile denies that to a container without `CAP_SYS_ADMIN`, so in a workspace
started with the default profile every sandboxed operation fails:

```
warning: Codex could not find bubblewrap on PATH ... will use the bundled
Expand All @@ -106,22 +147,53 @@ Failed to write file /workspace/palindrome.py
Read that stack carefully: the missing-bwrap line is a **warning** and Codex
continues with a bundled copy. The namespace denial underneath it is the real
fault, and the write failure is only the symptom. Diagnosing from the first
plausible line sends you to install bubblewrap, which does not help.

When the host is already a container, use:
plausible line sends you to install bubblewrap, which does not help. Worse,
`codex exec` still exits 0, so a caller that trusts the exit status records a
run that did nothing as completed.

The fix belongs to the workspace, not the invocation. In Agentic Workspace
images, `agentic_isolation` applies the Codex sandbox policy to every image labelled
`agentic.codex_cli_version` (the Codex-capable workspace images are). It adds a
narrow seccomp profile (Docker's default plus `clone`/`unshare` for the user,
mount, pid, net and ipc namespaces, and `mount`, `umount2`, `pivot_root`)
while `--cap-drop=ALL`, `no-new-privileges` and the read-only root stay in
force. On AppArmor hosts (Ubuntu 24.04, where the symptom is
`bwrap: Failed to make / slave: Permission denied`) it also applies the
AppArmor profile `agentic-codex-sandbox`, which the host administrator loads
on the Docker host (see "Loading the AppArmor profile" below); it admits only the mounts bubblewrap
performs, so Codex must run from a directory under `/workspace`. With both,
`-s workspace-write` works as designed: writes inside the workspace succeed
and writes outside it are denied. For any other container, grant the same
thing yourself: a seccomp profile that admits those syscalls (and, on AppArmor
hosts, an AppArmor profile that admits bubblewrap's mounts). Do not swap the
sandbox for a bypass flag.

#### Loading the AppArmor profile

The profile ships in the `agentic-isolation` Python package at
`agentic_isolation/apparmor/agentic-codex-sandbox`. Locate and load it on the
host that runs the Docker daemon, using the Python environment where
`agentic-isolation` is installed:

```sh
codex exec --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check \
-C /workspace "$TASK_PROMPT" < /dev/null
PROFILE="$(python3 -c 'from agentic_isolation import codex_sandbox_apparmor_profile_path as p; print(p())')"
sudo apparmor_parser -r "$PROFILE"
```

The container is the sandbox. Codex sandboxing inside it is redundant and
broken, so the flag restores correct behaviour rather than removing a
protection. On a developer laptop the earlier warning still stands.
`apparmor_parser -r` lasts until reboot. To load it at every boot, copy it to
`/etc/apparmor.d/agentic-codex-sandbox` (`sudo cp "$PROFILE" /etc/apparmor.d/`)
and load it from there.

Without the shim, run the same probe yourself before trusting a run:
`codex sandbox -c 'sandbox_mode="workspace-write"' -- true` must exit 0.

Reach for `--dangerously-bypass-approvals-and-sandbox` only in an
already-isolated host. On a developer machine it is the equivalent of handing
out an unsandboxed shell.
`syn-delegate codex` probes `codex sandbox -c 'sandbox_mode="<mode>"' -- true`
live before every launch and refuses when it fails: it records `launch_failed`
with reason `codex_sandbox_unavailable` and exits 69, rather than running a
Codex that cannot execute a single command. There is no status file to trust.
The entrypoint logs the same probe at startup (`[entrypoint] codex sandbox:`)
for diagnosis only. If you hit the refusal, the workspace lacks the policy or
you are outside `/workspace`; do not route around it with a raw `codex exec`.

## Budget: there is no built-in cap

Expand Down Expand Up @@ -246,7 +318,12 @@ the format section is what steers the output. See Trial T2.
| `--base <BRANCH> cannot be used with [PROMPT]` | `codex exec review` takes its built-in rubric OR custom instructions, not both | Pick one: `review --base` for the stock rubric, or plain `codex exec` with your own prompt |
| Cannot write files / run commands | Default sandbox is `read-only` | Set `-s workspace-write` explicitly |
| Refuses to run | Not inside a git repo | Add `--skip-git-repo-check` |
| Writes need a dir outside the workspace | `workspace-write` is workspace-scoped | Add `--add-dir <dir>` rather than escalating to `danger-full-access` |
| Writes need a dir outside the workspace | `workspace-write` is workspace-scoped | Raw `codex exec`: add `--add-dir <dir>`, keep the sandbox mode. `syn-delegate` has no `--add-dir`; run from a directory covering the paths |
| `bwrap: No permissions to create a new namespace`, every write fails, exit 0 | Workspace runs Docker's default seccomp profile | Agentic Workspace: use an image labelled `agentic.codex_cli_version` through `agentic_isolation`, which applies the Codex sandbox policy. Other containers: add a seccomp profile admitting the namespace syscalls |
| `bwrap: Failed to make / slave: Permission denied` | AppArmor host, workspace confined by `docker-default` | Load `agentic-codex-sandbox` on the host: `sudo apparmor_parser -r "$PROFILE"` (see "Loading the AppArmor profile"); copy to `/etc/apparmor.d/` to persist |
| `bwrap: Can't bind mount ... Permission denied` | Codex started outside `/workspace` on an AppArmor host | Run from a directory under `/workspace` |
| `syn-delegate` exits 69, `launch_failed` / `codex_sandbox_unavailable` | The live probe found the Codex sandbox unusable | Same fixes; the stderr line names the bwrap cause |
| `syn-delegate` exits 2, `--prompt: expected one argument` | Prompt starts with `-` | Use `--prompt="$TASK_PROMPT"` |
| Command fails on a quirky local env (e.g. `pytest` exit 127 under pyenv) | Sandbox shell inherits host PATH quirks | Under `-s workspace-write` Codex often self-recovers (Trial T1); for wrappers, pre-set env via `-c shell_environment_policy...` |

## Trial T1 — empirical reference
Expand Down
2 changes: 1 addition & 1 deletion skills/delegation/writing-handoffs/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: writing-handoffs
description: Use when you need to compact the current conversation into a handoff document so a fresh session or agent can continue a branch or task with full context. Trigger phrases include "write a handoff", "hand this off", "compact this for a fresh agent", "handoff doc", "summarize this branch's context", "I'll pick this up later", "create a handoff for the next session". Produces a structured Markdown doc (from a template) capturing purpose, current state, files affected, rationale, do's-and-don'ts learned, and suggested skills. Do NOT use to author PRDs, ADRs, plans, or specs — those are separate durable artifacts that a handoff references by path, not reproduces. Do NOT use for a routine end-of-task summary message; a handoff is a written file for a different session to load.
placement: "Domain skill. Lives at `plugins/delegation/skills/writing-handoffs/` in agentic-primitives. NOT in `.claude/skills/`; that scope is for meta skills."
placement: "Domain skill. Lives at `skills/delegation/writing-handoffs/` in agentic-skills; install with `npx skills add AgentParadise/agentic-skills --skill writing-handoffs`. NOT a meta skill."
---

# Writing Handoffs
Expand Down
Loading