@flowrunner/cli
v0.1.14
Published
Flowrunner CLI for deploying Custom Extensions
Readme
@flowrunner/cli
FlowRunner is the orchestration layer for AI agents in production. Model providers and tools arrive as verified connectors, flows are built no-code or in code, and an agent facing a consequential decision pauses for a human instead of guessing — human-in-the-loop by design, with an audit trail to match.
This package is the flowrunner CLI: author and deploy custom extensions — your own connectors — from
your own repository. It builds every service definition locally and uploads it with the package, so the
server never has to execute extension code to model it.
Install
A new project — npx, once
init installs the CLI into the project it creates, so the only command you need npx for is the very
first one:
npx @flowrunner/cli init # set up the project in the current directory
npx @flowrunner/cli init -d my-extensions # ...or in ./my-extensions, creating it if needed
npx @flowrunner/cli init blank # ...and scaffold a first service from a templateThen work inside the project, where flowrunner is already available:
cd my-extensions
flowrunner --helpAn existing project — npm install
Add the CLI to a repository you already have, then set it up in place:
npm install --save-dev @flowrunner/cli
flowrunner initinit never overwrites: files that already exist are left alone, so adding FlowRunner to an existing
repository is the same operation as starting from nothing, minus the files that are already there.
Quick start
npx @flowrunner/cli init -d my-extensions blank # project + first service, npm install, git repo
cd my-extensions
flowrunner login # browser authorization → .flowrunner/token
flowrunner deploy # discover → model → hash → zip → uploadCommands
| Command | Purpose |
|---|---|
| flowrunner init [template] | Create the project: package.json, flowrunner.json, .gitignore, README.md, the unit-test harness, git repo, optional first service |
| flowrunner init-claude | Install the FlowRunner subagents into .claude/agents/ and add a block to CLAUDE.md |
| flowrunner use [target] | Point the project at a cluster — prod, dev, local, or a full URL. Omit to list them |
| flowrunner login | Browser-based authorization; stores the deploy token and workspaceId |
| flowrunner logout | Revoke the token server-side and delete it locally |
| flowrunner create-service [template] (cs) | Scaffold a service into services/ from a bundled template |
| flowrunner deploy | Deploy every service in services/ to the connected workspace |
Common flags: -y, --yes (accept every default, ask nothing), --id / --name / --set name=value
(answer template prompts non-interactively), -s, --server <target> on init and login,
--no-install / --no-git / --no-tests on init, --list on create-service.
Every command works non-interactively — prompts appear only on a TTY, and anything unanswerable becomes an error with a stable code rather than a hang.
Testing
init puts a unit-test harness in the project — sandbox/ at the root, a jest config, and one suite per
service in services/{id}/tests/:
npm test # every suite
npx jest services/weather/tests # one serviceA suite runs your service through the real runtime, with HTTP intercepted at the socket, so what it asserts on is what the pod would have sent — the request, the headers, the query, the body. Nothing reaches the network.
const { createNockMock, getServiceConfigItems, runServiceMethod } = require('../../../sandbox')
httpMock.onGet(`${ BASE }/current`).reply({ temp_c: 21.4 })
const result = await runServiceMethod({
serviceId, serviceEntryPointPath, configs: { apiKey: 'test-key' },
methodName: 'getCurrent', methodData: { city: 'Lisbon' },
})
expect(httpMock.history[0].query).toEqual({ q: 'Lisbon', key: 'test-key' })The harness is copied into the project, not linked, so it is yours to edit — and init never overwrites
it. Running flowrunner init again in an existing project is how a project created before the harness
existed gets one. --no-tests skips it.
The full guide is in node_modules/@flowrunner/cli/ai-docs/instructions/service-code-format/15-unit-tests.md.
Writing services with an AI agent
This package ships the authoring reference itself, under
node_modules/@flowrunner/cli/ai-docs/instructions/service-code-format/. That location is the point: the
instructions your agent reads are pinned to the CLI version your project installed, so they describe the
format this CLI actually deploys rather than whatever a model remembers about it.
Point your agent at that path however your tool expects, or use the command for it. There is one per
provider, because every provider differs on which file it reads and where subagents live — Claude Code reads
CLAUDE.md and ignores AGENTS.md, so there is no single file init could write for everyone.
Claude Code
flowrunner init-claudeTwo things happen:
.claude/agents/gets two subagents.flowrunner-service-code-engineercreates, reviews and fixes services, and keeps each one's README in step.flowrunner-service-test-engineerwrites the unit suites against the harness above. Both already know the format, so you don't re-explain it every session — and they are separate on purpose: an engineer that owns both a service and its tests ends up fixing the service to make its own test pass.CLAUDE.mdgets a block telling Claude the agents exist, when to reach for each, and where the authoring reference lives.
It is safe to run over a CLAUDE.md you already have. The command owns exactly the region between its own
markers:
# Our own house rules ← yours, never touched
<!-- flowrunner-cli:ai:start -->
...the FlowRunner block... ← the CLI's, replaced on every run
<!-- flowrunner-cli:ai:end -->
# More of our rules ← also yours, also never touchedRe-run it after upgrading the CLI and only that block changes — nothing is duplicated, and everything outside
the markers survives byte-for-byte. The flowrunner-* files under .claude/agents/ are the CLI's and are
overwritten, which is how an upgrade ships you a better agent; keep your own agents under your own names and
they are left alone.
