1. Claude Code remote sandbox
A Claude Code skill that provides remote execution sandboxing — edit code locally, build/test/run/deploy on a remote App Mesh server in isolation.
1.1. 1. Why
Developers on Mac/Windows often need to compile, test, or deploy on a remote Linux server. Traditional approaches (SSH + rsync, Docker dev containers, VS Code Remote) all require heavyweight setup and don’t integrate with AI coding assistants.
App Mesh Remote Sandbox solves this with zero local infrastructure — no SSH keys, no Docker, no rsync. Just pip install appmesh, set two environment variables, and Claude Code automatically syncs files (tar + SDK upload) and executes commands remotely via the appmesh Python SDK. The developer experience is fully transparent: say “build” or “deploy” in natural language, and the AI routes it to the right place.
1.2. 2. Architecture
Local Mac (Claude Code) Remote Linux (App Mesh)
┌─────────────────────────┐ ┌─────────────────────────┐
│ Read/Edit/Write/ │ │ │
│ Grep/Glob/Git │ │ APPMESH_WORKSPACE/ │
│ ↓ local files │ tar + upload │ (code mirror) │
│ │ ─────────────→ │ │
│ remote.py │ SDK API │ appmesh daemon │
│ sync-exec "make" │ ─────────────→ │ ↓ execute cmd │
│ │ │ ↓ stdout │
│ real-time stdout │ ←───────────── │ ↓ stream back │
└─────────────────────────┘ └─────────────────────────┘
Two channels:
tar + SDK upload: File sync.
tar czflocally →upload_file()via SDK API → remotetar xzf. No SSH required.appmesh Python SDK: Command execution via
run_app_async()with real-time stdout streaming, app lifecycle management.
1.2.1. Why tar-based sync (not rsync)
No SSH required — works with SDK API only, through firewalls/NAT
No rsync dependency —
taris universal, available everywhereSimple — no state files, no incremental tracking needed
Trade-off — always full sync (no incremental), mitigated by compression and exclude patterns
1.3. 3. Environment Variables
| Variable | Purpose | Example |
|---|---|---|
APPMESH_HOST |
App Mesh server URL | https://192.168.1.100:6060 |
APPMESH_USER |
Login username | admin |
APPMESH_PASSWORD |
Login password | PASSWORD |
APPMESH_WORKSPACE |
Remote working directory | /home/dev/app-mesh |
APPMESH_SSL_VERIFY |
SSL certificate verification | false |
APPMESH_SYNC_EXCLUDE |
Extra exclude patterns (comma-separated) | *.o,dist/ |
Minimum config (two variables):
export APPMESH_HOST=https://192.168.1.100:6060
export APPMESH_WORKSPACE=/home/dev/app-mesh
1.4. 4. Prerequisites
Local:
pip install appmesh(Python SDK)Local:
tar(macOS/Linux ship with it)Remote: App Mesh daemon running
No SSH access needed. No rsync needed. No appm CLI needed.
1.5. 5. Implementation: remote.py
Single Python CLI tool (~240 lines) with 6 subcommands:
1.5.1. Commands
remote.py <command> [args]
Commands:
sync tar + upload + extract to remote workspace
exec <cmd> [--timeout N] execute on remote (no sync)
sync-exec <cmd> [--timeout N] sync + execute (main dev loop)
run-script <file> [--timeout N] upload script + execute + cleanup
deploy <name> <cmd> sync + register as long-running service
cleanup <app_name> stop and remove remote app
1.5.2. Core Functions
do_sync(client):
tar czflocal git repo root (excludes.git,build,node_modules,__pycache__,.claude,*.o,*.pyc)SHA-256 hash check — skip upload if unchanged since last sync (override with
--force)client.upload_file()tar to remote/tmp/client.run_app_sync("mkdir -p $WORKSPACE && tar xzf ... -C $WORKSPACE")extractSeparate cleanup call:
client.run_app_sync("rm -f ...")— always runs even if extract fails
do_exec(client, cmd, timeout, working_dir):
client.run_app_async(App({"command": cmd, "shell": True, "working_dir": workspace}))run.wait(stdout_print=True, timeout=timeout)— real-time stdout streamingKeyboardInterrupt→ disable + delete app, exit 130
1.5.3. Key Design Decisions
run_app_async(notrun_app_sync) for all execution — enables real-time stdout streamingrun_app_synconly for quick infrastructure ops (extract tar, chmod, rm)auto_refresh_token=Truefor long sessionsssl_verify=Falseby default (self-signed certs common in dev)Exit code propagation:
sys.exit(rc)so Claude sees build failures
1.6. 6. Workflow
1.6.1. 6.1 Setup
# 1. Install Python SDK
pip install appmesh
# 2. Set environment variables
export APPMESH_HOST=https://192.168.1.100:6060
export APPMESH_WORKSPACE=/home/dev/app-mesh
# 3. Start Claude Code
claude
1.6.2. 6.2 Daily Development Loop
User: "fix the segfault in Configuration.cpp"
Claude: Grep("segfault", path="src/daemon/") → local search
Claude: Read("src/daemon/Configuration.cpp") → local read
Claude: Edit("src/daemon/Configuration.cpp", old→new) → local edit
User: "build"
Claude: Bash('python3 .claude/skills/appmesh-remote/remote.py sync-exec "cd build && make -j$(nproc)"')
Output:
[sync] Packing /Users/dev/app-mesh ...
[sync] Uploading 2048 KB ...
[sync] Extracting to /home/dev/app-mesh ...
[sync] Done.
[exec] cd build && make -j8
[ 12%] Building CXX object ...
[100%] Built target appmesh
[exit] 0
User: "run the tests"
Claude: Bash('python3 .claude/skills/appmesh-remote/remote.py sync-exec "cd build && make test ARGS=-V"')
User: "commit and push"
Claude: Bash("git add ... && git commit -m '...'") → local git
Claude: Bash("git push origin main") → local git
1.6.3. 6.3 Routing Rules: Local vs Remote
Remote — needs to “run” something on the OS:
| User Intent | Subcommand | Sync? | Examples |
|---|---|---|---|
| Build / compile | sync-exec |
Yes | make, cmake --build, cargo build, go build |
| Run tests | sync-exec |
Yes | make test, pytest, go test, npm test |
| Run program | sync-exec |
Yes | python3 app.py, ./myapp, node server.js |
| Install packages / system diagnostics | exec |
No | apt install, uname -a, df -h, which python3 |
| Deploy as long-running service | deploy |
Yes | deploy my-api "python3 server.py" |
| Run a standalone script | run-script |
No | run-script /tmp/setup.sh |
| Stop / remove a remote app | cleanup |
No | cleanup my-api |
Local — Claude native tools, no remote involvement:
| User Intent | Tool | Examples |
|---|---|---|
| Read / view files | Read | Read("src/main.cpp") |
| Edit / fix code | Edit | Edit("src/main.cpp", old→new) |
| Search code | Grep / Glob | Grep("segfault"), Glob("**/*.py") |
| Create new files | Write | Write("src/new_module.cpp", ...) |
| Git operations | Bash | git add, git commit, git push, git diff |
Quick decision rule: Does it need to execute on the OS? → Remote. Just reading/writing files or git? → Local.
1.7. 7. Plugin Structure
src/sdk/claude-plugin/
├── plugin.json
├── skills/appmesh-remote/
│ ├── SKILL.md
│ └── remote.py
├── rules/remote-dev-mode.md
└── README.md
Installation: Copy skills/appmesh-remote/ and rules/ into the target project’s .claude/ directory. See README.md for details.
1.8. 8. Validation
| # | Test | Command | Expected |
|---|---|---|---|
| 1 | Sync | sync |
tar + upload + extract, files appear on remote |
| 2 | Edit + build | Edit → sync-exec "make" |
Sync changed files, build succeeds |
| 3 | Execute only | exec "uname -a" |
No sync, direct execute |
| 4 | Run script | run-script /tmp/test.sh |
Upload + execute + cleanup |
| 5 | Deploy | deploy svc "python3 svc.py" |
Sync + register keepalive service |
| 6 | Cleanup | cleanup app_name |
Disable + delete app |
| 7 | Ctrl+C | Interrupt during exec | App disabled + deleted |
| 8 | Cross-repo | Install plugin in another repo | Set env → works |
All tests 1-6 verified against live Docker container (2026-03-07).
1.9. 9. Known Limitations
Full sync each time — tar sends entire repo (minus excludes), not incremental like rsync. Mitigated by gzip compression.
Remote build artifacts not auto-retrieved — use
client.download_file()orexec "cat ..."to retrieve.Excludes are pattern-based — no
.gitignoreintegration, must configureAPPMESH_SYNC_EXCLUDEfor project-specific patterns.Single workspace — one remote directory per session. Multiple workspaces need separate env var sets.