
Permissions Manager
- 5 installs
- 4 repo stars
- Updated December 29, 2025
- spillwavesolutions/claude_permissions_skill
Helps with ai & agent building tasks during AI-assisted development.
About
permissions-manager is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- permissions-manager
- AI & Agent Building
- AI-coding skill
Permissions Manager by the numbers
- 5 all-time installs (skills.sh)
- Ranked #13,065 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/spillwavesolutions/claude_permissions_skill --skill permissions-managerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 5 |
|---|---|
| repo stars | ★ 4 |
| Last updated | December 29, 2025 |
| Repository | spillwavesolutions/claude_permissions_skill ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Permissions Manager
Table of Contents
- Quick Reference
- Intent Classification Decision Tree
- Core Detection Logic
- Resource Loading Policy
- Safety Rules
- Token Budget Management
- Error Handling
- Skill Integration Points
- Success Criteria Checklist
- Quick Start Examples
---
Quick Reference
Purpose: Auto-configure Claude Code permissions via natural language Token Budget: T1(100) + T2(2,500) + T3(1,500-3,000 per workflow) Architecture: Progressive Disclosure (3-tier) - Load only what's needed
---
Intent Classification Decision Tree
Step 1: Detect Request Type
Parse user message for patterns:
CLI Tool Request - Indicators:
- Keywords: "enable", "allow", "configure" + tool name
- Tool names: git, gcloud, aws, kubectl, docker, npm, pip, maven, gradle, cargo, helm, terraform, pulumi, ansible
- Modes: "read", "write", "read-only", "commits", "pushes"
- Route to:
guides/workflows/cli-tool-workflow.md
File Pattern Request - Indicators:
- Keywords: "make editable", "edit", "write" + file type/pattern
- Patterns: "**.md", "TypeScript files", "src/", "docs folder"
- Route to:
guides/workflows/file-pattern-workflow.md
Project Type Request - Indicators:
- Keywords: "this is a [language] project", "setup", "project"
- Languages: Rust, Java, TypeScript, Python, Go, Ruby, PHP, C#, C++, Swift
- Route to:
guides/workflows/project-setup-workflow.md
Profile Request - Indicators:
- Keywords: "apply profile", "use profile" + profile name
- Profiles: read-only, development, ci-cd, production, documentation, code-review, testing
- Route to:
guides/workflows/profile-application-workflow.md
Validation/Troubleshooting - Indicators:
- Keywords: "validate", "check", "troubleshoot", "not working"
- Route to:
guides/workflows/validation-workflow.md
Backup/Restore - Indicators:
- Keywords: "backup", "restore", "rollback", "undo"
- Route to:
guides/workflows/backup-restore-workflow.md
Step 2: Load Appropriate Workflow
CRITICAL: Load ONLY the workflow guide needed. Do NOT load multiple guides.
| Request Type | Workflow File | Token Cost |
|---|---|---|
| CLI Tool | guides/workflows/cli-tool-workflow.md | +1,500 |
| File Pattern | guides/workflows/file-pattern-workflow.md | +1,200 |
| Project Type | guides/workflows/project-setup-workflow.md | +1,800 |
| Profile | guides/workflows/profile-application-workflow.md | +1,000 |
| Validation | guides/workflows/validation-workflow.md | +1,200 |
| Backup/Restore | guides/workflows/backup-restore-workflow.md | +750 |
| Unknown Tool | guides/workflows/research-workflow.md | +2,000 |
---
Core Detection Logic
CLI Tool Recognition
Known Tools (check against references/cli_commands.json):
- Version Control: git
- Cloud: gcloud, aws, az
- Containers: docker, kubectl, helm
- Build: npm, pip, maven, gradle, cargo, go, yarn, bundle, composer
- Infrastructure: terraform, pulumi, ansible
Mode Detection:
- Contains "read", "list", "show", "describe" -> READ mode (safer default)
- Contains "write", "push", "commit", "deploy", "publish" -> WRITE mode
- No mode -> Default to READ
Tool Lookup: 1. Check if tool in references/cli_commands.json (use grep) 2. If found -> Extract commands for detected mode 3. If NOT found -> Route to research workflow
Project Type Detection
Auto-Detection (via file scanning):
Cargo.toml -> Rust
pom.xml -> Java Maven
build.gradle* -> Java Gradle
package.json + tsconfig.json -> TypeScript
package.json (alone) -> JavaScript
pyproject.toml | setup.py -> Python
go.mod -> Go
Gemfile -> Ruby
composer.json -> PHP
*.csproj | *.sln -> C#
CMakeLists.txt -> C++
Package.swift -> SwiftDetection Method: Run scripts/detect_project.py or scan for indicator files
Profile Recognition
Available Profiles (from assets/permission_profiles.json):
read-only- Code review, security auditdevelopment- Active development (most common)ci-cd- Continuous integrationproduction- Monitoring onlydocumentation- Docs writingcode-review- PR reviewtesting- TDD workflow
---
Resource Loading Policy - CRITICAL
NEVER load resources proactively or "just in case"
Loading Workflow Guides
DO: Load specific workflow when decision tree routes to it
Read guides/workflows/{workflow-name}.mdDON'T: Load all guides upfront or multiple guides
Loading Reference Data - Surgical Only
CLI Commands (one tool only):
grep -A 25 '"git"' references/cli_commands.json
# Token cost: ~150 tokens (vs 2,650 for full file)Project Templates (one language only):
jq '.rust' references/project_templates.json
# Token cost: ~200 tokens (vs 1,955 for full file)Security Patterns (one level only):
jq '.recommended_deny_set.standard' references/security_patterns.json
# Token cost: ~100 tokens (vs 805 for full file)Permission Profiles (one profile only):
jq '.development' assets/permission_profiles.json
# Token cost: ~200 tokens (vs 1,240 for full file)Executing Scripts
ONLY execute when workflow instructs:
- detect_project.py - When project type ambiguous or need recommendations
- apply_permissions.py - When all rules gathered, handles backup/validation/writing
- validate_config.py - When user requests validation or troubleshooting
---
Safety Rules - Always Apply
Every permission operation MUST:
1. Load security patterns: jq '.recommended_deny_set.standard' references/security_patterns.json 2. Apply minimum deny rules: See references/security_patterns.json#recommended_deny_set.standard for full list (14 rules) 3. Create backup before any settings write (automatic via scripts/apply_permissions.py) 4. Validate syntax before applying (automatic via scripts/apply_permissions.py)
---
Token Budget Management
Budget Tiers:
- Simple request (CLI tool): <5,000 tokens
- Medium request (project setup): <7,000 tokens
- Complex request (unknown tool): <10,000 tokens
- Warning threshold: >10,000 tokens
Cost Optimization:
- Use grep/jq for references (90% token savings)
- Load only needed workflow guide
- Execute scripts instead of explaining them
- Avoid loading examples unless requested
See references/token_tracking_template.md for tracking template.
---
Error Handling
If workflow guide not found:
- Proceed with best-effort inline logic
- Inform user of missing guide
- Suggest filing an issue
If reference file not found:
- Attempt operation without reference
- For unknown tools -> use web search
- Warn user about limited functionality
If script execution fails:
- Show error message to user
- Suggest manual permission editing
- Provide settings file location
If validation fails:
- Report specific errors
- Suggest fixes
- Offer to restore from backup
---
Skill Integration Points
Other Skills (invoke when appropriate):
- gemini skill: If user mentions "gemini CLI" and skill available
MCP Tools (priority order for research): 1. mcp__perplexity-ask__perplexity_ask (preferred) 2. mcp__brave-search__brave_web_search (fallback) 3. WebSearch (final fallback)
---
Success Criteria Checklist
Permission operation complete when:
- Backup created (timestamped)
- Permissions validated (syntax + conflicts)
- Safety rules applied (deny patterns)
- Settings written successfully
- User informed of changes
- Restart reminder provided
---
Quick Start Examples
| Request | Route |
|---|---|
| Enable git (read-only) | cli-tool-workflow.md |
| Make markdown editable | file-pattern-workflow.md |
| Setup TypeScript project | project-setup-workflow.md |
| Apply development profile | profile-application-workflow.md |
See guides/workflows/ for complete workflow documentation.
---
Workflow Pattern
Every request follows this pattern:
1. Classify intent using decision tree 2. Route to workflow based on detection 3. Load workflow guide from guides/workflows/ 4. Follow workflow step-by-step 5. Load references surgically as needed 6. Execute scripts when required 7. Track token budget throughout 8. Complete operation per success criteria 9. Inform user of changes
Remember: Load only needed workflow, use grep/jq for references, execute scripts for heavy lifting, apply safety rules always.
---
End of Tier 2 (SKILL.md)
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Virtual environments
venv/
ENV/
env/
.venv
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
# Testing
.pytest_cache/
.coverage
htmlcov/
.tox/
# Local configuration
*.local.json
.env
.env.*
# Backups (from skill operation)
*.backup
# Distribution
*.zip
# Logs
*.log
# Temporary files
*.tmp
*.temp
{
"_meta": {
"description": "Pre-built permission profiles for common use cases",
"version": "1.0.0",
"usage": "Apply with: claude-permissions --profile <name>"
},
"read-only": {
"description": "Minimal permissions for read-only analysis and exploration",
"allowedTools": [
"Read"
],
"deny": [
"Write",
"Edit",
"Bash",
"WebFetch",
"WebSearch"
],
"use_cases": [
"Code review",
"Security audit",
"Learning from existing code",
"Documentation review"
]
},
"development": {
"description": "Full development permissions with safety guards",
"allowedTools": [
"Read",
"Write(src/**)",
"Write(test/**)",
"Write(tests/**)",
"Write(docs/**)",
"Write(**.md)",
"Edit(src/**)",
"Edit(test/**)",
"Edit(tests/**)",
"Edit(**.md)",
"Bash(git status)",
"Bash(git log)",
"Bash(git diff)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git branch *)",
"Bash(npm install)",
"Bash(npm test)",
"Bash(npm run *)",
"Bash(pip install *)",
"Bash(pip list)",
"Bash(pytest *)",
"Bash(mvn test)",
"Bash(mvn compile)",
"Bash(gradle test)",
"Bash(gradle build)",
"Bash(cargo test)",
"Bash(cargo build)",
"Bash(go test)",
"Bash(go build)"
],
"deny": [
"Read(.env*)",
"Read(*.key)",
"Read(*.pem)",
"Read(.aws/**)",
"Read(.ssh/**)",
"Write(.env*)",
"Write(production.*)",
"Write(.git/**)",
"Bash(rm *)",
"Bash(sudo *)",
"Bash(git push * --force)",
"Bash(npm publish)",
"Bash(mvn deploy)",
"Bash(cargo publish)",
"Bash(terraform destroy *)"
],
"use_cases": [
"Active development",
"Feature implementation",
"Bug fixing",
"Unit testing",
"Local experimentation"
]
},
"ci-cd": {
"description": "Automated CI/CD pipeline permissions",
"allowedTools": [
"Read",
"Bash(git status)",
"Bash(git log)",
"Bash(git diff)",
"Bash(npm ci)",
"Bash(npm test)",
"Bash(npm run build)",
"Bash(pip install -r requirements.txt)",
"Bash(pytest)",
"Bash(mvn clean verify)",
"Bash(mvn test)",
"Bash(gradle clean build)",
"Bash(gradle test)",
"Bash(cargo test)",
"Bash(cargo build --release)",
"Bash(go test ./...)",
"Bash(go build)",
"Bash(docker build *)",
"Bash(docker tag *)"
],
"deny": [
"Write",
"Edit",
"Read(.env*)",
"Read(*.key)",
"Bash(git push *)",
"Bash(npm publish)",
"Bash(docker push *)",
"Bash(mvn deploy)",
"Bash(terraform apply *)",
"Bash(kubectl apply *)"
],
"use_cases": [
"Continuous integration",
"Automated testing",
"Build verification",
"Code quality checks"
]
},
"production": {
"description": "Minimal permissions for production environments",
"allowedTools": [
"Read(logs/**)",
"Read(config/**)",
"Bash(git status)",
"Bash(git log)",
"Bash(docker ps)",
"Bash(docker logs *)",
"Bash(kubectl get *)",
"Bash(kubectl describe *)",
"Bash(kubectl logs *)"
],
"deny": [
"Write",
"Edit",
"Read(.env*)",
"Read(*.key)",
"Read(.aws/**)",
"Bash(git *)",
"Bash(docker *)",
"Bash(kubectl delete *)",
"Bash(kubectl apply *)",
"Bash(npm *)",
"Bash(pip *)",
"Bash(terraform *)"
],
"use_cases": [
"Production monitoring",
"Log analysis",
"Troubleshooting",
"Status checks"
]
},
"documentation": {
"description": "Documentation writing and updating",
"allowedTools": [
"Read",
"Write(docs/**)",
"Write(**.md)",
"Write(**.rst)",
"Edit(docs/**)",
"Edit(**.md)",
"Edit(**.rst)",
"WebFetch",
"WebSearch"
],
"deny": [
"Write(src/**)",
"Write(test/**)",
"Bash(git push *)",
"Bash(npm *)",
"Bash(pip *)",
"Bash(mvn *)"
],
"use_cases": [
"Writing documentation",
"Updating README files",
"Creating guides",
"Documentation maintenance"
]
},
"code-review": {
"description": "Code review and analysis",
"allowedTools": [
"Read",
"Bash(git status)",
"Bash(git log)",
"Bash(git diff *)",
"Bash(git show *)",
"Bash(git blame *)"
],
"deny": [
"Write",
"Edit",
"Read(.env*)",
"Read(*.key)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git push *)",
"Bash(npm *)",
"Bash(pip *)"
],
"use_cases": [
"Pull request review",
"Code quality analysis",
"Security review",
"Architecture review"
]
},
"testing": {
"description": "Testing and quality assurance",
"allowedTools": [
"Read",
"Write(test/**)",
"Write(tests/**)",
"Edit(test/**)",
"Edit(tests/**)",
"Bash(npm test)",
"Bash(npm run test:*)",
"Bash(pytest *)",
"Bash(python -m pytest *)",
"Bash(mvn test)",
"Bash(gradle test)",
"Bash(cargo test)",
"Bash(go test *)"
],
"deny": [
"Write(src/**)",
"Read(.env*)",
"Bash(npm publish)",
"Bash(mvn deploy)",
"Bash(git push *)"
],
"use_cases": [
"Writing tests",
"Running test suites",
"Test-driven development",
"Quality assurance"
]
}
}
Backup and Restore Workflow
Token Budget Tracker
This Workflow:
- Tier 1 (Metadata): 100 tokens ✅ (already loaded)
- Tier 2 (SKILL.md): 2,250 tokens ✅ (already loaded)
- This guide: ~600 tokens
- Script execution: 0 tokens
- Estimated total: 2,950 tokens
- Status: ✅ Within budget (<10,000)
---
Purpose
Manage permission backups and restore previous configurations:
- "show available backups"
- "restore previous permissions"
- "rollback last change"
- "undo profile application"
When triggered: User requests backup/restore OR after catastrophic validation failure
---
Backup System
Automatic backups created by apply_permissions.py:
- Format:
settings.YYYYMMDD_HHMMSS.backup - Location: Same directory as settings.json
- Created: Before every permission modification
- Retention: Unlimited (user manages cleanup)
Example backups:
settings.20250116_153045.backup ← 2 hours ago (development profile)
settings.20250116_120122.backup ← 5 hours ago (added git permissions)
settings.20250115_180934.backup ← Yesterday (project setup)
settings.20250114_163420.backup ← 2 days ago (initial config)---
Workflow Steps
Step 1: List Available Backups
Command:
ls -lt ~/.config/claude-code/settings.*.backup | head -10Example Output:
-rw-r--r-- 1 user staff 4521 Jan 16 15:30 settings.20250116_153045.backup
-rw-r--r-- 1 user staff 3812 Jan 16 12:01 settings.20250116_120122.backup
-rw-r--r-- 1 user staff 2945 Jan 15 18:09 settings.20250115_180934.backup
-rw-r--r-- 1 user staff 1204 Jan 14 16:34 settings.20250114_163420.backupParse and present to user:
## Available Backups
| # | Timestamp | Age | Size | Description |
|---|-----------|-----|------|-------------|
| 1 | 2025-01-16 15:30 | 2 hours ago | 4.5KB | Most recent (development profile) |
| 2 | 2025-01-16 12:01 | 5 hours ago | 3.8KB | Before adding git permissions |
| 3 | 2025-01-15 18:09 | Yesterday | 2.9KB | Project setup (Rust template) |
| 4 | 2025-01-14 16:34 | 2 days ago | 1.2KB | Initial configuration |
**Which backup to restore? (1-4, or 'cancel')**Token Cost: 0 tokens (ls command + formatting)
---
Step 2: User Selects Backup
Parse user response:
- Number (1-4): Restore specific backup
- "cancel" / "none": Exit without restoring
- "latest" / "most recent": Restore #1
- "previous" / "last": Restore #2
If user selects backup #2:
- Backup file:
settings.20250116_120122.backup - Description: "Before adding git permissions"
Token Cost: 0 tokens (user interaction)
---
Step 3: Show Restore Preview
Before restoring, show what will change:
# Compare current settings with selected backup
diff settings.json settings.20250116_120122.backupPresent diff to user:
## Restore Preview
**Restoring**: Backup from 2025-01-16 12:01 (5 hours ago)
**Description**: Before adding git permissions
**Changes** (current → backup):
**Will be REMOVED** (added since backup):
- ✗ Bash(git status *)
- ✗ Bash(git log *)
- ✗ Bash(git diff *)
- ✗ Read(**.rs)
**Will be RESTORED** (removed since backup):
- ✓ Edit(docs/*.md) ← Was removed
- ✓ Bash(cargo test *) ← Was removed
**Net change**: -4 rules (current: 45 → backup: 41)
**Proceed with restore? (yes/no)**Token Cost: 0 tokens (diff command + formatting)
---
Step 4: Confirm Restore
If user says "yes":
- Proceed to Step 5 (execute restore)
If user says "no":
❌ Restore cancelled
Current permissions unchanged.
Options:
- Select different backup (run workflow again)
- View current permissions: `cat settings.json`
- Validate current: see validation-workflow.mdToken Cost: 0 tokens (user interaction)
---
Step 5: Execute Restore
Create safety backup of CURRENT state:
cp settings.json settings.pre-restore-$(date +%Y%m%d_%H%M%S).backupRestore selected backup:
cp settings.20250116_120122.backup settings.jsonValidate restored settings:
python3 scripts/validate_config.pyExpected Output:
✅ Safety backup created: settings.pre-restore-20250116_173045.backup
✅ Restored from: settings.20250116_120122.backup
✅ Validation passed: Restored settings are valid
✅ Settings written to: settings.json
Summary:
Restored from: 2025-01-16 12:01 (5 hours ago)
Total allow rules: 38 (-7 from current)
Total deny rules: 13 (+2 from current)
Validation status: ✅ VALIDIf validation FAILS:
❌ Restored backup failed validation!
Issues found:
- 2 syntax errors
- 1 security vulnerability
**Recommendation**: Restore different backup or revert to pre-restore state
**Revert to pre-restore state? (yes/no)**Token Cost: 0 tokens (script execution)
---
Step 6: Confirm with User
Report Format (successful restore):
✅ **Permissions restored successfully**
**Restored from**: 2025-01-16 12:01 (5 hours ago)
**Description**: Before adding git permissions
**Changes applied**:
- ✗ Removed 7 rules (added since backup)
- ✓ Restored 2 rules (that were removed)
**Current state**:
- Total allow rules: 38
- Total deny rules: 13
- Validation: ✅ PASSED
- Security score: 90/100
**Safety net**: Pre-restore state backed up to:
- `settings.pre-restore-20250116_173045.backup`
- Can undo this restore if needed
**Next step**: Restart Claude Code for restored permissions to take effect.Token Cost: 0 tokens (output to user)
---
Examples
Example 1: Undo Recent Profile Application
User Request: "restore previous permissions" (just applied development profile, too broad)
Workflow Execution: 1. List backups:
1. settings.20250116_170012.backup (5 min ago - development profile)
2. settings.20250116_153045.backup (2 hours ago - custom config)2. User wants to undo development profile → Select #2 3. Show preview:
Will remove: 68 rules from development profile
Will restore: 15 custom rules4. User confirms: "yes" 5. Execute:
- Safety backup current (development profile) → settings.pre-restore-*.backup
- Restore settings.20250116_153045.backup
- Validate: ✅ PASSED
6. Confirm: "Restored custom config. Development profile undone."
Total tokens: 2,950 ✅
---
Example 2: Recover from Validation Failure
User Request: "validation failed, restore backup"
Workflow Execution: 1. Triggered by validation-workflow (too many errors) 2. List backups (most recent 3) 3. Recommend most recent valid backup:
Recommended: #1 (settings.20250116_153045.backup)
Reason: Last known good state4. User accepts recommendation 5. Show preview (current is INVALID, backup is VALID) 6. Execute restore 7. Validate: ✅ PASSED 8. Confirm: "Recovered from validation failure. Settings now valid."
Total tokens: 2,950 ✅
Use case: Emergency recovery
---
Example 3: Rollback Last Change
User Request: "rollback last change"
Workflow Execution: 1. Interpret "last change" as most recent backup 2. Auto-select backup #1 (most recent) 3. Show preview of what will be undone 4. User confirms 5. Execute restore 6. Confirm: "Last change rolled back"
Total tokens: 2,950 ✅
Shortcut: "rollback" = restore most recent backup
---
Example 4: Compare Multiple Backups
User Request: "show me what changed between backups"
Workflow Execution: 1. List backups 2. User says "compare 1 and 3" 3. Run diff:
diff settings.20250116_153045.backup settings.20250115_180934.backup4. Show differences:
Between backup #1 and #3 (yesterday):
- Added 23 rules (git, docker, npm)
- Removed 2 rules (outdated patterns)
- Net: +21 rules5. User can choose to restore either one
Total tokens: 2,950 ✅
Use case: Understanding permission evolution
---
Error Handling
Error 1: No backups found
Detection: ls command returns empty
Action:
❌ **No backups found**
Location checked: ~/.config/claude-code/
Pattern: settings.*.backup
**Possible causes**:
1. First time using skill (no backups created yet)
2. Backups deleted/moved
3. Wrong settings.json location
**Recommendation**:
- Current settings have no backup safety net
- Create manual backup: `cp settings.json settings.manual-$(date +%Y%m%d_%H%M%S).backup`
- Future permission changes will auto-create backupsRecovery: Create manual backup going forward
---
Error 2: Restored backup fails validation
Detection: validate_config.py reports errors after restore
Example:
❌ Restored backup has 5 syntax errorsAction:
❌ **Restored backup is invalid**
Backup: settings.20250115_180934.backup
Errors: 5 syntax errors, 1 security issue
**This backup is corrupted or outdated.**
**Options**:
1. Restore different backup (newer/older)
2. Revert to pre-restore state (undo this restore)
3. Fix validation errors manually
**Which option? (1/2/3)**Recovery: Try different backup or revert
---
Error 3: Backup file corrupted
Detection: Cannot parse backup file as JSON
Action:
❌ **Backup file corrupted**
File: settings.20250115_180934.backup
Error: Invalid JSON (cannot parse)
**This backup cannot be restored.**
**Try**:
- Select different backup
- Or restore from oldest backup (likely valid)
- Or manually reconstruct settings.json
**Select different backup? (yes/no)**Recovery: Skip corrupted backup, try others
---
Error 4: Permission denied (cannot write)
Detection: cp command fails with permission error
Action:
❌ **Cannot restore backup**
Error: Permission denied writing to settings.json
**Cause**: File permissions issue
**Fix**:
1. Check file permissions: `ls -l settings.json`
2. If read-only, make writable: `chmod u+w settings.json`
3. Retry restore
Or: Restore manually with sudo (not recommended)Recovery: Fix file permissions
---
Edge Cases
Edge Case 1: Restore older backup (skip intermediate)
Example: Restore backup #4, skipping #2 and #3
Handling:
- Allow user to select any backup
- Show preview comparing current vs selected (may show large diff)
- Warn if diff is large (>50 rules):
⚠️ Large change detected: 78 rules different
This will undo multiple permission changes.
Are you sure? (yes/no)No restriction: User can restore any backup
---
Edge Case 2: Multiple restores in a row
Example: User restores backup #2, then immediately restores backup #3
Handling:
- Each restore creates pre-restore backup
- User can chain restores indefinitely
- Backup history grows:
settings.pre-restore-20250116_173045.backup ← After 1st restore
settings.pre-restore-20250116_173212.backup ← After 2nd restoreRecommendation: Inform user of growing backups, suggest cleanup
---
Edge Case 3: Restore to settings that require unavailable tools
Example: Backup has Perplexity MCP permissions but MCP not installed
Handling:
- Restore succeeds (settings are syntactically valid)
- Validation may warn: "mcp__perplexity-ask referenced but not available"
- Inform user:
⚠️ Restored settings reference tools not currently available:
- mcp__perplexity-ask__perplexity_ask
Settings are valid but these tools won't work until:
- Install missing MCP servers
- Or remove references to unavailable toolsNot an error: Settings valid, just some tools unavailable
---
Edge Case 4: Restore same as current
Example: User selects backup identical to current settings
Handling:
- Detect via diff (no changes)
- Inform:
ℹ️ **No changes needed**
Selected backup is identical to current settings.
Restore not necessary.
Current settings already match backup from 2025-01-16 12:01.- Skip restore (no-op)
Optimization: Detect no-op restores early
---
Backup Cleanup
User may accumulate many backups:
## Backup Cleanup (Optional)
You have 47 backup files (oldest: 2024-12-01)
**Cleanup options**:
1. Keep last 10 backups only
2. Delete backups older than 30 days
3. Keep 1 backup per day (consolidate)
4. Manual selection
**Cleanup? (1-4 or skip)**If user chooses #2 (delete >30 days):
find ~/.config/claude-code -name "settings.*.backup" -mtime +30 -deleteInform:
✅ Deleted 38 old backups (kept 9 recent)Token Cost: 0 tokens (cleanup optional, not part of core workflow)
---
Success Criteria
Workflow complete when:
- ✅ Available backups listed
- ✅ User selected backup (or cancelled)
- ✅ Restore preview shown
- ✅ User confirmed restore
- ✅ Pre-restore safety backup created
- ✅ Selected backup restored to settings.json
- ✅ Restored settings validated (passed)
- ✅ User informed of restore completion
- ✅ Restart reminder provided
---
Token Budget Summary
List backups only (user cancels):
Tier 1 (Metadata): 100 tokens ✅
Tier 2 (SKILL.md): 2,250 tokens ✅
backup-restore-workflow: 600 tokens (this file)
ls command: 0 tokens (execution)
---
Total: 2,950 tokens
Status: ✅ 70% under budgetFull restore operation:
Tier 1 + 2 + this: 2,950 tokens ✅
diff preview: 0 tokens (command)
cp restore: 0 tokens (command)
validate_config.py: 0 tokens (script)
---
Total: 2,950 tokens
Status: ✅ 70% under budget---
Integration with Other Workflows
Backup/restore is used BY:
- validation-workflow (restore after validation failure)
- profile-application-workflow (undo profile if user doesn't like it)
- Any workflow (emergency recovery)
Backup/restore is: Universal safety net for all workflows
Every modification workflow creates backups via apply_permissions.py
---
Next Steps After Workflow
After successful restore:
- ✅ Restart Claude Code (required)
- ✅ Test that restored permissions work as expected
- ✅ Optional: Validate restored settings (
python3 scripts/validate_config.py)
If restore didn't help:
- Try different backup (older/newer)
- Or manually reconstruct permissions
- Or apply fresh profile (development, read-only, etc.)
Backup safety net:
- Pre-restore backup allows undoing the restore
- Can always go back to pre-restore state
---
Quick Commands Reference
List recent backups:
ls -lt ~/.config/claude-code/settings.*.backup | head -5Restore specific backup manually:
cp settings.YYYYMMDD_HHMMSS.backup settings.jsonView backup contents:
cat settings.YYYYMMDD_HHMMSS.backup | jq .Compare two backups:
diff settings.BACKUP1.backup settings.BACKUP2.backupDelete old backups (>30 days):
find ~/.config/claude-code -name "settings.*.backup" -mtime +30 -delete---
End of Backup/Restore Workflow Size: ~400 lines (~2,000 tokens) Compliance: ✅ Tier 3 (loaded on-demand only)
CLI Tool Permission Workflow
Token Budget Tracker
This Workflow:
- Tier 1 (Metadata): 100 tokens ✅ (already loaded)
- Tier 2 (SKILL.md): 2,250 tokens ✅ (already loaded)
- This guide: ~1,250 tokens
- cli_commands.json (surgical): ~150 tokens
- Estimated total: 3,750 tokens
- Status: ✅ Within budget (<10,000)
---
Purpose
Enable specific CLI tool permissions based on natural language requests like:
- "enable git"
- "allow gcloud read-only"
- "configure docker with write access"
- "make kubectl commands work"
---
Prerequisites
This workflow triggered when:
- User mentions CLI tool name (git, gcloud, aws, kubectl, docker, npm, pip, maven, gradle, cargo, helm, terraform, pulumi, ansible, claude, gemini)
- Keywords present: "enable", "allow", "configure", "permit"
- Optional mode indicators: "read", "read-only", "write", "commits", "pushes"
---
Workflow Steps
Step 1: Extract Tool and Mode
Parse user message for: 1. Tool name (case-insensitive match) 2. Mode (if specified):
- Read indicators: "read", "read-only", "list", "show", "describe", "view"
- Write indicators: "write", "push", "commit", "deploy", "publish", "modify"
- Default: READ (safer)
Example Parsing:
"enable git read-only" → Tool: git, Mode: READ
"allow gcloud write" → Tool: gcloud, Mode: WRITE
"configure docker" → Tool: docker, Mode: READ (default)Token Cost: 0 tokens (in-memory logic)
---
Step 2: Check If Tool Known
Surgical lookup in cli_commands.json:
grep -A 25 '"TOOL_NAME"' references/cli_commands.jsonExample:
grep -A 25 '"git"' references/cli_commands.jsonToken Cost: ~150 tokens (vs 2,650 for full file = 94% savings)
Output Analysis:
- If grep returns results → Tool is KNOWN, proceed to Step 3
- If grep returns empty → Tool is UNKNOWN, route to research workflow
Unknown Tool Routing:
IF tool NOT found in cli_commands.json:
STOP this workflow
Load guides/workflows/research-workflow.md
Pass tool name and mode to research workflow
END---
Step 3: Extract Commands for Mode
From grep output, extract command arrays:
For READ mode:
- Look for
"read_only": [...]array - Extract commands like:
["status", "log", "diff", "show"]
For WRITE mode:
- Combine
"read_only"+"write"arrays - Extract all read + write commands
- Example:
["status", "log", "add", "commit", "push"]
Never include "dangerous" commands (even in WRITE mode):
- These require explicit user opt-in
- Example:
git push --force,rm -rf,sudo
Token Cost: 0 tokens (already loaded in Step 2 grep)
---
Step 4: Build Permission Rules
Convert commands to Bash() rules:
Format: Bash(TOOL_NAME COMMAND *)
Examples:
git read-only:
- Bash(git status *)
- Bash(git log *)
- Bash(git diff *)
- Bash(git show *)
docker write:
- Bash(docker ps *)
- Bash(docker images *)
- Bash(docker build *)
- Bash(docker run *)
- Bash(docker push *)Wildcard Strategy:
- Always append
*to allow arguments - Example:
Bash(git status *)allowsgit status,git status -sb, etc.
Token Cost: 0 tokens (in-memory rule generation)
---
Step 5: Apply Safety Rules
ALWAYS add deny rules from security_patterns.json:
jq '.recommended_deny_set.standard' references/security_patterns.jsonToken Cost: ~100 tokens
Critical deny rules to apply:
Deny Rules (minimum set):
- Read(.env*)
- Read(*.key)
- Read(*.pem)
- Read(.aws/**)
- Read(.ssh/**)
- Write(.env*)
- Bash(rm *)
- Bash(sudo *)
- Bash(git push * --force)
- Bash(docker * --privileged)
- Bash(kubectl delete namespace *)
- Bash(aws * --profile production)
- Bash(gcloud * --project production)Conflict Detection:
- If user requested write mode BUT safety rule denies specific dangerous command
- Keep deny rule (safety first)
- Inform user of restriction
Example Conflict:
User: "enable git write"
Allow Rules: Bash(git push *)
Deny Rules: Bash(git push * --force)
Result: Allow regular push, deny force push ✅Token Cost: ~100 tokens (surgical jq extraction)
---
Step 6: Execute apply_permissions.py
Command:
python3 scripts/apply_permissions.py \
--allow "Bash(git status *)" \
--allow "Bash(git log *)" \
--allow "Bash(git diff *)" \
--deny "Bash(git push * --force)" \
--deny "Bash(rm *)" \
--deny "Bash(sudo *)"What apply_permissions.py does: 1. ✅ Creates timestamped backup (settings.YYYYMMDD_HHMMSS.backup) 2. ✅ Validates all rules for syntax errors 3. ✅ Detects conflicts (allow vs deny on same pattern) 4. ✅ Merges rules with existing settings.json 5. ✅ Writes updated settings.json 6. ✅ Reports what changed
Token Cost: 0 tokens (script execution, not file reading)
Expected Output:
✅ Backup created: /path/to/settings.20250116_143022.backup
✅ Validation passed: All rules are valid
✅ Added 3 allow rules, 3 deny rules
✅ Settings written to: /path/to/settings.json
Summary:
Total allow rules: 15 (+3)
Total deny rules: 8 (+3)---
Step 7: Confirm with User
Report to user:
✅ **Enabled git (read-only mode)**
**Permissions added**:
- ✅ `git status` and variants
- ✅ `git log` and variants
- ✅ `git diff` and variants
- ✅ `git show` and variants
**Safety rules applied**:
- 🛡️ Blocked `git push --force` (dangerous)
- 🛡️ Blocked `rm` commands (destructive)
- 🛡️ Blocked `sudo` commands (privileged)
**Backup created**: `settings.20250116_143022.backup`
**Next step**: Restart Claude Code for changes to take effect.Token Cost: 0 tokens (output to user)
---
Examples
Example 1: Enable Git Read-Only
User Request: "enable git read-only"
Workflow Execution: 1. Extract: Tool=git, Mode=READ 2. Surgical lookup: grep -A 25 '"git"' references/cli_commands.json 3. Extract read_only commands: ["status", "log", "diff", "show", "branch"] 4. Build rules:
Bash(git status *)
Bash(git log *)
Bash(git diff *)
Bash(git show *)
Bash(git branch *)5. Apply safety: Add deny rules for git push * --force, rm *, sudo * 6. Execute: python3 scripts/apply_permissions.py --allow ... --deny ... 7. Confirm: Report success to user
Total tokens: 3,750 (within budget ✅)
---
Example 2: Enable Docker Write
User Request: "configure docker with write access"
Workflow Execution: 1. Extract: Tool=docker, Mode=WRITE 2. Surgical lookup: grep -A 35 '"docker"' references/cli_commands.json 3. Extract read_only + write commands:
read_only: ["ps", "images", "inspect", "logs"]
write: ["build", "run", "push", "pull", "start", "stop"]4. Build rules (read + write):
Bash(docker ps *)
Bash(docker images *)
Bash(docker build *)
Bash(docker run *)
Bash(docker push *)5. Apply safety: Add deny for docker * --privileged, docker rm -f 6. Execute: python3 scripts/apply_permissions.py ... 7. Confirm: Report 6 allow rules, 2 deny rules added
Total tokens: 3,800 (within budget ✅)
---
Example 3: Enable Kubectl (Unknown Commands)
User Request: "enable kubectl"
Workflow Execution: 1. Extract: Tool=kubectl, Mode=READ (default) 2. Surgical lookup: grep -A 25 '"kubectl"' references/cli_commands.json 3. FOUND in cli_commands.json (kubectl is pre-configured) 4. Extract read_only commands: ["get", "describe", "logs", "explain"] 5. Build rules:
Bash(kubectl get *)
Bash(kubectl describe *)
Bash(kubectl logs *)
Bash(kubectl explain *)6. Apply safety: Add deny for kubectl delete namespace *, kubectl apply * (not in read_only) 7. Execute: python3 scripts/apply_permissions.py ... 8. Confirm: Report success
Total tokens: 3,750 (within budget ✅)
---
Example 4: Enable Unknown Tool → Route to Research
User Request: "enable perl"
Workflow Execution: 1. Extract: Tool=perl, Mode=READ (default) 2. Surgical lookup: grep -A 25 '"perl"' references/cli_commands.json 3. NOT FOUND (perl not in database) 4. STOP this workflow 5. Load research workflow:
Read guides/workflows/research-workflow.md6. Pass context: Tool=perl, Mode=READ 7. Research workflow takes over (uses Perplexity → Brave → Gemini → WebSearch)
Token cost for this workflow: 3,600 tokens (then research workflow adds ~2,500 more)
---
Error Handling
Error 1: grep returns empty (unknown tool)
Detection: grep exit code 1 or empty output
Action:
STOP current workflow
INFORM user: "perl is not in the known tools database. Researching..."
LOAD guides/workflows/research-workflow.md
PASS tool=perl, mode=READ to research workflowToken impact: +2,000 tokens (research workflow)
---
Error 2: apply_permissions.py fails validation
Detection: Script exits with error code, output contains "Validation failed"
Example Error:
❌ Validation failed: Invalid tool name "Bahs" (did you mean "Bash"?)Action: 1. Show error to user 2. Ask user to verify tool name 3. Offer to retry with corrected input
Recovery: Do NOT write settings.json if validation fails
---
Error 3: Conflicting rules
Detection: apply_permissions.py reports conflict
Example:
⚠️ Conflict detected:
Allow: Bash(git push *)
Deny: Bash(git push * --force)
Resolution: Both rules kept (deny is more specific)Action: 1. Keep both rules (deny takes precedence for specific patterns) 2. Inform user of conflict and resolution 3. Proceed with write
No error - this is expected behavior (safety first)
---
Error 4: Backup creation fails
Detection: Script cannot create backup file (permissions issue)
Example Error:
❌ Failed to create backup: Permission denied on settings.jsonAction: 1. STOP workflow (never modify without backup) 2. Inform user of permission issue 3. Suggest manual backup: cp settings.json settings.backup 4. Offer to retry after manual backup
Recovery: User must fix file permissions or create manual backup
---
Edge Cases
Edge Case 1: Tool has no read_only commands
Example: User asks for "terraform read-only" but terraform.json only has write commands
Handling:
INFORM user: "terraform typically requires write access for state management"
OFFER: "Would you like to enable terraform with minimal write permissions?"
IF user confirms:
Apply smallest set of write commands
IF user declines:
Explain terraform cannot operate in read-only mode---
Edge Case 2: User requests both read and write
Example: "enable git read and write"
Handling:
- Interpret as WRITE mode (write implies read)
- Apply read_only + write commands
- Inform user: "Enabled git with read and write access"
---
Edge Case 3: User specifies dangerous command explicitly
Example: "enable git push --force"
Handling: 1. Detect dangerous command request 2. WARN user: "git push --force is dangerous and can cause data loss" 3. ASK user: "Are you sure you want to enable force push? (yes/no)" 4. IF yes:
- Add allow rule for specific command
- Remove deny rule for that pattern
- Add extra confirmation: "⚠️ Force push enabled. Use with extreme caution."
5. IF no:
- Keep deny rule
- Enable regular push only
Safety principle: Always require explicit confirmation for dangerous commands
---
Edge Case 4: Multiple tools in one request
Example: "enable git and docker"
Handling: 1. Detect multiple tools: ["git", "docker"] 2. Execute workflow SEQUENTIALLY for each tool 3. Track rules for all tools 4. Single apply_permissions.py execution at end with all rules 5. Report summary:
✅ Enabled git (read-only)
✅ Enabled docker (read-only)
Total rules added: 12 allow, 5 denyToken cost: ~1,500 per tool (3,000 total for 2 tools)
---
Success Criteria
Workflow complete when:
- ✅ Tool commands extracted from database
- ✅ Permission rules generated
- ✅ Safety deny rules applied
- ✅ Backup created (via apply_permissions.py)
- ✅ Validation passed (syntax + conflicts)
- ✅ settings.json written successfully
- ✅ User informed of changes
- ✅ Restart reminder provided
---
Token Budget Summary
Typical CLI tool request:
Tier 1 (Metadata): 100 tokens ✅
Tier 2 (SKILL.md): 2,250 tokens ✅
cli-tool-workflow.md: 1,250 tokens (this file)
cli_commands.json (grep): 150 tokens (surgical)
security_patterns.json: 100 tokens (surgical)
Script execution: 0 tokens
---
Total: 3,850 tokens
Status: ✅ 61% under budgetUnknown tool (routes to research):
Tier 1 + 2 + this: 3,600 tokens ✅
Research workflow: 2,000 tokens
MCP tool usage: 500 tokens
---
Total: 6,100 tokens
Status: ✅ 39% under budget---
Next Steps After Workflow
User must restart Claude Code for permissions to take effect.
Optional follow-ups:
- Validate with:
python3 scripts/validate_config.py - View backup:
ls -lt ~/.config/claude-code/settings.*.backup - Rollback if needed: See guides/workflows/backup-restore-workflow.md
---
End of CLI Tool Workflow Size: ~350 lines (~1,750 tokens) Compliance: ✅ Tier 3 (loaded on-demand only)
File Pattern Permission Workflow
Token Budget Tracker
This Workflow:
- Tier 1 (Metadata): 100 tokens ✅ (already loaded)
- Tier 2 (SKILL.md): 2,250 tokens ✅ (already loaded)
- This guide: ~1,000 tokens
- security_patterns.json (surgical): ~100 tokens
- Estimated total: 3,450 tokens
- Status: ✅ Within budget (<10,000)
---
Purpose
Enable file editing/writing permissions based on natural language requests like:
- "make all markdown files editable"
- "allow editing TypeScript files in src/"
- "make docs folder writable"
- "enable Write for **.json files"
---
Prerequisites
This workflow triggered when:
- User mentions file types: "markdown", ".md", "TypeScript", "**.rs", "JSON files"
- Keywords present: "make editable", "edit", "write", "modify", "allow writing"
- Pattern indicators: file extensions, glob patterns, directory names
- NOT a project setup request (that uses project-setup-workflow.md)
---
Workflow Steps
Step 1: Parse File Pattern
Extract from user message: 1. File type (e.g., "markdown", "TypeScript", "JSON") 2. Directory scope (e.g., "src/", "docs/", "all files") 3. Operation (edit vs write):
- Edit: Modify existing files only
- Write: Create new files + modify existing
Natural Language → Glob Pattern Mapping:
"markdown files" → **.md
"TypeScript files" → **.ts, **.tsx
"JavaScript" → **.js, **.jsx
"Python files" → **.py
"Rust files" → **.rs
"JSON files" → **.json
"YAML files" → **.yaml, **.yml
"config files" → **.toml, **.yaml, **.json, **.ini
"docs folder" → docs/**
"src directory" → src/**
"all files" → ** (use with caution)
"test files" → **/*.test.*, **/test_*.*, tests/**Specific file:
"README.md" → README.md (exact match, no wildcards)
"package.json" → package.json
"Cargo.toml" → Cargo.tomlToken Cost: 0 tokens (in-memory pattern matching)
---
Step 2: Determine Operations Needed
Decision Logic:
IF "edit" OR "modify" in request:
Operations: [Edit(pattern), Read(pattern)]
Reason: Edit requires reading first
IF "write" OR "create" OR "make writable" in request:
Operations: [Write(pattern), Edit(pattern), Read(pattern)]
Reason: Write implies edit + read
IF operation unclear:
DEFAULT: [Edit(pattern), Read(pattern)]
Reason: Edit is safer than Write (no new file creation)Examples:
"make markdown editable" → Edit(**.md), Read(**.md)
"allow writing to docs/" → Write(docs/**), Edit(docs/**), Read(docs/**)
"edit TypeScript files" → Edit(**.ts), Edit(**.tsx), Read(**.ts), Read(**.tsx)Token Cost: 0 tokens (in-memory logic)
---
Step 3: Build Permission Rules
Rule Construction:
Format: ToolName(pattern)
For single file type:
Request: "make markdown editable"
Rules:
- Edit(**.md)
- Read(**.md)For directory scope:
Request: "make docs folder writable"
Rules:
- Write(docs/**)
- Edit(docs/**)
- Read(docs/**)For multiple extensions:
Request: "edit TypeScript files"
Rules:
- Edit(**.ts)
- Edit(**.tsx)
- Read(**.ts)
- Read(**.tsx)For specific file:
Request: "make README.md editable"
Rules:
- Edit(README.md)
- Read(README.md)Glob Pattern Best Practices:
**= Match all subdirectories*.ext= Match in current directory only**.ext= Match in all subdirectories (most common)dir/**= Match everything in directorydir/**.ext= Match specific type in directory
Token Cost: 0 tokens (rule generation)
---
Step 4: Apply Safety Rules
CRITICAL: Check against security_patterns.json:
jq '.recommended_deny_set.standard' references/security_patterns.jsonToken Cost: ~100 tokens (surgical extraction)
Blocked Patterns (from security_patterns.json):
NEVER allow (even if user requests):
- Write(.env*)
- Write(*.key)
- Write(*.pem)
- Write(.aws/**)
- Write(.ssh/**)
- Write(.git/**)
- Edit(.env*)
- Edit(*.key)
- Edit(*.pem)Conflict Resolution:
IF user requests pattern that matches deny rule:
REMOVE that specific pattern from allow rules
INFORM user of security restriction
OFFER alternative (e.g., "You can edit .env.example instead")Example Conflict:
Request: "make all files in project editable"
Pattern: **
Safety Check:
- ** includes .env, *.key, *.pem (BLOCKED)
Action:
- Allow: Edit(**) ← Add to rules
- Deny: Edit(.env*), Edit(*.key), Edit(*.pem) ← Add deny rules
- Inform: "Enabled editing for all files except sensitive config (.env, keys)"Token Cost: ~100 tokens (security patterns)
---
Step 5: Execute apply_permissions.py
Command Construction:
python3 scripts/apply_permissions.py \
--allow "Edit(**.md)" \
--allow "Read(**.md)" \
--deny "Edit(.env*)" \
--deny "Write(*.key)"Script Actions (automatic): 1. ✅ Create timestamped backup 2. ✅ Validate glob patterns (check syntax) 3. ✅ Detect conflicts (allow vs deny overlap) 4. ✅ Merge with existing settings.json 5. ✅ Write updated settings.json 6. ✅ Report changes
Token Cost: 0 tokens (script execution)
Expected Output:
✅ Backup created: settings.20250116_145530.backup
✅ Validation passed: 2 patterns are valid
✅ Added 2 allow rules, 0 deny rules
✅ Settings written successfully
Summary:
Total allow rules: 17 (+2)
Total deny rules: 8 (+0)---
Step 6: Confirm with User
Report Format:
✅ **Made markdown files editable**
**Permissions added**:
- ✅ `Edit(**.md)` - Edit any .md file in project
- ✅ `Read(**.md)` - Read required for editing
**Files affected**:
- README.md
- docs/guide.md
- CHANGELOG.md
- (all .md files in project)
**Safety rules**:
- 🛡️ Sensitive files still protected (.env, *.key, *.pem)
**Backup created**: `settings.20250116_145530.backup`
**Next step**: Restart Claude Code for changes to take effect.Token Cost: 0 tokens (output to user)
---
Examples
Example 1: Make Markdown Editable
User Request: "make all markdown files editable"
Workflow Execution: 1. Parse: Type=markdown, Scope=all, Operation=edit 2. Pattern: **.md 3. Operations: Edit + Read (edit implies read) 4. Build rules:
Edit(**.md)
Read(**.md)5. Safety check: No conflicts (markdown is safe) 6. Execute: python3 scripts/apply_permissions.py --allow "Edit(**.md)" --allow "Read(**.md)" 7. Confirm: Report 2 rules added
Total tokens: 3,450 ✅
---
Example 2: Make Docs Folder Writable
User Request: "make docs folder writable"
Workflow Execution: 1. Parse: Type=any, Scope=docs/, Operation=write 2. Pattern: docs/** 3. Operations: Write + Edit + Read (write implies all) 4. Build rules:
Write(docs/**)
Edit(docs/**)
Read(docs/**)5. Safety check: Ensure docs/ doesn't contain .env files 6. Execute: python3 scripts/apply_permissions.py --allow "Write(docs/**)" --allow "Edit(docs/**)" --allow "Read(docs/**)" 7. Confirm: Report 3 rules added for docs/ directory
Total tokens: 3,550 ✅
---
Example 3: Edit TypeScript in src/
User Request: "allow editing TypeScript files in src/"
Workflow Execution: 1. Parse: Type=TypeScript (.ts, .tsx), Scope=src/, Operation=edit 2. Patterns: src/**.ts, src/**.tsx 3. Operations: Edit + Read 4. Build rules:
Edit(src/**.ts)
Edit(src/**.tsx)
Read(src/**.ts)
Read(src/**.tsx)5. Safety check: TypeScript files are safe 6. Execute: python3 scripts/apply_permissions.py --allow "Edit(src/**.ts)" --allow "Edit(src/**.tsx)" --allow "Read(src/**.ts)" --allow "Read(src/**.tsx)" 7. Confirm: Report 4 rules added for TypeScript in src/
Total tokens: 3,550 ✅
---
Example 4: Make Specific File Editable
User Request: "make README.md editable"
Workflow Execution: 1. Parse: Type=specific file, File=README.md, Operation=edit 2. Pattern: README.md (exact, no wildcards) 3. Operations: Edit + Read 4. Build rules:
Edit(README.md)
Read(README.md)5. Safety check: README.md is safe 6. Execute: python3 scripts/apply_permissions.py --allow "Edit(README.md)" --allow "Read(README.md)" 7. Confirm: Report 2 rules added for README.md only
Total tokens: 3,450 ✅
---
Example 5: Security Conflict - Attempt to Edit .env
User Request: "make all config files editable"
Workflow Execution: 1. Parse: Type=config (.toml, .yaml, .json, .env), Scope=all, Operation=edit 2. Patterns: **.toml, **.yaml, **.json, .env* 3. Safety check detects: .env* is in deny list 4. REMOVE .env* from allow patterns 5. Build rules:
Edit(**.toml)
Edit(**.yaml)
Edit(**.json)
Read(**.toml)
Read(**.yaml)
Read(**.json)
Deny(Edit(.env*)) ← Safety rule
Deny(Write(.env*))6. Execute with filtered patterns 7. Inform user:
✅ Made config files editable
Enabled:
- **.toml files
- **.yaml files
- **.json files
⚠️ Security restriction:
- .env files remain protected (contains secrets)
- Alternative: Edit .env.example insteadTotal tokens: 3,550 ✅
---
Error Handling
Error 1: Invalid glob pattern
Detection: apply_permissions.py validation fails
Example Error:
❌ Validation failed: Invalid glob pattern "**/.md" (leading dot after **)
Suggestion: Use "**.md" insteadAction: 1. Show error to user 2. Suggest corrected pattern 3. Offer to retry with correction
Recovery: Fix pattern and re-execute
---
Error 2: Too broad pattern
Detection: Pattern is ** or * (matches everything)
Example:
User: "make everything editable"
Pattern: **Action: 1. WARN user: "This will make ALL files editable, including build outputs and dependencies" 2. ASK user: "Did you mean source files only? (yes/no)" 3. IF yes:
- Suggest narrower pattern:
src/** - Ask for project type to apply template
4. IF no (user confirms **):
- Apply pattern with ALL security deny rules
- Extra warning about build files
Safety principle: Always challenge overly broad patterns
---
Error 3: Conflicting with existing rules
Detection: apply_permissions.py detects overlap
Example:
Existing: Edit(docs/*.md)
New request: Edit(docs/**)Action: 1. Detect: New pattern is BROADER than existing 2. Replace old with new (user is expanding access) 3. Inform: "Expanded docs/.md → docs/* (now includes subdirectories)"
Alternative:
Existing: Edit(docs/**)
New request: Edit(docs/*.md)Action: 1. Detect: New pattern is NARROWER than existing 2. Keep existing (already has broader access) 3. Inform: "docs/* already enabled (includes .md)"
---
Error 4: File not found at runtime
Detection: User tries to edit file not matching pattern
Example:
User enabled: Edit(src/**.ts)
User tries to edit: config/app.ts
Error: Permission deniedAction (in user prompt after error): 1. Explain: "app.ts is in config/, not src/" 2. Offer: "Would you like to enable Edit(config/**.ts)?" 3. If yes: Run this workflow again with new pattern
This is runtime guidance - not part of this workflow execution
---
Edge Cases
Edge Case 1: Multiple file types in one request
Example: "make TypeScript and JavaScript files editable"
Handling: 1. Parse multiple types: [TypeScript, JavaScript] 2. Map to patterns: [.ts, .tsx, .js, .jsx] 3. Generate rules for ALL patterns:
Edit(**.ts)
Edit(**.tsx)
Edit(**.js)
Edit(**.jsx)
Read(**.ts)
Read(**.tsx)
Read(**.js)
Read(**.jsx)4. Single apply_permissions.py execution with all rules 5. Report: "Enabled editing for TypeScript and JavaScript files (8 rules)"
Token cost: Same (~3,500 tokens)
---
Edge Case 2: Nested directory scopes
Example: "make src/components writable"
Handling:
- Pattern:
src/components/** - This is CORRECT (nested paths work in glob patterns)
- Rules: Write(src/components/), Edit(src/components/), Read(src/components/**)
No special handling needed - glob patterns support nested paths
---
Edge Case 3: Mixed operations
Example: "edit markdown but write to output.md specifically"
Handling: 1. Parse: Two distinct operations 2. Rules for "edit markdown":
Edit(**.md)
Read(**.md)3. Additional rule for "write to output.md":
Write(output.md)4. Apply all together (3 rules total)
---
Edge Case 4: File type ambiguity
Example: "make script files editable"
Handling: 1. "script" is ambiguous (.sh, .py, .js, .rb?) 2. ASK user: "Which script type? (Shell .sh, Python .py, JavaScript .js, Ruby .rb, or all?)" 3. Wait for clarification 4. Apply specific patterns based on user choice
Don't guess - always clarify ambiguous file types
---
Success Criteria
Workflow complete when:
- ✅ File pattern parsed correctly
- ✅ Glob pattern(s) generated
- ✅ Operations determined (Edit, Write, Read)
- ✅ Permission rules built
- ✅ Safety rules checked (no sensitive files)
- ✅ Backup created (via apply_permissions.py)
- ✅ Validation passed (glob syntax)
- ✅ settings.json written successfully
- ✅ User informed with specific files affected
- ✅ Restart reminder provided
---
Token Budget Summary
Typical file pattern request:
Tier 1 (Metadata): 100 tokens ✅
Tier 2 (SKILL.md): 2,250 tokens ✅
file-pattern-workflow.md: 1,000 tokens (this file)
security_patterns.json: 100 tokens (surgical)
Script execution: 0 tokens
---
Total: 3,450 tokens
Status: ✅ 65% under budgetComplex request (multiple types + directory scope):
Tier 1 + 2 + this: 3,350 tokens ✅
security_patterns.json: 100 tokens
Additional logic: 100 tokens
---
Total: 3,550 tokens
Status: ✅ 64% under budget---
Next Steps After Workflow
User must restart Claude Code for permissions to take effect.
Optional follow-ups:
- Validate with:
python3 scripts/validate_config.py - Test by editing a file matching the pattern
- View what was added:
grep "Edit(" settings.json - Rollback if needed: See guides/workflows/backup-restore-workflow.md
---
Related Workflows
If user says:
- "setup TypeScript project" → Use project-setup-workflow.md (applies template)
- "enable git" → Use cli-tool-workflow.md (different purpose)
- "apply development profile" → Use profile-application-workflow.md (bulk changes)
This workflow is for: Specific file pattern permission requests only
---
End of File Pattern Workflow Size: ~420 lines (~2,100 tokens) Compliance: ✅ Tier 3 (loaded on-demand only)
Profile Application Workflow
Token Budget Tracker
This Workflow:
- Tier 1 (Metadata): 100 tokens ✅ (already loaded)
- Tier 2 (SKILL.md): 2,250 tokens ✅ (already loaded)
- This guide: ~800 tokens
- permission_profiles.json (surgical): ~200 tokens
- Estimated total: 3,350 tokens
- Status: ✅ Within budget (<10,000)
---
Purpose
Apply pre-built permission profiles for common workflows:
- "apply development profile"
- "use read-only profile"
- "configure for ci-cd"
- "switch to production profile"
Key benefit: Bulk permission changes (50-100+ rules) in one command
---
Available Profiles
From permission_profiles.json:
| Profile | Use Case | Rules Count | Safety Level |
|---|---|---|---|
| read-only | Code review, security audit | ~30 | Maximum |
| development | Active coding (most common) | ~80 | High |
| ci-cd | Continuous integration | ~60 | High |
| production | Monitoring, read-only ops | ~25 | Maximum |
| documentation | Docs writing only | ~35 | High |
| code-review | PR review workflow | ~40 | High |
| testing | TDD workflow, test writing | ~70 | High |
---
Prerequisites
This workflow triggered when:
- User mentions "profile": "apply X profile", "use Y profile", "switch to Z"
- Profile names: read-only, development, ci-cd, production, documentation, code-review, testing
- User wants bulk permission changes vs individual rules
---
Workflow Steps
Step 1: Identify Profile
Parse user message for profile name:
"apply development profile" → Profile: development
"use read-only" → Profile: read-only
"configure for ci-cd" → Profile: ci-cd
"switch to production profile" → Profile: productionCase-insensitive matching:
- "Development", "DEVELOPMENT", "development" → all match
Aliases (handle variations):
"dev" → development
"readonly" → read-only
"ci" / "ci/cd" / "cicd" → ci-cd
"prod" → production
"docs" → documentation
"review" → code-review
"test" → testingToken Cost: 0 tokens (in-memory matching)
---
Step 2: Load Profile Definition
Surgical extraction from permission_profiles.json:
jq '.PROFILE_NAME' assets/permission_profiles.jsonExamples:
For development profile:
jq '.development' assets/permission_profiles.jsonFor read-only profile:
jq '."read-only"' assets/permission_profiles.jsonToken Cost: ~200 tokens (vs 1,240 for full file = 84% savings)
---
Step 3: Extract Profile Rules
Profile Structure:
{
"development": {
"description": "Full development permissions for active coding",
"use_cases": ["Active development", "Feature work", "Bug fixing"],
"allow": [
"Edit(**/*.{rs,py,js,ts,java,go,rb,php,cs,cpp,swift})",
"Edit(**.md)",
"Edit(**.json)",
"Edit(**.yaml)",
"Edit(**.toml)",
"Write(src/**)",
"Write(tests/**)",
"Write(docs/**)",
"Read(**)",
"Bash(git status *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git diff *)",
"Bash(cargo *)",
"Bash(npm *)",
"Bash(python3 *)",
"Bash(mvn *)",
"Bash(gradle *)"
],
"deny": [
"Write(.env*)",
"Write(*.key)",
"Write(*.pem)",
"Edit(.env*)",
"Read(.env*)",
"Bash(rm *)",
"Bash(sudo *)",
"Bash(git push * --force)",
"Bash(npm publish *)",
"Bash(cargo publish *)"
]
}
}Rule Count:
- Allow rules: ~50-80 per profile
- Deny rules: ~10-20 per profile
- Total: ~60-100 rules
Token Cost: 0 tokens (already loaded in Step 2 jq output)
---
Step 4: Confirm with User (Optional)
For potentially destructive profiles, confirm before applying:
Profiles requiring confirmation:
- read-only: Removes write access (may block work)
- production: Very restrictive (monitoring only)
Confirmation prompt (for read-only):
⚠️ **Read-Only Profile**
This profile will:
- ✅ Enable reading all files
- ✅ Enable read-only git commands (status, log, diff)
- ❌ DISABLE file editing (Edit, Write)
- ❌ DISABLE git commits and pushes
- ❌ DISABLE build commands
**Use case**: Code review, security audit, or read-only exploration
**Apply read-only profile? (yes/no)**Profiles NOT requiring confirmation:
- development (standard, expected)
- documentation (specific, limited)
- code-review (clear intent)
- testing (clear intent)
Token Cost: 0 tokens (user interaction)
---
Step 5: Execute apply_permissions.py
Command Construction (example for development profile):
python3 scripts/apply_permissions.py \
--allow "Edit(**/*.{rs,py,js,ts,java,go,rb,php,cs,cpp,swift})" \
--allow "Edit(**.md)" \
--allow "Edit(**.json)" \
--allow "Write(src/**)" \
--allow "Bash(git status *)" \
--allow "Bash(git add *)" \
--allow "Bash(cargo *)" \
... (50 more allow rules) \
--deny "Write(.env*)" \
--deny "Bash(rm *)" \
--deny "Bash(sudo *)" \
... (10 more deny rules)Script Actions (automatic): 1. ✅ Create timestamped backup 2. ✅ Validate all 60-100 rules 3. ✅ REPLACE mode: Clear existing allowedTools, apply profile from scratch
- This ensures clean slate (no stale permissions)
4. ✅ Write updated settings.json 5. ✅ Report comprehensive summary
Token Cost: 0 tokens (script execution)
Expected Output:
✅ Backup created: settings.20250116_153512.backup
✅ Validation passed: All 78 rules are valid
✅ Applied development profile: 68 allow, 10 deny rules
✅ Settings written successfully (replaced previous permissions)
Summary:
Total allow rules: 68 (replaced)
Total deny rules: 10 (replaced)
Profile: development---
Step 6: Confirm with User
Report Format (example for development profile):
✅ **Development profile applied**
**File editing enabled**:
- ✅ All source code files (Rust, Python, JS, TS, Java, Go, Ruby, PHP, C#, C++, Swift)
- ✅ Markdown documentation (**.md)
- ✅ Configuration files (**.json, **.yaml, **.toml)
- ✅ Source directories (src/**, tests/**, docs/**)
**Commands enabled**:
- ✅ Git: status, add, commit, diff, log, branch
- ✅ Build tools: cargo, npm, python3, mvn, gradle
- ✅ Common utilities: ls, cat, grep, find
**Protected patterns**:
- 🛡️ .env*, *.key, *.pem (sensitive files)
- 🛡️ rm, sudo (dangerous commands)
- 🛡️ git push --force, npm/cargo publish (destructive operations)
**Total rules**: 68 allow, 10 deny
**Previous permissions**: Backed up to settings.20250116_153512.backup
**Next step**: Restart Claude Code for changes to take effect.Token Cost: 0 tokens (output to user)
---
Examples
Example 1: Apply Development Profile
User Request: "apply development profile"
Workflow Execution: 1. Identify: Profile = development 2. Load: jq '.development' assets/permission_profiles.json 3. Extract: 68 allow rules + 10 deny rules 4. No confirmation needed (standard profile) 5. Execute: python3 scripts/apply_permissions.py in REPLACE mode 6. Confirm: Report 68 allow, 10 deny rules applied
Total tokens: 3,350 ✅
Use case: Starting active development on a project
---
Example 2: Switch to Read-Only
User Request: "use read-only profile"
Workflow Execution: 1. Identify: Profile = read-only 2. Load: jq '."read-only"' assets/permission_profiles.json 3. Extract: 30 allow rules (all Read + git read-only) + 15 deny rules 4. CONFIRM: Ask user if they want to disable editing 5. User confirms: "yes" 6. Execute: python3 scripts/apply_permissions.py in REPLACE mode 7. Confirm: Report read-only mode active, editing disabled
Total tokens: 3,400 ✅
Use case: Security audit, code review without editing
---
Example 3: Configure for CI/CD
User Request: "configure for ci-cd"
Workflow Execution: 1. Identify: Profile = ci-cd (matched from "ci-cd" or "ci/cd") 2. Load: jq '."ci-cd"' assets/permission_profiles.json 3. Extract rules:
- Allow: Read all, build commands (cargo, npm, mvn), test commands, git (no push)
- Deny: git push, publish commands, file editing (CI shouldn't edit source)
4. No confirmation needed 5. Execute: Apply ci-cd profile 6. Confirm: Report CI/CD permissions (build+test, no editing)
Total tokens: 3,350 ✅
Use case: Running in CI environment (GitHub Actions, GitLab CI)
---
Example 4: Documentation Writing
User Request: "apply documentation profile"
Workflow Execution: 1. Identify: Profile = documentation (or "docs") 2. Load: jq '.documentation' assets/permission_profiles.json 3. Extract rules:
- Allow: Edit(.md), Edit(docs/), Read(**), git status/add/commit
- Deny: Edit source code (.rs, .py, etc.), build commands
4. No confirmation needed 5. Execute: Apply documentation profile 6. Confirm: Report docs-only permissions
Total tokens: 3,350 ✅
Use case: Technical writer working only on documentation
---
Example 5: Testing/TDD Workflow
User Request: "switch to testing profile"
Workflow Execution: 1. Identify: Profile = testing (or "test") 2. Load: jq '.testing' assets/permission_profiles.json 3. Extract rules:
- Allow: Edit test files (*.test., test_, tests/), Read source, test commands (pytest, jest, cargo test)
- Allow: Read source code (for understanding), but no editing
- Deny: Edit production source code
4. No confirmation needed 5. Execute: Apply testing profile 6. Confirm: Report TDD permissions (write tests, read source, run tests)
Total tokens: 3,400 ✅
Use case: Test-driven development, QA engineer workflow
---
Error Handling
Error 1: Unknown profile name
Detection: Profile not in permission_profiles.json
Example: "apply super-dev profile"
Action: 1. Inform: "Profile 'super-dev' not found" 2. List available: "Available profiles: read-only, development, ci-cd, production, documentation, code-review, testing" 3. Suggest: "Did you mean 'development'?" 4. Wait for clarification
Recovery: User selects valid profile
---
Error 2: Confirmation declined
Detection: User says "no" to read-only confirmation
Example:
Prompt: "Apply read-only profile? (yes/no)"
User: "no"Action: 1. Cancel profile application 2. Inform: "Read-only profile NOT applied. Permissions unchanged." 3. Offer: "Would you like a different profile? (development, code-review, testing)"
Recovery: User selects alternative profile or exits
---
Error 3: Profile validation fails
Detection: apply_permissions.py validation error on profile rules
Example Error:
❌ Validation failed: Invalid glob pattern "**/{}" in profileAction: 1. CRITICAL: This indicates profile database corruption 2. Report: "Profile database error. Please file issue at GitHub." 3. Offer: "Restore previous permissions from backup?" 4. If yes: Run backup-restore-workflow
Recovery: Restore from backup or manual fix
---
Error 4: Backup creation fails
Detection: Cannot create backup before REPLACE
Example Error:
❌ Failed to create backup: Permission denied on settings.jsonAction: 1. STOP workflow (NEVER replace without backup) 2. Inform: "Cannot apply profile without backup" 3. Suggest: "Fix file permissions or create manual backup: cp settings.json settings.backup" 4. Wait for user to resolve
Recovery: User fixes permissions, retry
---
Edge Cases
Edge Case 1: Switching between profiles
Example: Currently using read-only, switching to development
Handling: 1. Detect: Existing profile in settings.json (from metadata or comments) 2. Inform: "Switching from read-only → development" 3. Backup current (read-only settings) 4. REPLACE entirely with development profile 5. Report: "Switched from read-only to development. Previous settings backed up."
REPLACE mode ensures clean transition (no stale rules)
---
Edge Case 2: Profile + custom rules
Example: User previously added custom rules, now applying profile
Handling:
Option A: REPLACE mode (default):
- Wipe all previous permissions
- Apply profile from scratch
- User loses custom rules
- Backup preserves custom rules (can be restored)
Option B: MERGE mode (if user requests):
User: "apply development profile but keep my custom git rules"Action: 1. Load profile 2. Detect custom rules in existing settings 3. ASK: "Found custom rules. Replace all or merge? (replace/merge)" 4. If merge:
- Apply profile
- Preserve custom rules that don't conflict
- Inform: "Merged development profile with your custom rules"
Default: REPLACE (clean slate)
---
Edge Case 3: Profile doesn't fit project type
Example: Using ci-cd profile but project needs specific build tool
Workflow: 1. Apply ci-cd profile (generic build commands) 2. User reports: "cargo test doesn't work" 3. Diagnose: ci-cd profile has generic commands, missing cargo-specific 4. Suggest: "Apply development profile OR run: 'enable cargo' to add cargo commands"
Solution: Profile + incremental CLI tool additions
---
Edge Case 4: Production profile too restrictive
Example: User applies production, then can't do anything
Workflow: 1. User: "apply production profile" 2. Confirm: "Production is read-only. Continue?" 3. User: "yes" (mistakenly) 4. Applied: Very restrictive permissions 5. User reports: "I can't edit files now" 6. Solution: "Restore from backup or apply development profile"
Prevention: Clear confirmation messages for restrictive profiles
---
Profile Descriptions Reference
read-only Profile
Purpose: Code review, security audit, exploration Allow: Read all files, git read-only (status, log, diff, show) Deny: All editing, all writes, all git commits/pushes, all build commands Rules: ~30 allow, ~15 deny Safety: Maximum (no modifications possible)
development Profile
Purpose: Active development (most common) Allow: Edit source files, write to src/tests/docs, git add/commit, all build tools Deny: Sensitive files (.env, .key), dangerous commands (rm, sudo), force push, publish Rules: ~68 allow, ~10 deny Safety: High (protects secrets, prevents accidents)
ci-cd Profile
Purpose: Continuous integration pipeline Allow: Read all, build commands, test commands, git read-only Deny: File editing, git push, publish commands Rules: ~60 allow, ~15 deny Safety: High (CI can build/test but not modify source)
production Profile
Purpose: Production monitoring, read-only operations Allow: Read all, git status/log, monitoring commands (ps, top, logs) Deny: All editing, all writes, all build commands, git modifications Rules: ~25 allow, ~20 deny Safety: Maximum (strictest profile)
documentation Profile
Purpose: Technical writing, docs-only work Allow: Edit .md, docs/, Read all, git add/commit for docs Deny: Edit source code, build commands Rules: ~35 allow, ~12 deny Safety: High (isolated to documentation)
code-review Profile
Purpose: PR review, providing feedback Allow: Read all, git read-only, comment tools Deny: All editing (except maybe review comments), git commits Rules: ~40 allow, ~15 deny Safety: High (can review but not modify)
testing Profile
Purpose: Test-driven development, QA Allow: Edit test files, Read source, run tests (pytest, jest, cargo test) Deny: Edit production source code Rules: ~70 allow, ~12 deny Safety: High (write tests, read source, no prod edits)
---
Success Criteria
Workflow complete when:
- ✅ Profile identified from user request
- ✅ Profile loaded from permission_profiles.json
- ✅ All profile rules extracted (50-100 rules)
- ✅ User confirmation obtained (if required)
- ✅ Backup created (via apply_permissions.py)
- ✅ Validation passed (all rules)
- ✅ settings.json written in REPLACE mode
- ✅ User informed with comprehensive summary
- ✅ Restart reminder provided
---
Token Budget Summary
Typical profile application:
Tier 1 (Metadata): 100 tokens ✅
Tier 2 (SKILL.md): 2,250 tokens ✅
profile-workflow: 800 tokens (this file)
permission_profiles.json: 200 tokens (surgical jq)
User confirmation: 0 tokens (interaction)
---
Total: 3,350 tokens
Status: ✅ 66% under budgetProfile with confirmation (read-only, production):
Tier 1 + 2 + this: 3,150 tokens ✅
Profile data: 200 tokens
Confirmation interaction: 50 tokens
---
Total: 3,400 tokens
Status: ✅ 66% under budget---
Integration with Other Workflows
Profile as foundation: 1. Apply profile (this workflow) → Sets baseline permissions 2. Add specific file patterns → file-pattern-workflow.md 3. Add specific CLI tool → cli-tool-workflow.md 4. Validate everything → validation-workflow.md
Example Combination:
1. Apply development profile (68 rules)
2. "also make **.proto editable" (file-pattern, +2 rules)
3. "enable docker" (cli-tool, +8 rules)
Total: 78 rules for custom development environment---
Next Steps After Workflow
User must restart Claude Code for permissions to take effect.
Recommended actions: 1. Test profile by editing a file or running a command 2. If too restrictive: Apply less restrictive profile or add specific permissions 3. If too broad: Apply more restrictive profile or add specific denies
Optional follow-ups:
- Validate:
python3 scripts/validate_config.py - Review:
cat settings.jsonto see what was applied - Rollback: See backup-restore-workflow.md if profile doesn't fit workflow
---
End of Profile Application Workflow Size: ~450 lines (~2,250 tokens) Compliance: ✅ Tier 3 (loaded on-demand only)
Project Setup Permission Workflow
Token Budget Tracker
This Workflow:
- Tier 1 (Metadata): 100 tokens ✅ (already loaded)
- Tier 2 (SKILL.md): 2,250 tokens ✅ (already loaded)
- This guide: ~1,500 tokens
- project_templates.json (surgical): ~200 tokens
- security_patterns.json (surgical): ~100 tokens
- Estimated total: 4,150 tokens
- Status: ✅ Within budget (<10,000)
---
Purpose
Apply comprehensive permission templates for specific project types:
- "this is a Rust project, setup permissions"
- "configure for TypeScript development"
- "setup Java Maven project"
- "apply Python project template"
Key difference from file-pattern-workflow:
- This applies full templates (20-30 rules per language)
- file-pattern-workflow applies specific patterns (2-5 rules)
---
Prerequisites
This workflow triggered when:
- User mentions project type: "Rust", "Java", "TypeScript", "Python", "Go", etc.
- Keywords: "setup", "configure", "this is a X project", "apply template"
- User wants comprehensive permissions, not just file editing
- May follow auto-detection from detect_project.py
---
Supported Project Types
Pre-configured templates (in project_templates.json):
| Language | Indicator Files | Template Includes |
|---|---|---|
| Rust | Cargo.toml | src/**.rs, cargo commands, target/ deny |
| Java Maven | pom.xml | src/**.java, mvn commands, target/ deny |
| Java Gradle | build.gradle* | src/**.java, gradle commands, build/ deny |
| TypeScript | tsconfig.json | src/.ts, .tsx, npm/yarn, node_modules/ deny |
| JavaScript | package.json (no tsconfig) | src/.js, .jsx, npm commands |
| Python | pyproject.toml, setup.py | **.py, pytest, pip, __pycache__/ deny |
| Go | go.mod | **.go, go build/test, vendor/ deny |
| Ruby | Gemfile | **.rb, bundle, vendor/ deny |
| PHP | composer.json | **.php, composer, vendor/ deny |
| C# | .csproj, .sln | **.cs, dotnet, bin/obj/ deny |
| C++ | CMakeLists.txt | .cpp, .h, cmake, build/ deny |
| Swift | Package.swift | **.swift, swift build/test |
---
Workflow Steps
Step 1: Determine Project Type
Three methods:
Method A: User explicitly states:
"this is a Rust project" → Type: rust
"setup TypeScript" → Type: typescript
"configure Java Maven" → Type: java-mavenMethod B: Auto-detection via detect_project.py:
python3 scripts/detect_project.pyExample Output:
{
"detected_types": ["rust"],
"confidence": "high",
"indicator_files": ["Cargo.toml", "Cargo.lock"],
"suggestions": [
"Apply Rust template for src/**.rs editing",
"Enable cargo commands (build, test, run)",
"Deny target/ directory (build outputs)"
]
}Method C: Ask user if ambiguous:
Detected: package.json + tsconfig.json
Question: "Is this a TypeScript or JavaScript project?"
Wait for user clarificationToken Cost:
- Method A (explicit): 0 tokens (parsing)
- Method B (auto-detect): 0 tokens (script execution)
- Method C (ask user): 0 tokens (user interaction)
---
Step 2: Load Template for Project Type
Surgical extraction from project_templates.json:
jq '.LANGUAGE_KEY' references/project_templates.jsonExamples:
For Rust:
jq '.rust' references/project_templates.jsonFor TypeScript:
jq '.typescript' references/project_templates.jsonFor Python:
jq '.python' references/project_templates.jsonToken Cost: ~200 tokens (vs 1,955 for full file = 90% savings)
---
Step 3: Extract Template Rules
Template Structure:
{
"rust": {
"description": "Rust development with Cargo",
"file_patterns": {
"allow": [
"Edit(src/**.rs)",
"Edit(Cargo.toml)",
"Edit(Cargo.lock)",
"Read(**.rs)",
"Read(Cargo.*)"
],
"deny": [
"Write(target/**)",
"Edit(target/**)"
]
},
"commands": {
"allow": [
"Bash(cargo build *)",
"Bash(cargo test *)",
"Bash(cargo run *)",
"Bash(cargo check *)",
"Bash(cargo clippy *)",
"Bash(cargo doc *)"
],
"deny": [
"Bash(cargo publish *)",
"Bash(cargo install *)"
]
},
"common_tools": {
"allow": [
"Bash(git status *)",
"Bash(git log *)",
"Bash(git diff *)"
]
}
}
}Rule Extraction: 1. Combine all "allow" arrays → allow_rules list 2. Combine all "deny" arrays → deny_rules list 3. Total rules: Typically 20-35 per language template
Token Cost: 0 tokens (already loaded in Step 2 jq output)
---
Step 4: Apply Universal Safety Rules
Load security_patterns.json:
jq '.recommended_deny_set.standard' references/security_patterns.jsonToken Cost: ~100 tokens (surgical)
Merge with template deny rules:
Template deny rules (from project_templates.json):
- Write(target/**)
- Bash(cargo publish *)
Universal safety rules (from security_patterns.json):
- Read(.env*)
- Write(*.key)
- Bash(rm *)
- Bash(sudo *)
Combined deny rules:
- All template denies
- All universal safety denies
- No duplicates (deduplicated by apply_permissions.py)Token Cost: ~100 tokens (security patterns)
---
Step 5: Execute apply_permissions.py
Command Construction (example for Rust):
python3 scripts/apply_permissions.py \
--allow "Edit(src/**.rs)" \
--allow "Edit(Cargo.toml)" \
--allow "Read(**.rs)" \
--allow "Bash(cargo build *)" \
--allow "Bash(cargo test *)" \
--allow "Bash(cargo run *)" \
--allow "Bash(git status *)" \
--deny "Write(target/**)" \
--deny "Bash(cargo publish *)" \
--deny "Read(.env*)" \
--deny "Bash(rm *)" \
--deny "Bash(sudo *)"Script Actions (automatic): 1. ✅ Create timestamped backup 2. ✅ Validate all 20-35 rules 3. ✅ Merge with existing settings.json (preserve user customizations) 4. ✅ Deduplicate rules 5. ✅ Write updated settings.json 6. ✅ Report summary
Token Cost: 0 tokens (script execution)
Expected Output:
✅ Backup created: settings.20250116_151045.backup
✅ Validation passed: All 28 rules are valid
✅ Added 18 allow rules, 10 deny rules
✅ Settings written successfully
Summary:
Total allow rules: 35 (+18)
Total deny rules: 18 (+10)---
Step 6: Confirm with User
Report Format (example for Rust):
✅ **Rust project permissions configured**
**File editing enabled**:
- ✅ `src/**.rs` - All Rust source files
- ✅ `Cargo.toml` - Project manifest
- ✅ `Cargo.lock` - Dependency lock file
- ✅ `**.md` - Documentation files
**Commands enabled**:
- ✅ `cargo build` - Compile project
- ✅ `cargo test` - Run tests
- ✅ `cargo run` - Execute binary
- ✅ `cargo check` - Fast compile check
- ✅ `cargo clippy` - Linter
- ✅ `cargo doc` - Generate docs
- ✅ `git` read-only commands (status, log, diff)
**Protected patterns**:
- 🛡️ `target/**` - Build outputs (no editing)
- 🛡️ `cargo publish` - No accidental publishing
- 🛡️ `.env*`, `*.key`, `*.pem` - Sensitive files
- 🛡️ `rm`, `sudo` - Dangerous commands
**Total rules**: 18 allow, 10 deny
**Backup created**: `settings.20250116_151045.backup`
**Next step**: Restart Claude Code for changes to take effect.Token Cost: 0 tokens (output to user)
---
Examples
Example 1: Setup Rust Project
User Request: "this is a Rust project, setup permissions"
Workflow Execution: 1. Determine type: rust (explicit from user) 2. Load template: jq '.rust' references/project_templates.json 3. Extract rules:
- Allow: 12 file patterns + 6 cargo commands + 3 git commands
- Deny: 2 cargo denies + 8 universal safety denies
4. Apply safety: Merge deny rules (10 total) 5. Execute: python3 scripts/apply_permissions.py with 21 allow, 10 deny 6. Confirm: Report comprehensive Rust setup
Total tokens: 4,150 ✅
---
Example 2: Auto-Detect TypeScript Project
User Request: "setup this project for editing"
Workflow Execution: 1. Run: python3 scripts/detect_project.py
{
"detected_types": ["typescript"],
"confidence": "high",
"indicator_files": ["package.json", "tsconfig.json"]
}2. Inform user: "Detected TypeScript project. Applying template..." 3. Load template: jq '.typescript' references/project_templates.json 4. Extract rules:
- Allow: src/.ts, .tsx, npm/yarn commands, tsconfig.json editing
- Deny: node_modules/, dist/, npm publish
5. Apply safety: Add .env, .key denies 6. Execute: python3 scripts/apply_permissions.py with ~25 rules 7. Confirm: Report TypeScript setup complete
Total tokens: 4,150 ✅
---
Example 3: Java Maven vs Gradle Detection
User Request: "configure Java project"
Workflow Execution: 1. Run: python3 scripts/detect_project.py
{
"detected_types": ["java-maven"],
"confidence": "high",
"indicator_files": ["pom.xml"]
}2. Detected: Maven (not Gradle) 3. Load template: jq '."java-maven"' references/project_templates.json 4. Extract rules:
- Allow: src/**.java, pom.xml, mvn commands (compile, test, package)
- Deny: target/**, mvn deploy
5. Apply safety rules 6. Execute: Apply Maven-specific permissions 7. Confirm: "Java Maven project configured"
Total tokens: 4,200 ✅
Alternative (if build.gradle found):
- Template:
jq '."java-gradle"' references/project_templates.json - Commands: gradle commands instead of mvn
- Deny: build/ instead of target/
---
Example 4: Python Project with Multiple Tools
User Request: "setup Python project"
Workflow Execution: 1. Type: python (explicit) 2. Load template: jq '.python' references/project_templates.json 3. Extract rules:
- Allow: **.py, pyproject.toml, setup.py, requirements.txt
- Allow: pytest, pip install (dependencies only), python commands
- Deny: __pycache__/*, .pyc, pip uninstall
4. Apply safety: .env, .key 5. Execute: Apply comprehensive Python permissions 6. Confirm: Report includes pytest, pip, python3 commands enabled
Total tokens: 4,150 ✅
---
Example 5: Ambiguous Project - Multiple Languages
Scenario: Project has both Rust and Python files
Workflow Execution: 1. Run: python3 scripts/detect_project.py
{
"detected_types": ["rust", "python"],
"confidence": "medium",
"indicator_files": ["Cargo.toml", "setup.py"]
}2. ASK user: "Detected Rust and Python. Which is the primary language?" 3. User responds: "Rust (with Python scripts)" 4. Apply Rust template as primary 5. Add Python subset for **.py files + python3 command 6. Execute: Combined ruleset (Rust full + Python subset) 7. Confirm: "Configured for Rust with Python scripting support"
Total tokens: 4,300 ✅
---
Error Handling
Error 1: Unknown project type
Detection: User mentions language not in project_templates.json
Example: "setup Perl project"
Action: 1. Inform: "Perl template not available in pre-configured templates" 2. Offer: "I can create custom permissions for Perl. What files need editing? (e.g., .pl, .pm)" 3. Route to: file-pattern-workflow.md for custom setup 4. Suggest: Research workflow if user wants tool-specific permissions
Recovery: Use file-pattern-workflow for manual template creation
---
Error 2: No indicator files found
Detection: detect_project.py returns empty
Example Output:
{
"detected_types": [],
"confidence": "none",
"indicator_files": [],
"suggestions": [
"No recognized project structure found",
"Check if this is a monorepo or unconventional layout"
]
}Action: 1. Inform user: "Could not auto-detect project type" 2. ASK: "What language/framework is this project? (Rust, Java, TypeScript, Python, Go, etc.)" 3. Wait for user response 4. Proceed with explicit type from Step 1
Recovery: User provides explicit type
---
Error 3: Conflicting with existing rules
Detection: apply_permissions.py detects overlap
Example:
Existing: Edit(src/main.rs)
Template: Edit(src/**.rs)Action: 1. Template rule is BROADER → Replace existing 2. Inform: "Expanded src/main.rs → src/**.rs (now includes all Rust files)" 3. Preserve any user custom denies
Policy: Template rules override existing patterns when broader
---
Error 4: Template validation fails
Detection: apply_permissions.py validation error on template rule
Example Error:
❌ Validation failed: Invalid tool name "BashOutput" in templateAction: 1. CRITICAL: This indicates template database corruption 2. Report error to user: "Template database error. Please file issue at GitHub." 3. Offer: "Use file-pattern-workflow for manual setup as workaround" 4. Log: Record which template failed for bug report
Recovery: Fallback to manual file-pattern workflow
---
Edge Cases
Edge Case 1: Monorepo with multiple projects
Example: workspace/ with both Rust and TypeScript sub-projects
Handling: 1. detect_project.py finds both 2. ASK user: "This is a monorepo. Which project are you working on?" 3. Options:
- "Rust project in services/api/" → Apply Rust template scoped to services/api/
- "TypeScript project in web/" → Apply TypeScript template scoped to web/
- "Both" → Apply BOTH templates with directory scoping
4. Scope patterns:
Rust: Edit(services/api/src/**.rs)
TypeScript: Edit(web/src/**.ts)Token cost: Same (~4,200 tokens)
---
Edge Case 2: Legacy project structure
Example: Java project without pom.xml or build.gradle (just *.java files)
Handling: 1. detect_project.py finds .java but no build files 2. Confidence: low 3. ASK user**: "Found Java files but no Maven/Gradle. Is this a legacy project?" 4. If yes:
- Apply Java file patterns only (**.java)
- Skip build tool commands
- Warn: "No build tool detected. Add Maven/Gradle for full template."
Fallback: Partial template (files only, no commands)
---
Edge Case 3: User wants ONLY files, not commands
Example: "setup Rust files but don't enable cargo commands"
Handling: 1. Load Rust template 2. Filter: Extract only file_patterns.allow, skip commands.allow 3. Apply:
Allow: Edit(src/**.rs), Edit(Cargo.toml), Read(**.rs)
Deny: (safety rules only, no command denies)4. Inform: "Enabled Rust file editing. Cargo commands NOT enabled."
Use case: Users who prefer manual terminal control
---
Edge Case 4: Template override - User customization
Example: User previously customized Rust deny rules, now applying template
Handling: 1. apply_permissions.py detects existing custom rules 2. Preserve user customizations that don't conflict 3. Merge template with custom rules 4. Inform: "Applied Rust template + preserved your custom deny rules"
Policy: User customizations always win over template defaults
---
Success Criteria
Workflow complete when:
- ✅ Project type determined (auto-detect or explicit)
- ✅ Template loaded from project_templates.json
- ✅ All template rules extracted (files + commands)
- ✅ Universal safety rules applied
- ✅ Backup created (via apply_permissions.py)
- ✅ Validation passed (all 20-35 rules)
- ✅ settings.json written successfully
- ✅ User informed with comprehensive summary
- ✅ Restart reminder provided
---
Token Budget Summary
Typical project setup:
Tier 1 (Metadata): 100 tokens ✅
Tier 2 (SKILL.md): 2,250 tokens ✅
project-setup-workflow: 1,500 tokens (this file)
project_templates.json: 200 tokens (surgical jq)
security_patterns.json: 100 tokens (surgical jq)
detect_project.py output: 0 tokens (script execution)
---
Total: 4,150 tokens
Status: ✅ 58% under budgetComplex project (monorepo, multiple types):
Tier 1 + 2 + this: 3,850 tokens ✅
Templates (2 languages): 400 tokens
Security patterns: 100 tokens
User interaction: 50 tokens
---
Total: 4,400 tokens
Status: ✅ 56% under budget---
Integration with Other Workflows
After project setup, user might:
1. Add specific file → Use file-pattern-workflow.md
- Example: "also make **.toml editable" (in addition to Cargo.toml)
2. Enable additional CLI tool → Use cli-tool-workflow.md
- Example: "enable docker" (for containerized Rust builds)
3. Apply profile on top → Use profile-application-workflow.md
- Example: "apply ci-cd profile" (for automated testing)
Template is foundation - other workflows add incremental permissions
---
Next Steps After Workflow
User must restart Claude Code for permissions to take effect.
Recommended testing: 1. Try editing a source file in the project 2. Run a build command (cargo build, npm test, mvn compile) 3. Verify deny rules work (try editing target/ or node_modules/)
Optional follow-ups:
- Validate:
python3 scripts/validate_config.py - Review:
grep "Edit(" settings.json | grep "LANGUAGE_EXTENSION" - Expand: Add more specific patterns via file-pattern-workflow
---
End of Project Setup Workflow Size: ~550 lines (~2,750 tokens) Compliance: ✅ Tier 3 (loaded on-demand only)
Research Workflow for Unknown Tools
Token Budget Tracker
This Workflow:
- Tier 1 (Metadata): 100 tokens ✅ (already loaded)
- Tier 2 (SKILL.md): 2,250 tokens ✅ (already loaded)
- This guide: ~1,500 tokens
- cli_commands.json metadata: ~150 tokens (research instructions)
- MCP tool usage: ~500 tokens (API calls)
- Estimated total: 4,500 tokens
- Status: ✅ Within budget (<10,000)
---
Purpose
Research and configure permissions for CLI tools NOT in the pre-configured database:
- "enable perl"
- "allow flutter commands"
- "configure elixir build tools"
- "setup zig compiler permissions"
When triggered: After cli-tool-workflow detects unknown tool
---
Research Tool Priority
From cli_commands.json `_meta.research_instructions`:
{
"priority_order": [
"mcp__perplexity-ask__perplexity_ask",
"mcp__brave-search__brave_web_search",
"Skill(gemini)",
"WebSearch"
]
}Waterfall Strategy: 1. Try Perplexity (preferred, most accurate) 2. If fails → Try Brave Search 3. If fails → Try Gemini skill (if available) 4. If fails → Fallback to WebSearch 5. If all fail → Ask user for manual input
---
Prerequisites
This workflow triggered when:
- cli-tool-workflow.md detected unknown tool (grep returned empty)
- User mentions tool not in cli_commands.json database
- Context passed from cli-tool-workflow:
{tool: "perl", mode: "READ"}
---
Workflow Steps
Step 1: Load Research Instructions
Extract research config from cli_commands.json:
jq '._meta.research_instructions' references/cli_commands.jsonToken Cost: ~150 tokens
Output:
{
"priority_order": [...],
"query_template": "What are the safe read-only commands for {tool}? What are the write/modify commands? What commands should never be allowed (dangerous)?",
"expected_format": {
"read_only": ["list of safe commands"],
"write": ["list of modification commands"],
"dangerous": ["list of dangerous commands"]
}
}Token Cost: ~150 tokens (surgical extraction)
---
Step 2: Construct Research Query
Query Template (from research_instructions):
Tool: {TOOL_NAME}
Mode: {MODE}
Research Questions:
1. What are the safe read-only commands for {TOOL_NAME}?
(Commands that only display information, no modifications)
2. What are the write/modify commands for {TOOL_NAME}?
(Commands that change state, write files, or modify configuration)
3. What are dangerous commands for {TOOL_NAME} that should NEVER be allowed?
(Commands that delete data, force operations, or have security implications)
4. What file patterns does {TOOL_NAME} typically work with?
(Config files, source files, build outputs)
Format response as JSON:
{
"tool": "TOOL_NAME",
"read_only": ["cmd1", "cmd2"],
"write": ["cmd3", "cmd4"],
"dangerous": ["cmd5", "cmd6"],
"file_patterns": {
"allow": ["pattern1", "pattern2"],
"deny": ["pattern3"]
}
}Example for Perl:
Tool: perl
Mode: READ
Research Questions:
1. What are the safe read-only commands for perl?
2. What are the write/modify commands for perl?
3. What are dangerous commands for perl that should NEVER be allowed?
4. What file patterns does perl typically work with?Token Cost: 0 tokens (template construction)
---
Step 3: Execute Research (Priority Waterfall)
Step 3a: Try Perplexity (Priority 1)
mcp__perplexity-ask__perplexity_ask({
"messages": [
{
"role": "user",
"content": "<constructed_query from Step 2>"
}
]
})Token Cost: ~300 tokens (API call + response)
Expected Response (Perplexity):
{
"tool": "perl",
"read_only": ["perl -v", "perl -c script.pl", "perldoc", "perl -e 'print'"],
"write": ["perl -pi.bak -e", "perl script.pl > output"],
"dangerous": ["perl -e 'unlink'", "perl -e 'system(\"rm\")'"],
"file_patterns": {
"allow": ["**.pl", "**.pm"],
"deny": []
}
}Success: Proceed to Step 4 Failure (timeout, error, no data): Proceed to Step 3b
---
Step 3b: Try Brave Search (Priority 2)
mcp__brave-search__brave_web_search({
"query": "perl safe read-only commands vs dangerous commands security best practices",
"count": 5
})Token Cost: ~200 tokens (API call + response)
Success: Parse results, extract command info Failure: Proceed to Step 3c
---
Step 3c: Try Gemini Skill (Priority 3)
Check if gemini skill available:
IF Skill(gemini) available:
Invoke Skill(gemini) with research query
ELSE:
Skip to Step 3dToken Cost: ~400 tokens (skill invocation)
Success: Extract commands from Gemini response Failure: Proceed to Step 3d
---
Step 3d: Fallback to WebSearch (Priority 4)
WebSearch({
"query": "perl commands list read-only vs write dangerous security"
})Token Cost: ~300 tokens
Success: Parse search results Failure: Proceed to Step 3e
---
Step 3e: Manual User Input (Last Resort)
If all research methods fail:
❌ **Could not auto-research Perl commands**
I tried:
- ✗ Perplexity API (not available or failed)
- ✗ Brave Search (no results)
- ✗ Gemini skill (not available)
- ✗ Web Search (insufficient data)
**Manual Input Required**:
Please provide Perl commands you want to allow:
1. Read-only commands (safe): ___________
2. Write commands (modify files): ___________
3. Dangerous commands to deny: ___________
Or respond "skip" to cancel Perl setup.Wait for user input
Token Cost: 0 tokens (user interaction)
---
Step 4: Parse and Validate Research Results
Parse response into structured data:
{
"tool": "perl",
"read_only": ["perl -v", "perl -c", "perldoc"],
"write": ["perl script.pl", "perl -pi.bak"],
"dangerous": ["perl -e 'unlink'", "perl -e 'system'"],
"file_patterns": {
"allow": ["**.pl", "**.pm"],
"deny": []
}
}Validation checks: 1. ✅ Tool name matches requested tool 2. ✅ At least 1 read_only command OR 1 write command 3. ✅ dangerous array exists (even if empty) 4. ✅ file_patterns has allow array
If validation fails:
- Log warning
- Use partial data if available
- Inform user of limitations
Token Cost: 0 tokens (validation logic)
---
Step 5: Build Permission Rules from Research
Mode-based rule construction:
For READ mode (user requested read-only):
Allow Rules:
- Bash(perl -v *)
- Bash(perl -c *)
- Bash(perldoc *)
- Read(**.pl)
- Read(**.pm)
Deny Rules:
- Bash(perl -e 'unlink' *)
- Bash(perl -e 'system' *)
- Bash(perl -pi.bak *) ← Write command (user requested read-only)For WRITE mode (user requested write access):
Allow Rules:
- Bash(perl -v *) ← read_only
- Bash(perl -c *) ← read_only
- Bash(perl script.pl *) ← write
- Bash(perl -pi.bak *) ← write
- Edit(**.pl)
- Edit(**.pm)
- Read(**.pl)
- Read(**.pm)
Deny Rules:
- Bash(perl -e 'unlink' *) ← dangerous
- Bash(perl -e 'system' *) ← dangerousRule Count: Typically 8-15 rules per unknown tool
Token Cost: 0 tokens (rule generation)
---
Step 6: Apply Universal Safety Rules
Load security_patterns.json:
jq '.recommended_deny_set.standard' references/security_patterns.jsonToken Cost: ~100 tokens
Add to deny rules:
- Read(.env*)
- Write(*.key)
- Bash(rm *)
- Bash(sudo *)
... (13 standard deny rules)Merge with tool-specific dangerous commands
Token Cost: ~100 tokens (security patterns)
---
Step 7: Execute apply_permissions.py
Command:
python3 scripts/apply_permissions.py \
--allow "Bash(perl -v *)" \
--allow "Bash(perl -c *)" \
--allow "Bash(perldoc *)" \
--allow "Read(**.pl)" \
--allow "Read(**.pm)" \
--deny "Bash(perl -e 'unlink' *)" \
--deny "Bash(perl -e 'system' *)" \
--deny "Bash(rm *)" \
--deny "Bash(sudo *)"Script Actions: 1. ✅ Create backup 2. ✅ Validate rules 3. ✅ Merge with settings 4. ✅ Write settings.json 5. ✅ Report
Token Cost: 0 tokens (script execution)
---
Step 8: Offer to Add to Database
Prompt user:
✅ **Perl permissions configured** (via research)
Would you like me to add Perl to the known tools database?
If yes:
- Future "enable perl" requests will be instant
- Commands saved to references/cli_commands.json
- No research needed next time
**Add Perl to database? (yes/no)**If user says yes:
Step 8a: Update cli_commands.json
jq '.perl = {
"description": "Perl scripting language",
"read_only": ["perl -v", "perl -c", "perldoc"],
"write": ["perl script.pl", "perl -pi.bak"],
"dangerous": ["perl -e '\''unlink'\''", "perl -e '\''system'\''"],
"file_patterns": {
"allow": ["**.pl", "**.pm"],
"deny": []
}
}' references/cli_commands.json > references/cli_commands.json.tmp \
&& mv references/cli_commands.json.tmp references/cli_commands.jsonStep 8b: Commit update (optional):
git add references/cli_commands.json
git commit -m "Add Perl tool configuration from research"Inform user:
✅ Perl added to database. Next time, "enable perl" will be instant!If user says no:
- Skip database update
- Permissions still applied (just for this session)
Token Cost: 0 tokens (file write, git ops)
---
Step 9: Confirm with User
Report Format:
✅ **Perl permissions configured** (researched via Perplexity)
**Commands enabled** (read-only mode):
- ✅ `perl -v` - Version check
- ✅ `perl -c script.pl` - Syntax check
- ✅ `perldoc` - Documentation viewer
**File patterns**:
- ✅ `Read(**.pl)` - Perl scripts
- ✅ `Read(**.pm)` - Perl modules
**Blocked commands** (dangerous):
- 🛡️ `perl -e 'unlink'` - File deletion
- 🛡️ `perl -e 'system'` - System command execution
- 🛡️ `perl -pi.bak` - In-place editing (write mode required)
**Research source**: Perplexity API
**Total rules**: 5 allow, 3 deny
**Backup created**: settings.20250116_155820.backup
**Next step**: Restart Claude Code for changes to take effect.Token Cost: 0 tokens (output to user)
---
Examples
Example 1: Research Perl (Success via Perplexity)
User Request: "enable perl"
Workflow Execution: 1. cli-tool-workflow detects unknown → Routes to research-workflow 2. Load research instructions from cli_commands.json._meta 3. Construct query for Perl 4. Try Perplexity: SUCCESS
{
"tool": "perl",
"read_only": ["perl -v", "perl -c", "perldoc"],
"write": ["perl script.pl"],
"dangerous": ["perl -e 'unlink'"]
}5. Build rules (mode=READ): 3 allow, 1 deny 6. Apply safety rules: +13 deny 7. Execute apply_permissions.py 8. Offer to add to database → User says "yes" 9. Update cli_commands.json with Perl entry 10. Confirm with user
Total tokens: 4,300 ✅
Research source: Perplexity (Priority 1)
---
Example 2: Research Flutter (Fallback to Brave)
User Request: "enable flutter"
Workflow Execution: 1. Route from cli-tool-workflow (flutter unknown) 2. Construct query for Flutter 3. Try Perplexity: FAILED (timeout) 4. Try Brave Search: SUCCESS
- Search results mention: flutter run, flutter build, flutter test
- Parse results into structured format
5. Build rules (mode=READ):
Allow: Bash(flutter doctor *), Bash(flutter --version *)
Deny: Bash(flutter build *), Bash(flutter pub publish *)6. Apply safety rules 7. Execute apply_permissions.py 8. Offer to add to database → User says "no" (wants to test first) 9. Confirm with user
Total tokens: 4,400 ✅
Research source: Brave Search (Priority 2 fallback)
---
Example 3: Research Zig (Manual Input Required)
User Request: "enable zig compiler"
Workflow Execution: 1. Route from cli-tool-workflow (zig unknown) 2. Construct query for Zig 3. Try Perplexity: FAILED (no Zig data) 4. Try Brave: FAILED (insufficient results) 5. Try Gemini skill: NOT AVAILABLE 6. Try WebSearch: FAILED (unclear results) 7. Manual input: Ask user for Zig commands
User provides:
- Read-only: zig version, zig targets
- Write: zig build, zig test
- Dangerous: zig build install (system-wide install)8. Build rules from user input 9. Apply safety rules 10. Execute apply_permissions.py 11. Offer to add to database → User says "yes" 12. Update cli_commands.json with Zig entry (from user input) 13. Confirm with user
Total tokens: 4,500 ✅
Research source: Manual user input (Priority 5 fallback)
---
Example 4: Research Unknown Tool with Write Mode
User Request: "enable elixir with write access"
Workflow Execution: 1. Tool=elixir, Mode=WRITE 2. Construct query for Elixir 3. Try Perplexity: SUCCESS
{
"tool": "elixir",
"read_only": ["elixir --version", "iex", "mix help"],
"write": ["mix compile", "mix test", "mix run"],
"dangerous": ["mix release --overwrite", "mix ecto.drop"]
}4. Build rules for WRITE mode:
Allow:
- Bash(elixir --version *) ← read_only
- Bash(mix help *) ← read_only
- Bash(mix compile *) ← write
- Bash(mix test *) ← write
- Edit(**.ex) ← Elixir source files
- Edit(**.exs) ← Elixir scripts
- Read(**.ex), Read(**.exs)
Deny:
- Bash(mix release --overwrite *) ← dangerous
- Bash(mix ecto.drop *) ← dangerous (drops database)5. Apply safety rules 6. Execute apply_permissions.py (12 allow, 15 deny) 7. Offer to add to database → User says "yes" 8. Confirm with comprehensive report
Total tokens: 4,400 ✅
---
Error Handling
Error 1: All research methods fail
Detection: All 4 priorities return no data + user declines manual input
Example:
Perplexity: timeout
Brave: no results
Gemini: not available
WebSearch: insufficient data
User: "skip" (declines manual input)Action: 1. Inform: "Cannot configure obscure-tool without command information" 2. Suggest alternatives:
- "Provide commands manually later"
- "Add tool to cli_commands.json yourself (see references/cli_commands.json format)"
- "Use file-pattern-workflow to enable file editing only"
3. Exit workflow without applying permissions
Recovery: Manual database entry or skip tool
---
Error 2: Research returns malformed data
Detection: Response doesn't match expected JSON format
Example:
{
"commands": "perl has many commands" ← Not structured
}Action: 1. Log: "Research returned malformed data for perl" 2. Attempt to parse natural language response:
- Extract commands using regex
- Look for patterns like "safe commands: X, Y, Z"
3. If parsing succeeds: Proceed with partial data 4. If parsing fails: Fallback to next priority or manual input
Recovery: Best-effort parsing or fallback
---
Error 3: Research contradicts user's mode request
Detection: User requested READ but research shows tool is write-only
Example:
User: "enable make read-only"
Research: "make is a build tool, inherently modifies files"Action: 1. WARN user: "make is a build tool and requires write access to function" 2. ASK: "Enable make with write permissions anyway? (yes/no)" 3. If yes: Apply write mode despite READ request 4. If no: Cancel make setup
Safety principle: Inform user when tool can't operate in requested mode
---
Error 4: Database update fails (Step 8)
Detection: jq update or git commit fails
Example Error:
❌ Failed to update cli_commands.json: Permission deniedAction: 1. Permissions STILL applied (user can use tool immediately) 2. INFORM: "Perl permissions applied but couldn't add to database" 3. SUGGEST: "Manually add to references/cli_commands.json or fix file permissions" 4. Exit workflow (permissions already applied in Step 7)
Recovery: Manual database entry later (not critical for immediate use)
---
Edge Cases
Edge Case 1: Tool already partially known
Example: Database has "perl" with only 2 commands, research finds 10 more
Handling: 1. Detect: Tool exists in database but incomplete 2. ASK user: "Perl is in database but research found more commands. Update entry? (yes/no)" 3. If yes:
- Merge research results with existing entry
- Keep user customizations if any
- Update database
4. If no:
- Use existing database entry only
Policy: User can choose to expand existing entries
---
Edge Case 2: Research suggests file patterns not requested
Example: User asked for "enable perl" (just commands), research suggests **.pl editing
Handling: 1. Research returns file_patterns in addition to commands 2. INFORM user: "Research suggests editing .pl files. Enable file editing too? (yes/no)" 3. If yes: Add Edit(.pl) + Read(**.pl) rules 4. If no: Skip file patterns, apply only command rules
Default: Ask user (don't assume file editing wanted)
---
Edge Case 3: Tool has aliases
Example: Research finds "python" and "python3" are same tool
Handling: 1. Research returns: "aliases": ["python", "python3"] 2. Apply rules for BOTH aliases:
Bash(python *)
Bash(python3 *)3. Inform: "Enabled python (including python3 alias)"
Token cost: Minimal (just extra rules)
---
Edge Case 4: Research quality varies by priority
Example:
- Perplexity: Detailed with 10 commands + examples
- Brave: Generic with 3 commands only
- WebSearch: Vague with unclear safety info
Handling: 1. Prefer higher priority even if less commands (more trustworthy) 2. Exception: If higher priority < 3 commands AND lower priority >= 5 commands
- Consider using lower priority with warning
- ASK user: "Perplexity found 2 commands, Brave found 7. Use Brave results? (yes/no)"
Safety first: Prefer authoritative source even if less comprehensive
---
Success Criteria
Workflow complete when:
- ✅ Unknown tool researched via priority waterfall
- ✅ Command structure extracted (read_only, write, dangerous)
- ✅ Mode-appropriate rules built
- ✅ Universal safety rules applied
- ✅ Backup created
- ✅ Validation passed
- ✅ settings.json written
- ✅ (Optional) Database updated with new tool
- ✅ User informed with research source
- ✅ Restart reminder provided
---
Token Budget Summary
Successful research (Perplexity):
Tier 1 (Metadata): 100 tokens ✅
Tier 2 (SKILL.md): 2,250 tokens ✅
research-workflow.md: 1,500 tokens (this file)
cli_commands metadata: 150 tokens (research config)
Perplexity API: 300 tokens (query + response)
Security patterns: 100 tokens (surgical)
---
Total: 4,400 tokens
Status: ✅ 56% under budgetResearch with fallbacks (Brave):
Tier 1 + 2 + this: 3,850 tokens ✅
Perplexity attempt: 100 tokens (failed)
Brave API: 200 tokens (success)
Security patterns: 100 tokens
---
Total: 4,250 tokens
Status: ✅ 57% under budgetManual input (all research failed):
Tier 1 + 2 + this: 3,850 tokens ✅
All research attempts: 600 tokens (all failed)
User interaction: 0 tokens
Security patterns: 100 tokens
---
Total: 4,550 tokens
Status: ✅ 54% under budget---
Next Steps After Workflow
User must restart Claude Code for permissions to take effect.
Testing the researched tool: 1. Try a read-only command (should work) 2. Try a write command if mode=WRITE (should work) 3. Try a dangerous command (should be blocked)
If tool doesn't work as expected:
- Research may have been incomplete
- User can add missing commands via cli-tool-workflow
- Or manually edit cli_commands.json
Optional follow-ups:
- Validate:
python3 scripts/validate_config.py - View what was researched:
jq '.TOOL_NAME' references/cli_commands.json(if added to database) - Share with community: Contribute researched tool to upstream repo
---
End of Research Workflow Size: ~600 lines (~3,000 tokens) Compliance: ✅ Tier 3 (loaded on-demand only)
MIT License
Copyright (c) 2025 Spillwave Solutions
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
"_meta": {
"description": "Comprehensive database of CLI tools with read-only vs write operations",
"version": "1.0.0",
"last_updated": "2025-01-16",
"research_instructions": {
"when_tool_not_found": "Use research workflow to discover commands",
"priority_order": [
"mcp__perplexity-ask__perplexity_ask (if available)",
"mcp__brave-search__brave_web_search",
"gemini skill (if available)",
"WebSearch (built-in Claude Code)"
],
"query_template": "What are the read-only commands vs write/destructive commands for {tool}? List them separately with examples.",
"validation": "Always present findings to user for confirmation before applying"
}
},
"git": {
"description": "Distributed version control system",
"read_only": [
"status",
"log",
"diff",
"show",
"branch",
"remote",
"config --list",
"blame",
"reflog"
],
"write": [
"commit",
"push",
"pull",
"add",
"merge",
"rebase",
"reset",
"checkout",
"tag",
"stash",
"cherry-pick"
],
"dangerous": [
"push --force",
"push -f",
"reset --hard",
"clean -fd",
"filter-branch"
]
},
"gcloud": {
"description": "Google Cloud Platform CLI",
"read_only": [
"list",
"describe",
"get-iam-policy",
"get",
"show"
],
"write": [
"create",
"delete",
"update",
"deploy",
"set",
"add-iam-policy-binding",
"remove-iam-policy-binding",
"run"
],
"dangerous": [
"delete",
"projects delete",
"remove-iam-policy-binding"
],
"notes": "Commands follow pattern: gcloud <service> <resource> <verb>"
},
"aws": {
"description": "Amazon Web Services CLI",
"read_only": [
"describe-*",
"list-*",
"get-*"
],
"write": [
"create-*",
"delete-*",
"update-*",
"put-*",
"register-*",
"deregister-*"
],
"dangerous": [
"delete-*",
"terminate-*"
],
"notes": "Verb-based naming: describe/list/get for read, create/delete/update for write"
},
"kubectl": {
"description": "Kubernetes command-line tool",
"read_only": [
"get",
"describe",
"logs",
"top",
"explain"
],
"write": [
"create",
"delete",
"apply",
"patch",
"edit",
"scale",
"rollout",
"exec",
"port-forward"
],
"dangerous": [
"delete",
"drain",
"cordon"
],
"rbac_mapping": {
"read": ["get", "list", "watch"],
"write": ["create", "update", "patch", "delete"]
}
},
"docker": {
"description": "Container platform CLI",
"read_only": [
"ps",
"images",
"logs",
"inspect",
"stats",
"version",
"info",
"history"
],
"write": [
"run",
"create",
"start",
"stop",
"restart",
"rm",
"rmi",
"build",
"pull",
"push",
"tag",
"commit"
],
"dangerous": [
"rm -f",
"rmi -f",
"system prune",
"volume rm"
]
},
"npm": {
"description": "Node.js package manager",
"read_only": [
"list",
"ls",
"view",
"search",
"audit",
"outdated",
"config list",
"doctor"
],
"write": [
"install",
"i",
"update",
"publish",
"audit fix",
"uninstall",
"ci"
],
"dangerous": [
"publish",
"unpublish"
]
},
"pip": {
"description": "Python package installer",
"read_only": [
"list",
"show",
"freeze",
"check",
"search",
"debug"
],
"write": [
"install",
"uninstall",
"download",
"wheel"
],
"dangerous": [
"uninstall -y"
]
},
"maven": {
"description": "Java build automation tool",
"read_only": [
"compile",
"test",
"package",
"dependency:tree",
"dependency:list",
"help:*",
"versions:display-dependency-updates"
],
"write": [
"install",
"deploy"
],
"dangerous": [
"deploy"
],
"notes": "compile/test/package only write to target/ directory"
},
"gradle": {
"description": "Build automation system",
"read_only": [
"tasks",
"dependencies",
"dependencyInsight",
"properties",
"-m",
"--dry-run",
"projects"
],
"write": [
"build",
"assemble",
"clean",
"test",
"publish",
"--write-locks"
],
"dangerous": [
"publish"
]
},
"terraform": {
"description": "Infrastructure as code tool",
"read_only": [
"plan",
"show",
"validate",
"state list",
"state show",
"output",
"version",
"providers"
],
"write": [
"apply",
"destroy",
"init",
"import",
"state mv",
"state push"
],
"dangerous": [
"destroy",
"apply -auto-approve",
"destroy -auto-approve"
]
},
"cargo": {
"description": "Rust package manager",
"read_only": [
"check",
"test",
"clippy",
"search",
"tree",
"metadata"
],
"write": [
"build",
"run",
"clean",
"publish",
"install",
"update"
],
"dangerous": [
"publish",
"yank"
]
},
"go": {
"description": "Go programming language toolchain",
"read_only": [
"list",
"version",
"env",
"doc",
"fmt -n"
],
"write": [
"build",
"run",
"install",
"get",
"mod tidy",
"mod download",
"clean",
"generate"
],
"dangerous": [
"clean -modcache"
]
},
"helm": {
"description": "Kubernetes package manager",
"read_only": [
"list",
"get",
"status",
"history",
"search",
"show",
"version"
],
"write": [
"install",
"upgrade",
"uninstall",
"rollback",
"create",
"package"
],
"dangerous": [
"uninstall",
"delete"
]
},
"ansible": {
"description": "IT automation platform",
"read_only": [
"inventory --list",
"config dump",
"doc",
"--check",
"--diff"
],
"write": [
"playbook",
"vault encrypt",
"vault decrypt",
"galaxy install"
],
"dangerous": [
"playbook (without --check)"
],
"notes": "--check flag makes playbook read-only (dry-run)"
},
"pulumi": {
"description": "Infrastructure as code",
"read_only": [
"preview",
"stack ls",
"stack output",
"config get",
"about"
],
"write": [
"up",
"destroy",
"refresh",
"import",
"stack init",
"config set"
],
"dangerous": [
"destroy",
"up --yes"
]
},
"az": {
"description": "Azure CLI",
"read_only": [
"list",
"show",
"get"
],
"write": [
"create",
"delete",
"update",
"set"
],
"dangerous": [
"delete",
"group delete"
],
"notes": "Similar pattern to gcloud: az <service> <resource> <verb>"
},
"claude": {
"description": "Claude Code CLI",
"commands": [
"claude",
"-p",
"--print",
"-c",
"--continue",
"update",
"mcp"
],
"slash_commands": [
"/help",
"/config",
"/status",
"/permissions",
"/allowed-tools",
"/mcp",
"/privacy-settings",
"/cost",
"/usage",
"/memory",
"/export",
"/vim"
],
"flags": [
"--allowedTools",
"--disallowedTools",
"--add-dir",
"--output-format",
"--agents"
],
"dangerous_flags": [
"--dangerously-skip-permissions"
]
},
"gemini": {
"description": "Gemini CLI",
"slash_commands": [
"/help",
"/chat",
"/settings",
"/mcp",
"/memory",
"/tools",
"/stats",
"/theme",
"/auth",
"/quit",
"/exit",
"/vim",
"/init",
"/bug",
"/compress",
"/copy",
"/directory",
"/editor",
"/extensions",
"/restore",
"/privacy",
"/about"
],
"special_syntax": {
"@": "File injection",
"!": "Shell mode toggle"
},
"modes": [
"-p (non-interactive print mode)"
]
},
"yarn": {
"description": "JavaScript package manager",
"read_only": [
"list",
"info",
"why",
"outdated",
"check"
],
"write": [
"add",
"remove",
"upgrade",
"install",
"publish"
],
"dangerous": [
"publish"
]
},
"bundle": {
"description": "Ruby dependency manager",
"read_only": [
"list",
"show",
"outdated",
"check"
],
"write": [
"install",
"update",
"add",
"remove"
],
"dangerous": []
},
"composer": {
"description": "PHP dependency manager",
"read_only": [
"show",
"search",
"outdated",
"validate"
],
"write": [
"install",
"update",
"require",
"remove"
],
"dangerous": []
}
}
{
"_meta": {
"description": "Universal security deny rules to prevent accidental exposure or destruction",
"version": "1.0.0",
"usage": "Always apply these deny rules when adding any permissions"
},
"sensitive_files": {
"description": "Files that should never be readable to prevent credential/secret exposure",
"patterns": [
"Read(.env)",
"Read(.env.*)",
"Read(*.key)",
"Read(*.pem)",
"Read(*.p12)",
"Read(*.pfx)",
"Read(.aws/**)",
"Read(.ssh/**)",
"Read(secrets/**)",
"Read(credentials/**)",
"Read(**/credentials.json)",
"Read(**/service-account.json)",
"Read(**/.npmrc)",
"Read(**/.pypirc)",
"Read(**/id_rsa)",
"Read(**/id_rsa.pub)",
"Read(**/.netrc)"
]
},
"sensitive_writes": {
"description": "Files that should never be writable to prevent corruption of critical configs",
"patterns": [
"Write(.env)",
"Write(.env.*)",
"Write(production.*)",
"Write(prod.*)",
"Write(*.key)",
"Write(*.pem)",
"Write(.git/**)",
"Write(.aws/credentials)",
"Write(.ssh/id_rsa)"
]
},
"dangerous_commands": {
"description": "Commands that can cause irreversible damage or security issues",
"patterns": [
"Bash(rm -rf *)",
"Bash(rm -rf /)",
"Bash(rm *)",
"Bash(sudo rm *)",
"Bash(sudo *)",
"Bash(chmod 777 *)",
"Bash(chmod *)",
"Bash(chown *)",
"Bash(dd *)",
"Bash(mkfs *)",
"Bash(fdisk *)",
"Bash(parted *)",
"Bash(curl * | bash)",
"Bash(wget * | bash)",
"Bash(curl * | sh)",
"Bash(wget * | sh)"
]
},
"force_operations": {
"description": "Force flags that bypass safety checks",
"patterns": [
"Bash(git push * --force)",
"Bash(git push * -f)",
"Bash(git reset --hard *)",
"Bash(git clean -fd *)",
"Bash(docker rm -f *)",
"Bash(docker rmi -f *)",
"Bash(kubectl delete * --force)",
"Bash(terraform apply -auto-approve)",
"Bash(terraform destroy -auto-approve)",
"Bash(pulumi up --yes)"
]
},
"production_deployments": {
"description": "Commands that deploy to production or public registries",
"patterns": [
"Bash(npm publish)",
"Bash(cargo publish)",
"Bash(mvn deploy)",
"Bash(gradle publish)",
"Bash(pip upload)",
"Bash(docker push * prod*)",
"Bash(docker push * production*)",
"Bash(gcloud * deploy * --project=*prod*)",
"Bash(aws * deploy * --env=prod*)",
"Bash(kubectl apply * --namespace=prod*)",
"Bash(helm install * production)",
"Bash(terraform apply * -var-file=prod*)"
]
},
"database_destructive": {
"description": "Database commands that can destroy data",
"patterns": [
"Bash(* DROP DATABASE *)",
"Bash(* DROP TABLE *)",
"Bash(* DELETE FROM *)",
"Bash(* TRUNCATE *)",
"Bash(psql * -c 'DROP *')",
"Bash(mysql * -e 'DROP *')"
]
},
"recommended_deny_set": {
"description": "Standard deny rules to apply for most projects",
"minimal": [
"Read(.env*)",
"Read(*.key)",
"Read(*.pem)",
"Bash(rm *)",
"Bash(sudo *)"
],
"standard": [
"Read(.env*)",
"Read(*.key)",
"Read(*.pem)",
"Read(.aws/**)",
"Read(.ssh/**)",
"Read(secrets/**)",
"Write(.env*)",
"Write(production.*)",
"Bash(rm *)",
"Bash(sudo *)",
"Bash(chmod *)",
"Bash(curl * | bash)",
"Bash(wget * | bash)",
"Bash(git push * --force)"
],
"strict": [
"Read(.env*)",
"Read(*.key)",
"Read(*.pem)",
"Read(*.p12)",
"Read(.aws/**)",
"Read(.ssh/**)",
"Read(secrets/**)",
"Read(credentials/**)",
"Write(.env*)",
"Write(production.*)",
"Write(*.key)",
"Write(*.pem)",
"Write(.git/**)",
"Bash(rm *)",
"Bash(sudo *)",
"Bash(chmod *)",
"Bash(chown *)",
"Bash(dd *)",
"Bash(mkfs *)",
"Bash(curl * | bash)",
"Bash(wget * | bash)",
"Bash(git push * --force)",
"Bash(git reset --hard *)",
"Bash(npm publish)",
"Bash(mvn deploy)",
"Bash(terraform destroy *)"
]
}
}