How to run the Mythic Vibe CLI under an SSH session — both interactive and scripted.
v1.0 threat-model context. The web-terminal surface (asset A4 in
docs/security/threat_model.md) binds to127.0.0.1by default; SSH forwarding is the supported remote-access path. The PH-19.0 hardening sweep added explicit request-body caps + per-connection socket timeouts (BS-1) — the bridge no longer hangs on a misbehaving client that advertises a hugeContent-Length.
The default config works out of the box. SSH inherits a TTY, so:
mythic-vibe shellopens the REPL.mythic-vibe tuirenders the four-panel interface (auto-falls back to the PH-17 narrow layout when the remote terminal is < 78 columns wide).mythic-vibe oathand other commands that gate through PH-14's policy gate prompt the operator on stdin.
Run the surface check before relying on the SSH workflow:
ssh user@host -- mythic-vibe surface ssh-doctorA clean exit code means the CLI is ready. Each finding includes a remediation hint.
When SSH runs without a TTY (ssh user@host -- mythic-vibe ...), the CLI auto-adapts:
- Slice 11.1 approval mode flips to
auto— no prompts on stdin. - Slice 6.1 voice TTS stays disabled (no
MYTHIC_VOICE_TTS_ENABLED). - Slice 4.4 status-bar / TUI cues are not rendered (TUI requires
mythic-vibe tui, which itself requires a TTY).
Common gotchas:
- ANSI color leaks — set
NO_COLOR=1in the remote shell to suppress ANSI codes when redirecting output to log files. Thessh-doctorcheck warns whenNO_COLORisn't set in a non-TTY context. - Bare
TERM— many SSH sessions inheritTERM=dumb. SetTERM=xterm-256color(or your local equivalent) before invokingmythic-vibe tui. - Long-running commands — slice 6.4 streaming + slice 8.3 fallback both honour
threading.Eventcancellation. SSHCtrl-Cpropagates asSIGINT; the CLI's signal handlers convert it into a cooperative cancel.
Want the slice 17.1 web terminal exposed to your laptop without opening a port on the remote host? Use SSH local forwarding:
# On the remote host:
mythic-vibe surface web --port 8765 --token "$TOKEN"
# From your laptop:
ssh -L 8765:localhost:8765 user@host
# Then open http://localhost:8765 in your browser.The web terminal binds to 127.0.0.1 only by default — SSH forwarding is the only ingress.
The CLI keeps per-project state in mythic/. If multiple operators SSH into the same machine and run commands against the same project root, the v1.0 hardening covers:
- Intra-process writes serialize via
runtime/file_mutation_queue.py(per-realpaththreading.Lock). - Cross-process writes can serialize via
runtime/cross_process_lock.py(POSIXfcntl.flock/ Windowsmsvcrt.locking) — opt-in for callers, wired intoforge_ledger.pyand intoJsonStateStore.FileLock(cross_process=True).
These cover concurrent-write races on shared files. Operator-level concurrency at the workflow layer (two operators running mythic-vibe ai run simultaneously against the same packet) is still not coordinated above the file-lock layer.
For multi-operator setups, one of:
- Each operator works in their own checkout under their own home dir.
- Operators coordinate out-of-band (chat, ticket).
- Wrap the bridge in tmux and share via
tmux attach -t mythic.
The PH-17 surfaces (web terminal, chat bridge) are designed to run unattended. A minimal systemd unit:
[Unit]
Description=Mythic Vibe CLI — web terminal
After=network-online.target
[Service]
Type=simple
User=mythic
WorkingDirectory=/srv/mythic-project
Environment=NO_COLOR=1
Environment=TERM=xterm-256color
ExecStart=/usr/local/bin/mythic-vibe surface web --port 8765 --token "%i"
Restart=on-failure
[Install]
WantedBy=multi-user.targetThe %i template parameter pairs with systemctl start mythic-web@<token>. Alternatively store the token in a file and reference it via EnvironmentFile=.
| Symptom | Likely cause | Fix |
|---|---|---|
Prompt freezes on Y/n |
TTY detection wrong | Run with --approval auto flag explicitly |
| Garbled colors in piped output | No-color not set | export NO_COLOR=1 |
| TUI layout looks broken | Narrow terminal | The narrow layout activates automatically below 78 columns; force with MYTHIC_TUI_NARROW=1 |
| Web terminal returns 401 | Token mismatch | Verify the URL-safe token; the field is case-sensitive |
mythic-vibe ai stream hangs |
Stdin not closed | Pipe < /dev/null for non-interactive runs |