Local runner

Run your runner on your own machine with the Evident CLI and reach it from Slack, GitHub, email and the web.

Your runner runs on your machine — where your code, secrets, and tools already live. The Evident CLI starts (or attaches to) opencode serve locally and connects it to Evident over a secure tunnel, so you can reach the same runner from the web, Slack, GitHub and email. Evident never runs your code and keeps no copy of your repository; the chat surface is proxied through Evident to reach your machine, and the messages you send are stored so they can be queued while your runner is offline.

Quick start

Go from nothing to a working runner you can chat with — in about five minutes. You'll need Node.js to install the CLI, and OpenCode available on your machine (the CLI starts it for you) with a model provider connected — see Model providers.

  1. Sign up and create your team. Create a free account at app.evident.run/sign-up. Your team is set up automatically the first time you use Evident.
  2. Create a runner. In the app, create a new runner and open its page — you'll find the exact command to run it, pre-filled with your runner ID.
  3. Install the CLI. Install it globally with npm:
    npm install -g @evident-ai/cli
    Or run it directly with npx without installing:
    npx @evident-ai/cli@latest <command>
    Verify it's installed:
    evident --version
  4. Sign in.
    evident login
    This uses a browser-based device flow: the CLI shows a one-time code and opens your browser to confirm it. Pass --no-browser to open the URL yourself.
  5. Run your runner. Copy your runner ID from the runner's page, then start it from the directory you want the runner to work in:
    evident run --runner <runner-id>
    Keep this terminal open while you want your runner to be reachable.

    Running unattended? Use a runner key.

    Create a runner key for the runner and set it as EVIDENT_RUNNER_KEY. With the key set, evident run connects as that runner — you don't need evident login or --runner:

    EVIDENT_RUNNER_KEY=<runner-key> evident run
  6. Confirm it's connected. Back on the runner's page in the app, the runner shows as online. The terminal also reports that the tunnel is connected.
  7. Send your first message. Open the chat from the web and send a message — for example, "What files are in this directory?". The reply streams back in real time. If the agent needs to ask you something or request permission to do something, you answer it right there in the chat.

How it works

When you run evident run, the CLI authenticates, works out which runner to serve, and then:

  1. Ensures opencode serve is running on your machine, on loopback (127.0.0.1) — starting it for you if it isn't already running.
  2. Opens an outbound, encrypted tunnel from your machine to Evident.
  3. Lets Evident reach your runner through that tunnel: web traffic (the chat UI) is proxied transparently, and connector messages (such as Slack) are delivered to your local OpenCode. Replies flow back the same way.

Because the runner runs locally, it has access to your repositories, environment, and tooling without any of that being uploaded to Evident.

View diagram source
graph LR
  subgraph Channels["web · Slack · GitHub · email"]
    In["inbound message"]
  end
  In --> Evident["Evident"]
  Evident <-->|"outbound encrypted tunnel"| CLI["evident run (your machine)"]
  subgraph Local["your machine"]
    CLI --> OpenCode["opencode serve (loopback)"]
    OpenCode --- Repo["your repository, secrets, tools"]
  end
Evident reaches your runner only through an outbound tunnel your machine opens — your repository, secrets and tools stay on your machine; Evident keeps no copy of your repository.

Connect with only a runner key

A runner key is a credential scoped to a single runner. With one set, the Evident CLI connects as that runner without a personal sign-in — and without you having to say which runner it is. This is ideal for unattended or CI-style setups.

You can generate a runner key from the API keys section of the runner's settings in the Evident web app. See the CLI reference for the full list of flags and environment variables.

Reconnection and a single active copy

  • Automatic reconnection. If your machine briefly loses its connection, the runner reconnects on its own, and any conversation you had is still there for you to continue.
  • One active copy at a time. If you start a second copy of the same runner, the second copy becomes the active one and the first stops serving it.

When the runner is offline

Messages sent while your runner isn't connected are held and delivered when it reconnects — there is nothing to enable. Trial and Starter plans cap at 50 queued conversations at a time; Pro and Enterprise have no cap.

  • From the web: you're shown how to start the runner on your machine and can write a message to be sent once it comes online. Your message is held until the runner connects, then delivered in a new conversation you can see in the chat. You can review and delete a queued message while it's still pending.
  • From a connector (e.g. Slack): the message is held and delivered when the runner comes online, and the reply is sent back to the connector it came from.

Keeping the runner alive in the background

The runner stays connected only while evident run is running. To keep it alive after closing your terminal, run it under a process manager.

tmux

tmux new-session -d -s evident 'evident run --runner <runner-id>'

pm2

pm2 start "evident run --runner <runner-id>" --name evident
pm2 save

Troubleshooting

Runner shows as offline in the web app

  • The tunnel may have dropped. The CLI reconnects on its own; if it doesn't, restart evident run.
  • Check the CLI's terminal output for the connection status and any errors. Use --log-level debug (alias -v / --verbose) for more detail.

Not signed in / authentication failed

evident logout
evident login

In unattended setups, make sure EVIDENT_RUNNER_KEY (or EVIDENT_TOKEN) is set.

OpenCode isn't reachable

  • evident run starts opencode serve on the port from --port (default 4096) if it isn't already running.
  • If you start OpenCode yourself, bind it to 127.0.0.1 (loopback IPv4) on that port.

Next steps