2026-05-03-allow-flag-cli-implementation-plan.md
–allow Flag CLI Support Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Add --allow <dir> flag support to jail.sh and vibe.sh to enable whitelisting additional directories with read/write access in the firejail sandbox.
Architecture: Parse --allow flags using bash’s getopts before processing commands, collect directories into an array, then add --whitelist and --read-write entries to firejail arguments for each directory.
Tech Stack: bash, firejail
Task 1: Modify jail.sh to support –allow flag
Files:
- Modify: /home/btburke/projects/vibe/jail.sh
Context: The script currently takes all arguments as the command to run ($@). We need to parse --allow flags first, then treat remaining args as the command.
- [ ] Step 1: Add argument parsing before existing logic
After line 10 (set -euo pipefail) and before line 12 (the firejail check comment), add:
# Parse --allow flags to add extra whitelisted directories
ALLOWED_DIRS=()
while [[ $# -gt 0 ]]; do
case "$1" in
--allow)
if [[ $# -lt 2 ]]; then
echo "Error: --allow requires a directory argument" >&2
exit 1
fi
ALLOWED_DIRS+=("$2")
shift 2
;;
--)
shift
break
;;
-*)
echo "Error: Unknown flag: $1" >&2
echo "Usage: jail [--allow <dir>]... <command> [args...]" >&2
exit 1
;;
*)
break
;;
esac
done
# Check that a command was provided
if [[ $# -eq 0 ]]; then
echo "Error: No command specified" >&2
echo "Usage: jail [--allow <dir>]... <command> [args...]" >&2
exit 1
fi
- [ ] Step 2: Add allowed directories to FIREJAIL_ARGS
After the FIREJAIL_ARGS array is fully built (around line 131, before the blacklist comment), add:
# Add user-specified allowed directories
for dir in "${ALLOWED_DIRS[@]}"; do
FIREJAIL_ARGS+=(--whitelist="$dir")
FIREJAIL_ARGS+=(--read-write="$dir")
done
Place this right before the “Blacklist specific tools” comment (around line 133).
- [ ] Step 3: Commit the changes
jj commit -m "feat(jail): add --allow flag for additional directory whitelisting" jail.sh
Task 2: Modify vibe.sh to support –allow flag and pass through to jail
Files:
- Modify: /home/btburke/projects/vibe/vibe.sh
Context: The script currently has specific handling for session tokens. We need to parse --allow flags first, collect them, then pass them to jail.sh along with the appropriate opencode arguments.
- [ ] Step 1: Replace the argument handling section
Replace lines 33-50 (everything from “Handle different argument patterns” comment to the fi) with:
# Parse --allow flags and handle session token
ALLOWED_DIRS=()
SESSION_TOKEN=""
while [[ $# -gt 0 ]]; do
case "$1" in
--allow)
if [[ $# -lt 2 ]]; then
echo "Error: --allow requires a directory argument" >&2
exit 1
fi
ALLOWED_DIRS+=("$2")
shift 2
;;
-s)
if [[ $# -lt 2 ]]; then
echo "Error: -s requires a token argument" >&2
exit 1
fi
SESSION_TOKEN="$2"
shift 2
;;
-*)
echo "Error: Unknown flag: $1" >&2
echo "Usage: vibe [--allow <dir>]... [<session_token>]" >&2
exit 1
;;
*)
if [[ -z "$SESSION_TOKEN" ]]; then
SESSION_TOKEN="$1"
shift
else
echo "Error: Unexpected argument: $1" >&2
echo "Usage: vibe [--allow <dir>]... [<session_token>]" >&2
exit 1
fi
;;
esac
done
# Build jail command with allowed directories
JAIL_ARGS=()
for dir in "${ALLOWED_DIRS[@]}"; do
JAIL_ARGS+=(--allow "$dir")
done
# Execute with or without session token
if [[ -n "$SESSION_TOKEN" ]]; then
exec jail "${JAIL_ARGS[@]}" opencode -s "$SESSION_TOKEN"
else
exec jail "${JAIL_ARGS[@]}" opencode
fi
- [ ] Step 2: Commit the changes
jj commit -m "feat(vibe): add --allow flag support and pass through to jail" vibe.sh
Task 3: Test the implementation
Files: - Test manually with bash commands
- [ ] Step 1: Test jail.sh with –allow flag
Run:
./jail.sh --allow /tmp bash -c "touch /tmp/test_jail_allow && echo 'Success: can write to /tmp' && rm /tmp/test_jail_allow"
Expected: Command succeeds and prints “Success: can write to /tmp”
- [ ] Step 2: Test jail.sh with multiple –allow flags
Run:
./jail.sh --allow /tmp --allow /var/tmp bash -c "touch /tmp/test1 /var/tmp/test2 && echo 'Success' && rm /tmp/test1 /var/tmp/test2"
Expected: Command succeeds and prints “Success”
- [ ] Step 3: Test jail.sh without –allow (backward compatibility)
Run:
./jail.sh bash -c "echo 'Hello from jail'"
Expected: Command succeeds and prints “Hello from jail”
- [ ] Step 4: Test jail.sh error handling
Run:
./jail.sh --allow 2>&1 | head -1
Expected: Error message about missing directory argument
Run:
./jail.sh 2>&1 | head -1
Expected: Error message about missing command
- [ ] Step 5: Test vibe.sh with –allow flag
Run (this will fail to start opencode without proper setup, but should show jail is called correctly):
./vibe.sh --allow /tmp 2>&1 | head -5
Expected: Should see “Starting in firejail sandbox…” message (or firejail error if opencode not in PATH)
- [ ] Step 6: Commit test verification
jj commit -m "test: verify --allow flag implementation works correctly"
Task 4: Final review and squash if needed
- [ ] Step 1: Review all changes
jj log -r '::@' -p
- [ ] Step 2: If multiple commits, consider squashing into one feature commit
jj squash -r @-- -r @
Or keep separate commits if preferred.
Implementation Notes
Why not use getopts?
getopts doesn’t support long options like --allow in a clean way without using GNU getopt. The manual case statement approach is more portable and clearer for this simple use case.
Argument parsing strategy
Both scripts use a while loop with a case statement to:
1. Collect all --allow <dir> pairs into an array
2. Handle vibe.sh’s -s <token> or positional token
3. Stop at first non-flag argument (for jail.sh, this is the command)
4. Validate that required arguments are present
Firejail integration
The allowed directories are added to FIREJAIL_ARGS as:
- --whitelist=<dir> - Makes the directory visible in the sandbox
- --read-write=<dir> - Grants read/write permissions
These are added after the default whitelist but before the blacklist, which is the correct order for firejail’s rule processing.