---
title: Command line
description: "Install Executor on your machine. Keep your apps, accounts and data local."
---

The local server runs Executor on one machine for one person. It holds your
accounts, runs your apps, and serves an MCP endpoint for your agents.

## Install and start

With npm, on Node 14.18.0 or newer. Executor carries its own runtime, so Node only starts it. Check that executor --version prints 2.0.0-beta.16 before starting. Supports macOS on Apple Silicon and Intel, Linux (glibc) on ARM64 and x64, and Windows on x64.

```bash
npm i -g executor@beta --include=optional
executor --version
executor
```

Without Node, on macOS or Linux: the script checks the download against the release's SHA256SUMS and links ~/.local/bin/executor.

```bash
curl -fsSL https://executor.sh/docs/install.sh | sh
executor --version
executor
```

Without Node, on Windows, in PowerShell:

```bash
irm https://executor.sh/docs/install.ps1 | iex
```

With Homebrew, on macOS or Linux:

```bash
brew install usefulsoftwareco/tap/executor-beta
```

`executor` starts the server and opens the dashboard in your browser. Executor
is one executable with its runtime, dashboard, Git and workerd beside it; no
source checkout, Node or Bun is needed to run it.

The npm package is a small launcher: npm installs the executable for your
platform as an optional dependency. If `executor` reports that its native
runtime is missing, npm skipped optional dependencies; install again with
`--include=optional`.

The install script keeps each release in `~/.executor/v2/runtime/versions/`,
points `~/.executor/v2/runtime/current` at the one in use and links
`~/.local/bin/executor` to it. It never edits your shell profile: if
`~/.local/bin` is not on your `PATH`, it prints the line to add. On Windows the
script adds `%USERPROFILE%\.executor\v2\runtime\current` to your user `PATH`.
Pass a version to install that release, for example
`curl -fsSL https://executor.sh/docs/install.sh | sh -s -- 2.0.0-beta.16`.

If `executor --version` still shows v1, your shell is finding an older install.
Run `type -a executor` on macOS or Linux, or `where.exe executor` on Windows,
to see which executable takes priority. Remove the old install with the package
manager that installed it, then open a new terminal. For example, use
`bun remove -g executor` for an old Bun install. This does not delete your data.

On first launch, Executor saves its API and encryption keys in macOS Keychain,
Windows Credential Manager, or Linux Secret Service. Unlock the credential store
and allow Executor access when asked. If there is no credential store on the
first launch, for example on a Linux server without GNOME Keyring, Executor saves
the keys to `keys.json` in its data directory instead. The file is readable only
by your user, and Executor prints its path when it creates it. Keep that
directory private. If a credential store exists but access is denied, for
example because you dismissed the prompt or the store is locked, Executor stops
without writing `keys.json`. Start it again to be asked again. Where no prompt
can appear, such as over SSH, unlock the store first: on Linux run
`gnome-keyring-daemon --unlock`, on macOS `security unlock-keychain`.

To use `keys.json` on a new data directory even when a credential store works,
set `EXECUTOR_KEY_STORAGE=file` for its first start. Set
`EXECUTOR_KEY_STORAGE=os` to require the credential store and never fall back to
`keys.json`. Executor never switches an existing directory's key storage: a
value that does not match the directory stops startup and changes nothing.

| Command | Purpose |
| --- | --- |
| `executor` | Start the server and open the dashboard. |
| `executor serve` | Start without opening a browser. |
| `executor pair` | Print a new connection link for the running server. |
| `executor apps` | Create, edit, deploy and install apps. See [Author an app](/author-an-app). |
| `executor upgrade` | Install the newest release the way Executor was installed; `--rollback` returns to the previous one. |
| `executor rotate-key` | Replace the saved API key. Restart Executor, then update clients that used the old key. |

`executor pair` asks the server on `EXECUTOR_PORT` for a link, using the API key
saved in `EXECUTOR_DATA_DIR`, or `EXECUTOR_API_KEY` when you set it. Run it with
the same values as the server. It only reads the key: it never creates a data
directory or keys. If it reports that the server did not accept the key, the
server uses another data directory, or its key was rotated and it has not
restarted yet. Executor desktop keeps its own data directory; use its
**File > Open in browser** menu item instead.

### Coming from Executor 1

Executor 2 answers the old commands with the command to run instead.

| Executor 1 | Executor 2 |
| --- | --- |
| `executor web` | `executor` starts the server and opens the dashboard. If the server is already running, `executor pair` prints a link to open instead. |
| `executor open` | `executor pair` prints a connection link for the running server. |
| `executor daemon run` | `executor serve` starts the server without opening a browser. |
| `executor install`, `executor service install` | No background service yet. Keep `executor serve` running while your agents use Executor. |
| `executor mcp` | The running server serves MCP over HTTP at `http://127.0.0.1:4312/mcp`; see [Connect an agent](#connect-an-agent). |
| `executor call`, `executor tools`, `executor resume` | Agents call tools through the MCP endpoint. |
| `executor server` | No server profiles. `executor apps` commands take `--host`, and `executor rotate-key` replaces `executor server rotate-token`. |
| `executor login` | `executor apps login --host https://api.executor.sh` signs in to hosted Executor for app commands. |
| `executor docs` | Open [executor.sh/docs](https://executor.sh/docs). |

## Configure it

| Variable | Purpose |
| --- | --- |
| `EXECUTOR_PORT` | Port, default `4312`. |
| `EXECUTOR_NO_UPDATE_CHECK` | Set to `1` to skip the daily check for a newer release. |
| `EXECUTOR_DATA_DIR` | Data directory, default `~/.executor/v2/cli`. |
| `EXECUTOR_BROWSER_ORIGIN` | Exact HTTPS origin for generated browser links. |
| `EXECUTOR_WEBHOOK_ORIGIN` | Exact HTTPS origin that receives webhooks. |
| `EXECUTOR_KEY_STORAGE` | `file` or `os`: key storage for a new data directory. |
| `DO_NOT_TRACK` or `EXECUTOR_DISABLE_ANALYTICS` | Set to `1` to turn off anonymous [usage analytics](/run/usage-analytics) and feedback. |

To keep keys in a secret manager instead, supply both `EXECUTOR_API_KEY` (at
least 32 characters) and `EXECUTOR_ENCRYPTION_KEY` (exactly 64 hexadecimal
characters) before the first start. Keep these same keys for every start.
Executor does not save supplied keys. A directory keeps its chosen key source
across upgrades: a directory using the credential store still needs it later,
and a directory using `keys.json` needs that file.

## Connect an agent

Use the dashboard's **Connect** card to add the local MCP endpoint to your
agent. See [Add an MCP client](/mcp-clients) for Claude Code, Cursor and Codex.
Keep Executor running while the client is connected.

## Back up and update

Back up the data directory, including `installation.json`, and its matching
OS credential. The credential service is `com.usefulsoftware.executor.v2`;
its account ID is in `installation.json`. Copying only the database to another
machine is not enough to restore it. If you supplied keys, back them up in
your secret manager.

Missing keys stop startup. Executor will not generate replacements for an
existing installation. Restore the original keys to recover access.

`executor` and `executor serve` check npm at most once a day for a newer
release on their channel and print a reminder to run `executor upgrade`. Beta
installs are told about stable once it is newer. The check never installs
anything and is skipped in CI. The v2 data directory stays the same when beta
becomes stable. Uninstalling the package does not delete data or keys.

`executor upgrade` installs the newest release on your channel the way
Executor was installed, which it tells from where Executor's files live. For an
install from the install script, it downloads the release, checks it against
the release's SHA256SUMS, confirms the new version starts, and then switches
`current` to it. The version it replaced stays installed, and
`executor upgrade --rollback` switches back to it. For npm, pnpm, Bun or Yarn,
it runs that package manager; `--method npm|pnpm|bun|yarn` chooses one instead.
It first checks that your Node.js meets the new launcher's requirement, and
afterwards runs `executor --version` to confirm the new command works. A
Homebrew install is upgraded with `brew upgrade`.

```sh
executor upgrade                 # newest release on your channel
executor upgrade 2.0.0-beta.16   # a specific release
executor upgrade --rollback      # back to the previous release (install script)
executor upgrade --method pnpm   # install with pnpm
```

On a terminal it asks before installing; `--yes` skips the question. Without a
terminal, as for agents and CI, it installs without asking. Installing an older
release needs the version and confirmation, or `--yes` without a terminal. If
you run Executor through `npx`, `bunx` or `pnpm dlx`, there is nothing to
upgrade: run `npx executor@beta` to get the newest release. When Executor cannot
tell which package manager installed it, it prints the install command for each
one instead of guessing. A running `executor` or `executor serve` keeps using
the old version until you restart it; `executor upgrade` says when one is
running. Executor never updates itself without being asked.

The desktop app uses the same local server with a separate
profile. It checks for updates in the background and asks before restarting to
install one. Beta installs follow beta releases and move to stable when it is
newer. On Linux, only the AppImage updates itself; install a newer `.deb` over
the existing package.

[Download the desktop installer.](https://executor.sh/#install)
