Skip to content
Sessions & Workflows Advanced

Plan → Review → Execute

Three-phase workflow: generate a plan, review it, then execute with full permissions

Command

"color:#9CA3AF;font-style:italic"># 1. Plan
$ PLAN=$("color:#7C5CFC">claude -p "Plan refactoring of auth.py" "color:#d97757">--permission-mode plan "color:#d97757">--output-format json)
  SESSION=$("color:#7C5CFC">echo "$PLAN" | "color:#7C5CFC">jq -r '.session_id')
  
"color:#9CA3AF;font-style:italic"># 2. Extract plan text
$ "color:#7C5CFC">echo "$PLAN" | "color:#7C5CFC">jq -r '.permission_denials[] | select(.tool_name=="ExitPlanMode") | .tool_input.plan'
  
"color:#9CA3AF;font-style:italic"># 3. Execute
$ "color:#7C5CFC">claude -p "yes, proceed" "color:#d97757">--resume "$SESSION" "color:#d97757">--permission-mode bypassPermissions

Response

{
  "session_id": "9d6158a8-...",
  "permission_denials": [
    {
      "tool_name": "ExitPlanMode",
      "tool_input": { "plan": "# Plan\n## Step 1: ..." }
    },
    {
      "tool_name": "Write",
      "tool_input": { "file_path": "auth.py", "content": "..." }
    }
  ]
}

Parsing Code

059669">">const plan = data.permission_denials
  .find(d => d.tool_name === 059669059669">">'ExitPlanMode')
  ?.tool_input.plan;

059669">">const pendingWrites = data.permission_denials
  .filter(d => d.tool_name === 059669">'Write')
  .map(d => ({ path: d.tool_input.file_path }));

Gotchas

! Plan text lives in permission_denials[].tool_input.plan where tool_name == 'ExitPlanMode'
! Opus may use AskUserQuestion instead of ExitPlanMode — check for both

Related Recipes