Vibe Code Textbook

Workflows · · 2,545 words · 12 min read

Prompt patterns for coding agents: plan mode, skills, saved prompts

Four prompt patterns from the Claude Code, Codex, and Gemini CLI docs, with exact commands and file formats, plus a script that writes one saved prompt three ways.

prompting plan mode skills slash commands claude code

You get the four prompt patterns that the documentation of three coding-agent harnesses now agrees on, in the harnesses' own words: plan before you edit, give the agent a check it can run, let it interview you, and save the prompts you keep retyping. For each pattern you get the exact command, flag, or file format in Claude Code, Codex, and Gemini CLI as read on 2026-09-10, and a standard-library Python script that validates a saved prompt against the shared skill specification and writes it out in all three formats. No agent ran in this session; what ran was the script, on Python 3.13.12 on Windows, and every output block below is real. Versions from each project's GitHub releases page on the same day: Claude Code v2.1.267 (2026-09-09), Codex CLI rust-v0.154.0 (2026-09-09), Gemini CLI v0.59.0 (2026-09-08).

The single-task prompt, the six-section spec, was the subject of /posts/spec-first-prompting-coding-agent.html. This article is about the patterns around that prompt: what you do before it, what you attach to it, and what you do with it once it works.

Pattern one: plan as a mode, not a request

Asking an agent to "make a plan first" used to be a sentence in the prompt. In all three harnesses it is now a mode the harness enforces, which changes what the pattern is worth. Claude Code's permission-modes page defines it: "Plan mode tells Claude to research and propose changes without making them. Claude reads files, runs shell commands to explore, and writes a plan, but does not edit your source." You enter it with Shift+Tab, by prefixing one prompt with /plan, or with claude --permission-mode plan. When the plan is ready the options are "Yes, and use auto mode", "Yes, manually approve edits", and "No, keep planning", and the page is explicit that "Approving a plan exits plan mode and switches the session to the permission mode each approve option describes". Ctrl+G opens the plan in your editor before anything runs.

Gemini CLI's page calls it "a read-only environment for architecting robust solutions before implementation" and lists the tools it leaves available, among them read_file, grep_search, web_fetch, ask_user, and, for writing, "write_file and replace only allowed for .md files in the plans directory". Entry is /plan [goal], Shift+Tab, or gemini --approval-mode=plan; Ctrl+X opens the plan in an external editor; plans land in ~/.gemini/tmp/<project>/<session-id>/plans/. Codex's prompting page says "For a multi-step task, enter /plan in the app composer when you want Codex to investigate and propose an approach before editing." Its app reference lists /plan as "Toggle plan mode for multi-step planning". The CLI commands page I fetched was cut off before any /plan row, and neither page says whether edits are blocked, so those are the cells in the table below I could not fill from the docs.

Claude Code v2.1.267 Codex rust-v0.154.0 Gemini CLI v0.59.0
Enter Shift+Tab, /plan prefix, --permission-mode plan /plan /plan [goal], Shift+Tab, --approval-mode=plan
Edits blocked yes, until approved (see caveat) not stated on the pages read yes; writes only to .md in the plans directory
Edit the plan Ctrl+G not stated Ctrl+X
Leave without approving Shift+Tab not stated Shift+Tab, Esc, or ask in words

The caveat on the Claude Code row is in the same document: "In sessions with bypass permissions available, Claude Code also doesn't enforce plan mode's blocks. Claude is still instructed to plan without editing, but a file edit or shell command it attempts during planning runs without prompting." A plan mode entered from a bypass session is a request again, not a gate.

The best-practices page also says when not to use the pattern: "Plan mode is useful, but also adds overhead." and "If you could describe the diff in one sentence, skip the plan." Planning earns its cost "when you're uncertain about the approach, when the change modifies multiple files, or when you're unfamiliar with the code being modified."

There is a research reason to treat the plan as an artifact rather than a vibe. The DCAS paper from August 2026 (arXiv:2608.06113), on why models fine-tuned under one CLI scaffold degrade under another, argues "that a load-bearing scaffold-specific behavior is planning structure, in two senses this paper distinguishes: explicit planning, a pre-execution plan produced as a first-class artifact, and implicit planning, the structural conventions that shape execution throughout the agent loop." Their controlled intervention "confirms planning quality is a high-leverage component, with gains exceeding the cross-scaffold drops we observe." The plan file you edit with Ctrl+G or Ctrl+X is exactly their explicit plan; the abstract does not give per-harness numbers, and I did not read the full paper, so I quote the claim and not a figure.

Pattern two: a check the agent can run

The tests-first loop was /posts/tests-first-with-an-agent-red-green.html; the prompt pattern behind it is now the first section of Claude Code's best-practices page. "Claude stops when the work looks done. Without a check it can run, "looks done" is the only signal available, and you become the verification loop: every mistake waits for you to notice it." The page's own before-and-after is the whole pattern in one row: the prompt "add tests for foo.py" becomes "write a test for foo.py covering the edge case where the user is logged out. avoid mocks." Then it escalates by how hard the check gates the stop: in one prompt, as a /goal condition re-checked "after every turn", as a Stop hook that "blocks the turn from ending until it passes" (ceiling: "8 consecutive blocks"), or by "a verification subagent" so "the agent doing the work isn't the one grading it". And the instruction that turns a claim into evidence: "Have Claude show evidence rather than asserting success: the test output, the command it ran and what it returned, or a screenshot of the result."

Codex's page states the same pattern as a habit rather than a mechanism: "For important work, ask ChatGPT for a final check, such as confirming every action item has an owner and due date or flagging information it couldn't verify." Its bug-fix advice is to give "a reproduction recipe, plus the file(s) you suspect" and to set boundaries such as "Do not change the API shape. Keep the fix minimal." The Codex app reference does list /goal, "Set a persistent goal for ChatGPT to work toward", and /review, "Start code review mode to review uncommitted changes". Gemini CLI's pages I read for this article do not describe a goal or stop-hook mechanism; its answer to verification is the read-only plan mode plus whatever test command you name in the prompt.

Pattern three: the interview

The most useful prompt on the Claude Code page is the one that produces the spec rather than the code. Under "Let Claude interview you": "I want to build [brief description]. Interview me in detail using the AskUserQuestion tool. Ask about technical implementation, UI/UX, edge cases, concerns, and tradeoffs. Don't ask obvious questions, dig into the hard parts I might not have considered. Keep interviewing until we've covered everything, then write a complete spec to SPEC.md." The step after matters as much: "Once the spec is complete, start a fresh session to execute it." The page's reason is context: "A clean session with a better prompt almost always outperforms a long session with accumulated corrections."

Codex's prompting page gets to the same place from the other end. "Start with the result, not a detailed list of steps." and "Your first prompt doesn't need to be perfect. Review the result, then ask for the specific change you want." Gemini CLI's plan mode keeps ask_user in its allowed tool list, which is the same move: the agent may interrogate you while it may not edit. None of the three pages claims the interview produces better code; they claim it produces a spec you can read before the code exists, and that is the claim I can support.

The Claude Code page also defends the opposite: "Vague prompts can be useful when you're exploring and can afford to course-correct." The pattern is not always-specify; it is specify once you know what you want.

Pattern four: the saved prompt

Any prompt you have typed three times is a file. All three harnesses now have a format for it, and two of the three formats are the same file.

Claude Code's skills page: "Custom commands have been merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way." The reason to prefer the skill form over a paragraph in a context file is cost: "Unlike CLAUDE.md content, a skill's body loads only when it's used, so long reference material costs almost nothing until you need it." The frontmatter controls who may run it. disable-model-invocation: true is for "workflows with side effects that you want to trigger manually", and the docs say what happens if the model tries: "Claude Code blocks the call and instructs it not to reproduce the deploy steps another way". allowed-tools pre-approves "Tools Claude can use without asking permission during the turn that invokes this skill. The grant clears when you send your next message." Arguments arrive as $ARGUMENTS, or positionally as $0, $1, or by name from an arguments: list. A line starting with ! runs a shell command first: "Claude Code runs the command and replaces the line with its output before Claude sees the skill content", and "A failed command aborts the entire skill invocation". Two budgets are stated: the listing shown to the model truncates the combined description text "at 1,536 characters", and after compaction each re-attached skill keeps "the first 5,000 tokens", with "a combined budget of 25,000 tokens".

Codex's build-skills page: "A skill is a directory with a SKILL.md file plus optional scripts and references." Discovery runs $CWD/.agents/skills, $REPO_ROOT/.agents/skills, $HOME/.agents/skills, /etc/codex/skills, then bundled skills; you invoke one explicitly with $skill-name in the CLI, and "ChatGPT or Codex can choose a skill when your task matches the skill description." A skill is switched off, not deleted, with a [[skills.config]] entry in ~/.codex/config.toml setting enabled = false. The description budget is stated as "at most 2% of the model's context window, or 8,000 characters when the context window is unknown." The older mechanism still exists: the custom-prompts page, marked "Deprecated in favor of skills", documents Markdown files in ~/.codex/prompts/ invoked as /prompts:filename, with $1 through $9, $ARGUMENTS, named $FILE-style values passed as KEY=value, and $$ for a literal dollar sign. That page says to restart Codex after editing a prompt file.

Gemini CLI has two mechanisms. Custom commands are TOML: a required prompt, an optional description, in ~/.gemini/commands/ for the user or <project>/.gemini/commands/ for the project, and "If a command in the project directory has the same name as a command in the user directory, the project command will always be used." Subdirectories become namespaces with a colon. {{args}} takes what you typed; without it "the CLI will append the full command you typed to the end of the prompt, separated by two newlines." Shell injection with !{...} is gated: "Gemini CLI will now prompt you for confirmation before proceeding." Skills are the second mechanism, "Based on the Agent Skills open standard", discovered from ~/.gemini/skills/ or the ~/.agents/skills/ alias and .gemini/skills/ or .agents/skills/; at session start the CLI "injects the name and description of all enabled skills into the system prompt", the model calls activate_skill when a task matches, and "You will see a confirmation prompt in the UI detailing the skill's name, purpose, and the directory path it will gain access to."

Claude Code Codex Gemini CLI
File .claude/skills/<name>/SKILL.md .agents/skills/<name>/SKILL.md .gemini/commands/<name>.toml, or .agents/skills/<name>/SKILL.md
Argument placeholder $ARGUMENTS, $0, $name none documented for skills; $1-$9, $ARGUMENTS in deprecated prompts {{args}} in commands
Shell before the model sees it ! prefix, failure aborts not documented !{...}, confirmation prompt
Keep the model from auto-running it disable-model-invocation: true enabled = false in config commands are user-typed only; skills need consent
Explicit call /name $name /name

The shared file is the Agent Skills specification, which Codex and Gemini both cite: name "Max 64 characters. Lowercase letters, numbers, and hyphens only. Must not start or end with a hyphen." and matching the directory; description "Max 1024 characters"; a recommended body under 500 lines; and the loading model, "The name and description fields are loaded at startup for all skills", with the body only on activation. A skill that follows the spec is a Codex skill and a Gemini skill unchanged and a Claude Code skill with two optional lines added.

One prompt, three files

The shipped script does two things and invokes no harness. validate <dir> checks a SKILL.md against the specification's constraints. emit takes a name, a description, a prompt file, and an output directory and writes the Claude Code skill, the Codex skill, and the Gemini command. The prompt I used is the issue-fix workflow from the pattern above, with $ARGUMENTS where the issue number goes.

def validate(skill_dir: str) -> list[str]:
    errors: list[str] = []
    fm, body = parse_frontmatter(open(os.path.join(skill_dir, "SKILL.md"), encoding="utf-8").read())
    name = fm.get("name", "")
    dirname = os.path.basename(os.path.abspath(skill_dir))
    if not 1 <= len(name) <= 64:
        errors.append(f"name: {len(name)} chars (spec: 1-64)")
    if not NAME_RE.match(name):          # ^[a-z0-9]+(-[a-z0-9]+)*$
        errors.append(f"name: {name!r} must be lowercase a-z, 0-9 and single hyphens, not at the ends")
    if name != dirname:
        errors.append(f"name: {name!r} does not match directory {dirname!r} (spec: must match)")
    desc = fm.get("description", "")
    if not desc or len(desc) > 1024:
        errors.append("description: required, 1-1024 chars")
    if body.count("\n") + 1 > 500:
        errors.append("body: over 500 lines (spec recommends under 500)")
    return errors

The run, verbatim:

> python prompt-patterns-coding-agents-plan-mode-skills.py emit fix-issue "Fix a GitHub issue by number: reproduce with a failing test, then the minimal change" prompt.md out
wrote out\claude\.claude\skills\fix-issue\SKILL.md
wrote out\codex\.agents\skills\fix-issue\SKILL.md
wrote out\gemini\.gemini\commands\fix-issue.toml
exit=0
> python prompt-patterns-coding-agents-plan-mode-skills.py validate out/claude/.claude/skills/fix-issue
out/claude/.claude/skills/fix-issue: OK
exit=0
> python prompt-patterns-coding-agents-plan-mode-skills.py validate bad/Fix_Issue
error: name: 'Fix--Issue' must be lowercase a-z, 0-9 and single hyphens, not at the ends
error: name: 'Fix--Issue' does not match directory 'Fix_Issue' (spec: must match)
error: description: required
bad/Fix_Issue: 3 error(s)
exit=1

The Gemini file it wrote, which Python's tomllib parsed back with the two expected keys:

description = "Fix a GitHub issue by number: reproduce with a failing test, then the minimal change"
prompt = """
Fix the issue {{args}} in this repository.

1. Read the issue text and restate the expected behaviour in one sentence.
2. Write a failing test that reproduces it before changing any code.
3. Make the smallest change that turns the test green.
4. Run the whole test suite and report the command and its exit code.
5. Stop and ask before touching any file outside the module the issue names.
"""

The first version of the script wrote the description unquoted, and a description with a colon in it is not valid YAML in that position. That is the kind of defect a validator finds only if you feed it your own output, so the script now quotes the field and the run above is the corrected one. The Codex copy replaces $ARGUMENTS with a plain sentence, because the Codex skills page documents no placeholder; you type the issue number after $fix-issue and the prompt tells the model where to find it.

What the pages do not say

None of the pages I read measures any of this. There is no number for how often plan mode changes the outcome, how much a saved prompt saves, or whether the interview produces a better spec than writing one yourself; the DCAS abstract is the only quantitative claim here, and it is about training scaffolds, not about you typing /plan. The Codex CLI commands page was long enough that the fetch cut off before its /plan row, so Codex's plan mode above rests on the prompting page and the app reference, and I found no statement that Codex blocks edits in that mode. Keyword tricks for extended thinking are not on any page I read today, so they are not in this article. Gemini CLI's skills page did not show a frontmatter table; I applied the Agent Skills specification it says it follows. The script validates syntax, not whether a skill is any good, and it never ran inside a harness in this session.

What I can say is narrower and checkable: on 2026-09-10 the three harnesses ship a plan mode with a keyboard shortcut, two of them ship an editor hook for the plan file, all three read the same SKILL.md layout from an .agents/skills or equivalent directory, and one of them has already deprecated its older prompt-file format in favor of it. The saved prompt in the code/ box is the one I would start from.

Code and data

Sources

  1. Anthropic, "Best practices for Claude Code" (Claude Code docs, read 2026-09-10)
  2. Anthropic, "Choose a permission mode" (Claude Code docs, read 2026-09-10)
  3. Anthropic, "Skills" (Claude Code docs, read 2026-09-10)
  4. Anthropic, "Slash commands" (Claude Code docs, read 2026-09-10)
  5. Anthropic, "Common workflows" (Claude Code docs, read 2026-09-10)
  6. OpenAI, "Prompting" (Codex docs, read 2026-09-10)
  7. OpenAI, "Slash commands" (Codex app reference, read 2026-09-10)
  8. OpenAI, "Commands" (Codex CLI reference, read 2026-09-10)
  9. OpenAI, "Build skills" (Codex docs, read 2026-09-10)
  10. OpenAI, "Custom prompts" (Codex docs, marked deprecated in favor of skills, read 2026-09-10)
  11. Google, "Plan Mode" (Gemini CLI docs, read 2026-09-10)
  12. Google, "Custom commands" (Gemini CLI docs, read 2026-09-10)
  13. Google, "Agent Skills" (Gemini CLI docs, read 2026-09-10)
  14. Google, "Commands" (Gemini CLI docs, read 2026-09-10)
  15. Agent Skills, "Specification" (read 2026-09-10)
  16. Thangarajah, Chen, and Hassan, "DCAS: Decoupling CLI Agent Scaffolding to Internalize Planning across Scaffolds" (arXiv:2608.06113, read 2026-09-10)
  17. anthropics/claude-code, "Release v2.1.267" (read 2026-09-10)
  18. openai/codex, "Release rust-v0.154.0" (read 2026-09-10)
  19. google-gemini/gemini-cli, "Release v0.59.0" (read 2026-09-10)