-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
Summary
I'd love to see support for executing shell commands on the client machine. This would unlock powerful CLI tool workflows that need to interact with the user's local environment.
Related to #5 (File and directory access entitlements) - both features would benefit from the same entitlement/permission system.
Use Cases
1. Running project commands
# Run tests and stream output back to server
def run_tests
result = client.shell.exec("bundle exec rspec", stream: true)
say "Tests #{result.success? ? 'passed' : 'failed'}"
end
# Run linter
def lint
client.shell.exec("rubocop --autocorrect")
end2. Git operations
# Get current branch (alternative to reading .git/config per #5)
def current_branch
client.shell.exec("git branch --show-current").stdout.strip
end
# Create and push a branch
def create_feature_branch(name)
client.shell.exec("git checkout -b feature/#{name}")
client.shell.exec("git push -u origin feature/#{name}")
end3. Project scaffolding / code generation
# Generate Rails scaffold based on server-side AI analysis
def generate_model(name, fields)
client.shell.exec("rails generate model #{name} #{fields.join(' ')}")
end
# Install dependencies
def setup_project
client.shell.exec("bundle install")
client.shell.exec("yarn install")
client.shell.exec("rails db:setup")
end4. Deployment workflows
# Deploy with server-coordinated steps
def deploy
say "Running pre-deploy checks..."
client.shell.exec("bundle exec rspec --fail-fast")
say "Building assets..."
client.shell.exec("rails assets:precompile")
say "Deploying..."
client.shell.exec("kamal deploy")
end5. Editor integration
# Open file in user's preferred editor
def edit_config
client.shell.exec("$EDITOR config/settings.yml")
end
# Open PR in browser
def open_pr(number)
client.shell.exec("gh pr view #{number} --web")
endSecurity Considerations
Shell execution needs careful security design. Since everything is denied by default, users just need a way to allowlist specific commands or patterns:
Command allowlists
# ~/.terminalwire/policies/myapp.com.yml
shell:
allow:
- "git *"
- "bundle exec *"
- "rails *"
- "npm run *"
- "kamal *"Interactive prompts (per #5 discussion)
$ myapp deploy
⚠️ Server requests: execute "bundle exec rspec"
[D]eny [O]nce [A]llow "bundle exec *" [T]rust this server
Proposed API
# Basic execution
result = client.shell.exec("command")
result.stdout # => "output"
result.stderr # => "errors"
result.exitstatus # => 0
result.success? # => true
# With options
client.shell.exec("long-command",
timeout: 300, # Max seconds
stream: true, # Stream output in real-time
env: { "FOO" => "bar" }, # Additional env vars
chdir: "subdir" # Working directory
)
# Check if command is allowed before running
if client.shell.allowed?("git push")
client.shell.exec("git push")
endReal-World Inspiration
This is inspired by tools like:
- GitHub CLI (
gh) - runs git commands, opens browser - Heroku CLI - runs local commands, syncs with server
- Kamal - orchestrates local Docker/git with remote deploys
- Claude Code - AI coding assistant that runs shell commands
The key insight is that many powerful CLI tools need to be a bridge between server-side logic and client-side execution.
Happy to help design or test this feature!
Metadata
Metadata
Assignees
Labels
No labels