EmptyOS / docs Sign in

Agent setup

Instructions for an agent that installs the empty client and connects its user's EmptyOS computer.

This page is for an agent setting up EmptyOS for its user. People can follow the shorter Getting started.

Where you are running

The machine where you are running is the client workstation, not the EmptyOS computer. Install the empty CLI here, then use it to connect to the user's existing cloud computer or help the user create one.

This page needs a shell on the user's machine. If you are a hosted chat assistant without one, such as Claude on claude.ai or ChatGPT, stop here. Send the user to Getting started, which shows how to add your computer as a connector.

Fetch this exact document directly from https://emptyos.com/docs/agent-setup.md. Do not search for EmptyOS first. If the fetch fails with a DNS or connection error, check for scoped runtime network permission, request it when needed, and retry the same official URL. Use the successful response without searching for or refetching another copy.

This page is sufficient for setup. Fetching and reading the longer EmptyOS Computer skill before installation is optional and should not delay these steps. After installing the client, run empty --skill and read its bundled skill before operating the computer beyond the connection check in step 6. Install the skill for later sessions as described in step 3.

What you do and what the user does

The user signs in, chooses the account and the computer name, and approves pairing. You prepare the workstation, install the client, guide the user through each step, and relay what the client prints.

Do not type credentials, choose an account or name, or submit those choices for the user. Never approve a pairing request or claim that the pairing values match.

1. Find the right computer

Resolve the intended computer before a lengthy installation. If the conversation already supplies an EmptyOS hostname, keep it: use a single valid owner hostname already supplied in the conversation without asking for it again. Otherwise ask whether the user already has an EmptyOS computer. Placeholders, app.emptyos.com, and public. or shared. addresses are not owner hostnames; if more than one possible owner hostname appears, ask which one to use.

Computers are invitation-only for now. An invitation-only notice does not by itself mean this user lacks an invitation; let them sign in and observe the account-specific result. Someone who had a Thing shared with them needs no invitation but must first sign in from that shared link; after that, signup lets the same account claim a computer. A user without an invitation can join the waitlist.

Names can contain only lowercase letters, digits, and hyphens. Each account can claim one computer.

2. Prepare the workstation

The complete setup supports macOS and Linux. Windows is not supported yet because empty skill install currently supports only macOS and Linux. The client package accepts Node 20 or newer, but use a Node release that the Node.js project currently supports; Node 20 itself is end-of-life. You also need npm, git, and ssh on PATH. The fresh Linux recipe below needs curl. Install missing Git, OpenSSH client, or curl through the operating system's package manager.

First inspect what is already installed, including through a fresh login shell so an existing per-user version manager is not missed. Keep a working, currently supported LTS installation and its startup configuration. If Node is absent, end-of-life, too old for the package, lacks npm, or uses a global npm prefix this user cannot write, install a current LTS alongside it with the per-user recipe below. Do not uninstall the existing runtime.

node --version
npm --version
git --version
ssh -V
/bin/bash -lc 'node --version && npm --version'

The last command checks Bash. Use the equivalent fresh login invocation for another current shell before deciding that its existing Node installation is absent.

If those tools are already installed and current, go to step 3.

On a fresh Linux workstation running Bash, if Node or npm is missing, install the current LTS release per-user with nvm. npm recommends a Node version manager, and the Node download page currently offers nvm for Linux. This recipe uses the nvm project's documented installer, prevents the installer from choosing or rewriting a startup file, and does not need sudo:

(
  set -eu
  command -v curl >/dev/null || { echo "Install curl first" >&2; exit 1; }
  nvm_installer="$(mktemp)"
  trap 'rm -f "$nvm_installer"' EXIT
  curl -fsSLo "$nvm_installer" https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.7/install.sh
  PROFILE=/dev/null bash "$nvm_installer"
) &&
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "$HOME/.nvm" || printf %s "$XDG_CONFIG_HOME/nvm")" &&
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" &&
nvm install --lts &&
nvm alias default "$(nvm current)" &&
npm install -g @emptyos/client &&
empty --version

The command deliberately keeps download, nvm loading, Node installation, client installation, and the first check in one shell. Until startup files pass the fresh-shell checks, explicitly load the same resolved NVM_DIR again at the start of every new shell command that needs Node, npm, or empty.

Do not replace an existing startup file. Resolve NVM_DIR once with printf '%s\n' "$NVM_DIR", and put that absolute path—not the conditional XDG_CONFIG_HOME expression—into the startup lines. Back up an existing file before editing it and add one clearly marked nvm block only if it does not already load nvm.sh. For Bash, cover ~/.bashrc and the first existing login file among ~/.bash_profile, ~/.bash_login, and ~/.profile; if none exists, create ~/.profile. If the login file already sources ~/.bashrc before any early return, do not add a duplicate block there. Put the block before any applicable early return.

On macOS with the default zsh, the same per-user nvm method applies; cover ~/.zshrc and ~/.zprofile without replacing either file. For another shell, use the startup files named by that shell and the LTS method from the official Node.js downloads and npm installation guidance. Do not use sudo npm, sudo empty, or change ownership of system directories.

The final line should print empty client 0.1.25 (protocol 3). The recipe has installed the client; continue with the fresh-shell checks in step 3.

3. Install the client and skill

The official client package is @emptyos/client. Its command is empty. Skip the installation command if the nvm recipe in step 2 already ran it.

$ npm install -g @emptyos/client
$ empty --version
empty client 0.1.25 (protocol 3)

Fresh-shell checks

Before connecting, verify node --version, npm --version, and empty --version in fresh login and interactive shells. Start each check independently with a base PATH so the check cannot inherit a temporary PATH fix from the installer. For Bash on Linux, run these two checks as the installing user:

env -i HOME="$HOME" USER="$(id -un)" PATH=/usr/local/bin:/usr/bin:/bin /bin/bash -lc 'node --version && npm --version && empty --version'
env -i HOME="$HOME" USER="$(id -un)" TERM=dumb PATH=/usr/local/bin:/usr/bin:/bin /bin/bash -ic 'node --version && npm --version && empty --version'

Each check passes when it exits with status 0 and prints all three versions. Without a terminal, the interactive check may also print job-control warnings. Those warnings alone do not mean the check failed.

If either check fails, fix that shell's startup configuration. After the fix, repeat both checks before reporting installation complete.

For Bash, preserve the existing startup files. Login shells read the first available file from ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order. Interactive non-login shells read ~/.bashrc. Ensure both kinds of shell load the required PATH entries.

Bash's ~/.bashrc can return early for non-interactive shells. If a login file sources ~/.bashrc, put login PATH entries in the login file or a shared file loaded before that return. For another shell, use its startup files and fresh-shell checks.

Install the skill

Run empty --skill to read the complete skill bundled with this client. It needs no skill installation or computer connection. Read it before working on the computer, and have any worker you delegate to read it before starting its task.

To install the skill, run empty skill install. In Claude Code, run empty skill install --dir ~/.claude/skills instead, because Claude Code reads skills from that directory. If the default directory is not writable, run empty skill install --dir <writable-skills-directory> with a writable skills directory supported by the agent runtime. Then read SKILL.md in the printed directory during this session. See The empty skill for other agent directories and an npx alternative.

Do not start pairing until client setup passes the fresh-shell checks and, for a new computer, provisioning has reached Continue to Home.

4. Get the hostname

Skip this step if step 1 already settled the owner hostname. For a new computer, ask the user to open Home. If you can passively observe that browser, read the final https://<name>.emptyos.com/ URL and use its hostname. Otherwise ask the user for the hostname shown in the browser. Never invent one or create a second computer for someone who already has one.

5. Connect

Name the client with --label. The owner sees that name on the approval page, in the approved-client list, and next to every action this client runs on the computer. Lead with the agent product, then the machine it runs on, such as codex-mbp, claude-work-laptop, or muse-wump-vm; a bare machine name does not say which agent acted. Without --label, the client uses this machine's hostname. The owner can change the name while approving the request and rename the client later on the Client access page; past actions show the new name.

$ empty connect https://yourname.emptyos.com --label codex-mbp
Pairing as codex-mbp
Pairing code: 7K3MQ2ZD
SSH key: SHA256:9f2cQx1Vb3e8RZs0KpD4w7LmYt6nHaJc2uXoEiVgN5A
Approve it at:
  https://yourname.emptyos.com/_system/agents
Opening the approval page in your browser...
Waiting for approval...

The command opens the approval page in the default browser and waits. If this machine has no browser the user can see, add --no-browser; the client prints the same values and waits.

Relay the real pairing code, complete SSH-key fingerprint, and approval URL verbatim. The owner—not the agent—compares both values on the approval page and decides whether to approve. Do not click approval or claim that the values match.

Approval requests expire after 15 minutes; the client prints the expiry. If waiting is interrupted or saving locally fails, run empty connect again with the same URL and alias. It resumes a valid pending request without a new code. A valid approval already saved by the client can finish local installation even after the request expires.

Approval gives the local client's SSH key full trust. The empty client can act as the computer's own user, and you use that client with the same access as the resident agent. The owner can revoke the client on the Client access page at any time. After approval, the command finishes:

Successfully connected computer yourname (yourname.emptyos.com) and selected it as the default
List computers with `empty computers`

6. Check the connection

Verify saved access with the read-only empty --computer yourname status --json. Owner approval grants access to the key on the computer; it does not prove the client finished saving locally or that any session is active.

$ empty computers
yourname  yourname.emptyos.com  (default)

Connect another computer with `empty connect <computer-url>`
$ empty things
Computer yourname is empty — no Things yet

Put its first Thing:
  empty put <path> [--as <id>]

For an overview of Things, Projects, Databases, recent changes, and recent activity, run empty --json. empty activity lists recent actions on the computer with the client that ran each one.

Setup is complete. Read the installed skill before doing more on the computer. EmptyOS is in beta, and backups are not automatic; tell the user to keep an independent copy of anything important.

Using more than one computer

The first connection selects the new profile as the default. If another default already exists, keep it. Check the newly connected alias with empty --computer yourname status --json. Use empty computer use yourname only when that computer should become the default.

Troubleshooting

Network access

Fetching these docs, downloading packages, and connecting to a computer all need network access, even for read-only requests. If your agent runtime restricts network access, follow these steps:

Installation and PATH

If npm reports EACCES, use a writable user installation rather than changing system-directory permissions. Follow npm's installation guidance.

Keep the directory that contains Node and npm on PATH. Keep the npm global executable directory, $(npm prefix -g)/bin, on PATH too. Both directories must be on PATH in the current shell and future sessions. Repeat the fresh-shell checks after any change.

Pairing errors

If empty connect prints pairing-expired, the approval window has ended. New requests allow 15 minutes. Retry with the same URL and alias to reuse any valid saved approval. If the request expired or became unknown after the owner approved, an unused grant may remain on Client access. Report the exact error and have the owner inspect it before requesting a new approval; do not repeat approval attempts unattended.

If empty connect prints pairing-rejected, the request was declined on the approval page.

Connecting a replacement computer

If the owner has replaced a computer at the same hostname, first inspect empty computers --json. Remove only the intended old local profile with empty computer remove <alias>, then run empty connect <computer-url> --as <alias> and obtain a new owner approval after the owner compares the full code and fingerprint. Profile removal preserves credentials and pinned trust. The new pairing uses a separate credential directory and never overwrites old files. Do not manually delete key directories. A changed hostname or a network failure alone is not a reason to delete keys or trust.

To stop a client from having access, run empty computer remove <alias> --revoke from that client. The computer revokes only that client's own credential, then the local profile is removed; the profile is kept if the computer cannot be reached. The Client access page revokes any client.

Connection errors

If the host does not resolve, check the hostname, network connection, and any sandbox network restrictions. The computer may still be provisioning.

If a command reports rejected this client's tunnel token (HTTP 401), the computer no longer accepts this client's credential: it was revoked on Client access, or the computer was replaced or restored without it. Check Client access, then connect again. An HTTP 404 usually means the computer is stopped or still starting, but a computer on an older EmptyOS release also answers 404 to a revoked client, so check Client access if the computer is up. An HTTP 503 is a temporary failure on the computer; retry shortly. Any other HTTP, DNS, or TLS error means the path to the computer did not answer as EmptyOS; the credential was not judged.

For an existing profile, run the read-only connection check empty --computer <alias-or-url> status --json. If the check fails, follow the network guidance above. A DNS failure alone is not a reason to remove a computer profile.

Busy computer and updates

If a command exits 75 with computer-busy, another change holds the computer's lock. Retry the command.

If a command reports that the client is out of date, run the printed install command. If it reports that it updated the skill, read that SKILL.md again. See The empty skill.

If a command reports a missing capability, the computer needs a platform update. Run empty computer update --check. Then apply the update with the printed resume command.

If an update stops with needs-reconciliation, the update overlaps local changes. Resolve the listed conflicts. Then run the printed resume command. See Updates.

For anything else, email support@emptyos.com.