/subagent-request-approval
Use when a T3 command was blocked or a predictable ordered T3 set must be requested before execution
Claude Code
$ npx -y skills add metraton/gaia --skill subagent-request-approval --agent claude-code
Codex
$ npx skills add metraton/gaia --skill subagent-request-approval -a codex -y
Cursor
$ npx skills add metraton/gaia --skill subagent-request-approval -a cursor -y
Gemini CLI
$ npx skills add metraton/gaia --skill subagent-request-approval -a gemini-cli -y
GitHub Copilot
$ npx skills add metraton/gaia --skill subagent-request-approval -a github-copilot -y
OpenCode
$ npx skills add metraton/gaia --skill subagent-request-approval -a opencode -y
Windsurf
$ npx skills add metraton/gaia --skill subagent-request-approval -a windsurf -y
SKILL.md
subagent-request-approval.SKILL.mdname: subagent-request-approval
description: Use when a T3 command was blocked or a predictable ordered T3 set must be requested before execution
Request Approval — Producer Branch
You ask for a signature by writing a few short phrases. Gaia builds everything the user sees -- in Claude Code one question per signature listing its commands, in OpenCode one question per command, each with Approve / Reject / Details, and behind Details a second question that explains it. No model writes or copies any of it.
What you write
Every phrase is required: Gaia refuses a request that lacks one, or has one over its limit, and names the flag. Write them in English, in full sentences, for someone who does not read commands: Gaia shows each phrase verbatim inside its own English frame.
| Flag | What it says | Limit | |------|--------------|-------| | `--what` | The title: what the request does, in human words, with no commands, flags, paths or IDs. | 120 characters | | `--question` | The short question the user answers. | 60 characters | | `--does` | Once per `--command`, in order: what that command does. | 100 characters | | `--impact` | Once per `--command`, in order: what changes for the user, and whether it can be undone. | 100 characters | | `--rollback` | Once per request: how to undo it, as a sentence, not a command -- or, when it cannot be undone, a sentence that says so plainly. | one line | | `--verification` | Once per `request-set`: how you will confirm the result. | one line | | `--shared-state` | Once per `request-set`: whether it rewrites state other people rely on (a shared branch, a cluster, a registry) and which -- or that it touches none. | one line |
`--does`, `--impact`, `--verification`, `--shared-state` and `--rollback` are what the user reads when they press Details. In Claude Code the question itself shows you, the commands and `--what` as what the set does, so `--what` must describe the whole set; in OpenCode it shows only you and the command. `--question` stays with the signature for whoever reviews it later.
The rollback is never optional. If the change can be undone, say how ("Delete the branch from the remote."). If it cannot, write that it cannot and why ("Cannot be undone: the published version stays published."). A request without `--rollback` is refused, and the refusal says what to write. A `request-set` without `--verification` or `--shared-state` is refused the same way.
The signature covers what the command executes, not only its text. The content of each file a command runs or reads -- an interpreter's script (`bash deploy.sh`), a program given as a path, a `--<name>-file` value, a `-f`/`--file`/`--filename`/`--values` value -- is sealed when you request. So write the file first: a script or `--<name>-file` that does not exist yet is refused, as is a directory. A `-f` value that is not a file yet (it may be a word, as in `git push -f origin`) is sealed as absent. An ELF binary or a file over 64 MiB is sealed by its identity (device, inode, size, modification and change times) instead of its content, so replacing or rewriting it breaks the match all the same. If any sealed file changes before the command runs -- or an absent one appears -- the command no longer matches the signature and is blocked; request it again.
Optional, per command: `--cwd` (the existing directory it must run in, once for all or once per command; the default is where you run the request) and `--expect-exit POSITION=CODES` (non-zero exits that still let the set go on, e.g. `2=1`; repeat the flag, or list codes with commas, for more than one code). Declare it for every command whose non-zero exit is part of its normal contract -- a `git rebase` that stops on a conflict you will resolve, a `git cherry-pick` likewise -- because only a declaration made here lets the set go on; an undeclared non-zero exit freezes it and the rest needs a new request. The user sees each declared exit beside that command, as `(allowed exit: 1)` in Claude Code and `ALLOWED EXIT` in OpenCode. Details names a command's folder when it runs somewhere other than where you asked from, or when the command uses relative paths.
When every command of a request is `git -C <same absolute folder> ...`, Claude Code's question names that folder once in its first line (`Signature 1/1: gaia-system requests 2 commands in ~/repo`, `~` only for an exact home prefix) and numbers each command without its `-C <folder>`; Details still shows every full command. Any other block is shown verbatim. Only the display changes: the signature binds each full command and its sealed folder.
One request holds at most 4 signed commands (`surface.check_phrases` refuses more when you request), because OpenCode asks each signed command as its own question and a host shows at most 4 at a time. More than that goes in another request.
A step of the same plan that is not T3 -- a local `git commit` between two pushes, a test run -- goes in the request in its position, with its own `--does` and `--impact`. Gaia seals it unsigned: the user sees it in order, marked `(unsigned step)` in Claude Code and `UNSIGNED STEP` in OpenCode, but it asks nothing of its own and holds no place in the signature, so you run it like any other command of yours. A request with no T3 step at all is refused.
A command sealed in another directory than the one your Bash runs in is run as exactly `cd <sealed directory> && <sealed command>`, with the directory and the command byte for byte as sealed. It is the only compound Gaia accepts; any other directory, command or chain is refused.
Example -- the request:
gaia approvals request-set \
--command 'python3 <workspace>/.project-worktrees/gaia/0ac7481a9c2e4f6b8d0a1c3e5f7b9d2e/bin/gaia dev --workspace <dev-install-folder> --ref bbc2f09 --channel npm' \
--what 'Reinstall Gaia in your workspace and upgrade its database.' \
--question 'Reinstall Gaia?' \
--does 'gaia dev: installs the new version of main in y
Read more
name: subagent-request-approval description: Use when a T3 command was blocked or a predictable ordered T3 set must be requested before execution
Request Approval — Producer Branch
You ask for a signature by writing a few short phrases. Gaia builds everything the user sees -- in Claude Code one question per signature listing its commands, in OpenCode one question per command, each with Approve / Reject / Details, and behind Details a second question that explains it. No model writes or copies any of it.
What you write
Every phrase is required: Gaia refuses a request that lacks one, or has one over its limit, and names the flag. Write them in English, in full sentences, for someone who does not read commands: Gaia shows each phrase verbatim inside its own English frame.
| Flag | What it says | Limit | |------|--------------|-------| | `--what` | The title: what the request does, in human words, with no commands, flags, paths or IDs. | 120 characters | | `--question` | The short question the user answers. | 60 characters | | `--does` | Once per `--command`, in order: what that command does. | 100 characters | | `--impact` | Once per `--command`, in order: what changes for the user, and whether it can be undone. | 100 characters | | `--rollback` | Once per request: how to undo it, as a sentence, not a command -- or, when it cannot be undone, a sentence that says so plainly. | one line | | `--verification` | Once per `request-set`: how you will confirm the result. | one line | | `--shared-state` | Once per `request-set`: whether it rewrites state other people rely on (a shared branch, a cluster, a registry) and which -- or that it touches none. | one line |
`--does`, `--impact`, `--verification`, `--shared-state` and `--rollback` are what the user reads when they press Details. In Claude Code the question itself shows you, the commands and `--what` as what the set does, so `--what` must describe the whole set; in OpenCode it shows only you and the command. `--question` stays with the signature for whoever reviews it later.
The rollback is never optional. If the change can be undone, say how ("Delete the branch from the remote."). If it cannot, write that it cannot and why ("Cannot be undone: the published version stays published."). A request without `--rollback` is refused, and the refusal says what to write. A `request-set` without `--verification` or `--shared-state` is refused the same way.
The signature covers what the command executes, not only its text. The content of each file a command runs or reads -- an interpreter's script (`bash deploy.sh`), a program given as a path, a `--<name>-file` value, a `-f`/`--file`/`--filename`/`--values` value -- is sealed when you request. So write the file first: a script or `--<name>-file` that does not exist yet is refused, as is a directory. A `-f` value that is not a file yet (it may be a word, as in `git push -f origin`) is sealed as absent. An ELF binary or a file over 64 MiB is sealed by its identity (device, inode, size, modification and change times) instead of its content, so replacing or rewriting it breaks the match all the same. If any sealed file changes before the command runs -- or an absent one appears -- the command no longer matches the signature and is blocked; request it again.
Optional, per command: `--cwd` (the existing directory it must run in, once for all or once per command; the default is where you run the request) and `--expect-exit POSITION=CODES` (non-zero exits that still let the set go on, e.g. `2=1`; repeat the flag, or list codes with commas, for more than one code). Declare it for every command whose non-zero exit is part of its normal contract -- a `git rebase` that stops on a conflict you will resolve, a `git cherry-pick` likewise -- because only a declaration made here lets the set go on; an undeclared non-zero exit freezes it and the rest needs a new request. The user sees each declared exit beside that command, as `(allowed exit: 1)` in Claude Code and `ALLOWED EXIT` in OpenCode. Details names a command's folder when it runs somewhere other than where you asked from, or when the command uses relative paths.
When every command of a request is `git -C <same absolute folder> ...`, Claude Code's question names that folder once in its first line (`Signature 1/1: gaia-system requests 2 commands in ~/repo`, `~` only for an exact home prefix) and numbers each command without its `-C <folder>`; Details still shows every full command. Any other block is shown verbatim. Only the display changes: the signature binds each full command and its sealed folder.
One request holds at most 4 signed commands (`surface.check_phrases` refuses more when you request), because OpenCode asks each signed command as its own question and a host shows at most 4 at a time. More than that goes in another request.
A step of the same plan that is not T3 -- a local `git commit` between two pushes, a test run -- goes in the request in its position, with its own `--does` and `--impact`. Gaia seals it unsigned: the user sees it in order, marked `(unsigned step)` in Claude Code and `UNSIGNED STEP` in OpenCode, but it asks nothing of its own and holds no place in the signature, so you run it like any other command of yours. A request with no T3 step at all is refused.
A command sealed in another directory than the one your Bash runs in is run as exactly `cd <sealed directory> && <sealed command>`, with the directory and the command byte for byte as sealed. It is the only compound Gaia accepts; any other directory, command or chain is refused.
Example -- the request:
gaia approvals request-set \ --command 'python3 <workspace>/.project-worktrees/gaia/0ac7481a9c2e4f6b8d0a1c3e5f7b9d2e/bin/gaia dev --workspace <dev-install-folder> --ref bbc2f09 --channel npm' \ --what 'Reinstall Gaia in your workspace and upgrade its database.' \ --question 'Reinstall Gaia?' \ --does 'gaia dev: installs the new version of main in y
Generative AI Interface for Agents. Specialist agents for Claude Code and OpenCode, with a memory that outlives the session and a consent gate on everything that changes state.
Other skills on gaia.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about subagent-request-approval.
- Which coding agents can use subagent-request-approval?
- subagent-request-approval installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

