Edge nodes — run jobs on your own machine

Pair a computer you own to Spikefrost so agents can dispatch work to it, executed by your own Claude Code or Codex seat. Setup, the agent-side API, what the machine can reach, the full flag reference, and the failure modes.

The Spikefrost Team3 Aug 20266 min read

An edge node is a computer you own running a Spike worker. It pulls jobs from Spikefrost, executes them locally with your own Claude Code or Codex seat, and streams the result back into the conversation that asked for it.

Reach for one when the work has to happen on your hardware: a private repository, an internal network the cloud can't route to, a machine that already holds the credentials and tooling. As a side effect, the model usage bills to your own coding-agent account rather than your Spikefrost balance.

The connector is the cluster. Agents address the cluster; whichever paired machine picks up the job executes it locally and streams the result back into the same conversation.

Agent
edgeComputerTool({ alias })

spike-edge-node
connector = the cluster

your Mac
sf edge service

build server
sf edge service

local Claude / Codex
your seat

result → back into
the same conversation

The connector is the cluster. Agents address the cluster; whichever paired machine picks up the job executes it locally and streams the result back into the same conversation.

Before you start

Requirement Why
The sf CLI, signed in Pairing and control run through it — The sf CLI
Claude Code or Codex on the machine, signed in The node uses it as the executor. Without one, there is nothing to run the work
git, only for GitHub or Bitbucket workspaces Spike app workspaces sync over built-in S3 support and need no git. PR creation additionally needs a source-code connector

1. Create the cluster

In the web console open Connectors and add a Spike edge node connector.

The connector is the cluster. One connector can hold several machines, and agents address the cluster rather than any individual computer — so you can add a second machine later without touching agent code. Add a node to the connector and the console shows a pairing code.

2. Pair the machine

On the machine that will do the work:

sf edge pair

It prompts for the pairing code. Pairing binds the machine to the cluster and stores a runner token locally. Rotate that token any time:

sf edge regenerate-token

3. Start the worker

Run it in the foreground first, so you can watch the startup checks:

sf edge run --verbose

Once it looks right, install it as a background service. This survives a restart, starts on login, and keeps the machine awake so dispatched jobs aren't missed:

sf edge service start

status, stop and restart do what you'd expect. start installs the service first if it isn't installed yet.

4. Watch it

sf edge logs -f
sf edge logs -f stderr      # one stream only
sf edge logs --lines 200

The line worth recognising early:

Connected, but this node is NOT paired to a cluster yet — its pairing token is not registered.

That means the runner reached Spikefrost but the pairing code was never registered against the cluster. Finish step 1 in the console; the node binds itself on the next retry. It is not an error state to debug on the machine.

5. Give the cluster its environment

Environment variables set on the cluster are handed to every execution on every node in it — the right home for an internal API base or a key the jobs need locally:

sf edge env list
sf edge env set API_BASE https://internal.example.com
sf edge env unset API_BASE

Using it from an agent

The machine becomes an agent's tool. Declare it on the agent class:

override tools = {
  workstation: this.edgeComputerTool({
    alias: 'my_mac_mini',        // the connector — i.e. the cluster
    provider: 'claude',          // or 'codex'
    repos: [                     // mounted beside the app, always pulled
      { provider: 'github', fullName: 'acme/api' },
    ],
  }),
};

Five behaviours decide whether your design works. They are not edge cases:

The turn ends at dispatch. The tool returns "started", not a result. The machine then works alone for minutes and the answer arrives later as a new message in the same conversation. Never await it, poll it, or re-dispatch — holding the turn open produces duplicate replies.

Dual mount, always fresh. The app's own code is always checked out, every declared repository beside it, and all of them pulled before the CLI starts. A tree with uncommitted work from a previous turn is not pulled — the agent is told so in its preamble rather than losing the work.

Two push verbs. sf app push publishes app code; git push publishes a mounted repository. The machine publishes neither on its own, and its workspace persists — so ending a turn mid-refactor is normal and safe.

The session is the conversation. Follow-up instructions resume the same CLI session on the machine, so the agent can refer back to earlier work. A different conversation gets a fresh session.

One job per computer and app. A second command for the same app while one is running is rejected with a typed error. Relay that to the user in plain language rather than retrying. A different app on the same computer runs concurrently.

And the constraint that shapes the prompt: no progress, no steering, no cancel mid-run. Describe the outcome you want, not the keystrokes, and expect nothing back until it finishes.

What the machine can reach

The node's access is yours to bound, and the defaults are conservative:

Control Default Effect
--workspace-root <path> Allowlist of directories the node may work in. Repeatable
--no-ai-cli AI enabled Disables agent execution entirely — the node still handles other local actions
--max-tasks <n> 5 Concurrent local actions
--max-runtime-ms <ms> Hard ceiling on a single local action
--max-output-bytes <n> Caps inline stdout/stderr captured back

Beyond that: a node only ever executes jobs dispatched to its own cluster, the runner token is rotatable, and the credentials the work uses are the ones already on your machine — Spikefrost never sees your Claude or Codex login.

Configuration reference

Every flag has an environment-variable equivalent, which is usually the better choice for a background service.

Flag Environment variable
--gateway-url <url> SPIKE_EDGE_GATEWAY_URL
--workspace-root <path> SPIKE_EDGE_WORKSPACE_ROOTS
--no-ai-cli SPIKE_EDGE_ALLOW_AI_CLI=0
--max-tasks <n> SPIKE_EDGE_MAX_TASKS
--no-cli-health-check SPIKE_EDGE_CLI_HEALTH_CHECK=0
--cli-health-timeout-ms <ms> SPIKE_EDGE_CLI_HEALTH_TIMEOUT_MS
--no-auto-upgrade SPIKE_EDGE_AUTO_UPGRADE=0
--auto-upgrade-interval-ms <ms> SPIKE_EDGE_AUTO_UPGRADE_INTERVAL_MS
--verbose SPIKE_EDGE_VERBOSE=1
--stream-output SPIKE_EDGE_STREAM_OUTPUT=1
--stream-agent-events SPIKE_EDGE_STREAM_AGENT_EVENTS=1
--no-reconnect

sf edge help prints the complete list, including the upgrade-source overrides.

Keeping it current

sf edge version              # runner version
sf edge upgrade              # reinstall
sf edge upgrade --force      # reinstall even at the same version

The runner checks for upgrades while idle by default. Disable that on a machine where you want the version pinned, with --no-auto-upgrade or SPIKE_EDGE_AUTO_UPGRADE=0.

Troubleshooting

Symptom Cause
"Connected, but this node is NOT paired" The pairing code was never registered against the cluster. Finish the console step; it binds on retry
Startup stalls on CLI checks The node says hello to Claude/Codex on boot. If that seat isn't signed in, sign in — or skip the probe with --no-cli-health-check
Dispatch rejected with a typed error Another job is already running for that computer and app. Wait, or dispatch to a different app
Jobs never arrive Check the service is running (sf edge service status) and that the agent's alias matches the connector
Work not visible in the repository The machine doesn't auto-publish. Use sf app push for app code or git push for a mounted repository
Agent describes work that didn't happen Read the trace, not the reply — see Observability and costs

Next

Frequently asked questions

What is an edge node?

A computer you own running a Spike worker. It pulls jobs from Spikefrost, executes them locally using your own Claude Code or Codex seat, and streams results back. The work happens on your hardware, with your credentials and your network access.

When would I want one?

When the work has to happen where you are — against a private repository, an internal network the cloud can't reach, or a machine that already holds the tools and credentials. Also when you'd rather the model usage bill to your own coding-agent seat.

Does the node bill against my Spikefrost balance?

No. The machine runs your own Claude or Codex seat, so that usage bills to that account. Spikefrost dispatches the work and carries the result.

Can an agent watch the job while it runs?

No, and designing around that matters. The agent's turn ends at dispatch; the machine works alone for minutes and the result arrives later as a new message in the same conversation. There is no progress stream, no steering and no cancel mid-run.

What can the machine actually reach?

Whatever you allow. Workspace roots are an explicit allowlist, the AI CLI can be disabled entirely, and concurrency and runtime are capped. The node only ever executes jobs dispatched to its own cluster.