CLI
The matrix CLI — log in, sync files, attach to remote zellij sessions, and drive your instance from the terminal.
The Matrix OS CLI is a single binary — matrix (also installed as matrixos and mos) — for everything you do against your Matrix OS instance from outside the browser: signing in, syncing files, opening terminal sessions, and (soon) driving the upcoming VSCode extension.
Run Without Installing
The CLI is published as @finnaai/matrix on npm. npx and pnpm dlx run the same CLI entrypoint as an installed matrix binary, and profile/auth files are stored in ~/.matrixos/ so later installs reuse the same login.
# npm package runner
npx --yes @finnaai/matrix login --profile cloud
npx --yes @finnaai/matrix whoami
# pnpm package runner
pnpm dlx @finnaai/matrix login --profile cloud
pnpm dlx @finnaai/matrix whoamiIf you do not have a Matrix account yet, login --profile cloud keeps waiting while the browser walks you through signup, hosted trial checkout, and provisioning your Matrix computer. When setup finishes, approve the CLI in that same browser tab and return to your terminal.
The package runner requires Node.js 24 or newer. If your shell uses an older Node runtime, install Node 24+ first and rerun the same command.
Install Permanently
# Homebrew (macOS / Linux)
brew install finnaai/tap/matrix
# npm
npm install -g @finnaai/matrix
# Inside the matrix-os repo (development)
pnpm install
pnpm exec matrix --helpVerify:
matrix --version
matrix doctorUpgrade
Use the same channel you installed with, then verify the resolved binary:
# Homebrew
brew update
brew upgrade finnaai/tap/matrix
# npm
npm install -g @finnaai/matrix@latest
# Install script
curl -fsSL https://get.matrix-os.com | shVerify:
matrix --version
matrix doctor
which matrixIf matrix --version still prints an older version after upgrading, start a new terminal or refresh your shell command cache with hash -r in bash/zsh. If Homebrew says the formula is already current but you still see an old binary, run brew reinstall finnaai/tap/matrix and check which matrix for a stale npm-installed copy earlier in PATH.
First run
matrix login --profile cloud # opens a browser, completes the hosted device flow
matrix whoami # confirms handle, gateway, token expiry
matrix shell new main # creates your "main" session
matrix shell new main --attach # creates and attaches in one stepCtrl-\ Ctrl-\ detaches from a session without killing it. Reattach any time with mos shell attach main.
Profiles
Profiles let you point the same CLI at different stacks. Two are pre-configured:
| Profile | Platform URL | Gateway URL |
|---|---|---|
cloud | https://app.matrix-os.com | https://app.matrix-os.com |
local | http://localhost:9000 | http://localhost:4000 |
matrix profile ls
matrix profile use local
matrix profile show
# One-shot
matrix --profile local shell ls
# Sugar for --profile local
matrix --dev shell lsProfiles are stored at ~/.matrixos/profiles.json. Auth tokens are scoped per-profile under ~/.matrixos/profiles/<name>/auth.json.
matrix login writes auth into the active profile. matrix login --profile local (or matrix login --dev) skips the OAuth device flow and writes a long-lived dev stub — the local gateway in dev mode accepts any bearer. The success line always names the profile that was just written, so you always know where you are.
Shell sessions
Every Matrix OS instance ships with zellij pre-installed. The CLI treats zellij sessions as the source of truth — the same sessions you see in the web shell are the ones you list and attach from the terminal.
matrix shell ls # list sessions
matrix shell new code # create a session
matrix shell new code --attach # create + attach
matrix shell new code --layout dev # create with a saved layout
matrix shell new agent --cmd "claude" # create with an inline command
mos shell attach code # reattach to an existing session
mos shell attach -c review # create if missing, then attach
matrix shell rm code --force # destroy a sessionDetaching. Press Ctrl-\ twice in quick succession to leave the session running and return to your shell — the same combo whether you're in attach, connect, or just created a session with new --attach. To kill it instead, exit the shell normally inside the session or run matrix shell rm <name>.
Tabs
Tabs may be anonymous (zellij assigns an index) but named tabs are recommended so you can address them from scripts and the VSCode extension.
matrix shell tab ls --session code
matrix shell tab new --session code --name editor --cwd ~/projects/site
matrix shell tab go --session code --tab 1
matrix shell tab close --session code --tab 1Panes
matrix shell pane split --session code --direction right --cmd "claude"
matrix shell pane split --session code --direction down --cmd "pnpm dev" --cwd shell
matrix shell pane close --session code --pane pane-2Panes are addressed by focus in the current release: split or close operates on the focused pane.
Layouts
Layouts are KDL files stored in your instance at ~/.config/matrix-os/layouts/. Save the structure of an active session and apply it later (or to a fresh session).
matrix shell layout ls
matrix shell layout save --name dev --kdl "$(matrix shell layout dump --session code --json | jq -r '.data.layout.kdl')"
matrix shell layout apply --session code --name dev
matrix shell layout show --name dev # print the KDL
matrix shell layout rm --name devPort forwarding
Forwarding opens a listener on your local machine and connects it to a service listening on your Matrix computer. V1 supports local-to-Matrix-computer forwarding only. Reverse tunnels and public/shareable HTTPS URLs are not part of this command yet.
# Local 127.0.0.1:3000 -> Matrix computer 127.0.0.1:3000
matrix port forward 3000
# Local 127.0.0.1:8080 -> Matrix computer 127.0.0.1:3000
matrix port forward 8080:127.0.0.1:3000
# Top-level alias
matrix forward 3000
matrix forward 8080:127.0.0.1:3000The local listener always binds to 127.0.0.1. The remote target must be loopback on the Matrix computer: 127.0.0.1:<port>, localhost:<port>, or [::1]:<port>. To forward a dev server, start that server on the Matrix computer first, then run the CLI command from your local terminal.
matrix port forward 5173
open http://127.0.0.1:5173With --json, port forwarding emits NDJSON. The first event is ready, then connection lifecycle events follow until the command exits.
matrix port forward 3000 --json
{"v":1,"type":"ready","data":{"localHost":"127.0.0.1","localPort":3000,"remoteHost":"127.0.0.1","remotePort":3000,"profile":"cloud","gatewayUrl":"https://app.matrix-os.com"}}
{"v":1,"type":"connection_open","data":{"localHost":"127.0.0.1","localPort":3000,"remoteHost":"127.0.0.1","remotePort":3000,"connectionId":1}}File sync
The sync daemon mirrors a local folder against your instance's home directory. It runs as a background service installed by matrix sync start.
matrix sync ~/matrixos # initialize and start
matrix sync status
matrix sync pause
matrix sync resumeScope sync to a subtree of your instance with --folder:
matrix sync ~/work-projects --folder projectsSingle-file transfer
Use matrix upload and matrix download for one-off files that should not start the sync daemon or touch R2 sync state.
matrix upload ./README.md projects/demo/README.md
matrix upload --force ./config.json system/config.json
matrix download projects/demo/README.md ./README.remote.md
matrix download --force projects/demo/README.md ./README.remote.mdRegular downloads are written with standard user-readable file permissions.
Tool authentication
For GitHub and coding agents, prefer browser/device login inside the Matrix VPS instead of moving credential files from the local machine.
matrix run -it --session setup -- gh auth login
matrix run -it --session setup -- claude
matrix run -it --session setup -- codexAgents should not scan local machines for credential files or transfer local secret files as part of setup. If the human explicitly asks to migrate an existing credential, stop and confirm the exact provider, source path, destination path, and reason before running any transfer command.
Instance ops
matrix instance info # handle, region, image, last restart
matrix instance restart # graceful restart of your Matrix services
matrix instance logsPeers
matrix peers # list connected sync peers (machines)Machine-readable output
Every command supports --json for scripting and integration with the upcoming VSCode extension. Streams (terminal output, sync events, log follow) emit NDJSON, one event per line.
matrix shell ls --json
matrix sync status --json
matrix port forward 3000 --json
matrix shell tab ls main --json | jq '.[] | .name'The schema is documented at docs/cli-json-schema.md. Every payload includes "v": 1 for forward compatibility.
Global flags
--profile <name> Use a named profile (default: profiles.json:active)
--platform <url> Override platform URL (also $MATRIXOS_PLATFORM_URL)
--gateway <url> Override gateway URL (also $MATRIXOS_GATEWAY_URL)
--token <jwt> Override auth (also $MATRIXOS_TOKEN; useful in CI)
--json Machine-readable output (NDJSON for streams)
--no-color Disable ANSI colors
-q, --quiet
-v, --verbose
--dev Sugar for --profile localDiagnostics
matrix doctor checks every layer of the stack and prints fix-it hints when something looks wrong. Run it before opening an issue.
$ matrix doctor
Profile cloud (active)
Auth ok logged in as @hamed, expires in 47m
Daemon running pid 4821, sync resumed
Sync ok manifest v412, 184 files, last sync 12s ago
Gateway ok https://app.matrix-os.com (87ms)
Zellij ok v0.44.1 on customer VPS
Disk ok 23G availableShell completions
matrix completion zsh > ~/.zfunc/_matrix
matrix completion bash > ~/.local/share/bash-completion/completions/matrix
matrix completion fish > ~/.config/fish/completions/matrix.fishTroubleshooting
Cannot connect to daemon. Is it running?
The sync daemon is installed but not running. Start it with matrix sync start. If matrix doctor says the daemon is running but the socket is unreachable, remove the stale socket: rm ~/.matrixos/daemon.sock then matrix sync start.
401 Unauthorized on any command
Your token expired. Run matrix login again. Tokens are valid for the duration set by the platform (typically a few hours).
mos shell attach shows a blank screen
Usually means the zellij session exited on your instance. Check matrix shell ls — if the session is in the exited state, recreate it with matrix shell new <name>.
session "foo" not found when connecting
The session does not exist on your instance. mos shell attach is intentionally strict unless you pass -c. Use mos shell new foo or mos shell attach -c foo to create it.
matrix port forward returns invalid_forward_spec
Check the spec shape and port ranges. Valid examples are 3000, 8080:127.0.0.1:3000, 8080:localhost:3000, and 8080:[::1]:3000. Ports must be integers from 1 through 65535.
matrix port forward connects but the browser shows connection refused
The target service must be running on the Matrix computer loopback interface, not on your laptop. Attach with mos shell attach <session> and verify the service is listening on 127.0.0.1:<port> inside the Matrix computer.
Local stack returns connection refused
matrix --profile local expects the gateway on localhost:4000 and the platform on localhost:9000. Run pnpm dev in the matrix-os repo to boot both.
How is this guide?