Skip to content

Conversation

@kirmalyshev
Copy link

Summary

  • Custom Claude commands can now be configured at three levels with override hierarchy: worktree → repository → folder (global)
  • Shell injection vulnerability fixed using shlex.quote() in tmux command execution
  • New modal with preset buttons for quick selection (claude, opus, sonnet)

Configuration Hierarchy

┌──────────────────────────────────────────────────────────┐
│  Worktree Level (most specific)                          │
│  └─ custom_claude_command in Worktree model              │
│     ↓ falls back to                                      │
├──────────────────────────────────────────────────────────┤
│  Repository Level                                        │
│  └─ custom_claude_command in Repository model            │
│     ↓ falls back to                                      │
├──────────────────────────────────────────────────────────┤
│  Folder Level (global)                                   │
│  └─ custom_claude_command in Settings                    │
│     ↓ falls back to                                      │
├──────────────────────────────────────────────────────────┤
│  Default: "claude"                                       │
└──────────────────────────────────────────────────────────┘

UI Changes

New "Command" Button in Detail Views

Both repository and worktree detail views now have a Command button in the MANAGE section:

┌─────────────────────────────────────────┐
│ MANAGE                                  │
│ ┌─────────┐ ┌─────────┐ ┌────────┐     │
│ │ Command │ │ Archive │ │ Delete │     │
│ └─────────┘ └─────────┘ └────────┘     │
└─────────────────────────────────────────┘

New ClaudeCommandModal

┌─────────────────────────────────────────┐
│        ⚙ Custom Claude Command          │
│        for myrepo:feature-branch        │
│                                         │
│ PRESETS                                 │
│ ┌────────┐ ┌──────┐ ┌────────┐         │
│ │ claude │ │ opus │ │ sonnet │         │
│ └────────┘ └──────┘ └────────┘         │
│                                         │
│ COMMAND                                 │
│ ┌─────────────────────────────────────┐ │
│ │ claude --model opus                 │ │
│ └─────────────────────────────────────┘ │
│ Leave empty to use repo default         │
│                                         │
│      ┌────────┐  ┌────────┐            │
│      │ Cancel │  │  Save  │            │
│      └────────┘  └────────┘            │
└─────────────────────────────────────────┘

Settings Modal Update

Added CUSTOM CLAUDE COMMAND section:

┌─────────────────────────────────────────┐
│ CUSTOM CLAUDE COMMAND                   │
│ ┌─────────────────────────────────────┐ │
│ │ claude --model opus                 │ │
│ └─────────────────────────────────────┘ │
│ Default command for all repos           │
│ (can be overridden per-repo)            │
└─────────────────────────────────────────┘

Security Fix

Shell injection vulnerability in tmux.py fixed:

# Before (vulnerable):
shell_cmd = f'{shell} -ic "{cmd}"'

# After (safe):
shell_cmd = f"{shell} -ic {shlex.quote(cmd)}"

Files Changed

File Changes
models.py Added custom_claude_command field to Settings, Repository, Worktree; Added ClaudeCommandResult dataclass; Added validation functions and Pydantic validators
app.py Added _resolve_claude_command() hierarchy; Added _show_claude_command_modal() handler; Pass custom command to tmux service
modals.py Added ClaudeCommandModal with presets; Updated SettingsModal with command input and validation
tmux.py Added custom_command parameter; Fixed shell injection with shlex.quote()
state.py Added update_repository_command() and update_worktree_command() methods
repository_detail.py Added "Command" button
worktree_detail.py Added "Command" button with worktree_id support
components/messages.py New file with shared ConfigureClaudeCommand message
theme.py Removed orphaned .section-header-row CSS

Test plan

  • Configure folder-level command in Settings → verify all new Claude sessions use it
  • Configure repo-level command → verify it overrides folder-level
  • Configure worktree-level command → verify it overrides repo-level
  • Clear worktree command → verify it falls back to repo level
  • Clear repo command → verify it falls back to folder level
  • Test preset buttons fill input correctly
  • Test validation rejects commands with newlines/control characters
  • Test validation rejects commands > 200 characters
  • Verify shell injection attempt is safely quoted

🤖 Generated with Claude Code

Allows users to configure custom Claude commands (e.g., "claude --model opus")
at three levels with override priority: worktree > repository > folder (global).

Key changes:
- Add custom_claude_command field to Settings, Repository, and Worktree models
- Add ClaudeCommandModal with preset buttons (claude, opus, sonnet)
- Add "Command" button in repository/worktree detail views
- Implement command resolution hierarchy in app.py
- Fix shell injection vulnerability using shlex.quote() in tmux.py
- Add Pydantic field validators for command validation
- Extract shared ConfigureClaudeCommand message to components/messages.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant