Get Moshi
help

Troubleshooting

Connection failures, UDP firewalls, locked keychains, missing pushes, CJK locale fixes, dictation problems, and hook diagnostics.

updated 6 days ago9 min readpage 38 / 41

SSH cannot connect

Check the basics from another machine first:

from a laptop
$ssh user@host -p 22

If plain SSH fails outside Moshi, fix host reachability, username, port, firewall, DNS, VPN, or credentials first.

Mosh cannot connect

Mosh needs SSH for startup and UDP for the live session. If SSH works but mosh does not:

  • Confirm mosh-server exists on the host.
  • Open UDP 60000:61000 or the custom range you configured.
  • Check whether the current network blocks UDP.
  • Try connection type SSH as a fallback.
  • Set a custom mosh path if mosh-server is installed outside PATH.

mosh-server is installed but not found

Mosh bootstraps through a non-interactive SSH session, which does not load ~/.zshrc, ~/.bashrc (interactive section), or ~/.profile. A Homebrew-installed mosh-server (/opt/homebrew/bin on Apple Silicon, /usr/local/bin on Intel/Linuxbrew) often isn't on the non-interactive PATH.

Two fixes:

  1. Add the path to a file the non-interactive shell does load:
host shell init
# zsh: ~/.zshenv
# bash: top of ~/.bashrc, before any interactive guard
$export PATH="/opt/homebrew/bin:$PATH"
  1. Or set Mosh path in the connection's Mosh options to the absolute path:
Moshi connection settings
$/opt/homebrew/bin/mosh-server
$/usr/local/bin/mosh-server

Tailscale connections

For Tailscale-specific issues — wrong address, "unable to authorize", OS Error 4, Mac sleep behavior — see Tailscale.

Jump host fails

Jump hosts are available for SSH connections. If you configured a jump host while forcing mosh, switch the connection type to SSH or connect through a network path where the final host is directly reachable.

Key import fails

Moshi expects a private key. Public keys starting with ssh-rsa, ssh-ed25519, ecdsa-sha2-*, or PEM public-key blocks are rejected in the private-key field.

If a private key has a passphrase, enter the passphrase in the connection form.

moshi-hook install download fails (403 / Cloudflare challenge)

The install.sh script and brew install moshi-hook both pull binaries from cdn.getmoshi.app (Cloudflare). On rare networks Cloudflare's bot protection serves a JS challenge to curl, which returns HTTP 403 with a cf-mitigated: challenge header.

Confirm the challenge is what you're hitting:

diagnose
$curl -v https://cdn.getmoshi.app/hook/v0.1.4/moshi-hook_Linux_x86_64.tar.gz 2>&1 | head -30

If the response includes HTTP/2 403 and cf-mitigated: challenge, no curl flag will get past it — the challenge requires a real browser to solve.

Manual install:

  1. Open the URL printed by the install script in a browser. The browser solves the challenge and downloads the tarball.
  2. Move the file onto the host (scp, USB, AirDrop, etc.).
  3. Extract and place the binary on PATH:
manual install
$tar -xzf moshi-hook_Linux_x86_64.tar.gz
$sudo mv moshi-hook /usr/local/bin/
$moshi-hook pair --token <token>
$moshi-hook install

If you hit this from a region or PoP that consistently challenges, send a curl -v capture to Settings -> Support so the CDN rule can be tuned.

macOS Keychain blocks moshi-hook

If pairing from SSH or a locked macOS session fails, unlock the login keychain:

macOS
$security unlock-keychain ~/Library/Keychains/login.keychain-db
$moshi-hook pair --token <token>

For headless use, pair with file storage:

headless
$moshi-hook pair --token <token> --store file

tmux is installed but Moshi doesn't detect it

Moshi detects tmux over a non-interactive SSH session, which often skips ~/.bashrc, ~/.profile, and ~/.zshrc. If tmux lives in a directory those rc files add to PATH (for example /usr/local/bin or /opt/homebrew/bin), the non-interactive shell won't see it.

Check what the SSH session actually sees:

laptop
$ssh <host> 'echo PATH=$PATH; command -v tmux'

If command -v tmux prints nothing, either symlink tmux into a directory already on PATH or extend the non-interactive PATH in ~/.zshenv (zsh) or the top of ~/.bashrc before any interactive guard (bash). See tmux for setup.

A multiplexer works in the shell but Moshi still misses it

The session picker and the hook daemon can see different PATH values. The picker discovers tmux, Zellij, and Herdr through an SSH preflight; daemon-backed features such as live context, pane capture, and shortcut actions use the environment of the running moshi-hook service.

Run moshi-hook doctor on the host. Its Multiplexers checks show which tmux and Herdr the daemon resolved, and which copy the app's session picker would run:

moshi-hook doctor
$moshi-hook doctor
Multiplexers
✓ tmux /opt/homebrew/bin/tmux (3.5a)
⚠ herdr installed, but the moshi-hook daemon cannot find it [1]
  • If doctor reports the moshi-hook daemon cannot find it, the daemon service cannot resolve that binary. Add its directory to the service PATH, use a standard install location, then restart moshi-hook.
  • If doctor reports two installs or a copy that cannot talk to your running tmux server, the picker or the daemon would run a different tmux or Herdr than the one serving your sessions. Apply the numbered fix it prints — usually ln -sf <server's binary> ~/.local/bin/<tmux|herdr>, or removing the stray copy. See Two tmux installations.
  • If the daemon side is healthy but the session picker still misses a multiplexer, check the SSH preflight with ssh <host> 'command -v tmux; command -v zellij; command -v herdr'.

moshi-hook doctor needs moshi-hook 0.4.3 or newer. On older versions, the human-readable moshi-hook status prints a multiplexers (daemon) section with the same daemon paths (and the hook state per agent). moshi-hook status --json intentionally omits these paths so the app's lightweight preflight stays fast.

moshi-hook is installed but shows as not installed

A hollow-grey not installed dot means Moshi's host check could not resolve the moshi-hook binary. That check runs over a non-interactive login SSH shell and searches the standard install locations — ~/.local/bin, ~/bin, /opt/homebrew/bin, /usr/local/bin, /opt/local/bin — before your login shell's own PATH (from /etc/profile and ~/.profile, not ~/.bashrc, ~/.zshrc, or fish config). A Homebrew or default install.sh install lives in one of those directories and is detected automatically.

You only hit a false not installed when moshi-hook sits in a custom directory — for example installed with INSTALL_DIR=/some/where — that is neither one of those standard paths nor on the login-shell PATH.

Confirm what a login shell resolves. A plain ssh <host> 'command -v moshi-hook' skips the login shell and the standard search paths, so it is not representative:

laptop
$ssh <host> 'sh -lc "command -v moshi-hook"'

If that prints nothing, either symlink the binary onto a standard path:

host
$sudo ln -sfn /custom/dir/moshi-hook /usr/local/bin/moshi-hook

or add its directory to ~/.profile so the login shell exports it:

host
$echo 'export PATH="/custom/dir:$PATH"' >> ~/.profile

The other dot colors are not PATH problems: not running (solid grey) means start the daemon, wrong port (red) means the gateway isn't on 127.0.0.1:24543, and update (amber) means upgrade moshi-hook. See Host status dot for each.

Agent events do not appear

Run:

hook diagnostics
$moshi-hook doctor
$moshi-hook logs -f
$moshi-hook install

moshi-hook doctor confirms the daemon is running, the host is still paired with your Moshi account, and each agent's hooks are current — an out-of-date agent gets a moshi-hook install --target <agent> fix. It ends with a short checklist of things only you can confirm, such as notifications being allowed for Moshi on your phone and agents restarted after a hook change. Make sure the agent you are using is one of the supported installers.

Codex sessions show the wrong pane or all look like one terminal

Symptoms: Codex Chat View shows No messages or another session's transcript, replies and inbox approvals go to the wrong pane, or every Codex session appears as the same terminal.

Codex 0.157 turned on features.daemon_auto_start by default. Interactive codex sessions then run inside one shared background server (codex app-server --managed-daemon) that runs the hooks and holds every session's transcript, and it keeps the environment of whichever terminal started it. Moshi therefore attributes every Codex session to that first terminal.

Run moshi-hook doctor (moshi-hook 0.4.3 or newer). When the shared server is on, it reports every Codex session looks like one terminal and, after asking, turns it off: it sets daemon_auto_start = false under [features] in $CODEX_HOME/config.toml (default ~/.codex/config.toml) and stops the running server plus its updater. moshi-hook doctor --yes applies the fix without asking, and moshi-hook install offers the same fix.

turn off Codex's shared background server
$moshi-hook doctor --yes

Codex sessions attached to the server disconnect, so finish any active turns first and restart those sessions afterwards. Turning the feature off alone is not enough while a server is still running, because new Codex sessions keep attaching to it. The manual equivalent is:

manual fix
$codex features disable daemon_auto_start
$codex app-server daemon stop
$pkill -f 'app-server daemon pid-update-loop'
# `daemon stop` leaves the updater running

moshi-hook uninstall leaves the setting as it is. Passing -c, --enable, or --disable on the codex command line also makes Codex skip the shared server for that launch. Clients deliberately connected to a remote app-server (for example with --remote) share one server the same way, and Moshi cannot tell their panes apart. See Codex 0.157+ background server.

Push notifications do not arrive

  • Confirm iOS notification permission is enabled for Moshi.
  • Confirm notifications are not paused in Moshi settings.
  • Send a test notification from the settings screen.
  • On simulator, test push delivery is not representative of a real device.
  • For agent events, confirm moshi-hook serve or the macOS service is running.

Diff or browser preview is unavailable

Both features rely on the local gateway WebSocket that moshi-hook exposes. If the iOS app shows "Diff unavailable" or no dev servers appear under browser preview, walk through Debugging the gateway WebSocket to confirm the daemon is running, the session lookup resolves, and the SSH tunnel is still in place.

Live Activity does not update

Check Settings -> Agent Hooks:

  • Live Activity toggle is enabled.
  • The demo Live Activity can start.
  • Agent events are reaching the inbox.

Live Activities depend on iOS support and system policy. If the inbox updates but the Live Activity does not, restart the app and test with the demo action.

Pro is not recognized on a new device

A Pro purchase (subscription or lifetime) is tied to your Apple ID and works on every device signed in to the same Apple ID. After installing Moshi on a new device, open Settings -> Pro and tap Restore.

If Restore does nothing, confirm the device is signed in with the Apple ID that made the purchase. Restore brings back entitlements only — to also bring saved connections, enable iCloud sync in Moshi settings on both devices.

Korean or CJK characters do not render

The remote shell needs a UTF-8 locale for CJK output to render. Confirm with locale on the host; if it shows C or POSIX, set LANG=en_US.UTF-8 (or the equivalent for your locale) in ~/.zshenv or the non-interactive section of ~/.bashrc. See CJK and IME input for the full setup.

Dictation quality is poor

  • Try a different Whisper model.
  • Pin the language instead of using automatic detection.
  • Use chat mode for natural-language agent prompts.
  • Turn off auto-send while testing so you can edit before submission.

Need help

Use Settings -> Support to email support with the host OS, connection type, Moshi version, and the exact error shown in the app.