Nano BPM Advanced Research Prototype Get started with c8ctl

Get started with c8ctl

The easiest way to run and manage Nano BPM — a single node or a whole cluster — is the c8ctl CLI with the c8ctl-plugin-nano plugin. The plugin ships a prebuilt Nano binary for your platform and installs it for you, so there is nothing to compile.

The fastest way to go from zero to a running Nano Workforce — the engine, a supervised workforce of hired coding agents, and the Workforce app — is the one-command installer:

curl -fsSL https://nanobpm.io/install.sh | sh

It installs the Camunda 8 CLI and the c8ctl-plugin-nano plugin, lets you pick which of your installed coding harnesses to hire (and with which model and how many instances), composes a workforce manifest from those choices, brings the engine and workforce up, then installs and runs the Workforce app. It never runs sudo on your behalf — it installs the CLI with npm i -g, so where the global package lands depends on your Node/npm setup (a user-owned prefix such as nvm needs no elevation; a system-owned prefix may require you to fix your npm prefix first).

Prefer to read the script before running it? Download, inspect, then run:

curl -fsSL https://nanobpm.io/install.sh -o install.sh
less install.sh
sh install.sh

https://nanobpm.io/install.sh always mirrors the script on main in the nano-workforce repository — the single source of truth.

The rest of this section sets up just the engine, by hand. Use it when you want a single node or a cluster without the workforce, or to understand exactly what the installer automates for you.

Prerequisites

Install these tools before you start.

Verify each tool:

node --version
c8ctl --version

Then manage Nano with c8ctl:

# Load the plugin (installs the matching prebuilt binary for your OS/arch)
c8ctl load plugin c8ctl-plugin-nano

# Start a single-node cluster on port 8080
c8ctl nano start

# Start a 3-node cluster (ports 8080, 8081, 8082)
c8ctl nano start 3

# Start a 3-node Raft-replicated cluster (RF=3 enables replication automatically)
c8ctl nano start 3 --rf 3

# Show cluster status and per-node health
c8ctl nano status

# Tail a node's log (node ids are 0-indexed, so a single node is node 0)
c8ctl nano logs 0 --follow

# Simulate a node failing and recovering
c8ctl nano pause 0
c8ctl nano resume 0

# Stop the cluster (engine data retained); add --purge to delete engine data
c8ctl nano stop

c8ctl nano keeps your authoring assets (BPMN models and worker code) in a shared workspace that survives stop and clean, separate from the throwaway per-node engine data. It also wires every node's ports, ids, partitions, replication, and data directories for you.

Once a cluster is up:

A demo process (processDefinitionId: "demo") is pre-deployed at startup, so you have something to run immediately.

Compose and run a workforce by hand

The one-liner installer composes a workforce manifest for you. To build one by hand — or to curate a fleet you can diff, edit, and copy between machines — use the hireworkforce commands. A workforce is a fleet of supervised coding-agent workers (each running a harness such as copilot, claude, or qwen on your PATH) described by a single manifest file. This needs a running engine (above) and at least one agent harness installed.

1. Hire agent profiles. A profile is a reusable definition — a rank, the harness command, an optional model, and any launch args (the examples below set no model, so the harness uses its own default):

# Create a "copilot" senior profile that runs `copilot --allow-all`
c8ctl nano hire --name copilot --rank senior --command copilot --arg --allow-all
# Create a "qwen" profile that runs the `qwen` harness
c8ctl nano hire --name qwen --rank senior --command qwen
c8ctl nano hire --list

2. Compose the manifest with workforce add. --instances N spawns N copies of a profile; --auto serves every deployed agent job type, or --roles a,b scopes it to specific roles:

c8ctl nano workforce add copilot --instances 5 --auto
c8ctl nano workforce add qwen --instances 2 --roles pr-review,feature

The manifest is a portable JSON document at <stateHome>/workforce/<name>.json (default.json unless you pass --manifest <name>), where <stateHome> is c8ctl's OS-dependent state directory (e.g. ~/.local/share/c8ctl-nano on Linux). It is meant to be read, hand-edited, diffed, and copied between machines:

{
  "version": 1,
  "name": "default",
  "workers": [
    { "profile": "copilot", "instances": 5, "roles": "auto" },
    { "profile": "qwen", "instances": 2, "roles": ["pr-review", "feature"] }
  ]
}

Each entry references a hired profile and sets instances (how many copies) and roles — either "auto" (serve every agent job type, no capability gate) or a list, each mapped to a <rank>:<role> job type. Optional fields: autoScope (narrow --auto to a single bpmn:process id prefix — one app/network) and args (verbatim flags appended to each worker).

3. Bring the whole fleet up under a supervisor with one command:

c8ctl nano workforce start                      # the default manifest
c8ctl nano workforce start --manifest review-only

start reconciles the running supervisor to the manifest using deterministic wf-<manifest>-<profile>-<index> worker names, so re-running an unchanged manifest starts, stops, and restarts nothing (it is idempotent).

4. Inspect and manage the fleet:

c8ctl nano workforce status --json   # desired (manifest) joined with actual (live supervisor)
c8ctl nano workforce list
c8ctl nano workforce stop            # bring the fleet down

The supervisor is a fleet runner, so you can also adjust individual workers without editing the manifest:

c8ctl nano supervisor add copilot --instances 3 --auto   # or --roles pr-review,feature
c8ctl nano supervisor restart copilot
c8ctl nano supervisor status
c8ctl nano supervisor stop            # stop the daemon and all its workers

GitHub authentication. Agent workers clone each task's repository over HTTPS, so every worker needs non-interactive GitHub credentials. Without them a job fails to provision with fatal: could not read Username for 'https://github.com': terminal prompts disabled. Two ways to provide them:

  • Recommended — gh credential helper. Run gh auth login and enable the git integration (gh auth setup-git). This writes a credential helper into your global ~/.gitconfig, which every worker's git clone picks up automatically — nothing to export. Verify with gh auth status.
  • Or a token in the environment. Export a token in the shell that runs workforce start; the supervisor and all its workers inherit it: export GITHUB_TOKEN="$(gh auth token)" (or any PAT with repo scope).

macOS + a remote engine over SSH (Local Network Privacy). If you run the fleet on a Mac over SSH against an engine on your LAN (e.g. merlin.local:8080, 192.168.x.x), workers may show running but sit idle — listening on 0 job type(s), agentic disconnected, logs spinning on activateJobs failed: fetch failed / reconcile skipped — fetch failed. On macOS 15 Sequoia / 26 Tahoe the supervisor's session-independent LaunchAgent (installed so the fleet survives SSH logout) is a separate Local Network Privacy identity that is not granted LAN access — so it cannot reach a LAN engine, even though internet hosts and an interactive SSH shell work. The signature is EHOSTUNREACH to the engine's LAN IP from the service. Fix it with one of:

  • Grant Node.js Local Network access on the Mac's GUI: System Settings → Privacy & Security → Local Network, enable the Node.js runtime entry (it may appear as “Node.js Foundation” / “App Background Activity”), then c8ctl nano supervisor stop && c8ctl nano supervisor start.
  • Route over Tailscale — traffic over the utun interface is not treated as “local network”, so point the engine at the tailnet address (e.g. NANO_REST_URL=http://<host>.<tailnet>.ts.net:8080).
  • Run in the SSH session (c8ctl nano supervisor uninstall) — inherits the Terminal grant, but then pin a tmux/SSH session so it does not die on logout.

See the c8ctl Nano plugin README (“Surviving SSH logout”) for the full explanation.