Conversation guide and technical reference

Using Flock

Describe the work as you normally would; mention the flock or say “delegate” when you want other agents involved. Your agent handles the tools and commands. Everything below the divider is for agents and operators, literal to the displayed release unless labelled illustrative.

literal to 0.7.21-alphamacOS and Linuxbinaries are currently unsigned

Use Flock through your agent

With Flock tools loaded, describe the outcome and ask your agent to delegate or request a review. The examples below show intended agent reports; they are not guaranteed output. Structured task review requires a completed task with a recorded Git worktree.

Illustrative examples, not captured output

Share the work

You say“Refactor the auth flow. Use the flock to split independent work where it helps, and bring me one result with test evidence.”

Your agent reportsI kept the API changes here and delegated the parser cleanup to the codex profile. The task is on the ledger; I will bring back one result with the test evidence.

Choose a provider

You say“Delegate the migration check to Codex.”

Your agent reportsDispatched to the codex profile. The routing and the result are recorded locally.

Ask for review

You say“Have a second profile review the authorization changes.”

Your agent reportsReview dispatched. The verdict lands on the task itself, next to the exact diff it judged.

Check the flock

You say“Who in the flock can take work right now?”

Your agent reportsTwo Claude profiles are accepting; the codex session is mid-task. One profile is near its capacity window.

Check progress

You say“Where is the flock stuck?”

Your agent reportsOne session asked a clarifying question; I have its exact questions for you. Everything else is done and recorded.

Resume earlier work

You say“Find our earlier auth migration work and continue from there.”

Your agent reportsRecall matched two sessions; I am resuming the one with the migration branch.

Three optional words

  • flock: The agents currently available to work together.
  • delegate: Give a bounded part of the work to another agent.
  • review: Ask a second profile for a verdict on finished work, across providers if you route it there.

What your agent should report

  • What it delegated, to which profile, and what it kept in the conversation.
  • Any owner boundary or destructive action that needs your approval.
  • Any refusal, blocker, or clarification request, with its reason.
  • The returned result and the evidence behind it.
  • For automatic routing, the profile chosen; auto-routing always names it.

The natural-language layer requires a wired agent: MCP tools load at session start after wiring. The example reports are illustrative; report quality is instructed behavior, not enforced product output.

For agents and operators

Everything below documents how Flock-aware agents, maintainers, and support tooling operate: the MCP tools agents call, then the operator and diagnostic CLI, the hook and event contract, state on disk, and the operating invariants. People normally do not need to run any of it.

MCP tools

These are the tools your agent calls after Flock is wired; they are not user-facing commands or prompt keywords. flk mcp serves MCP over stdio; flk profile wire registers it as server flock in each profile home. Claude registration is written to the profile's Claude state file; Codex registration is written under mcp_servers.flock in config.toml. Gemini CLI registration uses gemini mcp add with user scope under the profile's home. Native tools load at session start. An agent must inspect the tools exposed to its own session before promising to call one; another profile's wiring does not prove this session has loaded the server.

flock_roster

Arguments
(none)
Returns
{live: [...], dead: [...], lead: {...}}

flock_delegate

Arguments
to_profile*, brief*, mode (wait default | async), cross_owner ('true' confirms a cross-owner dispatch), isolation (worktree), thread, model, effort, keep_model (borrow a model and effort for the task; restored after the turn unless 'true')
Returns
wait: {task_id, routing, state, result, error} · async: {task_id, routing, state, note}. Async runs inside the MCP server process, which must stay alive until collection; unlike CLI --wait=false, it does not detach

flock_msg_send

Arguments
to*, text*
Returns
mailbox write + turn-boundary delivery attempt

flock_msg_ls

Arguments
(none)
Returns
this session's mailbox, unread first

flock_msg_read

Arguments
(none)
Returns
unread messages, marked read on return

flock_task_review

Arguments
task_id*, to*, focus
Returns
dispatches the review; returns {task_id, thread, state, verdict, note, result}

flock_thread

Arguments
name*
Returns
the thread's tasks in order, briefs and results trimmed to first lines

flock_task_clarify

Arguments
task_id*, answers*, mode
Returns
answers a needs-clarification task and redispatches it (same record, same worker, three-round cap)

flock_task_brief

Arguments
task_id*
Returns
the framed brief the task's target session must receive (what the wake-up line points at); records the delivery

flock_model

Arguments
session*, model, effort, default
Returns
with only session: the model and effort the agent last reported. With model and/or effort: model selection (see flk model); returns the previous model and effort

flock_handoff

Arguments
to_profile*, context*
Returns
{session, brief, hint}; appends a HANDOFF note and spawns a session pointed at it

flock_note

Arguments
text*
Returns
appends to .flock/brief.md with author and timestamp

flock_recall

Arguments
query*
Returns
matches with resume commands

flock_lead

Arguments
(none)
Returns
{lead, session_id, profile, granted_by, granted_at, alive, chain_len}

flock_lead_recuse

Arguments
successor*, reason
Returns
the new assignment; the caller must be the current lead

flock_usage

Arguments
session, live (bool)
Returns
transcript stats, or authoritative quota per profile with per-profile cache fallback

Operator and diagnostic CLI

flk provides CLI commands for agents and operators. State defaults to ~/.flock, with FLOCK_HOME as an override. Requested operations can also write provider homes, project files, the executable and a macOS LaunchAgent plist. The quota LaunchAgent records its FLOCK_HOME in the plist.

Inspect before you dispatch

Illustrative example, not captured output

This sequence checks identity and fleet state, then assigns one bounded task and waits for its recorded result.

flk whoami
flk ls
flk delegate --to claude:auto "Inspect the failing test, propose the smallest fix, and return the file path plus evidence."

Automatic routing prints the profile chosen. A refusal, failure, or clarification request stays visible as task state.

Identity & configuration

flk init --discover [--owner o] [--yes] [--only names] [--no-wire]

adopt existing logged-in agent homes from four sources: the top level of ~ (.claude, .claude-*, .codex, .codex-*), the environment of running agent processes, a sweep under ~, and profiles' own isolated homes. A home with no login is not proposed; a home already attached to a profile is skipped. Each proposed home is bound in one of four ways: a new account and profile (named from the identity's local part, deduped); a new profile on an account already on record whose declared address matches the login; attachment to an existing profile whose account declares the same address and whose current home holds no login; or re-attachment of a profile to its own isolated home, which clears the profile's external home pointer. --only <names> narrows adoption to the named candidates (names are the first column of the proposal). On confirmation each candidate is bound as listed and wired, and the conversation migration is applied; --no-wire skips both. Adoption does not copy tokens; flk profile rm detaches an adopted home and leaves its directory and login. Owner: --owner, else inherited when exactly one owner is on record across your accounts, else prompted on a TTY; a non-TTY run that would create an account with no owner to inherit errors. --yes skips the confirmation for non-interactive runs

flk upgrade [--check]

download a platform binary, verify its checksum, write and execute a temporary candidate with --version, then replace the executable atomically. --check still downloads, writes and executes the candidate, but removes it without replacing the installed binary

flk install <path> [--repo checkout] [--target path] [--wait duration] [--force]

install a local Flock build. Stages a private copy, reads build metadata without executing the candidate, checks ancestry, backs up the existing binary and atomically replaces it. A known non-descendant is refused unless --force permits an intentional rollback; missing Git history or commit ancestry metadata emits an unverified-ancestry warning and does not block installation. A candidate whose Go build metadata cannot be read is refused. Compatible MCP processes using that executable re-exec after active requests finish, preserving their PID and stdio connection. The default eight-second adoption wait can report pending processes; pending is not success. Legacy servers need one reconnect to start reporting. Check flk ls and flk doctor for per-server provenance, drift and failures. Hot adoption executes the replacement at each MCP server's executable path without a new approval prompt, with that process's existing permissions. Protect write access to the installed file and its directory: another writer bypasses flk install's ancestry guard

flk profile login <name> [--agent a] [--owner o] [--email e]

human-only TTY login into the profile's home; --email declares the address on the profile's account when the account has none. For claude, when claude auth login --help succeeds and no arguments follow --, the login is claude auth login, with --email <address> added when the account declares an address; otherwise Claude Code opens for /login. Checks the result (per claude auth status, else the state file) against the declared account (when the account declares an email and the home exposes a logged-in identity). Requires a TTY on both stdin and stdout and refuses when either is missing. With --agent, a missing profile is created first (account declared, home created, events wired). When no default profile exists, the created profile becomes the default

flk profile ls

list profiles with agent, account, and default marker

flk profile rm <name> --yes

delete the profile configuration and its isolated home directory, including that home's login state. An adopted external home and the wiring inside it remain on disk; detach does not mean unwire

flk profile set-home <name> <path> [--force]

point a profile at an existing external agent home (e.g. ~/.claude). Both arguments are required; a path of - or "" restores the isolated home. When the profile's account declares an address and the home's login (per claude auth status, else the state file) is a different address, the command refuses and names the profile whose account declares that address when one exists; --force binds it anyway

flk profile wire

configure provider lifecycle hooks and Flock MCP registration in profile homes. Provider-specific context, commands and statuslines differ. Codex wiring replaces notify; isolated Codex homes also auto-approve Flock MCP tools

flk whoami

machine-wide identity report. Flags a mismatch between a profile's declared account and its logged-in identity (when the account declares an email and the home exposes one)

flk welcome

print each logged-in profile's capacity and the live session count

Commands shown here are an operator reference. Provider-specific settings and write scopes differ; inspect the installation guide before wiring.

Sessions & workers

flk ls

roster with current state. Rendered states: accepting working paused blocked(input). paused means the profile's worker capacity is determinately exhausted, the same test claude:auto uses to skip a worker. When a pane is gone, flk renders the retained record as resumable (transcript on file) or stale record. Hook statuses map onto these: idle and started render as accepting; needs-attention as blocked(input). The roster also shows reported MCP builds and flags stale or unverified provenance. MODEL is the model and effort the agent last reported (claude through its statusline input, codex through its rollout's turn_context), - until it reports

flk model <session> [<model>] [--effort e] [--default]

model selection. With no model, prints what the agent last reported. With a model and/or --effort (low, medium, high, xhigh), drives the agent's own /model picker from the composer at a turn boundary, reading each picker screen and the agent's confirmation, and fails closed (Escape) on any step it cannot read. Claude: default, opus, fable, sonnet, haiku, applied to the session only unless --default (the picker's Enter, which saves the pick for new sessions); a model without an effort selector (Haiku) takes the model and ignores the effort. Codex: a model slug such as gpt-6-astra; codex writes the pick to its config.toml as well, so it becomes the profile's default. Neither agent's /model <name> argument form is used: on claude it saves a default

flk worker ensure <profile>

spawn or reuse an account's worker (<account>-worker-<seq>) in a detached tmux session. Profiles sharing an account share its worker seat. Fresh workers use the profile workspace or current directory. Reuse outside the existing workspace can require recycling; attached clients prevent that restart. Delegation itself selects a profile's live member, which may be a worker-role session, and can spawn a member if none exists. Gemini API-key mode does not attest a person's identity. Gemini auto_approve_tools defaults off; enabling it passes --approval-mode yolo to new sessions, bypassing tool prompts without adding a filesystem sandbox. With it off, a detached worker can wait for human approval. Claude worker creation requires spawnable credentials

flk restart <session> | flk restart --all

restart live Claude conversations in place only after verified idle or hookless quiescence. The conversation id must be known, the pane must be live, and the composer must be positively recognized as empty (an agent's dim placeholder or prompt suggestion counts as empty). The command enters /exit, verifies the composer changed, exits gracefully, and resumes the same conversation in the preserved pane. Recognition and graceful-exit failures fail closed

flk resume <profile> <conversation-id> [--name n] [--dir d]

start a recorded conversation as a managed tmux session under the profile: the agent's first-boot prompts for the directory are pre-answered, the session is registered on the roster, named --name or <account>-<first 8 characters of the conversation id>, in --dir or the current directory. Refused when the profile's home holds no transcript for the id (claude: projects/*/<id>.jsonl; codex: sessions/**/rollout-*-<id>.jsonl), when the home holds no spawnable login (claude credentials; codex auth.json), when a tmux session of that name exists, or when the conversation is already live in a roster session

flk migrate [--dry-run] [--allow-signal]

converge attested pre-Flock Claude processes into resumed managed sessions. --dry-run prints the plan without stopping or spawning and is the required first pass before a standalone flk migrate in the install runbook (discovery applies migration under its own consent). The current process is skipped for last restart. Tmux candidates require verified idle or quiescence and fail-closed empty-composer recognition before graceful exit. Plain-terminal candidates are skipped by default; --allow-signal additionally requires process-tree quiescence, 120 seconds of transcript quiescence, and no non-shell children before SIGTERM. A resume failure after stop records migrate-stranded with the old pid, exact resume command, and error

flk doctor [--prune] [--deep]

check environment, wiring, identity, task state and MCP provenance. The base command can repair Claude lifecycle hooks and inherited tmux flags and refresh quota state; it is not read-only. --deep probes live contracts and requires network access and access to the credential store. --prune removes proven-dead roster pins even when tasks reference them; otherwise unreferenced ended or aged unattested rows can be removed. --heal enables additional repair paths

A new session uses an account-based name unless explicitly named. Claude sessions can be renamed from transcript slugs. Delegation prefers a live non-desktop session named after the profile, otherwise the most recently updated eligible member. It excludes the caller; if that caller is the only live member, dispatch is refused. With no member it can spawn one, unless a session is awaiting rehome. Worker-role sessions participate in member selection. Leadership does not rename sessions.

Delegation & memory

The lead assignment is stored as a lease file, state/lead.json, recording holder, pane, pid, and the grant chain (rendered publicly as the lead history). 'Lease' in the rest of this reference names that file.

flk delegate --to <profile|<agent>:auto> "brief" [--wait] [--cross-owner] [--timeout d] [--isolation worktree] [--thread name] [--model m] [--effort e] [--keep-model]

dispatch a framed brief to a profile's live member. Selection prefers the profile-named session, otherwise the most recently updated eligible session, excluding the caller and desktop sessions. With no member it can spawn one; self-only and rehome-pending targets are refused. Dispatch checks login, event wiring, declared-owner boundaries and recorded capacity. A cross-owner task needs --cross-owner when both owners are known. Non-worker members wait for a recognized empty composer at a turn boundary; a busy member can leave the task accepted with parked_at for later idle-hook or explicit redispatch. Parking has no delivery deadline. Worker-role targets may have composer residue cleared once. Flock pastes a task-id wake-up; the worker obtains the framed brief from its hook or task-brief tool. Results must match the dispatch input; missing or mismatched results are not success. Codex collection checks rollout completion and can use a fresh notify fallback. --timeout defaults to 15 minutes for the result wait; boot, boundary and reconciliation phases have separate bounds, so it is not an end-to-end deadline. --wait=false uses a detached CLI child. --isolation worktree creates a separate checkout and records branch/base; merge and cleanup remain the sender's responsibility. A worker-role target rejects an explicitly assigned worktree outside its root; an implicit sender-directory default outside that root yields to the root. This routing check is not a filesystem sandbox. --thread groups task records. --model and --effort request a borrowed provider model; restoration is attempted unless --keep-model, with outcomes recorded on the task

flk task status <id>

one task's record. A worker that hits blocking ambiguity ends its turn with a message beginning CLARIFY: (stating the exact ambiguity, why it decides the deliverable, the smallest question set, safe work done, and its declined-to-decide default), and the task settles as needs-clarification with the questions as its result

flk task brief <id>

the framed brief a task's target session must receive, as the wake-up line points at it

flk msg send <session|lead> "text" / flk msg ls / flk msg read

turn-boundary fleet messages. A successful send stores the message in the target session's mailbox, a typed message event joins the events stream, and an automated worker or the persistent helper session (the attendant) gets a one-line notice pasted (queued input if it is mid-turn); A human-driven session with a live pane can receive a typed wake-up line at a verified turn boundary. Where hook delivery is available, the waker first allows three minutes for it to deliver the notice; the wake attempt gives up after 45 minutes. Paneless sessions rely on their configured notification surface. The line is submitted in that session's composer as its next turn; if the read-back finds other input beside it, it is left in the composer unsent, and a composer that already holds a draft refuses it. lead resolves through the lease at send time; with no valid lease the message waits in a pending-lead box the next holder claims on read. Use messages for coordination; task briefs go on the delegation ledger. doctor --prune clears read messages older than seven days; unread mail is never pruned

flk task clarify <id> "answers"

answer a needs-clarification task and redispatch it: the round is appended to the one task record (question, answer, timestamps, and a worktree snapshot when isolated), the full brief plus history replays to the same worker as the canonical authority, and the timeout restarts. Three rounds per task; past that, re-scope the brief

flk task review <id> --to <profile> ["focus"]

builder-to-reviewer on the ledger: dispatches a review of a completed --isolation worktree task, with the handoff package assembled from artifacts: the original brief, branch, base and HEAD pinned as commit SHAs, git diff --stat, and the builder's result verbatim. The reviewer works read-only in the builder's worktree (contractual; the worktree HEAD is checked after review and a move warns) and ends with one line, REVIEW: approve|revise — <sentence>, settled typed on the review task (approve, revise, or unknown when malformed — completion never fails on it). The review joins the builder's thread, minting t-<task-id> when it has none. Merge stays the sender's step, now with a verdict beside it

flk thread <name>

the thread's tasks in order — id, state, reviewer verdicts, first line of brief and result: the durable cross-task narrative that survives session recycles

flk recall <query>

search all profiles' transcripts; returns matches with resume commands

Lead protocol

The lead lease identifies the coordinating session. The operator policy assigns it dispatch, verification and reporting responsibilities; use Flock commands for session operations so outcomes are recorded.

flk lead grant <session>

designate the lead. Owner-run by policy; the CLI does not authenticate its caller. Claude and Codex sessions are eligible, subject to admission checks; Gemini sessions are refused. The lease records pane and pid and is verified against the live process. Claude leads are expected to run Fable; a Claude lead on another model gets a statusline warning

flk lead check

prints a retirement order when the lead's reading is determinate and any quota window is at or above 98%. On an indeterminate reading (unknown, stale, drift) it prints the reason and no order

flk lead enforce

check the recorded lease, upgrade legacy pins when verifiable, and allow a down holder's same identity to retake the lease. Quota-driven succession requires a live, determinately exhausted lead and an already-live successor with determinate lead capacity. Unknown capacity does not trigger quota succession

Quota

flk usage [--live]

consumption computed from transcripts; --live fetches authoritative quota instead

flk quota fetch [--quiet]

refresh per-profile quota records: Claude uses its credential file or macOS Keychain for the usage endpoint; Codex reads local rollout quota and refusal signals. Gemini has no numerical quota reader. Writes the cache, records capacity changes and runs lead enforcement

flk quota show [--json]

render quota as text or JSON. A cold cache can trigger an inline fetch and cache write; this command is not guaranteed to be read-only

flk quota install-agent

install and start the optional macOS quota watcher after operator consent. The persistent process runs at a 15-minute cadence, known reset deadlines and requested refreshes, using the FLOCK_HOME recorded in its plist

Worker capacity excludes model-scoped windows from the 98% refusal threshold; lead capacity includes them. Readings must be determinate. Unknown, stale, schema-drift and passed-reset states do not establish exhaustion and remain dispatch-eligible. Codex model buckets and observed provider refusals are reflected in the cached reading. Claude can read credentials from a file or the macOS Keychain; only the latter requires Keychain access.

Rules for agents using these tools

  • The worker cannot see your session. A brief must carry the goal, all needed context, the deliverable format, and acceptance criteria. Include executable file paths and commands in the brief.
  • claude:auto reports the profile chosen; repeat that to the user.
  • Dispatch to a determinately exhausted profile is refused; do not work around the refusal. If any of your own windows reaches 98% while you hold the lead, recuse (see the runbook's capacity section). A worker whose only window at 98% is model-scoped may still accept work on other models.
  • On task failure, report the state, error, and log path verbatim.
  • Preserve a flock_msg_send deaf-mail warning. The mailbox write succeeds, but a target without a hook or statusline surface can wait silently; do not describe that warning as delivered coordination.

Hook & event contract

flk profile wire installs these. They call flk event … (hidden command; errors go to stderr with exit 0, so a hook failure never fails the agent).

Claude Code: every hook posts its stdin JSON to flk event claude:

Claude hookRoster state
SessionStartstarted
UserPromptSubmit, PreToolUse, PostToolUse, PostToolUseFailure, SubagentStart, SubagentStopworking (repeated status updates throttled to 3s)
Notificationneeds-attention
Stopidle
SessionEndended

Payload fields used: hook_event_name, session_id, transcript_path, cwd, tool_name, message, prompt. Session resolution order: tmux pane → FLOCK_ID env → session_id. Unknown sessions register as external with deterministic id ext-<session_id[:8]>: one record per agent session. On UserPromptSubmit, prompt is recorded as the turn's input for dispatch integrity, and when it carries a delegation wake-up line the hook prints that task's framed brief to stdout, which Claude Code adds to the turn's context: this is how a delegated brief reaches a claude session.

The first Claude SessionStart or UserPromptSubmit event consumes a durable first-contact flag and writes one context notice into Claude's conversation. It names the roster identity and profile, states whether lifecycle surfaces are wired, and, when wired, says that native tools load after restart. It tells the agent to operate Flock on the user's behalf without exposing commands. Silent hook events never consume the flag. Codex receives its context through managed AGENTS.md and MCP; there is no codex hook context channel. A delegated brief reaches a codex session through flock_task_brief or flk task brief <id>, named in the wake-up line. The statusline input (model.id, model.display_name) is recorded on the session whenever it changes; it is what flk ls and model selection read for a claude session.

Codex: notify in the flock-owned config.toml calls flk event codex-notify <json>. Only agent-turn-complete is ingested; it sets idle and records the turn's final message and input for result collection, and the model and effort of the turn from the rollout's turn_context. Codex has no start or working hooks: boot is discovered from the profile home's session files, and death from pane liveness.

State on disk

Flock keeps state as local files under FLOCK_HOME (default ~/.flock). MCP servers and the optional macOS quota watcher can remain running. Requested operations may also write provider homes, project notes/pins/worktrees, the installed executable and installer backups.

~/.flock/
  accounts.toml                 # named accounts: provider, owner, email
  profiles/<name>/
    profile.toml                # agent, account, model, workspace, env
    home/                       # the agent's isolated home (CLAUDE_CONFIG_DIR / CODEX_HOME / GEMINI_CLI_HOME)
  state/
    sessions/<id>.json          # roster records (atomic writes)
    events.jsonl                # append-only log: lifecycle, capacity-transition, succession, message
    lead.json                   # the lease: holder, pane, pid, granted_by, chain
    quota.json                  # quota cache (per profile, timestamped)
    tasks/                      # delegation ledger + per-task logs
    messages/                   # mailboxes, one box per session + lead-pending

Spawned sessions receive FLOCK_ID and FLOCK_PROFILE. The provider home variable is CLAUDE_CONFIG_DIR, CODEX_HOME or GEMINI_CLI_HOME; Flock omits CLAUDE_CONFIG_DIR for Claude's default home to preserve its native identity behavior. Profile environment settings can override defaults. TMUX_PANE is supplied by tmux.

Invariants

  • Discovery attaches provider homes without importing credentials. Quota checks read stored credentials; isolated homes and task content can still contain secrets.
  • MCP uses stdio. The checked Flock source contains no network listener; the optional macOS quota watcher is a persistent background process.
  • Wiring preserves unrelated MCP entries and custom Claude statuslines, but claims the Codex notify setting. Isolated Codex homes auto-approve Flock MCP tools. Profile removal deletes an isolated home; an adopted external home is detached and retained.
  • The lease records process identity and checks liveness. Account consistency can be checked when an account declares an email and the provider exposes an identity; API-key authentication mode alone does not identify an owner.