Configuration
The repository ships one copyable starter file: .env.example. Docker Compose reads the resulting .env file automatically, and other runtimes can use the same LOCAL_SHELL_MCP_ environment variables. YAML remains an optional advanced input for binary or source deployments; create a file explicitly and select it with LOCAL_SHELL_MCP_CONFIG or --config. Environment variables override YAML values, so avoid defining the same setting in both unless the override is intentional. YAML keys use the field names shown below.
Precedence
- Built-in defaults from
Settings.
- YAML config selected by
LOCAL_SHELL_MCP_CONFIG or --config.
- Environment variables with the
LOCAL_SHELL_MCP_ prefix.
- CLI flags such as
--mode, --config, --remote, and --no-remote, which set the corresponding environment values before settings load.
Minimal public configuration
LOCAL_SHELL_MCP_PUBLIC_BASE_URL=https://your-public-host.example.com
LOCAL_SHELL_MCP_AUTH_MODE=oauth
LOCAL_SHELL_MCP_OAUTH_ADMIN_PIN=change-me-long-random-pin
LOCAL_SHELL_MCP_OAUTH_JWT_SECRET=change-me-long-random-secret
For local-only testing, auth_bypass_localhost is enabled by default. Do not expose unauthenticated full MCP tools on a public network.
Settings reference
Server and workspace
| YAML key |
Environment variable |
Default |
Notes |
host |
LOCAL_SHELL_MCP_HOST |
'0.0.0.0' |
|
port |
LOCAL_SHELL_MCP_PORT |
8765 |
|
forwarded_allow_ips |
LOCAL_SHELL_MCP_FORWARDED_ALLOW_IPS |
'127.0.0.1' |
Comma-separated trusted proxy IPs for Uvicorn forwarded-header handling. Use * only when direct ingress is restricted. |
mode |
LOCAL_SHELL_MCP_MODE |
'mcp' |
mcp, http, stdio, or reserved both value. |
workspace_root |
LOCAL_SHELL_MCP_WORKSPACE_ROOT |
PosixPath('/workspace') |
|
state_dir |
LOCAL_SHELL_MCP_STATE_DIR |
PosixPath('/workspace/.local-shell-mcp') |
|
audit_log_path |
LOCAL_SHELL_MCP_AUDIT_LOG_PATH |
PosixPath('/workspace/.local-shell-mcp/audit.jsonl') |
|
agent_config_dir |
LOCAL_SHELL_MCP_AGENT_CONFIG_DIR |
PosixPath('/workspace/.local-shell-mcp/agent_config') |
|
allow_full_container |
LOCAL_SHELL_MCP_ALLOW_FULL_CONTAINER |
False |
Disables workspace/path restrictions when true; use only inside disposable boundaries. |
disable_local |
LOCAL_SHELL_MCP_DISABLE_LOCAL |
False |
Disables the controller host as a shell/file/browser execution target. Remote workers and control-plane services remain available. |
stateless_controller |
LOCAL_SHELL_MCP_STATELESS_CONTROLLER |
False |
Makes the controller suitable for ephemeral/serverless instances: implies disable_local, disables local file links/wallpaper caching, and defaults state_backend to memory. With the default auth_mode=oauth, configure a strong oauth_jwt_secret explicitly. |
state_backend |
LOCAL_SHELL_MCP_STATE_BACKEND |
'file' |
file, memory, or redis. Use Redis when serverless controller state must survive cold starts. |
state_backend_url |
LOCAL_SHELL_MCP_STATE_BACKEND_URL |
None |
Redis connection URL when state_backend=redis. Redacted from diagnostics. |
state_backend_prefix |
LOCAL_SHELL_MCP_STATE_BACKEND_PREFIX |
'local-shell-mcp' |
Namespace for memory/Redis control-plane state. |
Limits
| YAML key |
Environment variable |
Default |
Notes |
default_timeout_s |
LOCAL_SHELL_MCP_DEFAULT_TIMEOUT_S |
60 |
|
max_timeout_s |
LOCAL_SHELL_MCP_MAX_TIMEOUT_S |
3600 |
|
max_output_bytes |
LOCAL_SHELL_MCP_MAX_OUTPUT_BYTES |
200000 |
|
max_file_read_bytes |
LOCAL_SHELL_MCP_MAX_FILE_READ_BYTES |
512000 |
|
max_file_write_bytes |
LOCAL_SHELL_MCP_MAX_FILE_WRITE_BYTES |
5000000 |
|
max_grep_results |
LOCAL_SHELL_MCP_MAX_GREP_RESULTS |
200 |
|
max_directory_entries |
LOCAL_SHELL_MCP_MAX_DIRECTORY_ENTRIES |
5000 |
|
max_glob_results |
LOCAL_SHELL_MCP_MAX_GLOB_RESULTS |
5000 |
|
max_tree_entries |
LOCAL_SHELL_MCP_MAX_TREE_ENTRIES |
5000 |
|
max_skills |
LOCAL_SHELL_MCP_MAX_SKILLS |
256 |
Maximum Skill directories returned by one registry scan. |
max_skill_related_files |
LOCAL_SHELL_MCP_MAX_SKILL_RELATED_FILES |
1000 |
Maximum related files returned for one Skill. |
max_skill_scan_entries |
LOCAL_SHELL_MCP_MAX_SKILL_SCAN_ENTRIES |
5000 |
Maximum filesystem entries examined by one skill_list registry scan or one direct Skill load. |
max_skill_path_bytes |
LOCAL_SHELL_MCP_MAX_SKILL_PATH_BYTES |
200000 |
Maximum UTF-8 bytes used by returned related-file paths. |
max_read_many_files |
LOCAL_SHELL_MCP_MAX_READ_MANY_FILES |
100 |
|
max_read_many_total_bytes |
LOCAL_SHELL_MCP_MAX_READ_MANY_TOTAL_BYTES |
5000000 |
|
max_http_request_bytes |
LOCAL_SHELL_MCP_MAX_HTTP_REQUEST_BYTES |
16000000 |
Maximum buffered HTTP request body across MCP, REST, OAuth, UI, and remote-worker endpoints. |
max_job_log_bytes |
LOCAL_SHELL_MCP_MAX_JOB_LOG_BYTES |
10000000 |
Maximum retained output bytes for each long-running job attempt. |
max_jobs |
LOCAL_SHELL_MCP_MAX_JOBS |
1000 |
Maximum retained long-running job records; active jobs are never pruned. |
max_audit_tail_bytes |
LOCAL_SHELL_MCP_MAX_AUDIT_TAIL_BYTES |
1000000 |
|
max_audit_log_bytes |
LOCAL_SHELL_MCP_MAX_AUDIT_LOG_BYTES |
20000000 |
|
max_audit_archive_bytes |
LOCAL_SHELL_MCP_MAX_AUDIT_ARCHIVE_BYTES |
512000000 |
Compressed audit archive budget; oldest .jsonl.zst archives are pruned first. |
max_tmp_files |
LOCAL_SHELL_MCP_MAX_TMP_FILES |
500 |
|
max_tmp_bytes |
LOCAL_SHELL_MCP_MAX_TMP_BYTES |
50000000 |
|
max_transfer_archive_entries |
LOCAL_SHELL_MCP_MAX_TRANSFER_ARCHIVE_ENTRIES |
100000 |
Maximum entries accepted while unpacking a transferred directory archive. |
max_transfer_unpacked_bytes |
LOCAL_SHELL_MCP_MAX_TRANSFER_UNPACKED_BYTES |
10000000000 |
Maximum declared expanded bytes accepted for a transferred directory archive. |
max_concurrent_commands |
LOCAL_SHELL_MCP_MAX_CONCURRENT_COMMANDS |
4 |
|
max_tmux_sessions |
LOCAL_SHELL_MCP_MAX_TMUX_SESSIONS |
16 |
Maximum persistent shell sessions across tmux, ConPTY, and native fallback backends. |
File links
| YAML key |
Environment variable |
Default |
Notes |
file_download_enabled |
LOCAL_SHELL_MCP_FILE_DOWNLOAD_ENABLED |
True |
|
file_download_default_ttl_s |
LOCAL_SHELL_MCP_FILE_DOWNLOAD_DEFAULT_TTL_S |
3600 |
|
file_download_max_ttl_s |
LOCAL_SHELL_MCP_FILE_DOWNLOAD_MAX_TTL_S |
604800 |
|
file_download_default_max_downloads |
LOCAL_SHELL_MCP_FILE_DOWNLOAD_DEFAULT_MAX_DOWNLOADS |
0 |
0 means no default download-count limit. |
file_download_max_file_bytes |
LOCAL_SHELL_MCP_FILE_DOWNLOAD_MAX_FILE_BYTES |
0 |
0 means no configured file-size cap for download links. |
Human interface
| YAML key |
Environment variable |
Default |
Notes |
logical_sessions_enabled |
LOCAL_SHELL_MCP_LOGICAL_SESSIONS_ENABLED |
True |
Exposes session_manage and plan_manage and adds the required nullable logical_session_id argument to ordinary MCP tools. Disable for a smaller session-free tool surface. |
live_workspace_enabled |
LOCAL_SHELL_MCP_LIVE_WORKSPACE_ENABLED |
True |
Exposes the MCP App Live Workspace tools, resources, and /api/live/* routes. Requires ui_enabled and is unavailable in stdio mode. |
ui_enabled |
LOCAL_SHELL_MCP_UI_ENABLED |
True |
Mounts the native OpenTUI launcher, WebUI shell, PTY WebSocket, and /api/ui/* routes. |
ui_path |
LOCAL_SHELL_MCP_UI_PATH |
'/ui' |
WebUI mount path on the same service. |
ui_tui_command |
LOCAL_SHELL_MCP_UI_TUI_COMMAND |
None |
Optional command override for the OpenTUI executable. |
ui_wallpaper |
LOCAL_SHELL_MCP_UI_WALLPAPER |
'bing' |
bing, aurora, or none. |
ui_terminal_idle_timeout_s |
LOCAL_SHELL_MCP_UI_TERMINAL_IDLE_TIMEOUT_S |
3600 |
Inactive browser PTY timeout; 0 disables it. |
ui_terminal_max_sessions |
LOCAL_SHELL_MCP_UI_TERMINAL_MAX_SESSIONS |
8 |
Maximum concurrent browser OpenTUI PTYs. |
Remote workers
| YAML key |
Environment variable |
Default |
Notes |
remote_enabled |
LOCAL_SHELL_MCP_REMOTE_ENABLED |
True |
Controls /join, /remote/*, and remote_* MCP tools. |
remote_invite_ttl_s |
LOCAL_SHELL_MCP_REMOTE_INVITE_TTL_S |
600 |
|
remote_poll_timeout_s |
LOCAL_SHELL_MCP_REMOTE_POLL_TIMEOUT_S |
25 |
|
remote_job_timeout_s |
LOCAL_SHELL_MCP_REMOTE_JOB_TIMEOUT_S |
3600 |
|
remote_max_pending_jobs |
LOCAL_SHELL_MCP_REMOTE_MAX_PENDING_JOBS |
256 |
Maximum queued or pending jobs per worker. |
remote_cancelled_job_ttl_s |
LOCAL_SHELL_MCP_REMOTE_CANCELLED_JOB_TTL_S |
3600 |
Retention time for cancellation tombstones used to skip timed-out queued jobs. |
remote_transfer_strategy |
LOCAL_SHELL_MCP_REMOTE_TRANSFER_STRATEGY |
'auto' |
auto, relay, direct, or object_store. auto tries enabled peer-direct, then configured S3, then bounded-memory controller relay. |
remote_peer_transfer_enabled |
LOCAL_SHELL_MCP_REMOTE_PEER_TRANSFER_ENABLED |
False |
Opt in to a one-shot HTTP receiver on the destination worker for worker-to-worker direct transfer. Enable only on a trusted private network such as a VPC/Tailscale network. |
remote_peer_transfer_bind_host |
LOCAL_SHELL_MCP_REMOTE_PEER_TRANSFER_BIND_HOST |
'0.0.0.0' |
Bind address for the one-shot destination-worker receiver. |
remote_peer_transfer_advertise_host |
LOCAL_SHELL_MCP_REMOTE_PEER_TRANSFER_ADVERTISE_HOST |
None |
Address advertised to the source worker; defaults to the destination worker hostname/FQDN. |
remote_peer_transfer_port |
LOCAL_SHELL_MCP_REMOTE_PEER_TRANSFER_PORT |
0 |
Receiver port; 0 chooses an ephemeral port. |
remote_peer_transfer_timeout_s |
LOCAL_SHELL_MCP_REMOTE_PEER_TRANSFER_TIMEOUT_S |
3600 |
Lifetime/timeout for a one-shot direct receiver. |
remote_transfer_s3_bucket |
LOCAL_SHELL_MCP_REMOTE_TRANSFER_S3_BUCKET |
None |
Optional S3-compatible bucket used for presigned worker-to-worker transfers. Requires the s3 extra. |
remote_transfer_s3_prefix |
LOCAL_SHELL_MCP_REMOTE_TRANSFER_S3_PREFIX |
'local-shell-mcp' |
Object-key prefix for temporary transfer objects. |
remote_transfer_s3_region |
LOCAL_SHELL_MCP_REMOTE_TRANSFER_S3_REGION |
None |
Optional S3 region. |
remote_transfer_s3_endpoint_url |
LOCAL_SHELL_MCP_REMOTE_TRANSFER_S3_ENDPOINT_URL |
None |
Optional S3-compatible endpoint URL. |
remote_transfer_s3_presign_ttl_s |
LOCAL_SHELL_MCP_REMOTE_TRANSFER_S3_PRESIGN_TTL_S |
3600 |
Presigned PUT/GET URL lifetime. Temporary objects are deleted after transfer. |
Shell and executable paths
| YAML key |
Environment variable |
Default |
Notes |
shell_executable |
LOCAL_SHELL_MCP_SHELL_EXECUTABLE |
'/bin/bash' |
|
shell_env_blocklist |
LOCAL_SHELL_MCP_SHELL_ENV_BLOCKLIST |
['CLOUDFLARE_TUNNEL_TOKEN'] |
|
shell_env_blocked_prefixes |
LOCAL_SHELL_MCP_SHELL_ENV_BLOCKED_PREFIXES |
['LOCAL_SHELL_MCP_', 'DOCKER_'] |
Comma-separated in environment variables; list in YAML. |
tmux_bin |
LOCAL_SHELL_MCP_TMUX_BIN |
'tmux' |
Preferred tmux executable. If it is unavailable, Linux release and Docker builds use the bundled helper; otherwise persistent shells fall back to the native backend. |
rg_bin |
LOCAL_SHELL_MCP_RG_BIN |
'rg' |
|
git_bin |
LOCAL_SHELL_MCP_GIT_BIN |
'git' |
|
python_bin |
LOCAL_SHELL_MCP_PYTHON_BIN |
'python3' |
|
Authentication and OAuth
| YAML key |
Environment variable |
Default |
Notes |
auth_mode |
LOCAL_SHELL_MCP_AUTH_MODE |
'oauth' |
Use oauth for public deployments. |
auth_bypass_localhost |
LOCAL_SHELL_MCP_AUTH_BYPASS_LOCALHOST |
True |
|
require_auth_for_mcp_discovery |
LOCAL_SHELL_MCP_REQUIRE_AUTH_FOR_MCP_DISCOVERY |
True |
Require OAuth before MCP initialization and tool discovery. |
mcp_session_idle_timeout_s |
LOCAL_SHELL_MCP_MCP_SESSION_IDLE_TIMEOUT_S |
180 |
Idle timeout for stateful Streamable HTTP sessions. |
mcp_max_sessions |
LOCAL_SHELL_MCP_MCP_MAX_SESSIONS |
1024 |
Maximum concurrent stateful MCP sessions. |
public_base_url |
LOCAL_SHELL_MCP_PUBLIC_BASE_URL |
None |
External HTTPS origin. Do not include /mcp. |
oauth_issuer |
LOCAL_SHELL_MCP_OAUTH_ISSUER |
None |
|
oauth_resource |
LOCAL_SHELL_MCP_OAUTH_RESOURCE |
None |
|
oauth_admin_pin |
LOCAL_SHELL_MCP_OAUTH_ADMIN_PIN |
None |
|
oauth_jwt_secret |
LOCAL_SHELL_MCP_OAUTH_JWT_SECRET |
|
|
oauth_access_token_ttl_s |
LOCAL_SHELL_MCP_OAUTH_ACCESS_TOKEN_TTL_S |
0 |
0 means access tokens do not expire automatically. |
oauth_code_ttl_s |
LOCAL_SHELL_MCP_OAUTH_CODE_TTL_S |
300 |
|
Built-in policy lists
| YAML key |
Environment variable |
Default |
Notes |
command_denylist |
LOCAL_SHELL_MCP_COMMAND_DENYLIST |
[] |
Cleared automatically when full-container mode is enabled. |
path_denylist |
LOCAL_SHELL_MCP_PATH_DENYLIST |
[] |
Cleared automatically when full-container mode is enabled. |
YAML example
host: 0.0.0.0
port: 8765
mode: mcp
workspace_root: /workspace
auth_mode: oauth
remote_enabled: true
disable_local: false
logical_sessions_enabled: true
live_workspace_enabled: true
ui_enabled: true
ui_path: /ui
file_download_enabled: true
shell_env_blocked_prefixes:
- LOCAL_SHELL_MCP_
- DOCKER_
Serverless controller with durable Redis state:
mode: mcp
stateless_controller: true
state_backend: redis
state_backend_url: redis://redis.internal:6379/0
remote_transfer_strategy: auto
stateless_controller removes the need for a persistent controller volume. The memory
backend is intentionally ephemeral: a cold start invalidates pending remote invites and worker
identities and discards OAuth clients, jobs, and audit records. Use Redis when any of that state
must survive cold starts, including durable worker revocation semantics. With the default
auth_mode=oauth, inject at least 32 bytes of random key material through
LOCAL_SHELL_MCP_OAUTH_JWT_SECRET. Active remote RPC queues/futures are process-local, so
deployments that use remote workers should currently run one active controller instance at a
time rather than multiple load-balanced controller replicas.
Operational advice
- Keep
allow_full_container=false unless the container or VM is disposable.
- Keep
auth_mode=oauth for any public endpoint.
- Disable
remote_enabled if you do not use remote workers.
- Disable
file_download_enabled if you never need chat-downloadable artifacts.
- Keep command, file, and audit limits high enough for coding tasks but low enough to prevent accidental runaway output.