Script Reference

Tofie Script Reference #

Complete reference for all Tofie automation scripts.

Overview #

All Tofie scripts are located in: tools/local/scripts/tofie/

Script Variants:

  • Standard scripts: Direct Claude CLI invocation (faster)
  • Subagent scripts: Launch isolated Claude subagents (thorough)

Common Script Patterns #

All Tofie scripts follow this structure:

Input/Output Format #

Input: JSON via stdin Output: JSON via stdout Logs: stderr (for debugging)

Exit Codes #

Code Meaning
0 Success
1 Dependency missing (jq, claude CLI)
2 Invalid input (missing required fields)
3 Worktree creation failed
4 Metadata creation failed
5 Claude CLI execution failed

Common Functions #

All scripts include:

log_info()    # Log informational messages (stderr)
log_error()   # Log error messages (stderr)
output_json() # Output structured JSON result (stdout)

planning.sh #

Purpose: Create implementation plan using Context Engineering framework

When to use: Standard planning for well-defined issues

Execution time: 2-5 minutes

Input Schema #

{
  "branchName": "string (required)",
  "issueIdentifier": "string (required)",
  "agentSessionId": "string (optional)",
  "project": {
    "id": "string",
    "name": "string",
    "key": "string"
  },
  "issue": {
    "id": "string",
    "identifier": "string",
    "title": "string (required)",
    "description": "string",
    "comments": []
  }
}

Output Schema #

{
  "success": boolean,
  "message": "string",
  "worktreePath": "string",
  "planPath": "string",
  "linearMetadataPath": "string",
  "n8nMetadataPath": "string",
  "claudeOutput": "string",
  "timestamp": "ISO 8601 timestamp"
}

Workflow #

  1. Validate JSON input
  2. Create/reuse git worktree from main
  3. Create .plans/ directory
  4. Write linear-metadata.json and n8n-metadata.json
  5. Execute Claude CLI with /tofie-plan slash command
  6. Validate PLAN.md was created
  7. Return JSON result

Claude CLI Invocation #

claude \
  --print \
  --output-format text \
  --model sonnet \
  --permission-mode acceptEdits \
  "$CLAUDE_PROMPT"

Example Usage #

echo '{
  "branchName": "john/eng-1144-feat-filtering",
  "issueIdentifier": "ENG-1144",
  "issue": {
    "title": "Add date range filtering",
    "description": "Users need filtering..."
  }
}' | ./planning.sh

planning-subagent.sh #

Purpose: Create comprehensive plan using isolated Claude subagent

When to use: Complex issues requiring deep research

Execution time: 5-15 minutes

Input Schema #

Same as planning.sh plus:

{
  "thoroughness": "quick|medium|very thorough (optional, default: medium)"
}

Key Differences from planning.sh #

  1. Prompt: Asks Claude to use “tofie-planner SUBAGENT”
  2. Permission mode: --dangerously-skip-permissions
  3. Collapsible sections: Instructions embedded in prompt (not slash command)
  4. Research depth: Subagent does more thorough codebase analysis

Claude CLI Invocation #

claude \
  --print \
  --output-format text \
  --model sonnet \
  --dangerously-skip-permissions \
  "$CLAUDE_PROMPT"

When to Use #

  • ✅ Multiple approach exploration needed
  • ✅ Long-running research without blocking
  • ✅ Isolated planning context required
  • ❌ Quick, straightforward planning (use planning.sh)

implement.sh #

Purpose: Execute implementation plan with code changes

When to use: Standard implementation following a plan

Execution time: 5-15 minutes

Input Schema #

{
  "branchName": "string (required)",
  "issueIdentifier": "string (required)",
  "skipTests": boolean (optional, default: false),
  "skipCodegen": boolean (optional, default: false),
  "enableReview": boolean (optional, default: false),
  "createPR": boolean (optional, default: false)
}

Output Schema #

{
  "success": boolean,
  "message": "string",
  "worktreePath": "string",
  "planPath": "string",
  "prUrl": "string (if createPR: true)",
  "prNumber": number (if createPR: true),
  "reviewStatus": "not_requested|in_progress|completed",
  "claudeOutput": "string",
  "timestamp": "ISO 8601 timestamp"
}

Workflow #

  1. Find existing worktree from planning stage
  2. Read .plans/PLAN.md and .plans/linear-metadata.json
  3. Execute Claude CLI with /tofie-implement slash command
  4. Claude implements changes phase by phase
  5. Run quality checks (mise fix && mise ci)
  6. Create conventional commits
  7. Optionally create PR via submit-pr.sh
  8. Return JSON result

Quality Checks #

Always runs:

  • mise fix: Format code
  • mise ci: Lint, type-check, tests, build

Conditional:

  • mise codegen: If skipCodegen: false and API changes detected
  • E2E tests: If skipTests: false and E2E tests exist

Example Usage #

echo '{
  "branchName": "john/eng-1144-feat-filtering",
  "issueIdentifier": "ENG-1144",
  "createPR": true
}' | ./implement.sh

implement-subagent.sh #

Purpose: Execute implementation using isolated Claude subagent

When to use: Parallel orchestration, experimental implementation, background execution

Execution time: 10-30 minutes

Input Schema #

Same as implement.sh

Key Differences from implement.sh #

  1. Prompt: Asks Claude to use “tofie-coder SUBAGENT”
  2. Permission mode: --dangerously-skip-permissions
  3. Parallel review: Can spawn tofie-reviewer subagent simultaneously
  4. Checkpointing: Better for long-running implementations

When to Use #

  • ✅ Implement + review in parallel
  • ✅ Experimental approach exploration
  • ✅ Background execution with checkpoints
  • ❌ Quick, straightforward implementation (use implement.sh)

adjust.sh #

Purpose: Make targeted adjustments based on review feedback

When to use: Fix issues after code review or QA

Execution time: 2-10 minutes

Input Schema #

{
  "branchName": "string (required)",
  "issueIdentifier": "string (required)",
  "scope": "string (optional, e.g., 'fix tests', 'update types')",
  "files": "string (optional, glob pattern like 'src/**/*.ts')",
  "dryRun": boolean (optional, default: false)
}

Output Schema #

Same as implement.sh

Workflow #

  1. Find existing worktree
  2. Read review feedback from Linear or .plans/review-notes.md
  3. Execute Claude CLI with /tofie-adjust slash command
  4. Claude makes targeted fixes
  5. Run quality checks
  6. Create commit if dryRun: false
  7. Return JSON result

Example Usage #

echo '{
  "branchName": "john/eng-1144-feat-filtering",
  "issueIdentifier": "ENG-1144",
  "scope": "fix timezone handling in tests"
}' | ./adjust.sh

adjust-subagent.sh #

Purpose: Make adjustments using isolated Claude subagent

When to use: Complex refactoring or large-scale adjustments

Execution time: 5-20 minutes

Key Differences from adjust.sh #

  1. Permission mode: --dangerously-skip-permissions
  2. Scope: Can handle broader refactoring
  3. Isolation: Changes don’t affect main conversation context

submit-pr.sh #

Purpose: Create GitHub pull request with proper formatting

When to use: Standalone PR creation or after implementation

Execution time: 1-2 minutes

Input Schema #

{
  "branchName": "string (required)"
}

Output Schema #

{
  "success": boolean,
  "alreadyExists": boolean,
  "prNumber": number,
  "prUrl": "string",
  "prTitle": "string",
  "prState": "string (if alreadyExists: true)"
}

Workflow #

  1. Check if PR already exists for branch (gh pr list)
  2. If exists: Return existing PR info (no duplicate)
  3. If not exists:
    • Find branch location (worktree or main repo)
    • Read .plans/PLAN.md for context
    • Read .plans/linear-metadata.json for issue info
    • Execute Claude CLI with submit-github-pr skill
    • Claude generates PR title and description
    • Create draft PR (gh pr create --draft)
    • Store PR info in .plans/pr-info.json
  4. Return JSON result

PR Format #

Title: Conventional commit format

feat(webapp): add date range filtering to invoice list

Description: Structured markdown

## Summary
[Brief description]

Closes: https://linear.app/bonsai/issue/ENG-1144

## Changes
- [Bullet points]

## Testing
- [x] Test checklist

## Risks
- [Risk assessment]

---
🤖 Generated with Claude Code - Tofie

IMPORTANT: Always Creates Drafts #

All PRs are created as drafts (--draft flag) to ensure human review before marking ready.

Example Usage #

echo '{
  "branchName": "john/eng-1144-feat-filtering"
}' | ./submit-pr.sh


cleanup.sh #

Purpose: Clean up worktree and branch after PR is merged

When to use: After PR is merged to remove worktree and local branch

Execution time: < 10 seconds

Input Schema #

{
  "branchName": "string (required)"
}

Output Schema #

{
  "success": boolean,
  "message": "string",
  "worktreeRemoved": boolean,
  "worktreePath": "string",
  "branchDeleted": boolean,
  "branchName": "string",
  "timestamp": "ISO 8601 timestamp"
}

Workflow #

  1. Validate JSON input
  2. Find worktree for the branch (git worktree list)
  3. If worktree exists:
    • Remove worktree (git worktree remove)
    • Force remove if needed (--force)
    • Manual cleanup if git command fails
  4. Delete local branch (git branch -D)
  5. Optionally delete remote branch (if DELETE_REMOTE=true)
  6. Prune worktree metadata
  7. Return JSON result

Cleanup Strategies #

Standard removal:

git worktree remove /path/to/worktree

Force removal (if files modified):

git worktree remove --force /path/to/worktree

Manual cleanup (last resort):

rm -rf /path/to/worktree
git worktree prune

Environment Variables #

DELETE_REMOTE: Set to true to also delete remote branch

DELETE_REMOTE=true echo '{"branchName": "..."}' | ./cleanup.sh

Example Usage #

Basic cleanup:

echo '{
  "branchName": "john/eng-1144-feat-filtering"
}' | ./cleanup.sh

Output:

{
  "success": true,
  "message": "Cleanup completed successfully",
  "worktreeRemoved": true,
  "worktreePath": "/home/coder/trees/john-eng-1144",
  "branchDeleted": true,
  "branchName": "john/eng-1144-feat-filtering",
  "timestamp": "2025-11-03T12:00:00Z"
}

With remote branch deletion:

DELETE_REMOTE=true echo '{
  "branchName": "john/eng-1144-feat-filtering"
}' | ./cleanup.sh

Common Scenarios #

Worktree not found (already removed):

{
  "success": true,
  "message": "Branch deleted (worktree not found)",
  "worktreeRemoved": false,
  "worktreePath": "",
  "branchDeleted": true,
  "branchName": "john/eng-1144-feat-filtering"
}

Branch already deleted:

{
  "success": true,
  "message": "Worktree removed (branch not found)",
  "worktreeRemoved": true,
  "worktreePath": "/home/coder/trees/john-eng-1144",
  "branchDeleted": true,
  "branchName": "john/eng-1144-feat-filtering"
}

Integration with n8n #

Can be triggered automatically after PR merge:

  1. GitHub webhook: PR merged event
  2. n8n workflow: Extract branch name from PR
  3. Execute cleanup.sh: Remove worktree and branch
  4. Update Linear: Comment “Cleanup complete”

Manual Usage #

# List all worktrees
git worktree list

# Clean up specific branch
echo '{"branchName": "john/eng-1144"}' | ./cleanup.sh

# Check result
echo $?  # Should be 0 for success

Script Comparison Matrix #

Feature planning.sh planning-subagent.sh implement.sh implement-subagent.sh adjust.sh adjust-subagent.sh submit-pr.sh cleanup.sh
Speed Fast (2-5min) Slow (5-15min) Medium (5-15min) Slow (10-30min) Fast (2-10min) Medium (5-20min) Fast (1-2min) Very Fast (<10s)
Permission Mode acceptEdits skip-permissions acceptEdits skip-permissions acceptEdits skip-permissions skip-permissions N/A
Uses Slash Command Yes (/tofie-plan) No (custom prompt) Yes (/tofie-implement) No (custom prompt) Yes (/tofie-adjust) No (custom prompt) No (uses skill) No
Parallel Execution No No No Yes (with reviewer) No No No No
Requires Worktree No (creates it) No (creates it) Yes Yes Yes Yes Yes (or finds branch) Yes (removes it)
Creates PR No No Optional Optional No No Always (if not exists) No
Quality Checks No No Yes Yes Yes Yes No No

Debugging Scripts #

Enable Debug Mode #

DEBUG=1 ./planning.sh < input.json

Debug output includes:

  • Parsed input values
  • File path checks
  • Claude CLI prompts
  • Command outputs

Test Script Locally #

# Create test input
cat > /tmp/test-input.json <<EOF
{
  "branchName": "test/debug-plan",
  "issueIdentifier": "ENG-TEST",
  "issue": {
    "title": "Test planning script"
  }
}
EOF

# Run script
cat /tmp/test-input.json | ./planning.sh

# Check output
echo $?  # Exit code

Common Issues #

“claude CLI not found”

# Check Claude CLI installation
which claude
ls -la /home/$USER/.local/bin/claude

# Verify it's executable
chmod +x /home/$USER/.local/bin/claude

“Invalid JSON input”

# Validate JSON before piping
cat input.json | jq empty
# If this fails, fix JSON syntax

“Failed to create worktree”

# Check if branch already exists
git branch -a | grep "john/eng-1144"

# Remove existing branch if needed
git branch -D john/eng-1144

# Remove existing worktree
git worktree remove /home/coder/trees/john-eng-1144

Script Maintenance #

Adding New Scripts #

  1. Copy template from existing script
  2. Update input/output schemas
  3. Implement main logic
  4. Add to this documentation
  5. Update n8n workflow router

Testing Changes #

# Test with real Linear data
echo "$LINEAR_WEBHOOK_PAYLOAD" | \
  jq '{branchName, issueIdentifier, project, issue}' | \
  ./planning.sh

# Verify output
echo $?  # Should be 0

Version Control #

All scripts are version controlled in the main repository:

git log --follow tools/local/scripts/tofie/planning.sh