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 serverdefrun_testsresult=client.shell.exec("bundle exec rspec",stream: true)say"Tests #{result.success? ? 'passed' : 'failed'}"end# Run linterdeflintclient.shell.exec("rubocop --autocorrect")end2. Git operations
# Get current branch (alternative to reading .git/config per #5)defcurrent_branchclient.shell.exec("git branch --show-current").stdout.stripend# Create and push a branchdefcreate_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 analysisdefgenerate_model(name,fields)client.shell.exec("rails generate model #{name}#{fields.join(' ')}")end# Install dependenciesdefsetup_projectclient.shell.exec("bundle install")client.shell.exec("yarn install")client.shell.exec("rails db:setup")end4. Deployment workflows
# Deploy with server-coordinated stepsdefdeploysay"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 editordefedit_configclient.shell.exec("$EDITOR config/settings.yml")end# Open PR in browserdefopen_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.ymlshell:
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 executionresult=client.shell.exec("command")result.stdout# => "output"result.stderr# => "errors" result.exitstatus# => 0result.success?# => true# With optionsclient.shell.exec("long-command",timeout: 300,# Max secondsstream: true,# Stream output in real-timeenv: {"FOO"=>"bar"},# Additional env varschdir: "subdir"# Working directory)# Check if command is allowed before runningifclient.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!
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
2. Git operations
3. Project scaffolding / code generation
4. Deployment workflows
5. Editor integration
Security 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
Interactive prompts (per #5 discussion)
Proposed API
Real-World Inspiration
This is inspired by tools like:
gh) - runs git commands, opens browserThe 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!