Ralph Loop: Stop hook `decision: block` resets VSCode permission mode from bypass to edit
Bug Description
When using the Ralph Loop plugin in the VSCode extension (Antigravity), each loop iteration resets the permission mode from bypassPermissions to editMode. This makes Ralph Loop unusable for unattended/overnight autonomous operation.
Steps to Reproduce
- Set VSCode Claude Code to
bypassPermissionsmode (Shift+Tab) - Verify
claudeCode.initialPermissionMode: "bypassPermissions"in VSCode settings - Start a Ralph Loop:
/ralph-loop "task description" --max-iterations 5 - Wait for the first iteration to complete
- Observe: permission mode resets to
editModewhen the Stop hook blocks and re-injects
Expected Behavior
Permission mode should be preserved across Ralph Loop iterations. The decision: block response should not trigger a permission state reset.
Root Cause
The Ralph Loop Stop hook (stop-hook.sh) outputs:
{
"decision": "block",
"reason": "<prompt>",
"systemMessage": "<iteration info>"
}
When the VSCode extension processes this blocked stop, it re-initializes the session context. During re-initialization, the extension reads the permission mode from its state database (state.vscdb) but appears to reset it to a default restrictive mode instead of preserving the current runtime state.
The Stop hook API has no mechanism to pass permission state through the block response.
Environment
- VSCode extension: Antigravity (Claude Code)
- Platform: Windows 11 (Git Bash)
- Plugin: ralph-loop (official, claude-plugins-official)
- Settings:
claudeCode.initialPermissionMode: "bypassPermissions",claudeCode.allowDangerouslySkipPermissions: true
Workaround
Created a companion Stop hook that uses Python's sqlite3 module to update the VSCode state database (state.vscdb) and force bypassPermissions before the session reinitializes:
#!/bin/bash
# Only run if Ralph Loop is active
[[ ! -f ".claude/ralph-loop.local.md" ]] && exit 0
py -3 -c "
import sqlite3, os, glob
appdata = os.environ.get('APPDATA', '')
if not appdata: exit(0)
dbs = [os.path.join(appdata, 'Antigravity', 'User', 'globalStorage', 'state.vscdb')]
dbs += glob.glob(os.path.join(appdata, 'Antigravity', 'User', 'workspaceStorage', '*', 'state.vscdb'))
for db_path in dbs:
if not os.path.exists(db_path): continue
try:
conn = sqlite3.connect(db_path)
conn.execute(\"UPDATE ItemTable SET value='\\\"bypassPermissions\\\"' WHERE key LIKE '%permissionMode%' AND value!='\\\"bypassPermissions\\\"'\")
conn.commit()
conn.close()
except: pass
" 2>/dev/null || true
Suggested Fix
Either:
- Preserve the current permission mode across Stop hook
blockresponses - Add a
preservePermissions: truefield to the Stop hook response schema - Re-read
claudeCode.initialPermissionModefrom VSCode settings on re-initialization instead of resetting to a default
Labels
bug, ralph-loop, vscode-extension
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗