---
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.26 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 Executor in the background, opens the dashboard in your
browser and exits. Executor keeps running until you stop it; see
[The background Executor](#the-background-executor). 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. 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 background Executor if it is not running, open the dashboard and exit. |
| `executor service` | Start, stop and configure the background Executor. |
| `executor serve` | Run Executor in this terminal, without opening a browser, until you press Ctrl+C. |
| `executor pair` | Print a new connection link for the background Executor. |
| `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. Run `executor service restart`, then update clients that used the old key. |

`executor pair` asks the background Executor for a link, waiting up to 30
seconds while it starts. It only reads: it never starts Executor or creates a
data directory or keys. When you set `EXECUTOR_API_KEY`, it sends that key
instead, to the background Executor or, when none runs, to the server on
`EXECUTOR_PORT`.

### 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 background Executor if needed and opens the dashboard. |
| `executor open` | `executor pair` prints a connection link for the background Executor. |
| `executor daemon run` | `executor service start` starts the background Executor without opening a browser. It runs until `executor service stop`. |
| `executor install` | Nothing to install. `executor` or `executor service start` starts the background Executor, which runs until you stop it; it does not start with your computer. |
| `executor mcp` | The background Executor 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). |

## The background Executor

Each data directory has one background Executor that every command shares. The
first command that needs it starts it: `executor`, `executor service start` or
an `executor apps` command. It keeps running after that command exits, until you
run `executor service stop`. Nothing is installed with your operating system, so
it does not start again after you restart your computer: MCP clients cannot
connect until you run `executor` or `executor service start`.

The desktop app uses the same background Executor. When you stop it, with
`executor service stop` or by changing a setting, the desktop app says it was
stopped and does not start it again. It reconnects once a command starts it, or
when you click **Start** there.

When the background Executor runs another version, for example after
`brew upgrade` or an install with your package manager, `executor` stops it and
starts its own version. Other commands use whichever version is running.

| Command | Purpose |
| --- | --- |
| `executor service start` | Start the background Executor, or confirm that it runs, and print its URL. |
| `executor service stop` | Stop it. |
| `executor service restart` | Stop it and start this version. |
| `executor service status` | Print its URL, version and process ID, with `starting` before them while it starts, or `stopped`. |
| `executor service get [setting]` | Print every setting as JSON, or one setting. |
| `executor service set <setting> <value>` | Change a setting. |
| `executor service unset <setting>` | Remove a setting. |

| Setting | Purpose |
| --- | --- |
| `port` | The port it listens on. `EXECUTOR_PORT` wins over it; the default is `4312`. Each data directory's background Executor needs its own port. |
| `env` | Extra environment variables for it: `executor service set env <name> <value>`, `executor service unset env <name>`. |
| `disabled` | `true` makes `executor`, and `executor apps` commands without `--host` or `EXECUTOR_HOST`, run a private server for the command instead, as `--standalone` does. `executor service start`, `executor pair` and the desktop app still use the background Executor. |

Changing `port` or `env`, or setting `disabled` to `true`, stops the background
Executor; the next command that needs it starts it with the new settings. It
runs with the environment of the command that started it plus `env`, so use
`env` for variables it should always have, such as `EXECUTOR_BROWSER_ORIGIN`.
`EXECUTOR_API_KEY` and `EXECUTOR_ENCRYPTION_KEY` reach it only when both are
set, as for supplied keys; `EXECUTOR_API_KEY` alone is only the key the command
itself sends.

The data directory holds the settings in `service.json`. While Executor runs,
`server.json` records its address, process ID and a password that changes each
time it starts, and `.server.lock` stops a second server from opening the same
data directory. `service.json` and `server.json` are readable only by your user.

`executor --standalone` runs a private server on a free port for that command
instead, until you press Ctrl+C. It uses the same data directory, so stop the
background Executor first or set `EXECUTOR_DATA_DIR` to another folder.
`executor --server <url>` opens the dashboard of an Executor server that already
runs at that URL, using `EXECUTOR_API_KEY` or the API key saved in the data
directory. `executor serve` runs Executor in your terminal instead of the
background, so stop the background Executor first; while it runs, other commands
use it as they would the background Executor.

## Configure it

| Variable | Purpose |
| --- | --- |
| `EXECUTOR_PORT` | Port. Wins over the `port` setting; the default is `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.
The client connects to the background Executor. After you restart your
computer, run `executor` or `executor service start` first; until then the
client's connection is refused. If you change the port, update the client's URL.

## 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.

The upgrade replaces the files the background Executor runs from, so
`executor upgrade` and `executor upgrade --rollback` stop it first and start it
again on the new version afterwards. If the upgrade fails or you cancel it, the
old version starts again. If the new version does not start, the upgrade still
succeeds and tells you to run `executor service start`. A background Executor
from a development build keeps running. Executor never updates itself without
being asked.

The desktop app shares the background Executor with the command line. 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)
