FeaturesThe CLI

All of fctl, from your terminal.

Everything the app does, the CLI does too: start a session and watch it stream, steer it, search every transcript, manage projects, runners and schedules. And every command answers in JSON when a script, a pipeline or another agent is the one asking.

The CLI reference fctl for agents

Follow Live, in the shell

fctl run and fctl attach stream the transcript as the app shows it, and take your messages.

Script JSON everywhere

Add --json to any command. Exit codes say what went wrong, so scripts can tell.

Agents For them too

Another agent with the CLI and the docs at fctl.sh/llms.txt hands work to fctl and collects the result.

Machines Runners included

The same binary runs your hosts: install, status, drain, logs and its own updates.

The floor, in a dozen lines.

fctl sessions lists what's at work and what finished, across your workspaces or in one, and fctl show tells you everything about one: who asked, its ticket, its branch, its pull request and checks, where it runs and how full its context is. Sessions go by shop#231, their id or their link, whichever you have to hand.

noor@Noors-MacBook-Pro ~

fctl sessions -w romanesco --limit 6

infra#38 ● running Check production and staging for Terraform … 8m ago

shop#231 ● running Add Danish to the shop 1m ago

driver-app#77 ● running Show the delivery window on each stop 2m ago

platform#445 ○ idle Retry Stripe webhook processing that fails 21m ago

shop#230 ◍ paused Match the box builder to the new illustrati… 33m ago

shop#227 ○ stopped Update 9 npm dependencies 6h ago

fctl show shop#231

shop#231 Add Danish to the shop

Translates the shop for the Copenhagen launch: Lucía's copy from SHOP-419, prices in kroner and delivery days from the Copenhagen depot.

status: ● running

ticket: SHOP-419 Danish translations for the shop · https://linear.app/romanesco/issue/SHOP-419/danish-translations-for-the-shop

by: Tomás Ferreira

branch: fctl/231-add-danish-to-the-shop (from main)

pr: shop#1291 open, 12 of 23 checks pending https://github.com/romanescohq/shop/pull/1291

runner: kohlrabi

model: opus

effort: high

work: 1 turn · 21 tool calls · 4 files (+127 −4)

context: 46.5k of 200k tokens (23%) · compacts at 167k

https://app.fctl.sh/s/ses_01K8YD4T2W9QXN6B3HVM7CZRPE

Steer it like you'd steer a colleague.

A message reaches the agent at its next step, with files attached if you like. Interrupt the turn it's on, stop it, resume it tomorrow with a new task, or share it with a teammate. The same session is in the app, on your phone and in your terminal at once, and everyone sees the same thing.

Follow along and steer
tomas@studio ~/src/shop

fctl send shop#231 -a dk-prices.png "Prices end in ,- in Denmark: 189,- not 189,00 kr."

✓ Sent to shop#231

fctl attach shop#231

▍ Tomás Ferreira

▍ Prices end in ,- in Denmark: 189,- not 189,00 kr.

Good catch. Danish shops write whole kroner as 189,- so I'll format DKK that way when the øre are zero, and keep 189,50 kr. otherwise.

⏺ Edit(src/lib/money.ts)

⏺ Bash(npm test -- money)

⎿ ✓ src/lib/money.test.ts (9 tests) 5ms

Made for scripts, and the agents that write them.

With -d, fctl run returns as soon as the session exists; with --json, it says so in a form jq can read. Check on it when you like, read what it did, and move on: the same commands work in a cron job, a GitHub Actions step, or another agent's tool call.

  • Signed in as you, or as a token. fctl login on your machine, FCTL_TOKEN anywhere else.
  • A guide for agents. The docs say how a program should drive fctl, and what to avoid.
ci@build-7 ~/platform

id=$(fctl run -p platform -d --json -f tasks/flaky.md | jq -r .id)

# …once its turn has ended

fctl show $id --json | jq '{status, pr: .pull_requests[0].url}'

{

"status": "idle",

"pr": "https://github.com/romanescohq/platform/pull/846"

}

fctl memory -p platform --json | jq -r '.memories[0].text'

Answer Stripe's webhooks at once and do the work in the job queue (`jobs::enqueue`): a handler slower than Stripe's timeout gets the event again.

And the rest of the factory.

Every capability of the app has its command. A few of them:

Sessions

  • fctl runStart one, and follow it
  • fctl attachStream it and type messages
  • fctl logs -fThe transcript, as it grows
  • fctl searchEvery transcript, by what was said

Projects

  • fctl projects setModel, setup script, image, sizes
  • fctl projects secretsSecrets for its sandboxes
  • fctl projects reposOther repositories it may use
  • fctl projects ticketsLinear or GitHub issues

Reviews and memory

  • fctl review settingsTurn review agents on
  • fctl review startReview a pull request now
  • fctl memoryWhat agents left for each other
  • fctl retro listHow each piece of work went

Runners and teams

  • fctl host installTurn this machine into a runner
  • fctl host drainFinish its sessions, take no new ones
  • fctl workspaces inviteBring someone in
  • fctl shareOne session, with one person

Automation

  • fctl schedules addWork that starts on its own
  • fctl schedules runNow, with context
  • fctl tokenA token for a tool, with limits
  • fctl ticketTickets, from an agent's sandbox

You

  • fctl loginThrough your browser and passkey
  • fctl claude connectYour Claude subscription
  • fctl account two-factorAn authenticator app
  • fctl self updateThe newest fctl

In the docs

Every command and flag, and how programs should use them.

Start a factory tonight.

curl -fsSL https://fctl.sh/install | sh