FAQ & troubleshooting
Port 3333 is already in use
Another process is occupying the port. Find the PID and kill it:
lsof -i :3333kill -9 <PID from the output>Alternatively, set a different port in .env:
PORT=3334The hub does not start after a reboot
The LaunchAgent may need to be reloaded. Run both commands in sequence:
launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.penates.plistlaunchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.penates.plistIf the second command prints Bootstrap failed: 5, check that the plist file has mode 644 (chmod 644 ~/Library/LaunchAgents/com.penates.plist). launchd silently rejects world-writable files.
claude (or codex, agy) is not found in the terminal
The server process launched by the LaunchAgent may not inherit your shell PATH. Add the relevant directories to ~/.zprofile so that launchd picks them up:
echo 'export PATH="$HOME/.local/bin:/opt/homebrew/bin:$PATH"' >> ~/.zprofilesource ~/.zprofileThen restart the LaunchAgent to apply the new PATH.
I forgot the auth token
Read it directly from the .env file:
grep AUTH_TOKEN ~/penates/.envThe token is also the value you entered in the browser prompt. It is stored in localStorage under the key penates_token.
I get 401 errors after enabling Cloudflare Access
Check the audit log to see the specific failure reason:
tail -20 ~/.penates/audit.log | grep auth.fail | jq -cCommon reason codes:
bad-jwt:no-jwt- the browser did not pass through Cloudflare Access. Clear cookies for your domain and reload so the Access login flow runs again.bad-jwt:bad-aud-CF_ACCESS_AUDin.envdoes not match the Audience Tag of your Access application. Verify the value in the Cloudflare dashboard under Access > Applications.bad-jwt:bad-iss-CF_ACCESS_TEAM_DOMAINis wrong. It must be the exact team URL withouthttps://.bad-jwt:expired- the JWT has expired. Increase the session duration in your Access application settings.bad-bearer- the bearer token stored in the browser does not matchAUTH_TOKENin.env. Clear the stored token withlocalStorage.removeItem('penates_token')in the browser DevTools console. The hub will prompt for the token again on the next request.
The tmux socket is missing
This can happen after a fresh install before tmux has ever been started. Create the socket by starting a throwaway session:
tmux new-session -d -s initThe socket persists for the lifetime of the tmux server. The hub can then attach to it normally.
Sessions show activity “unknown”
Sessions started outside the hub (via SSH, Moshi, or a plain terminal) do not have Claude Code hooks wired up automatically. Activity stays unknown until a hook fires. Run setup.sh on the machine where the session runs to install the hooks, or use POST /api/sessions/:name/adopt to register the session so it appears in the hub.
The terminal shows garbled multi-byte characters
The PTY environment needs the correct locale. The hub sets LANG and LC_CTYPE automatically for sessions it creates. If you see _ instead of characters like ö, ⏺, or ✻, check that tmux is started with the -u flag and that your shell profile exports a UTF-8 locale.