conductor

module
v0.1.11 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: Apache-2.0

README

Conductor

A coordination control plane for teams where humans and coding agents work the same repository at the same time.

Coding agents got fast; coordination did not. On a three-person team all running Claude Code, Codex, or OpenCode against one repo, the expensive failures are not bad code — they are two people building the same thing, two branches rewriting the same file, two migrations racing the same table, and nobody able to answer "what is actually in flight right now?"

The obvious fix — share the chats — is the wrong fix. Prompts and model output are the most private thing a developer produces. Conductor never shares them. It shares intent and territory: who holds what, what shape of work they are doing, and where two efforts are about to collide.

The full architecture is in docs/DESIGN.md. This README is how to run it and what is actually built.


Install

You need:

  • git, and curl for the release installer;
  • PostgreSQL 16 or newer that you already run, or Docker, in which case conductor up starts Postgres 17 in a container for you;
  • Go 1.25.14 or newer only to build from source (an older go downloads the right toolchain itself unless GOTOOLCHAIN=local is set).

Pick one way to get the three binaries (conductor, conductord, conductor-mcp) onto your PATH:

# A release build for macOS or Linux (amd64/arm64), no Go needed. Checks SHA256SUMS before
# installing into ~/.local/bin; add that directory to PATH if it is not already there.
curl -fsSL https://raw.githubusercontent.com/aburan28/conductor/main/scripts/install-release.sh \
  | bash -s -- aburan28/conductor ~/.local/bin

# From a clone: `make install` downloads the release as above, `make install-local` builds
# this checkout. Both add ~/.local/bin to PATH in your shell's startup file (zsh, bash, fish).
git clone https://github.com/aburan28/conductor && cd conductor && make install-local

# With Go, straight from the module:
go install github.com/aburan28/conductor/cmd/...@latest

Every release archive carries a GitHub build-provenance attestation: gh attestation verify conductor_vX.Y.Z_linux_amd64.tar.gz --repo aburan28/conductor. conductor version (or --version on any of the three binaries) says which build you have.

The macOS app

Conductor.app (in macos/) is the same three binaries plus a private PostgreSQL in one app: it runs the control plane and its database as launchd agents, signs you in without a token, puts who is live and what is contested in the menu bar, invites a teammate by text through the share sheet, and continues a session that hit its usage limit under another login. Settings → Storage points it at an S3 bucket that keeps the database, session backups and checkpoints (docs/STORAGE.md). Build it with macos/build.sh; the plan, and what has been verified so far, is docs/MACOS_APP.md.

Quickstart

From the repository you want to coordinate:

conductor up          # Postgres (Docker only if none is reachable), the control plane, your login
conductor init        # optional: scaffold .conductor/ policy files into this repository
conductor status      # what is in flight
conductor dashboard   # prints a ready-to-open link
conductor wrap claude # run Claude Code as a registered session (or codex, opencode)
conductor down        # stop the control plane (--db also stops the Postgres container)

conductor up is the whole setup. It reuses a Postgres that already answers at the DSN (--dsn, or DATABASE_URL) and starts one in Docker only when none does; it starts the control plane (API, SSE, dashboard, scheduler) on 127.0.0.1:8080 in the background, with its log and pidfile under ~/.conductor/runtime/; and it saves your CLI login at ~/.conductor/credentials. No token to copy, no second terminal. Running it again reuses whatever is already up. In a clone of this repository, make up and make down do the same.

conductor doctor checks everything at once: the control plane and its version, the database, conductord, git, Docker, and which coding tools are installed and connected.

For a shared leader with local Postgres or Amazon RDS, and workers connecting through UPnP or Tailscale, see leader deployment. conductor leader starts the leader here even when its advertised URL is remote; workers need only API credentials.

Getting help
conductor help                # the commands you need first
conductor help all            # every command
conductor help task           # one command, with an example (same as: conductor task -h)
source <(conductor completion bash)   # tab completion; also zsh and fish

What it does

$ conductor check --summary "add retry-aware model routing" --scope dir:internal/router

block_conflict: scope conflict on dir:internal/router

  alice holds dir:internal/router for T-1 (write_exclusive).
  Wait for it, split your scope, or join their task.

That is the whole product in one command. Everything else exists to make that answer correct, fast, and safe to trust.

It also catches the harder case — two people describing the same work in different words, with no overlapping files yet:

$ conductor check --summary "Build team invitation flow: send invite emails, accept invitations"

suggest_join: similar work already in flight

  T-3 (owner alice) looks like the same work. Join it, or narrow your scope.

Alice wrote "Implement the team invite flow with email invitations and acceptance". The server never saw either sentence in a form it can read back: both were reduced to HMAC'd token sets under a per-tenant key and compared with MinHash. Detection without disclosure.

Work goes where the capability is

A session advertises what it is driving. Conductor resolves that against the organization's model catalog — so a session cannot promote itself by asserting a tier — and work that needs a particular ceiling is offered to a session that has one.

$ conductor capabilities

demo

  3 session(s), 2 accepting work
  ceiling: tier T4, reasoning effort xhigh

  alice        claude    online_idle
       claude-fable-5-1 · tier T4 · effort xhigh (running high)
  rachel       codex     working
       gpt-5-codex · tier T2 · effort medium
       on T-12

$ conductor task assign T-42 --require-tier T4 --require-effort xhigh

T-42 offered to alice (claude-fable-5-1 on claude).
  requirement: tier ≥ T4, effort ≥ xhigh
  1 of 3 live session(s) qualified

  Not chosen:
    rachel       tier T2 is below the required T4

A floor is a floor: an idle cheap session never wins a selection it does not qualify for. Above the floor the cheapest qualifying session wins, so a frontier session is still there when something actually needs it. From inside a run, an agent that hits work beyond its own ceiling calls coord_delegate — the same continuation bundle as a handoff, plus a floor the receiver must meet. If nothing live qualifies, the bundle is still written and the caller is told what the ceiling actually is.

The CLI dispatches to the right model, by policy

conductor capabilities is about the sessions live right now. The other half is a repository policy that says which concrete model each kind of work should go to — declared in .conductor/dispatch.yaml, versioned with the code, and hashed onto every attempt so a routing decision is always explainable.

# .conductor/dispatch.yaml
lanes:
  implement:
    role: implementer
    candidates:
      - model: ollama/qwen3:27b        # a local model for small, low-risk work
        harness: opencode
        tags: [local]
        when: task.estimated_files <= 3 && !task.security_sensitive
        max_concurrent: 1              # one GPU, one attempt at a time
      - model: claude-sonnet-5-5
        harness: claude
      - model: claude-opus-5-5         # escalation walks down the ladder on failure
        harness: claude

rules:
  - id: docs-local
    when: task.labels has "docs"
    prefer: { tag: local }
  - id: routing-changes
    when: task.paths any "internal/router/**"
    require: { tier: T3 }

defaults: { lane: implement, on_failure: escalate, max_escalations: 2 }

The when expressions read deterministic facts derived from the ledger — scopes, labels, attempt history, budget position — never a prompt. conductor route T-42 shows what the policy would decide and why, before a token is spent:

$ conductor route T-42

T-42 would route to:

  claude-sonnet-5-5 on claude  (lane implement, effort medium, tier T2)

  Considered:
    ✗ ollama/qwen3:27b on opencode — condition not met: task.estimated_files <= 3 && !task.security_sensitive
    ✓ claude-sonnet-5-5 on claude
    · claude-opus-5-5 on claude

  Rationale:
    • lane implement (3 candidates)
    • chose claude-sonnet-5-5 on claude at effort medium

A dispatch candidate can never route below a hard floor: a security-sensitive task keeps its T4 floor whatever the ladder says. conductor policy lint validates the whole file — unknown facts, undefined lanes, malformed expressions — and conductor models discover finds the local model servers (Ollama, LM Studio, vLLM) worth adding to the ladder.

Model tiers

.conductor/models.yaml sorts models into four capability tiers. A tier is a class, not a price: a T1 model at max effort is still a T1 model.

Tier Alias(es) Does Anthropic OpenAI (Codex) GLM / Qwen (local vLLM)
T4 frontier reasoner.frontier (effort max) breakthrough-grade review and architecture Claude Fable 5.1 (claude-fable-5-1); Mythos 5 disabled until verified GPT-6 Sol, GPT-6.1 Sol (disabled) none classified yet
T3 core planner.frontier, reviewer.strong planning, coordination, adversarial review Claude Opus 5.5 (claude-opus-5-5) GPT-5.6 Sol (disabled) GLM 5.3; Qwen 3.8 large (disabled)
T2 director director, worker.general writes the mechanical tier's instructions and assesses its output; general work Claude Sonnet 5.5 (claude-sonnet-5-5) GPT-5.6 Terra (disabled) GLM 5.3 Flash; GLM 5.3 as director (disabled)
T1 mechanical executor.mechanical (effort low), worker.fast, verifier.cheap executes fully specified work, no reasoning of its own Claude Haiku 5.5 (claude-haiku-5-5) GPT-5.6 Luna (disabled) Qwen 3.8 27B

planner.frontier and reviewer.strong keep their names, which WORKFLOW.md and stored tasks reference, but are the core tier. The escalation ladder runs worker.fast → worker.general → planner.frontier → reasoner.frontier. In .conductor/dispatch.yaml, a task labelled breakthrough or frontier takes the frontier lane with a T4 floor (and a required review), and one labelled mechanical or runbook takes the mechanical lane: the Haiku executor at low effort, escalating once to the Sonnet director at high effort, never further, since a spec that needs core-tier reasoning was not fully specified. Security-sensitive and schema work never takes the mechanical lane. Profiles marked enabled: false are unverified on this installation.

Model ids need not be typed at all: register the inference APIs you use (conductor models endpoints add anthropic) and a profile that says select: {endpoint: anthropic, match: ["claude-sonnet-*"]} follows the newest matching model the provider lists, so a new release is adopted without editing a file. The dashboard's Fleet page has the same, with a dropdown of discovered models on every catalog profile. docs/INFERENCE_ENDPOINTS.md has the details.

Budgets bound the team, not the person

With budget.member.monthly_tokens set, every member gets the same token allowance over a rolling 30-day window — and it is transferable. Alice heading into a slack week hands her headroom to Bob mid-refactor, in one command, with no admin in the loop:

$ conductor budget share bob 2m --note "finishing the router refactor"

Shared 2m tokens with bob.

  you    1.1m remaining
  bob    3.4m remaining

A member whose window balance is spent cannot claim new work (HTTP 402, exit-code fail from the CLI) — until a teammate shares theirs. Balances are pure arithmetic over two ledgers (attempt spend and budget grants), so there is no counter to drift and no way to mint tokens: grants are checked against the giver's live balance under the same lock the claim path takes. conductor budget shows everyone's position; conductor budget grants is the transfer history; a budget.shared event lands on the team stream. As everywhere else, amounts and identities are shared — what the tokens were spent on is not.

The team pools capacity, and queues when it is full

Coworkers connect to each other through Conductor: a teammate joins the same control plane and their machines and sessions become shared capacity — a swarm. conductor swarm rolls up who is contributing what, and who has budget to spare:

$ conductor swarm

Capacity: 2 runner(s), 3 session(s) accepting work, 5 free slot(s), 1 waiting in queue

  WHO            KIND     STATE       LOAD        BUDGET LEFT
  alice          session  working     ready       3.4m
  rachel         runner   online      1/4         1.1m
  bob            session  online_idle ready       0

Share budget with a teammate: conductor budget share <who> <tokens>

A teammate joins from the link conductor invite <them> prints — conductor join "<link>" (conductor swarm join "<link>" is the same thing) — and then contributes interactive capacity with conductor wrap, autonomous capacity with conductor worker, or spare tokens with conductor budget share.

When too many sessions or attempts are running at once, new work does not fail — it takes a place in an admission queue and waits. Set the caps in .conductor/policies.yaml:

concurrency:
  max_active_sessions: 6          # across the whole team
  max_sessions_per_principal: 2   # so one person cannot take every slot
  max_concurrent_attempts: 4

Past the cap, conductor wrap parks with its place in line (waiting for a session slot, position 2…) and starts the moment a slot frees up; the scheduler grants tickets in arrival order, and a granted slot that stops heartbeating is handed on rather than held forever. conductor queue shows the whole line. As everywhere else, a ticket carries identity, a kind, and a model name — never what the work is about.

Privacy is structural, not procedural

A teammate looking at Alice's private task sees:

T-2      ready      alice      (private)
         dir:internal/api

Enough to not collide. Nothing about what it is. And the schema has no column for a prompt, the event payload passes an allowlist, and the harness stream adapters drop assistant text at the parse boundary before it can reach the store. Three tests assert this mechanically: TestNoTranscriptFieldsInSharedTypes, TestNoTranscriptColumnsInSchema, and TestEventTypeHasNoContentField.

Optional personal memory has a separate Redis connection in the local CLI/MCP process. It does not add content columns to the team database or publish observations as task events.


Setting up, in detail

Quickstart covers the one-command path. The rest of this section is what happens underneath, and how to do it by hand or for a team.

Signing in on your own machine needs no token

Open http://127.0.0.1:8080 and you are in. On the machine that runs conductord, its owner (whoever first ran conductord bootstrap there) is signed in automatically. The dashboard, the CLI, and the macOS app call POST /v1/local/session and get an ordinary token without anyone pasting one. Delete ~/.conductor/credentials and the next conductor command signs itself back in.

Only that one endpoint changed; every other request still needs a token. It answers only a request that:

  • arrives on loopback, from a daemon that is not behind a proxy;
  • names localhost or 127.0.0.1 as its Host, which defeats DNS rebinding;
  • sends a JSON body, which a cross-site form cannot;
  • if it carries a browser Origin, carries this same origin;
  • came through no proxy: forwarding headers (X-Forwarded-For, Forwarded, Via, …) or HTTP/1.0, which is how a stock nginx talks to its upstream, refuse it.

If you put a reverse proxy in front of a loopback-bound conductord, pass --behind-proxy (which turns local sign-in off) or run conductor security enhanced. Do the same before forwarding the port at the TCP level (ssh -R, socat, kubectl port-forward): such forwarders add no headers, so nothing distinguishes their traffic from local traffic. Loopback also cannot tell apart two OS users on one machine.

A token issued by local sign-in works only while local sign-in is allowed. In enhanced mode it is rejected, revoked or not, and so is any token it was used to mint. That is what enhanced security mode is for:

conductor security               # which mode, who owns the machine
conductor security enhanced      # tokens only, everywhere; revokes every token local sign-in issued
conductor security local         # back to automatic sign-in (the owner only)

A daemon listening on loopback defaults to local; one reachable from a network defaults to enhanced. conductord --security-mode pins either. Any project admin can tighten the mode; only the owner can loosen it. The same switch is on the dashboard's Settings page.

Manual, or on another repository
make db-up && make build                     # Postgres + bin/conductord, bin/conductor, bin/conductor-mcp

cd /path/to/your/repo
conductor init                               # scaffold .conductor/ policy files

export DATABASE_URL="postgres://conductor:conductor@localhost:55432/conductor?sslmode=disable"
conductord bootstrap --org acme --project myrepo --principal $USER --repo .
# saves your login at ~/.conductor/credentials — no copy-paste
# (--no-login skips that; --endpoint saves a different URL than http://localhost:8080)

conductord &                                 # or: make serve, same thing in the foreground
conductor dashboard                          # prints a ready-to-open link
Adding your coworkers

The fastest way is one link. conductor invite mints a teammate their own token and bundles the endpoint, project, and token into a single join link; they redeem it with conductor join (or by opening it in a browser) and they are in:

$ conductor invite rachel --role maintainer --expires 7d

Invited rachel as maintainer on myrepo.

Send them this link, once, over a channel you trust:

  https://conductor.team/#project=myrepo&token=cdt_QaltIz7t…

They run:  conductor join "<link>"     (or open it in a browser)

The token expires 2026-09-03T19:37:59Z.
# on the teammate's machine
conductor join "https://conductor.team/#project=myrepo&token=cdt_QaltIz7t…"
# Joined https://conductor.team as rachel. Then: conductor wrap claude / conductor worker.

The token rides in the URL fragment (after #), which a browser never sends to the server — so the credential stays out of every request line and access log, unlike a query-string link. The same link opens the web dashboard: it reads the fragment on load, then strips it from the address bar. If the endpoint you are logged in against is loopback (127.0.0.1), invite warns that a teammate cannot reach it and shows how to expose the control plane and pass a public --endpoint.

A token is minted only for a new account. If the handle already belongs to someone in your organization (they are in another project, say), invite and member add add them to this project and print no token or link: they keep signing in with their own credentials, which now reach this project (conductor login --project myrepo switches their default). Handing the inviter a fresh token for an existing account would let any project admin sign in as anyone.

Inviting someone who is already a member is refused rather than quietly changing their role. Roles change with conductor member role, which never grants a role above your own, never touches someone who outranks you, and never demotes the project's last administrator:

conductor member role rachel maintainer

The longer form still works, and is what a script or CI wants:

conductor member add rachel --role contributor   # a new account: prints a `conductor login …` line, once
conductor member list
conductor member role rachel reviewer            # change a member's role
conductor member remove rachel                   # also revokes their tokens
conductor token create --save                    # mint one more; the old ones stay valid
conductor token reset --save                     # rotate: one replacement, everything else revoked

A joined teammate contributes to the swarm — conductor wrap for interactive work, conductor worker for autonomous work, conductor budget share for spare tokens (see below).

conductord binds loopback by default and refuses to serve a reachable address in plaintext, because bearer tokens would cross the network in the clear. To expose it:

conductord --addr 0.0.0.0:8080 --tls-cert cert.pem --tls-key key.pem
conductord --addr 0.0.0.0:8080 --behind-proxy      # your proxy terminates TLS

Clients using a private CA set CONDUCTOR_CA_CERT=/path/to/ca.pem. Failed authentication is throttled per client; a correct token is never throttled, so one person mistyping theirs cannot lock out an office behind a shared NAT.

Prove the whole execution loop with no API key and no vendor CLI installed:

conductor task create --title "Try Conductor" --scope path:README.md
conductor worker --dry-run succeed --once -v

The built-in fake harness claims a task, creates a worktree, edits a file, runs your required checks, commits, and submits evidence — exercising every coordination path with a deterministic stand-in for a model. The task ends in verifying: the work is finished but not merged, so it keeps README.md reserved. conductor task show T-1 shows the branch and commit; once that branch is merged, conductor task done T-1 completes the task and frees the file (with the GitHub App linked, the merge does it for you).

Or run the scripted demo, which reproduces the scenario above end to end:

make e2e
Single sign-on

A team with Google Workspace, GitHub, Okta, Auth0, Keycloak or any other OpenID Connect provider can sign in through it instead of passing tokens around. A sign-in ends with an ordinary Conductor token (named sso:<provider>, 12 hours by default), so roles, project scopes and enhanced security mode apply to it exactly as to any other token. Nobody gets in just by having an account at the provider: an administrator registers each person's address first, and their first sign-in links to that account.

Every provider needs one redirect URI registered with it, exactly:

<--public-url>/v1/sso/<name>/callback        e.g. https://conductor.example.com/v1/sso/google/callback

conductord logs it for each provider at startup. SSO needs --public-url to be https (plain http only on a loopback address, for trying it out).

Google. In the Google Cloud console, open APIs & Services → OAuth consent screen and configure it (Internal keeps it to your Workspace). Then Credentials → Create credentials → OAuth client ID, type Web application, and add the redirect URI above under Authorized redirect URIs. Start conductord with the client id, and the secret in the environment:

export CONDUCTOR_SSO_GOOGLE_CLIENT_SECRET='GOCSPX-…'      # or client-secret-file=/run/secrets/google
conductord --addr 0.0.0.0:8443 --tls-cert cert.pem --tls-key key.pem \
  --public-url https://conductor.example.com \
  --sso-provider name=google,issuer=https://accounts.google.com,client-id=1234-abc.apps.googleusercontent.com,domain=example.com

GitHub. GitHub is not an OpenID Connect provider for people, so it has its own type. Create an OAuth App (Settings → Developer settings → OAuth Apps → New OAuth App, or the same under your organization's settings), with Homepage URL your public URL and Authorization callback URL https://conductor.example.com/v1/sso/github/callback. Generate a client secret, then:

export CONDUCTOR_SSO_GITHUB_CLIENT_SECRET='…'
conductord … --sso-provider name=github,client-id=Ov23li…,org=acme

org= admits only active members of that organization (repeat it to allow several); if the organization restricts OAuth App access, an owner has to approve the app once. GitHub Enterprise Server adds api-url=https://HOST/api/v3,web-url=https://HOST.

Any other OpenID Connect provider (Okta, Auth0, Keycloak, …): register a web application with the redirect URI, and pass its issuer exactly as its /.well-known/openid-configuration states it, e.g. --sso-provider name=okta,issuer=https://acme.okta.com,client-id=0oa…. The provider must assert email_verified; one that does not is refused rather than trusted with unverified addresses — except a single Microsoft Entra ID tenant you explicitly trust (below).

--sso-provider key Meaning
name lowercase id, used in the redirect URI, URLs and conductor login --sso NAME
type oidc (default) or github (the default when name=github and no issuer is given)
issuer, client-id the provider's issuer and this application's client id
client-secret-file, client-secret-env where the secret is; by default CONDUCTOR_SSO_<NAME>_CLIENT_SECRET. Never on the command line, where every user can read it
domain admit only verified addresses in this domain (repeatable)
org GitHub: admit only active members of this organization (repeatable)
label the button text, "Sign in with …"
api-url, web-url GitHub Enterprise Server
groups-claim the ID token claim listing the account's groups, for group → role mapping (default groups)
trust-email-domain Entra ID only: accept this tenant's sign-in names in this domain without email_verified (repeatable)

Microsoft Entra ID. Entra issues no email_verified claim, so it needs an explicit trust. In the Entra admin center, App registrations → New registration, single tenant, with a Web redirect URI https://conductor.example.com/v1/sso/entra/callback; under Certificates & secrets create a client secret; under Token configuration add the optional email claim (and a groups claim if you will map groups to roles). Then use the tenant's own issuer — with its tenant id, never common or organizations — and list the domains whose addresses it may vouch for:

export CONDUCTOR_SSO_ENTRA_CLIENT_SECRET='…'
conductord … --sso-provider name=entra,issuer=https://login.microsoftonline.com/<tenant-id>/v2.0,client-id=<application-id>,trust-email-domain=example.com

The address is taken from upn, then preferred_username, then email, and only in a listed domain; the token's tid must be the tenant, and guests from other directories are refused. Why that is safe enough, and what it does not protect against, is in DESIGN.md §25.7.

Several providers are several --sso-provider flags, or one CONDUCTOR_SSO_PROVIDERS variable with the specs separated by ;.

Registering people. A first sign-in links to the account whose registered address the provider verified, and only if that account does not sign in some other way already — an email address alone never takes over an account that has an identity:

conductor member add rachel --role contributor --email rachel@example.com --no-token
conductor sso email bob bob@example.com         # an existing member

Setting someone's sign-in address, or unlinking their identity, takes an administrator of every project they belong to. Then they sign in — in the dashboard with Sign in with Google, or from a terminal (a browser opens, and the CLI listens on 127.0.0.1 for the result):

conductor login --endpoint https://conductor.example.com --sso google
conductor sso status                    # providers, and the identities linked to you
conductor sso link github               # add another provider to the account you are signed in as
conductor sso unlink bob google         # administrators: remove an identity and end its sessions

To skip registering people, --sso-auto-provision contributor --sso-default-project acme/web gives a first sign-in that matches no registered address a new account in that project. It grants contributor, reviewer or observer, never more, and requires every provider to be restricted with domain= or org= — otherwise anyone with a Google account would be let in. --sso-token-ttl sets how long a sign-in lasts; signing in again re-checks the provider (an address still allowed, a membership still active). The design and threat model are in DESIGN.md §25.7.

For enterprises

Everything an organization's administrator needs is in the dashboard's Admin area (shown to org_admins only) and under /v1/admin. The first person bootstrapped into a new organization is its org_admin; promote others with conductor member role HANDLE org_admin.

Admin section What it does
Organization display name, accent color (checked for contrast), logo (PNG/JPEG/GIF, 64 KiB), sign-in banner
Authentication providers, require single sign-on, allowed email domains and GitHub organizations, account provisioning, group → role mapping, token lifetimes
Provisioning SCIM tokens and the SCIM base URL for Okta or Entra ID
Members & roles every account, its projects and roles, linked identities; change a role, unlink, deactivate
Features which advanced areas (queue, swarm, budget sharing, mesh, local models, checkpoints by account) the dashboard shows. A new organization starts with none; turning one off hides it, it never revokes access
Audit log filter by actor, action and time; export as CSV or JSON lines
Configuration the server's effective configuration, secrets redacted, and what its config file locks

A config file. conductord --config /etc/conductor/conductor.yaml (or CONDUCTOR_CONFIG) holds what otherwise takes a page of flags, and can lock organization settings: a locked setting is read-only in the admin area, marked "managed by your administrator's config file". Secrets are never written in it — only the environment variable or file that holds them:

version: 1
server:
  addr: 0.0.0.0:8443
  public_url: https://conductor.example.com
  tls_cert: /etc/conductor/tls/cert.pem
  tls_key: /etc/conductor/tls/key.pem
  security_mode: enhanced
database:
  url_env: DATABASE_URL            # or url_file: /run/secrets/database-url
retention:
  events_days: 90
  audit_days: 400
metrics:
  token_file: /run/secrets/metrics-token
sso:
  token_ttl: 10h
  providers:
    - name: okta
      issuer: https://example.okta.com
      client_id: 0oa1b2c3
      client_secret_env: OKTA_CLIENT_SECRET
      domains: [example.com]
    - name: entra
      issuer: https://login.microsoftonline.com/<tenant-id>/v2.0
      client_id: <application-id>
      client_secret_file: /run/secrets/entra
      trusted_email_domains: [example.com]
features:            # locked for every organization on this server
  queue: true
branding:            # locked; logo_file is read and checked at startup
  display_name: Example Engineering
  login_banner: Authorized use only. Activity is logged.
policy:              # locked
  require_sso: true
  human_token_max_ttl: 30d
  allowed_domains: [example.com]

A command-line flag wins over its environment variable, which wins over the file, which wins over the default. conductord config check --config FILE validates a file — every unknown key, wrong type, inline secret, empty reference and invalid policy is reported — without touching the database, and prints each effective setting with where it came from. The full key list is in docs/OPERATIONS.md.

Require single sign-on. Admin → Authentication, or policy.require_sso in the file. A person's token is then accepted only if single sign-on minted it (or a token minted from such a session, which never outlives it); runners and other service accounts keep their tokens, and local sign-in on the server's own machine follows the security mode. Older tokens are refused, not revoked, so turning the policy off — say, while the identity provider is down — restores them; anyone whose access should end for good is deactivated. Turn it on while signed in through single sign-on: the server refuses to do it from a token session, so you cannot lock yourself out.

SCIM provisioning. Admin → Provisioning → New token, then:

  • Okta: in the app, General → App Settings → Provisioning: SCIM; under Provisioning → Integration, SCIM connector base URL https://conductor.example.com/scim/v2, Unique identifier field for users userName, supported actions Push New Users, Push Profile Updates, Push Groups, authentication mode HTTP Header with the token. Enable Create Users, Update User Attributes and Deactivate Users under To App.
  • Microsoft Entra ID: Enterprise applications → (your app) → Provisioning → Automatic, Tenant URL https://conductor.example.com/scim/v2, Secret Token the token, Test Connection, then start provisioning.

Provisioning creates and updates people (they join the policy's default project with its default role, contributor at most), deactivates them (active=false: every token revoked and refused at once; history and memberships kept), and deletes them (memberships and identities removed, the account kept for the audit trail). Groups it pushes feed group → role mapping. SCIM never grants org_admin, and refuses to deactivate a project's last administrator.

Group → role mapping. Rules such as engineering → contributor in app apply at every sign-in, from the ID token's groups claim, GitHub teams (org/team-slug) and SCIM groups. A mapped role never exceeds the configured ceiling (maintainer by default, never org_admin), never touches a role above it, never demotes a project's last administrator, and never removes anyone.

Audit export. Admin → Audit log, or:

curl -H "Authorization: Bearer $TOKEN" "https://conductor.example.com/v1/admin/audit?format=csv&since=2026-09-01" > audit.csv
curl -H "Authorization: Bearer $TOKEN" "https://conductor.example.com/v1/admin/audit?format=jsonl&action=sso." > sso.jsonl

Filters: actor=HANDLE, action= (exact, or a family ending in .), since=/until= (RFC 3339 or a date). Exports are audited, and CSV cells that a spreadsheet would run as formulas are defused.


Daily use

conductor check --summary "…" --scope dir:internal/api    # before you edit. exit 3 = stop
conductor task claim --next                               # take work and its territory
conductor wrap claude                                     # register a session + heartbeat, then launch
conductor task done T-42                                  # it merged: close it and free its files
conductor task reopen T-42                                # review wants changes: back to the queue
conductor serve qwen                                      # local vLLM for OpenCode (also: flash, glm53)
conductor wrap opencode --model vllm/qwen3.8-27b
conductor presence --watch                                # who is live, on what
conductor conflicts                                       # what is contested and what to do
conductor task handoff T-42 --to codex --next "write tests"
conductor capabilities                                    # which models are live, and how hard they can think
conductor task assign T-42 --require-tier T4 --require-effort xhigh
conductor inbox                                           # work offered to this session
conductor budget                                          # the team's token budget this window
conductor budget share rachel 500k                        # give a teammate part of your allowance
conductor pause                                           # freeze every agent terminal on this machine
conductor resume                                          # wake them; closed terminals are reopened
conductor sessions save all                               # keep every session resumable, even after a reboot
conductor usage --by day,harness                          # tokens and cost over time, across claude/codex/opencode
conductor sessions export                                 # the project's session history, as JSON
conductor sessions install-hook                          # capture every session at shutdown (systemd/launchd)
conductor systemd install --with-vllm qwen               # user units for postgres + conductord (+ vLLM), images pre-pulled
conductor backup push | pull | status                    # copy this machine's resume records to/from S3
conductor checkpoint capture --note "tests pass"         # snapshot a session: transcript + working tree, portable
conductor checkpoint resume 9a474a --account work        # continue it under another login, or --harness codex
conductor security [local|enhanced]                       # sign in without a token on this machine, or tokens only
conductor github setup | link | status                    # a "Conductor" check on every pull request
conductor pulls --needs-review                            # the repository's pull requests: task, checks, review
conductor pull 118                                        # one pull request: its task, checks, review, attempts
conductor task link-pr T-42 118                           # say which task a pull request is (outranks every guess)
conductor github issues enable --label conductor          # labelled GitHub issues become tasks
conductor integrate cursor                                # wire a coding tool to this project (MCP + hooks)
conductor route T-42                                      # what would this route to, and why — before spending a token
conductor dispatch T-42                                   # send work to a model by policy, through the queue
conductor models                                          # the model catalog (profiles marked "auto" follow discovery)
conductor models endpoints add anthropic                  # connect an inference API; its models are discovered, not typed
conductor delphi ask --task T-42 "Is this sound? ..."      # delegate to a frontier model via a batch API (half price, answered later)
conductor models available --new                          # models the endpoints started serving this week
conductor models pin worker.general claude <model>        # choose a model yourself; `unpin` returns it to discovery
conductor models discover                                 # find Ollama / LM Studio / vLLM on this machine
conductor policy lint                                     # validate .conductor/ policy and dispatch rules
conductor swarm                                           # the team's pooled capacity and who has budget to share
conductor queue                                           # the admission line when the team is at capacity

Every command takes --json.

The loop, start to finish
  1. Check. conductor check (or the agent's conductor_check_conflicts) says whether anyone holds what you are about to touch. A blocked check leaves a short note that you are waiting; when the holder lets go, a scope.released event names you.
  2. Claim. conductor task claim T-42 --scope path:… takes the task and its territory. Run inside a wrapped session (or by an agent through coord_start_work), the claim is bound to that session. From a plain shell it is recorded against the checkout and waits up to ten minutes for a session to take it over.
  3. Wrap. conductor wrap claude registers the session and adopts any claim made in the same checkout. Its heartbeat (every 20 seconds) keeps the session and every claim it holds alive for as long as it runs, and reports which paths the working tree has touched (paths only), so merge-risk detection sees interactive work too. When the session ends, the claim lapses one lease TTL later and the reconciler releases it. An MCP gateway keeps the claim it took alive the same way, without the model spending a token on it.
  4. Work. The pre-edit hook blocks an edit to a file someone else holds. The first edit of a file outside your own claim reserves it under the claim (--auto-reserve, the default conductor integrate installs) and tells the agent so; a session with no claim is reminded that its edits reserve nothing.
  5. Publish. coord_publish_result records the commit, the changed paths, and each validation command with its exit code; coord_finish_work moves the task to verifying.
  6. Merge. Finished work keeps its territory while it waits to merge — anyone who checks one of its files is told the change is in an unmerged pull request, not that someone is editing. When the pull request merges, the task is done and its files are free: the GitHub App does this from the merge webhook (or by polling), and conductor task done does it by hand. A pull request closed without merging sends a waiting task back to ready and releases its hold; conductor task reopen sends work back but keeps it.
Sharing with someone by text

conductor invite makes one link: endpoint, project, and token, with the token in the URL fragment so it never reaches a server log. Text it; they run conductor join "<link>" or just open it in a browser. conductor join then offers to connect every coding tool on their machine in one step (--integrate / --no-integrate to decide in advance).

A link to 127.0.0.1 only reaches you. When Tailscale is running, conductor invite and conductor doctor print the commands that let someone in over your private tailnet:

tailscale serve --bg 8080
conductor invite brother --endpoint https://your-mac.tailnet.ts.net
# also: conductord --public-url https://your-mac.tailnet.ts.net
# remote MCP: https://your-mac.tailnet.ts.net/mcp

Requests through the MagicDNS name are not local, so they need the token in the link; local sign-in stays yours. Live updates stay on HTTPS + SSE (no WebSocket). NAT traversal for the overlay is Tailscale’s; Conductor does not run STUN/TURN. Full notes: docs/REMOTE_ACCESS.md.

GitHub: a check on every pull request

Conductor knows which files every in-flight task holds. With its GitHub App installed, each pull request on a linked repository gets a Conductor check run. The check says whether the pull request changes files that other open work has reserved, or has already changed itself. It names the overlapping file, the task, and its owner. It never names the task's title, because anyone who can read the repository sees the check.

conductor github setup          # opens one page with one button: GitHub creates the app
conductor github install        # pick the repositories
conductor github link           # inside a checkout: this project is that repository (bootstrap does it too)
conductor github status         # the app, where it is installed, what is linked
conductor github check acme/widgets#12   # check one pull request now

The app is the machine owner's: only they can create it (--replace to swap it out), and only projects in their organization can be linked, so another tenant on a shared control plane can neither take the app over nor read a repository through it. In a check run, a private task appears as "a private task", and a public repository gets no task references or owners at all. A pull request's own task is excluded only for a branch in the repository itself, never a fork's. The app asks for read access to contents, pull requests and commit statuses, and write access to checks and issues (issues only for issue sync, below). It cannot push, merge, or change settings. Its credentials are kept in Conductor's database, so every conductord sharing it serves the same app, with the private key and secrets sealed under a key that is not in the database (~/.conductor/secret.key, --secret-key-file, or CONDUCTOR_SECRET_KEY; replicas must share it — see docs/OPERATIONS.md). An app saved by an older version in ~/.conductor/github-app.json is imported once. CONDUCTOR_GITHUB_APP_ID / CONDUCTOR_GITHUB_APP_PRIVATE_KEY(_FILE) / CONDUCTOR_GITHUB_WEBHOOK_SECRET override the stored values. A changed result updates the commit's check run rather than adding another, and an unchanged one is not posted again after a restart. A conductord that GitHub cannot reach, such as a laptop, polls open pull requests every two minutes (--github-poll). One started with a public --public-url receives signed webhooks at /github/webhook. The check is neutral when there is an overlap, so it informs a reviewer without blocking a merge unless branch protection requires it.

The app also closes the loop. A pull request is linked to its task when its branch is one an attempt recorded or follows the agent/<task-ref>/attempt-<n> convention (branches in the repository itself only, never a fork's); conductor task show and the dashboard show the link. When a linked pull request merges, the task moves to done — from wherever its work stood, ending a still-live claim — and its reserved files are released. When one is closed without merging, a task that was waiting on it goes back to ready and drops its hold, and a task still being worked is left alone. Without webhooks, the poller does the same from the pull requests closed since its last pass (and looks up any linked pull request that left the open list), so a pull request opened and merged between two polls still completes its task. Seeing the same merge twice changes nothing and announces nothing.

Pull requests as a list

Every pull request on a linked repository is a row in Conductor, not only the one a task travels in: conductor pulls (and Pull requests in the dashboard) lists them with their task, author, checks, and review decision, and conductor pull 118 shows one in full.

conductor pulls                       # open pull requests (--all adds merged and closed)
conductor pulls --needs-review        # open, ready for review, not yet approved or sent back
conductor pulls --failing --mine      # failing checks; you opened it, or you own its task
conductor pulls --unlinked            # no task claims it
conductor pull 118                    # task and how it was linked, checks, reviews, mergeability, attempts
conductor task link-pr T-42 118       # by hand: a number, owner/repo#118, or the URL
conductor task unlink-pr T-42 118
  • What is kept. The title (bounded), the author's GitHub login and id, the branch and head commit, the state, and counts: checks passed, failed, and pending; unresolved review threads; size. The review decision and mergeability. Never a pull request's description, comments, review text, commit messages, CI logs, or diff: they are written by strangers, and are where prompt injection travels. An agent reads them on its own machine through gh when it needs them.
  • Which task. By precedence, strongest first: a link made by hand; a Conductor-Task: T-42 trailer on any commit (the runner writes one); the first T-42 in the description; the head branch, as above. A task may have several pull requests and a pull request has one task. The trailer and the description are text a pull request's author wrote, so they link only pull requests from a branch in the repository itself; a fork can name a task and be ignored. A link made by hand, or an unlink, is never overridden by the rest.
  • Several pull requests. The first linked becomes the task's primary (the one task show and the card name), and a link by hand takes over. The task is done when its primary merges, or when the last of its open pull requests does. Closing one while another is open leaves the task where it is; closing the last sends waiting work back to ready.
  • Visibility. Members read a pull request's title, author and states, the same assumption issue sync makes about the repository. A pull request of a private task is shown to everyone but its owner as its number and state ("pull request of a private task").
  • Freshness. With webhooks, reviews, review comments, comments, check suites, check runs, commit statuses and pushes each prompt a re-read of the pull request they touch. Without them, the poller (every two minutes) lists open pull requests as a conditional request, so an unchanged repository costs a 304, and reads each changed pull request's checks and review state in one GraphQL call. CI finishing does not change a pull request's updated_at, so a pull request with checks pending is read every pass and a settled one every fifteen minutes. A contributor can force a read, rate limited: POST /v1/projects/{project}/pulls/{owner}/{repo}/{number}/refresh or Refresh from GitHub in the drawer.
  • Events for notification channels (conductor notify events): github.pr_opened, github.pr_updated (new commits), github.pr_review, github.pr_checks (settled: all passed, or some failed), and github.pr_ready (left draft). They carry the repository, number and counts, never the title; an event about a private task is private. A pull request first found by the poller long after it opened is not announced as opened.
  • Permissions. The check rollup needs statuses: read, and the app now subscribes to pull_request_review, pull_request_review_comment, issue_comment, check_suite, check_run, status and push. An app created before this lacks them, because GitHub applies a manifest's permissions only when it creates the app: conductor github status says so, with the app-settings page to grant them and each installation's page where GitHub asks its owner to accept. Without them the list still works, filled in from the pull request events and the poll, with no check state until they are granted.
GitHub Issues as tasks

A team's backlog already lives in its issue tracker. Issue sync keeps it there: opt a linked project in, and its repository's issues become Conductor tasks without anyone filing them twice.

conductor github issues enable                 # open issues labelled `conductor` become tasks
conductor github issues enable --all           # ...or every open issue
conductor github issues enable --no-progress-label --public-visibility team_summary
conductor github issues status                 # settings, how many imported, the last problem
conductor github issues sync                   # import now instead of at the next poll
conductor github issues disable
  • Import. Each qualifying open issue becomes a ready task with external_ref github:owner/repo#N: the issue's title, its body as the objective (comments stripped, bounded like any objective, the full text a click away), and the list under a ## Acceptance (or ## Acceptance criteria) heading as acceptance criteria. Importing is idempotent: the webhook, the poller, sync, and a second replica all find the same task. An open task that already names the issue in its external_ref is linked rather than duplicated. Removing the label later does not drop the task.
  • Edits, last writer wins. An edit to the issue's title, or to its body, reaches the task unless the task's copy was also edited in Conductor since the last sync; then whichever edit is later wins (the issue's updated_at against when the task's text was edited). A Conductor edit that wins stays until the issue's text changes again. Content only ever flows from GitHub to Conductor.
  • Close and reopen. Closing an issue cancels its task, unless the task is done or its work is landing (verifying, in review, or an open pull request): a pull request's Closes #N closes the issue moments before the merge completes the task, and the merge decides. Reopening an issue brings back a task the sync cancelled; one a person cancelled stays.
  • Write-back. A claim adds one comment, "Claimed by <handle> via Conductor", and the in-progress label (configurable, or off); a release removes the label. When the task is done (by conductor task done or by its pull request merging) the issue gets one comment linking the pull request and is closed, unless it is closed already. Comments are written once per claimant and once per completion, in fixed words.
  • Privacy. Nothing written in Conductor reaches GitHub: no title, objective, criteria, or progress. A task imported from a public repository is team_artifacts (configurable), since every word of it is public already; one from a private repository gets the project's default visibility. A private task is never written back to a public repository's issue, and its claimant is never named; on a public repository only team_artifacts and shared_debug tasks name their claimant. A pull request is linked only when it is in the issue's own repository.
  • Delivery and rate limits. issues webhooks when GitHub can reach Conductor; otherwise the poller lists only issues changed since its last pass, as a conditional request, so an idle repository costs a 304 that GitHub does not count. The write-back runs every 15 seconds on the poller's lock, bounded per pass, and stops for as long as GitHub asks when it hits a rate limit.
  • Permissions. Issue sync needs the app's issues: write permission, which apps created before it existed lack: GitHub applies a manifest's permissions only when it creates the app. conductor github status says so, with the app-settings page to grant it and each installation's page where GitHub asks its owner to accept the new permission.

Task lists, conductor task show, and the dashboard's task detail link to the issue. GitHub is the only tracker for now; the sync's rules live in internal/tracker, behind a small adapter interface, and Linear is the next adapter planned.

Connecting your coding tool

One command wires Conductor's MCP tools — and, where the tool supports them, pre-edit hooks — into whatever you drive:

conductor integrate claude        # Claude Code: .mcp.json + PreToolUse/SessionStart hooks
conductor integrate cursor        # Cursor: .cursor/mcp.json + a rules file
conductor integrate codex         # Codex: ~/.codex/config.toml + .codex/hooks.json (apply_patch checked) + AGENTS.md
conductor integrate opencode      # OpenCode: opencode.json + a pre-tool plugin
conductor integrate all           # every tool this machine has

Also supported: windsurf, vscode, zed, gemini. Each merges into the tool's own config without disturbing anything else already there, and --print shows exactly what it would write before it writes it. conductor doctor reports which tools are connected.

Codex edits files through apply_patch, so its pre-edit hook checks every file a patch adds, updates, deletes or moves, and blocks the patch if any one of them is held. Codex runs a project's .codex/hooks.json only once the project is trusted, so accept its trust prompt the first time it opens the repository.

Every write is idempotent and never puts a bearer token into a project file that could be committed: stdio configs need no token (the conductor-mcp binary reads your saved login), and HTTP configs reference the token through the tool's own ${env:CONDUCTOR_TOKEN} syntax.

Two transports. The conductor-mcp binary speaks MCP over stdio, for any tool that launches a local process:

{ "mcpServers": { "conductor": {
  "command": "conductor-mcp", "args": ["--project", "myrepo"] } } }

Or point an HTTP-capable client straight at the control plane — no local binary, which is what a teammate on a shared server wants:

{ "mcpServers": { "conductor": { "type": "http",
  "url": "https://conductor.team/mcp",
  "headers": { "Authorization": "Bearer ${CONDUCTOR_TOKEN}", "X-Conductor-Project": "myrepo" }
} } }

conductord serves the Streamable HTTP transport at /mcp (and /mcp/{project}), negotiating protocol revisions 2024-11-05 through 2025-06-18, with per-session ids and the same bearer auth every other client uses — the gateway holds no private path into the store, over either transport.

Thirteen tools: conductor_check_conflicts, coord_start_work, coord_get_work, coord_expand_scope, coord_report_progress, coord_publish_result, coord_finish_work, coord_handoff, coord_delegate, coord_capabilities, coord_checkpoint, coord_quota, coord_project_status. Heartbeats are deliberately not an MCP tool — a model should never spend tokens telling the server it is still alive. And where a harness supports pre-edit hooks, conductor integrate installs conductor hook pre-tool, which calls the same conflict check before every edit and blocks the tool call (exit 2, with the holder named) when someone else holds the file — enforcement, not just advice.

Token usage across harnesses

Every harness meters itself and none of them compare notes. Claude Code writes a usage block on each message of its transcript, Codex logs a running total after every response, OpenCode stores tokens and cost on every message — each on one machine, each for itself. Conductor reads those logs and keeps one ledger.

conductor usage                          # last 7 days, by harness
conductor usage --by day,harness         # a daily series per harness
conductor usage --by model --since 30d   # which models carry the load
conductor usage --by principal           # who used what
conductor usage sync                     # report this directory's unwrapped sessions

A session launched through conductor wrap reports as it runs: the sidecar re-reads the harness's own log once a minute, folds it into hourly buckets — one per harness session and model — and sends only what changed, with a final flush at exit (CONDUCTOR_USAGE=off disables it). Sessions that were not wrapped are reported after the fact with conductor usage sync, which reads the same logs for the current directory. Runner attempts land in the same ledger from their progress reports. Buckets carry absolute counts, so re-reporting replaces rather than adds, and a restarted collector cannot double-count.

Cost is what the harness reported where it reports one (OpenCode); otherwise Conductor estimates it from the organization's model catalog at list price, cache reads at a tenth, and marks the row catalog. A model the catalog does not know stays unpriced rather than guessed.

What crosses the wire is numbers, a model name, and an hour. The readers decode only the usage fields of each record; there is no struct field the transcript text could land in, and OpenCode's export is asked to redact before Conductor even sees it. Team totals by day, harness, and model are visible to every member. Per-session detail is your own unless you maintain the project, and other people's model names follow publishModelIdentity, exactly as they do in presence. The dashboard shows usage over time by harness and model, alongside the task board, fleet, swarm, and admission queue.

Pausing the wall of terminals

A person running three agents has three terminals. Standing up from that desk — a meeting, a laptop lid, an office move — is one command, and sitting back down is one command, even if some of those terminals no longer exist by then.

conductor pause     # freeze every interactive agent session on this machine
conductor resume    # wake them all; --list shows what is saved

conductor pause finds every interactive Claude Code, Codex, and OpenCode session — launched through conductor wrap or bare — saves a record of how to revive each one under ~/.conductor/sessions/, and freezes it with SIGSTOP. The terminals stay open, stopped mid-thought. Before signaling anything, each pid is re-identified against the process table, because a SIGSTOP delivered to a recycled pid would freeze a stranger.

conductor resume wakes each session where it can and reopens it where it must:

  • Its terminal survived. SIGCONT, in place. Wrapped sessions come back seamlessly — the wrap sidecar stopped only the harness, so the shell never reclaimed the terminal. Bare sessions were their shell's foreground job; the shell took the terminal back when they stopped, so if the keyboard is dead, fg in that terminal hands it over — resume says so.
  • Its terminal was closed. A new terminal is opened — a window in your current tmux, the platform's terminal app, an installed emulator, or a detached tmux session named conductor as a last resort (CONDUCTOR_TERMINAL="kitty --directory {cwd} sh -c {cmd}" overrides the choice) — running the harness's own conversation-resume invocation: claude --continue, codex resume --last, opencode --continue. Each harness keeps its transcript in its own local state, so the conversation survives the terminal; Conductor never sees it. One caveat: codex resume --last is Codex's most recent conversation globally, not per-directory, so two revived Codex sessions can land on the same one — codex resume opens the picker for the other.

Pausing is for stepping away; saving is for the terminals themselves going away.

conductor sessions save all     # keep every live session resumable — nothing is stopped
conductor sessions list         # what this machine knows: saved, paused, running

A running session's record normally vanishes with its process — right after a crash, wrong after a reboot with three conversations open. conductor sessions save all marks every session on the machine as deliberately kept. The sessions keep running; if a terminal is closed or the machine restarts, the record stays, listed as saved, and conductor resume reopens the conversation exactly as it reopens a paused session whose terminal was closed. A saved session you quit yourself is forgotten, as it should be, and a reopened one starts a fresh record — save again if it should survive the next reboot too. Saving is per-machine and touches nothing on the server; conductor sessions export is the other direction — the project's whole session history, everyone's, as a JSON file.

One button back — and onto a fresh account

The dashboard's Overview page has a Resume all sessions button: one POST to /v1/local/resume-all does what conductor resume does — wake every paused or saved session on the machine, reopening the terminals a restart took away — after first moving any harness off an account that has run out of usage. The endpoint only exists on a control plane running on the machine with the terminals (conductord on the laptop); the sessions and the accounts it touches are that machine's.

Accounts are named snapshots of a harness's own login, kept under ~/.conductor/accounts/:

conductor accounts add claude main       # snapshot the login the harness is using now
conductor accounts list                 # profiles, which is active, quota markers
conductor accounts switch claude backup # make another account the live one
conductor accounts exhaust claude main  # mark an account out of usage
conductor accounts ok claude main       # window rolled over: usable again

Add accounts by logging in with the harness itself, then snapshotting — Conductor never performs a harness's login dance, it only moves credential files it can already read. Which account is live is read from the harness's own credential file, never tracked separately, so it cannot drift. exhaust drops a marker beside the profile; the resume-all button (and only it) avoids marked accounts when waking sessions — switching before resuming, because a harness reads its credentials at startup. Clear the marker with ok when the quota window rolls over. Nothing is sent anywhere: profiles live beside the machine's other local state, 0600, like the credentials themselves.

A login per project

Snapshots swap one live login for the whole machine. When projects belong to different accounts (a work repository, a client repository, a personal one), give each its own isolated account instead: a state directory the harness is pointed at, so nothing is swapped and two projects can run under two logins at the same time.

conductor accounts login claude work --use   # sign in inside a fresh directory; bind this project
conductor accounts use codex client          # bind this project's Codex to another account
conductor accounts unbind codex              # back to the default login here
CONDUCTOR_ACCOUNT=personal conductor wrap claude   # one launch under another account

conductor wrap applies the binding: Claude Code gets CLAUDE_CONFIG_DIR, Codex CODEX_HOME, OpenCode XDG_DATA_HOME, and Cursor --user-data-dir, all pointing at ~/.conductor/accounts/<harness>/<name> (or an existing ~/.<harness>-<name>, the community convention). accounts login runs the harness's own sign-in with that directory in place, so the credentials land there and nowhere else. checkpoint resume installs the conversation under the bound account too. Bindings are machine-local, in ~/.conductor/accounts/bindings.json keyed by checkout root; which login you use for a repository is yours, not repository policy. A CLAUDE_CONFIG_DIR or CODEX_HOME you export yourself always wins over the binding.

Accounts can have aliases, per harness: another name for an account, or a name for a state directory you already have.

conductor accounts alias claude acme work              # acme means work
conductor accounts alias codex legacy ~/codex-old      # adopt an existing CODEX_HOME
conductor accounts use claude acme                     # bind the alias, not the account
conductor accounts alias claude acme client            # every project bound to acme moves
conductor accounts unalias claude acme

An alias works anywhere a name does (use, login, switch, exhaust, ok, CONDUCTOR_ACCOUNT, checkpoint resume --account). Aliases live in ~/.conductor/accounts/aliases.json; they cannot shadow a real account or point at another alias, so a lookup is always one step.

Surviving a shutdown, and the machine itself

You should not have to remember to run save before a reboot. Three layers make a shutdown non-destructive:

  1. Wrapped sessions save themselves. conductor wrap catches the SIGTERM a shutdown sends (and the SIGHUP a closed terminal or dropped SSH connection sends) and marks its record kept-for-resume before the harness is killed. The harness has already written its own transcript, so all that must be preserved is how to reopen it. Nothing to run first.

  2. A machine-wide capture hook covers bare sessions (no sidecar to catch the signal) and unclean shutdowns. conductor sessions install-hook generates a systemd user service+timer (Linux) or a launchd agent (macOS) that runs conductor sessions save all at logout/shutdown and periodically — so even a machine that dies without a clean shutdown loses at most one interval of state. It writes the unit files and prints the one command to enable them; it never starts a system service for you.

  3. Off-host backup, for when the machine itself does not come back — a terminated cloud instance takes its disk, and the local ~/.conductor/sessions records with it. Point Conductor at an S3 bucket and the resume records travel too:

    export CONDUCTOR_BACKUP_S3_BUCKET=my-team-conductor
    export CONDUCTOR_BACKUP_S3_REGION=us-east-1
    export AWS_ACCESS_KEY_ID=…  AWS_SECRET_ACCESS_KEY=…   # or an instance role's env
    
    conductor backup push        # bundle this machine's records to S3 (a manifest + a snapshot)
    conductor backup status      # where they go, and the latest snapshot
    conductor backup pull        # on a fresh instance: restore them, then `conductor resume`
    

    conductor sessions save all pushes automatically once a bucket is configured, the shutdown hook and the wrap SIGTERM handler push on the way down, and conductor resume pulls first when a machine has no local records — so a replaced instance resumes where the old one left off. Objects are keyed by machine under a prefix; set CONDUCTOR_MACHINE_ID to a stable id if hostnames are not (autoscaled hosts), or to another machine's id to adopt its sessions. The S3 client is dependency-free (SigV4 signed over the standard library) and works against any S3-compatible store — real S3, MinIO, R2 — via CONDUCTOR_BACKUP_S3_ENDPOINT. As everywhere else, only coordination metadata travels: how to reopen a session, never a transcript. CONDUCTOR_BACKUP=off disables it.

One bucket, configured once. conductor storage set writes ~/.conductor/storage.json, which backup, checkpoints, and the database archive all read, and which the macOS app's Settings → Storage pane edits. It signs in to the bucket three ways: an access key (secret kept in the macOS Keychain), a profile from ~/.aws (static keys, IAM Identity Center SSO, an assumed role, or credential_process), or the environment (AWS_* variables, web identity, the ECS task role, the EC2 instance role through IMDSv2). Credentials that expire are refreshed. conductor storage test signs in and round-trips a probe object, step by step. The CONDUCTOR_BACKUP_S3_* variables above still work and take precedence. See docs/STORAGE.md.

conductor storage set --bucket my-team-conductor --region us-east-1 --auth profile --profile dev
conductor storage test

The database, durable in the same bucket. Postgres stays local and fast; conductor db archiving --data-dir … --write points its archive_command at Conductor, so every WAL segment reaches the bucket as it fills (at least once a minute), sealed with your passphrase. conductor db base-backup streams a base backup and prunes old ones. On another machine, conductor db restore --data-dir … rebuilds the database to the last archived segment, or to any moment with --target-time. See conductor db status and docs/STORAGE.md.

Wrapped sessions stay honest with the team while paused: the sidecar keeps heartbeating as waiting_for_input, so presence shows a parked session that is not offered work, rather than a mystery that stopped moving. A relaunched wrap registers a fresh session with the same capability flags it was started with.

Moving a session: another login, another machine, another harness

Everything above reopens a conversation where its harness keeps it — this machine, this login, this directory. That is the wrong place the day the account hits its usage limit with the task half done, the cloud instance is reclaimed with the transcript on its disk, or Claude planned something Codex should finish. A checkpoint is the session in one file: the harness's own transcript, the uncommitted working tree (plus any commits not yet on a remote), and a harness-neutral CONTINUATION.md distilled from the conversation.

conductor wrap claude                        # checkpoints itself every 2 minutes, and on the way down
conductor checkpoint list                    # what this machine holds
conductor checkpoint resume latest --account work      # usage limit hit: carry on under another login
conductor checkpoint resume latest --harness codex     # carry on in a different agent
conductor checkpoint export latest --seal              # one file, encrypted, for another machine
conductor checkpoint resume session.ckpt --dir ~/src/repo --clone   # …and on that machine

A conductor wrap session checkpoints itself: every CONDUCTOR_CHECKPOINT_INTERVAL (default two minutes), on the SIGTERM/SIGHUP a shutdown sends, and when the harness exits. Bare sessions are covered by hooks — conductor integrate claude adds Stop and PreCompact hooks, conductor integrate opencode captures on session.idle — and by conductor sessions save all, so the shutdown hook captures conversations as well as resume records. Inside a session, an agent that reaches a milestone or suspects it is near a limit can call the coord_checkpoint MCP tool with a note on where the work stands. Nothing is written when nothing changed, and the newest five per session are kept (CONDUCTOR_CHECKPOINT_KEEP).

conductor checkpoint resume restores the working tree into a checkout (the current one, or --dir, cloned on demand with --clone), then:

  • Same harness. The native transcript is installed where that harness looks, with the session's working directory rewritten to the new checkout, and the harness reopens the very same conversation: claude --resume <path>, codex resume <id>, or opencode import followed by opencode --session <id>. --account NAME (or --state-dir DIR) points the harness at a different state directory — CLAUDE_CONFIG_DIR, CODEX_HOME, or XDG_DATA_HOME — which is where each keeps both its login and its sessions, so the conversation is reopened by that directory's account.
  • Different harness. Codex cannot read a Claude Code transcript, so it starts from the checkpoint's CONTINUATION.md — the original request, the conversation so far with one line per tool call, the files touched, and the last exchange — with a first prompt that tells it to read that file and continue, not start over.

Where this sits in the privacy model matters: a checkpoint contains the conversation, which the control plane never holds. Checkpoints are written only by the CLI, on your machine, under ~/.conductor/checkpoints/ (0600 in 0700, beside your credentials), and leave it only as a file you move yourself or sealed — AES-256-GCM under a passphrase — in your own bucket: conductor checkpoint push refuses to upload plaintext and shares the CONDUCTOR_BACKUP_S3_* configuration with conductor backup. The coord_checkpoint tool works only in the stdio gateway, on the session's own machine; the HTTP gateway, which runs in the control plane, refuses it. docs/PORTABILITY.md has the bundle format and the per-harness mechanics.

Usage limits: warned before a login runs out
conductor quota                          # every login × tool × window: used, resets in, source
conductor quota statusline install       # record Claude Code's documented 5h / weekly limits
conductor quota suggest                  # the resume command for the login with the most room

Subscription logins — Claude Pro/Max, a ChatGPT plan in Codex, a Cursor plan — stop the session when a rolling window runs out. Conductor reads what each tool exposes about those windows on your machine: Claude Code's status line payload (a documented rate_limits object, recorded by a shim that chains to your own status line so nothing visible changes) and its "limit reached · resets …" transcript records; the rate_limits Codex writes into every rollout; and, only if you hand it your session cookie, Cursor's undocumented usage-summary endpoint. Logins are named by their state directory (~/.claude-work is work), never by email or token.

At 80% (warn) and 95% (critical) — CONDUCTOR_QUOTA_WARN / _CRITICAL, or quota: in .conductor/project.yaml — the conductor wrap sidecar raises the level once per window: a desktop notification, a quota.warning / quota.exhausted event, and at critical an immediate checkpoint plus the exact conductor checkpoint resume … --account / --harness … command for the login or tool with the most headroom. Agents can check their own headroom with coord_quota. Readings are visible only to their owner; teammates see how many of the team's logins are near their limit, nothing more. CONDUCTOR_QUOTA=off disables it all. docs/USAGE_LIMITS.md has every source, its classification, and the research behind it.

VS Code: integrated terminals are ordinary ptys, so pausing and in-place resume already work there. Reopening a closed session into VS Code needs the companion extension in integrations/vscode — VS Code offers no command-line way to open an integrated terminal running a command, so conductor resume hands the session to the extension via a vscode:// URI (carrying only a record id, never a command) and the extension opens the terminal in the session's working directory. Which sessions lived in VS Code is recorded from TERM_PROGRAM at save time; without the extension installed, resume simply falls back to the terminal chain above. The extension also adds Conductor: Pause All Agent Sessions and Conductor: Resume All Agent Sessions to the command palette.

Notifications: Slack, Discord, and webhooks
conductor notify add slack https://hooks.slack.com/services/T…/B…/… --name "#eng-agents"
conductor notify add webhook https://ci.example.com/conductor      # prints its signing secret once
conductor notify test <id>          # send a test message now
conductor notify                    # channels and their delivery health
conductor notify events             # what can be sent, and the defaults

A channel sends the project's events to a Slack incoming webhook, a Discord webhook, or any HTTPS endpoint as signed JSON. By default it gets the moments a team acts on: someone refused territory another task holds (conflict.blocked) or starting work that looks like a task already in flight (conflict.suggest_join) — each at most once per person, task and outcome every 15 minutes, however often an agent retries — a new medium-or-worse conflict in the merge-risk graph (conflict.detected, once while it stays open), work paused on a conflict (task.status_changed:blocked_conflict), territory someone was waiting for is free (scope.released, naming who was waiting), an agent stalled or lost its lease (attempt.stalled, lease.expired), a pull request merged, a task done or failed, the project budget crossing its downshift or pause threshold, and a teammate's login near or at its usage limit (quota.warning, quota.exhausted). --events picks others from conductor notify events; "*" sends all of them. A channel hears about what happens after it is added, not the backlog. Channels are managed by maintainers, from the CLI, the API (/v1/projects/{p}/notifications), or the Notifications card in the dashboard's Settings.

What leaves. A channel is project-wide, and Slack is not Conductor: every event goes through the same visibility projection the API applies for an ordinary project member, then narrower still for private work — an event about a private task says "a private task" and nothing else: no title, no ref, no paths or territory. Prompts and transcripts were never in events to begin with.

Credentials. A Slack or Discord URL is the credential, and a webhook's signing secret is what its receiver trusts, so both are sealed in the database under conductord's secret key (docs/OPERATIONS.md) and never returned after creation — the API shows the host and last four characters. URLs must be https, and conductord refuses to connect to loopback, private, link-local and other non-public addresses (checked on the address actually dialed, after DNS), so a channel cannot be pointed at the control plane's own network. A self-hosted chat server on your LAN needs conductord --notify-allow-private-networks; --notify-allow-http is for local testing only. Where conductord reaches the internet only through a proxy, pass --notify-proxy URL (or CONDUCTOR_NOTIFY_PROXY); destinations are still resolved and checked before the proxy is asked for them.

Delivery is at least once — deduplicate on the id field (also X-Conductor-Delivery). A failing endpoint is retried with exponential backoff (15s doubling, at most an hour) and an event is given up after 8 failed attempts or 24 hours; a 4xx answer other than 408 or 429 is not retried. conductor notify shows each channel's last error.

Verifying a webhook. Each request carries X-Conductor-Timestamp (Unix seconds) and X-Conductor-Signature: sha256=<hex>, an HMAC-SHA256 keyed with the whole secret (whsec_…) over the timestamp, a ., and the raw body. Check both, against the raw bytes before any JSON parsing, and refuse a timestamp more than five minutes off — that is what stops a captured request from being replayed.

import hashlib, hmac, time

def verify(secret: str, headers, body: bytes, tolerance: int = 300) -> bool:
    ts = headers.get("X-Conductor-Timestamp", "")
    sig = headers.get("X-Conductor-Signature", "")
    if not ts.isdigit() or abs(time.time() - int(ts)) > tolerance:
        return False
    mac = hmac.new(secret.encode(), ts.encode() + b"." + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(sig, "sha256=" + mac)
func verify(secret string, h http.Header, body []byte) bool {
	ts := h.Get("X-Conductor-Timestamp")
	sec, err := strconv.ParseInt(ts, 10, 64)
	if err != nil || time.Since(time.Unix(sec, 0)).Abs() > 5*time.Minute {
		return false
	}
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(ts + "."))
	mac.Write(body)
	want := "sha256=" + hex.EncodeToString(mac.Sum(nil))
	return hmac.Equal([]byte(h.Get("X-Conductor-Signature")), []byte(want))
}

The body is {"id", "type", "project", "occurred_at", "subject", "private", "text", "url", "data"}: text is a one-line summary, data the event's payload as a project member sees it, and url a dashboard link when conductord has a public --public-url.


Private memory and Redis

Conductor can retain compact observations from coding sessions in a Redis store you control. This feature is off until configured. The local conductor process encrypts every record with AES-GCM before sending it to Redis and HMACs project and search-index keys. The shared Conductor API, Postgres database, event stream, S3 resume backup, and HTTP MCP endpoint never receive memory content. Keep ~/.conductor/memory.key (mode 0600) to read the records again; for a second machine, copy that key and memory.json securely or provide the same base64 key through CONDUCTOR_MEMORY_KEY and the same CONDUCTOR_MEMORY_NAMESPACE. Automatic project scoping uses the local Git common directory, so registered worktrees share notes without trusting a repository's project.yaml ID. Set CONDUCTOR_MEMORY_PROJECT to a user-chosen stable name on each machine if you want the same project scope across machines.

# Redis on this machine. Start Redis separately with your preferred persistence settings.
conductor memory configure --local
conductor memory status

# ElastiCache/Valkey or another TLS Redis. Pipe the URL from your secret manager to stdin.
conductor memory configure --url-stdin --cluster   # cluster-mode configuration endpoint
# Omit --cluster for a primary endpoint in cluster mode disabled.

conductor integrate claude      # refresh capture and recall hooks
conductor integrate codex       # adds project .codex/hooks.json; review/trust with /hooks
conductor integrate opencode    # refreshes the local plugin

conductor memory search 'index calculus'
conductor memory timeline <observation-id>
conductor memory show <observation-id>
conductor memory forget <observation-id>
conductor memory disable        # stops capture; keeps existing records and key

Use redis://127.0.0.1:6379/0 for the local server. A remote address must use rediss://; TLS certificate verification stays on. For ElastiCache, the client must be able to reach the cache inside its VPC or through your network path, and a cluster-mode configuration endpoint needs --cluster. CONDUCTOR_MEMORY_REDIS_URL can override the saved URL at runtime for credential rotation. Redis persistence or ElastiCache snapshots remain your responsibility.

Claude Code and Codex hooks capture bounded tool actions and the assistant's final turn summary, then inject a small project-scoped selection of earlier summaries and explicit notes at session start and on new prompts. OpenCode captures tool actions and injects recent context through its plugin. Retrieved observations are quoted as untrusted historical data. Hook capture skips sensitive file paths and arbitrary shell commands, never retains raw tool input or output, and fails open if Redis is unavailable. conductor memory remember accepts a note on stdin for explicit decisions. The local stdio MCP gateway exposes memory_search, memory_timeline, memory_get, and memory_remember; the HTTP MCP gateway does not.


How it holds together

 Claude Code · Codex · OpenCode · human sessions
        │                    │
   MCP tools           conductor CLI / wrap
        └────────┬───────────┘
                 ▼
      control plane (conductord)
   ledger · leases · reservations · conflict graph · presence
                 │
          PostgreSQL (source of truth)
                 │
      scheduler ─┴─ adaptive router
                 │
   harness drivers → isolated git worktrees

Four mechanisms do the real work:

Transactional claims. SELECT … FOR UPDATE SKIP LOCKED makes duplicate dispatch structurally impossible rather than unlikely. Two schedulers racing the same ready queue cannot select the same row, so replicas need no leader election.

Fencing epochs. Every claim gets a strictly higher epoch. A worker that was paused, lost its lease, and woke up later presents a stale epoch and is rejected — it can keep writing in its own worktree, but it can never publish. Expiry alone does not close that window; the epoch does.

Reservations under an advisory lock. Territory is per-resource (file, directory, glob, migration lane, table, API route, symbol), and acquisition takes a per-project advisory lock so check-then-insert cannot interleave. Without it, two agents each see a clear field and both plant a flag.

Merge risk from observed diffs. Runners report the paths git says changed, and so does the conductor wrap heartbeat for interactive sessions, so the conflict graph is built from what agents and people are doing, not only what they declared. That is what turns a merge-time disaster into a minute-five warning.


What is built, and what is not

Implemented and exercised by tests:

  • Task ledger with the full DESIGN.md §9 state machines, enforced in Go and in Postgres.
  • Atomic claims, expiring leases, fencing epochs, reclamation, retry budgets.
  • Scope reservations across all nine resource types, with the complete §11.3 conflict matrix.
  • Privacy-preserving duplicate detection (HMAC + MinHash), field-level visibility projections.
  • Conflict graph: scope overlap, duplicate intent, merge risk, with join/wait/split advice.
  • Presence, event log with gapless per-aggregate sequencing, SSE stream, live dashboard.
  • REST API, MCP gateway, CLI, session wrapper with heartbeat sidecar.
  • Delphi: delegation of prompts to frontier models through the Anthropic and OpenAI batch APIs, with vault keys, spend in the usage ledger, and no request text or answer stored (docs/DELPHI.md).
  • Scheduler: reconcile (with outage recovery, so a control-plane outage does not reclaim live work), session reaping, stall detection, dependency gating, budget events announced once per threshold crossing, and retention.
  • Operations: ordered graceful shutdown, request ids and access logs, Prometheus /metrics, /v1/ready, bounded database calls, request-body deadlines, capped event streams over a shared per-project feed, a schema-version guard, multi-replica-safe GitHub state, and a tested Postgres backup/restore script (docs/OPERATIONS.md).
  • Adaptive router: hard floors, tiers, escalation, de-escalation, budget guard.
  • Session capability advertisement and capability-aware assignment: sessions declare the model and reasoning effort they are running, the catalog decides what that is worth, and work with a capability floor is offered to a session that clears it.
  • Shareable per-member token budgets: a rolling-window allowance each member can transfer to a teammate, enforced at claim time and settled entirely by ledger arithmetic.
  • Harness drivers for Claude Code, Codex, OpenCode, a generic templated exec driver, and a deterministic in-process fake.
  • Shutdown-durable sessions: conductor wrap saves its own session on the SIGTERM/SIGHUP a shutdown or closed terminal sends; conductor sessions install-hook adds a systemd/launchd hook that captures bare sessions at shutdown and periodically; and a dependency-free, SigV4-signed S3 backend (conductor backup push|pull) carries the resume records off-host, so a terminated cloud instance resumes on its replacement.
  • Machine-local pause/resume: conductor pause freezes every interactive agent session on the machine and conductor resume revives them — in place, or in freshly opened terminals on each harness's own conversation-resume invocation.
  • Token-free local sign-in for the machine's owner (dashboard, CLI, macOS app), guarded against drive-by pages, DNS rebinding, and proxies, with an enhanced security mode that requires tokens everywhere and revokes what local sign-in issued.
  • A GitHub App created in one click through GitHub's manifest flow. It posts a "Conductor" check run on each pull request that overlaps reserved or in-flight work, links the pull request to its task, and completes the task when it merges — by webhook, or by polling when GitHub cannot reach the daemon. Opt-in issue sync turns a repository's labelled issues into tasks and writes each task's claim and completion back to its issue.
  • Session portability: conductor checkpoint bundles a session's native transcript, working tree, and a harness-neutral continuation into one file — taken periodically by conductor wrap, by Claude Code and OpenCode hooks, at shutdown, and on an agent's own coord_checkpoint call — and conductor checkpoint resume continues it on another machine, under another login, or in a different harness, sealed with a passphrase whenever it leaves the machine.
  • Isolated git worktrees, scope-drift detection, runner-attested validation, evidence manifests, handoff bundles, portable Markdown task cards.
  • Member and token administration, TLS, a loopback-by-default bind, and auth throttling.
  • Single sign-on through any OpenID Connect provider or GitHub, for the dashboard and the CLI, issuing ordinary tokens; external identities link only to accounts an administrator registered (§25.7).
  • Daemon-to-daemon peering over mutual TLS: a private CA names every control plane in a mesh, each daemon dials its configured or DNS-discovered peers and keeps a live link table, and conductor peers reports it. Connectivity and identity only — no data is replicated across the link. --peer-discover-dns finds peers via a DNS SRV record so a mesh can grow without an operator hand-listing every daemon's address.
  • A runner that reaches the control plane over HTTP and holds no database credential (§28.2), alongside the in-process backend for single-host use (§28.1).
  • One-link onboarding: conductor invite <handle> mints a teammate their own token and prints a single join link (token in the URL fragment, off the wire); conductor join <link> redeems it, and the same link self-connects the web dashboard.
  • One-command integration into eight coding tools (Claude Code, Cursor, Codex, OpenCode, Windsurf, VS Code, Zed, Gemini CLI): MCP config plus, where supported, pre-edit hooks that run the conflict check before every edit and block on a hard conflict.
  • MCP over Streamable HTTP served by conductord itself, so an HTTP-capable client connects with a bearer token and no local binary — the same thirteen tools as the stdio gateway (all but coord_checkpoint, which only the stdio gateway can honour, since it runs on the harness's own machine).
  • Repository dispatch policy: named lanes, ordered model ladders, when-gated candidates, and hard-floor-respecting escalation, evaluated by a small deterministic expression language, with conductor route to preview and conductor policy lint to validate.
  • A pooled-capacity swarm view and per-member budget sharing across a team, and an admission queue that makes sessions and attempts wait for a slot instead of failing when the team is at capacity, granted in arrival order with heartbeat-expiry hand-off.
  • A single-page dashboard (no build step, no external requests): Home (check before an edit, who is on what, what is waiting on you), Tasks, People and Settings, with the fleet, swarm, usage, events, queue and integration views under More, and an Admin area for organization administrators.
  • Enterprise administration: a server config file that can lock organization settings, require-SSO, Entra ID tenant trust, SCIM 2.0 provisioning, group → role mapping, token lifetime caps, feature flags, branding, and an exportable audit log.
  • Notifications to Slack, Discord, and signed webhooks, relayed from the transactional outbox with retries, through the same privacy projection as the API.

Not built, and where the design says it goes:

  • Planner and reviewer services (§14, §15.3). The contracts, validation rules, and reviewer.* routing are in place; nothing yet invokes a model to decompose an objective or review a diff.
  • Codex App Server driver (§16.3). The Codex driver shells out to codex exec --json rather than binding the bidirectional JSON-RPC App Server.
  • Merge queue, symbol/tree-sitter indexing (§29, §30 phase 5). Pull requests are integrated as far as the check run and merge-to-done above; nothing queues or performs merges.
  • Tracker sync beyond GitHub Issues (§17.5). GitHub Issues sync is built; Linear is the next adapter, then Jira.
  • Codex is profiled as gpt-5.3-codex in .conductor/models.yaml but left disabled until someone verifies it against their account; its exec --json stream adapter is tested against fixture transcripts built from Codex's documented event schema, not a live run. OpenCode is wired to local vLLM: Qwen 3.8 27B, GLM-5.3-Flash, and GLM-5.3 (conductor serve qwen|flash|glm53, then conductor wrap opencode --model vllm/…).

One deliberate deviation from the design document: it recommends TypeScript (§28.1). This is Go, at the repository owner's direction. The tradeoff is real — the Claude Agent SDK and OpenCode SDK are TypeScript, so their drivers here are CLI-based rather than SDK-based.


Testing

Run the checks CI runs before you push:

make check    # gofmt, vet, staticcheck, build, and the tests that need no database (~40s)
make ci       # everything CI's Linux jobs run: + govulncheck, the Postgres suite,
              # the race detector, and the end-to-end script (~2 min)
make hooks    # once per clone: git push runs `make check` first

Both are scripts/ci-local.sh, which CI itself calls step by step, so a local pass is the same check CI makes. make ci needs Postgres 16+ and brings its own: a throwaway server from the local Postgres binaries (Debian/Ubuntu postgresql, Homebrew postgresql@17, or Postgres.app), or a postgres:17-alpine container if Docker is running, stopped again when the run ends. To use an existing database instead, set CI_DATABASE_URL. Run single steps with scripts/ci-local.sh race e2e (--help lists them). The pre-push hook skips once with git push --no-verify; CONDUCTOR_PREPUSH=full makes it run make ci, and off disables it.

The narrower targets still work:

make unit     # pure logic, no database
make test     # everything; integration tests skip without DATABASE_URL
make db-up && make test
make e2e      # scripted two-person scenario end to end

CI runs all of it against a real Postgres (16 and 17) on every push, with and without the race detector, and fails if the integration tests skip — a misconfigured database service would otherwise produce a silently green run. It also runs staticcheck and govulncheck, and builds and unit-tests on macOS, which the release ships binaries for.

scripts/e2e.sh asserts the MVP acceptance criteria of DESIGN.md §31 rather than printing output for a human to eyeball: that a completed task carries a commit and runner-observed validation, that the attempt ran in a per-task worktree, that the workflow and config hashes and the model routing were recorded, and that presence exposes a branch and a heartbeat and nothing resembling a conversation.

Two acceptance criteria are still unverified, both for the same reason: nothing here has ever launched a real Claude Code, Codex, or OpenCode process. §31.5 (each harness registers and publishes progress) and the live half of §31.6 are exercised only through the built-in fake.

The suite proves the invariants rather than asserting them in prose. Notably:

Test Proves
TestConcurrentClaimsYieldExactlyOneLease 24 concurrent claims → exactly one winner
TestStaleFenceIsRejected a reclaimed worker cannot heartbeat, release, or publish
TestConcurrentOverlappingReservationsSerialize 12 racing migration reservations → one winner
TestClaimNextDoesNotDoubleDispatch 6 scheduler replicas, 8 tasks, no double dispatch
TestReclamationReleasesReservations a dead session frees its territory
TestPrivateTaskHidesIntentButKeepsTerritory private work still prevents collisions
TestNoTranscriptColumnsInSchema the database has nowhere to put a prompt
TestMatrixMatchesDesign all 25 cells of the §11.3 conflict matrix
TestSecurityFloorIsAbsolute budget pressure cannot downgrade a security-sensitive task
TestPrivateTaskIsRedactedOverHTTP the projection survives serialization, not just unit tests
TestNonMemberSeesNotFoundNotForbidden a 403 would confirm the project exists
TestStaleFenceIsA409 a stale worker gets "stop", not "retry"
TestParseFlagsAcceptsFlagsAfterPositionals CLI flags after a positional are not silently dropped
TestSimilarityIsStableAcrossKeys duplicate detection does not miss real collisions across tenant keys
TestMCPWorkLifecycleAgainstLiveServer the MCP gateway works against the real API, not a stub
TestQueuedAttemptCannotSucceed an attempt cannot report success without having run
TestProbeUntrustedPeer a daemon certified by another CA can never pass as a peer
TestDiscoverAddsPeersFromSRV a daemon joins the mesh via DNS alone, no --peer list required
TestPeerInfoRequiresMeshCertificate a bearer token is not a peer credential; only a mesh certificate is

Peering daemons

A mesh is a set of conductord instances that know each other by certificate. One CA is generated per mesh; every daemon holds a certificate signed by it and uses that single certificate in two roles — served as its TLS certificate, and presented as its client certificate when dialing peers. A peer link is therefore mutual TLS: each side proves it holds a mesh-issued key, and the mesh CA is the only root either side trusts for it.

Peering carries connectivity and identity, nothing else. Each daemon probes its configured peers (GET /v1/peer/info) and records state, round-trip time, and the identity that answered; project members read that link table with conductor peers. No tasks, scopes, or events cross the link — the database remains each daemon's own source of truth.

# once per mesh: a CA, then one certificate per daemon
scripts/gen-peer-certs.sh laptop desktop

# per daemon (each points at the other)
conductord --addr 0.0.0.0:8443 \
  --peer-ca .conductor/certs/ca.pem \
  --peer-cert .conductor/certs/laptop/cert.pem --peer-key .conductor/certs/laptop/key.pem \
  --peer desktop=https://desktop.example.com:8443

conductord --addr 0.0.0.0:8443 \
  --peer-ca .conductor/certs/ca.pem \
  --peer-cert .conductor/certs/desktop/cert.pem --peer-key .conductor/certs/desktop/key.pem \
  --peer laptop=https://laptop.example.com:8443

conductor peers   # PEER ADDRESS STATE RTT LAST CHECK

Env equivalents: CONDUCTOR_PEERS=name=url,… (comma-separated) plus CONDUCTOR_PEER_CA, CONDUCTOR_PEER_CERT, CONDUCTOR_PEER_KEY. Clients verify the daemon with CONDUCTOR_CA_CERT=.conductor/certs/ca.pem. Peer URLs must be https — a plaintext peer would put the mesh identity on an unauthenticated wire, and the daemon refuses it.

Joining a mesh without seed nodes

--peer name=url does not scale past a couple of daemons — every one needs every other one's address by hand. --peer-discover-dns replaces that with one shared DNS SRV record (RFC 2782): every daemon resolves it on each probe tick and treats each target as a peer to dial, the same join-by-DNS pattern a Kubernetes headless service or Consul uses.

# publish an SRV record once, e.g. _conductor-mesh._tcp.mesh.internal pointing at every
# daemon's host:port — DNS round-robin, a headless Service, or a Consul/etc service catalog

conductord --addr 0.0.0.0:8443 \
  --peer-ca .conductor/certs/ca.pem \
  --peer-cert .conductor/certs/laptop/cert.pem --peer-key .conductor/certs/laptop/key.pem \
  --peer-discover-dns _conductor-mesh._tcp.mesh.internal

conductord --addr 0.0.0.0:8443 \
  --peer-ca .conductor/certs/ca.pem \
  --peer-cert .conductor/certs/desktop/cert.pem --peer-key .conductor/certs/desktop/key.pem \
  --peer-discover-dns _conductor-mesh._tcp.mesh.internal

No daemon names another by hand: a discovered address is dialed, and once it answers with a certificate the mesh CA vouches for, it's identified by whatever name its own /v1/peer/info reports — DNS only proposes where to look, never who to trust. --peer and --peer-discover-dns compose freely (conductor peers marks a discovered link (dns)), and a resolver hiccup only pauses discovery of new peers — it never drops one already linked. Env equivalent: CONDUCTOR_PEER_DISCOVER_DNS.

The lookup uses the system resolver, which on some machines never sees a laptop-local directory (Go ignores /etc/resolver). --peer-dns-server host:port points the lookup straight at a directory server instead — CONDUCTOR_PEER_DNS_SERVER is the env form.


Configuration

Policy lives in the repository, versioned with the code it governs, and every attempt records the hash of the files in force when it ran — so a result can always be explained by the rules that produced it.

File What it controls
.conductor/project.yaml lease TTLs, heartbeat cadence, visibility defaults, isolation
.conductor/policies.yaml conflict matrix, duplicate thresholds, hard routing rules, budgets
.conductor/models.yaml model aliases (roles), capability floors, profiles — each a fixed model or a select that follows discovery
.conductor/WORKFLOW.md the prose contract every agent reads; required checks; protected scopes

These files are code, not just settings, wherever a conductor worker runs. The harness command, arg_template, and mcp_servers in project.yaml are executed by the worker, and the required checks run as sh -c inside the worktree the agent just edited — an edited Makefile included. The worker runs them as its own user with no sandbox; it strips credentials from their environment (and hands the agent a short-lived, project-scoped token instead of yours), but it cannot stop code from reading that user's files. Run a worker only for repositories and teammates you would let run code on that machine (DESIGN.md §25.3).

The control plane's own configuration — flags, environment, and the server config file (conductord --config) — is described in docs/OPERATIONS.md and, for organization policy, in For enterprises.

Running the control plane itself — probes and /metrics, shutdown and outage behaviour, database timeouts, retention windows, running several replicas, and backing up and restoring Postgres (scripts/pg-backup.sh) — is covered in docs/OPERATIONS.md.


Removing Conductor

make uninstall (or deleting the three binaries) removes the program, not what it created. All of it, from least to most destructive:

conductor down --db                          # stop the control plane and the conductor-db container
conductor integrate <tool> --remove          # for each tool you connected (claude, codex, cursor, …)
conductor sessions install-hook --uninstall  # if you installed the shutdown hook
make uninstall                               # the binaries in ~/.local/bin and the PATH entry
                                             # (~/.zshrc, ~/.bashrc or ~/.bash_profile, or fish conf.d)
rm -rf ~/.conductor                          # credentials, pidfile and log, saved sessions,
                                             # checkpoints, extra harness accounts, GitHub App key

~/.conductor/checkpoints may hold the only copy of a session you captured; export anything you want to keep (conductor checkpoint export) first.

In each repository you ran conductor init in, .conductor/ holds the policy files (versioned with your code; keep them if you might come back) and .conductor/runtime/ the task worktrees. init also added a block between <!-- conductor:begin --> and <!-- conductor:end --> to CLAUDE.md and AGENTS.md; delete it by hand.

The database is last because it is every task, reservation, and member of every project on this control plane. If conductor up started it in Docker:

docker rm -f conductor-db && docker volume rm conductor-pgdata

If you pointed Conductor at your own Postgres, drop its database there instead.


License

Apache License 2.0. See LICENSE and NOTICE.

Directories

Path Synopsis
cmd
conductor command
Command conductor is the operator and developer CLI (DESIGN.md §33).
Command conductor is the operator and developer CLI (DESIGN.md §33).
conductor-mcp command
Command conductor-mcp is the MCP gateway an agent harness mounts.
Command conductor-mcp is the MCP gateway an agent harness mounts.
conductor-mesh-dns command
conductor-mesh-dns: the DNS answer table and hand-rolled wire format.
conductor-mesh-dns: the DNS answer table and hand-rolled wire format.
conductord command
Command conductord is the Conductor control plane: REST API, SSE event stream, dashboard, and the background scheduler.
Command conductord is the Conductor control plane: REST API, SSE event stream, dashboard, and the background scheduler.
delphi command
delphi delegates hard prompts to frontier models through provider batch APIs (Anthropic, OpenAI) and runs the loop around them: queue, flush as batches, poll, collect, retry, hand results on.
delphi delegates hard prompts to frontier models through provider batch APIs (Anthropic, OpenAI) and runs the loop around them: queue, flush as batches, poll, collect, retry, hand results on.
internal
accounts
Package accounts manages named harness login profiles — one Claude Code account, one Codex account, one OpenCode account per file — so a machine can move off an exhausted account and onto a fresh one without redoing each harness's OAuth dance.
Package accounts manages named harness login profiles — one Claude Code account, one Codex account, one OpenCode account per file — so a machine can move off an exhausted account and onto a fresh one without redoing each harness's OAuth dance.
admin
Package admin is an organization's enterprise policy: who may sign in and how, how long credentials live, how identity-provider groups map to roles, which advanced areas of the dashboard are on, and how the organization is branded (DESIGN.md §25.8).
Package admin is an organization's enterprise policy: who may sign in and how, how long credentials live, how identity-provider groups map to roles, which advanced areas of the dashboard are on, and how the organization is branded (DESIGN.md §25.8).
api
Package api is the northbound HTTP interface (DESIGN.md §19).
Package api is the northbound HTTP interface (DESIGN.md §19).
awscreds
Package awscreds finds AWS credentials the way the AWS CLI does, without the AWS SDK: a static key pair (its secret in the macOS Keychain or a file), a named profile from ~/.aws/config and ~/.aws/credentials (static keys, credential_process, IAM Identity Center SSO, and role_arn assumed through STS), or the environment (the AWS_* variables, a web identity token, ECS container credentials, the EC2 instance role through IMDSv2).
Package awscreds finds AWS credentials the way the AWS CLI does, without the AWS SDK: a static key pair (its secret in the macOS Keychain or a file), a named profile from ~/.aws/config and ~/.aws/credentials (static keys, credential_process, IAM Identity Center SSO, and role_arn assumed through STS), or the environment (the AWS_* variables, a web identity token, ECS container credentials, the EC2 instance role through IMDSv2).
backup
Package backup sends this machine's resume records off-host, so a session survives not just a reboot but the loss of the machine itself — the case that matters on an ephemeral cloud instance, whose disk (and the local ~/.conductor/sessions records with it) vanishes when the instance is terminated.
Package backup sends this machine's resume records off-host, so a session survives not just a reboot but the loss of the machine itself — the case that matters on an ephemeral cloud instance, whose disk (and the local ~/.conductor/sessions records with it) vanishes when the instance is terminated.
backup/s3fake
Package s3fake is an in-memory, path-style S3 endpoint for tests: PUT (with If-None-Match: *), GET, HEAD, DELETE, ListObjectsV2 with paging, and multipart uploads.
Package s3fake is an in-memory, path-style S3 endpoint for tests: PUT (with If-None-Match: *), GET, HEAD, DELETE, ListObjectsV2 with paging, and multipart uploads.
bounds
Package bounds reads the sealed documents of the ecbench bounds protocol -- a frontier of measured ECDLP method costs and the verdicts of challenges against it -- for routing policies that want to spend model capacity where a bound is beatable and escalate where a challenge has stalled.
Package bounds reads the sealed documents of the ecbench bounds protocol -- a frontier of measured ECDLP method costs and the verdicts of challenges against it -- for routing policies that want to spend model capacity where a bound is beatable and escalate where a challenge has stalled.
cairn
Package cairn reads objective state from a cairn node, for routing policies that want to spend model capacity in proportion to what a result is verifiably worth.
Package cairn reads objective state from a cairn node, for routing policies that want to spend model capacity in proportion to what a result is verifiably worth.
checkpoint
Package checkpoint makes a running agent session portable.
Package checkpoint makes a running agent session portable.
client
Package client is the HTTP client for the Conductor control plane.
Package client is the HTTP client for the Conductor control plane.
config
Package config loads the repository-owned policy files of DESIGN.md §20.
Package config loads the repository-owned policy files of DESIGN.md §20.
coord
Package coord is the coordination service: the logic that sits between the store and the two northbound interfaces (REST and MCP).
Package coord is the coordination service: the logic that sits between the store and the two northbound interfaces (REST and MCP).
db
Package db is the persistence layer.
Package db is the persistence layer.
delphi
Package delphi delegates hard prompts to frontier models through provider batch APIs (Anthropic Message Batches, OpenAI Batch): requests are queued, flushed as batches, and answered minutes to 24 hours later at half the interactive price.
Package delphi delegates hard prompts to frontier models through provider batch APIs (Anthropic Message Batches, OpenAI Batch): requests are queued, flushed as batches, and answered minutes to 24 hours later at half the interactive price.
delphi/anthropic
Package anthropic runs delphi requests through the Anthropic Message Batches API with the official SDK.
Package anthropic runs delphi requests through the Anthropic Message Batches API with the official SDK.
delphi/hosted
Package hosted runs delphi inside conductord: members delegate prompts to frontier models through provider batch APIs, with keys from the project vault and spend in the usage ledger.
Package hosted runs delphi inside conductord: members delegate prompts to frontier models through provider batch APIs, with keys from the project vault and spend in the usage ledger.
delphi/openai
Package openai runs delphi requests through the OpenAI Batch API against the Responses endpoint, with the official SDK: the requests are uploaded as a JSONL file, a batch is created over it, and the output and error files are read back when it ends.
Package openai runs delphi requests through the OpenAI Batch API against the Responses endpoint, with the official SDK: the requests are uploaded as a JSONL file, a batch is created over it, and the output and error files are read back when it ends.
domain
Package domain holds Conductor's core types and the rules that govern them.
Package domain holds Conductor's core types and the rules that govern them.
externalwork
Package externalwork inventories local coding-agent session metadata.
Package externalwork inventories local coding-agent session metadata.
githubapp
Package githubapp connects Conductor to GitHub as a GitHub App.
Package githubapp connects Conductor to GitHub as a GitHub App.
harness
Package harness is the southbound execution interface: the common shape every coding agent runtime is driven through (DESIGN.md §16).
Package harness is the southbound execution interface: the common shape every coding agent runtime is driven through (DESIGN.md §16).
integrations
Package integrations connects Conductor to the coding tools people actually use.
Package integrations connects Conductor to the coding tools people actually use.
localstate
Package localstate tracks the interactive harness sessions running on this machine, so `conductor pause` can freeze a wall of agent terminals and `conductor resume` can bring it back — waking each process where its terminal survived, reopening a terminal where it did not.
Package localstate tracks the interactive harness sessions running on this machine, so `conductor pause` can freeze a wall of agent terminals and `conductor resume` can bring it back — waking each process where its terminal survived, reopening a terminal where it did not.
mcp
Package mcp implements the Model Context Protocol gateway of DESIGN.md §18.
Package mcp implements the Model Context Protocol gateway of DESIGN.md §18.
memory
Package memory keeps coding-session observations in a user-owned Redis store.
Package memory keeps coding-session observations in a user-owned Redis store.
metrics
Package metrics is a small Prometheus text-format registry (DESIGN.md §26.1).
Package metrics is a small Prometheus text-format registry (DESIGN.md §26.1).
modelsrc
Package modelsrc discovers which models an inference endpoint serves, so the model catalog can follow what providers release instead of what someone remembered to type into a file.
Package modelsrc discovers which models an inference endpoint serves, so the model catalog can follow what providers release instead of what someone remembered to type into a file.
nat
Package nat manages opt-in connectivity for the authenticated Conductor API.
Package nat manages opt-in connectivity for the authenticated Conductor API.
notify
Package notify sends a project's domain events to the places a team already looks: generic webhooks (signed JSON), Slack incoming webhooks, and Discord webhooks.
Package notify sends a project's domain events to the places a team already looks: generic webhooks (signed JSON), Slack incoming webhooks, and Discord webhooks.
peer
Package peer maintains daemon-to-daemon links between Conductor control planes.
Package peer maintains daemon-to-daemon links between Conductor control planes.
pgarchive
Package pgarchive makes a local Postgres durable in an S3 bucket: every WAL segment is archived as Postgres finishes it (archive_command), base backups are streamed on a schedule (pg_basebackup), and a lost machine is rebuilt on another from the newest base backup plus the archived WAL, to the last segment or to a chosen moment.
Package pgarchive makes a local Postgres durable in an S3 bucket: every WAL segment is archived as Postgres finishes it (archive_command), base backups are streamed on a schedule (pg_basebackup), and a lost machine is rebuilt on another from the newest base backup plus the archived WAL, to the last segment or to a chosen moment.
policy
Package policy makes repository-owned routing policy executable.
Package policy makes repository-owned routing policy executable.
privacy
Package privacy implements the intent envelope of DESIGN.md §12 and the field-level visibility rules of §24.3.
Package privacy implements the intent envelope of DESIGN.md §12 and the field-level visibility rules of §24.3.
quality
Package quality implements advisory quality.lint: structural checks on a public task envelope.
Package quality implements advisory quality.lint: structural checks on a public task envelope.
quota
Package quota tracks how close each subscription login is to its usage limit.
Package quota tracks how close each subscription login is to its usage limit.
resource
Package resource implements the reservation resource keys of DESIGN.md §11.1, the path normalization rules of §11.4, and the overlap algebra that the conflict matrix in §11.3 is applied to.
Package resource implements the reservation resource keys of DESIGN.md §11.1, the path normalization rules of §11.4, and the overlap algebra that the conflict matrix in §11.3 is applied to.
resume
Package resume wakes the sessions `conductor pause` froze and reopens the ones `conductor sessions save` kept.
Package resume wakes the sessions `conductor pause` froze and reopens the ones `conductor sessions save` kept.
router
Package router implements the two-dimensional model and harness routing of DESIGN.md §13.
Package router implements the two-dimensional model and harness routing of DESIGN.md §13.
runner
Package runner is the execution plane (DESIGN.md §7.10).
Package runner is the execution plane (DESIGN.md §7.10).
scheduler
Package scheduler is the control plane's background loop (DESIGN.md §7.7).
Package scheduler is the control plane's background loop (DESIGN.md §7.7).
secretbox
Package secretbox seals small secrets that conductord stores in Postgres (the GitHub App's private key and webhook secret, notification channel credentials, and project vault secrets) with AES-256-GCM under a key that is kept outside the database.
Package secretbox seals small secrets that conductord stores in Postgres (the GitHub App's private key and webhook secret, notification channel credentials, and project vault secrets) with AES-256-GCM under a key that is kept outside the database.
secrets
Package secrets is the project secret vault: small credentials sealed at rest under conductord's secretbox key and retrieved by agents (MCP) or local tools (CLI / wrap).
Package secrets is the project secret vault: small credentials sealed at rest under conductord's secretbox key and retrieved by agents (MCP) or local tools (CLI / wrap).
selector
Package selector answers two questions about the sessions that are live right now: what can this project currently do, and which session should take this piece of work.
Package selector answers two questions about the sessions that are live right now: what can this project currently do, and which session should take this piece of work.
shutdownhook
Package shutdownhook generates the OS integration that captures agent sessions when a machine goes down — a clean shutdown, or the periodic capture that covers a crash or a terminated cloud instance.
Package shutdownhook generates the OS integration that captures agent sessions when a machine goes down — a clean shutdown, or the periodic capture that covers a crash or a terminated cloud instance.
sso
Package sso signs people in through an external identity provider: any OpenID Connect issuer (Google, Okta, Auth0, Keycloak, …) or GitHub's OAuth flow, which is not OIDC for user login.
Package sso signs people in through an external identity provider: any OpenID Connect issuer (Google, Okta, Auth0, Keycloak, …) or GitHub's OAuth flow, which is not OIDC for user login.
sso/ssotest
Package ssotest provides fake identity providers for tests: an OpenID Connect issuer (discovery, JWKS, authorization and token endpoints, RS256 or ES256 signing) and GitHub's OAuth endpoints.
Package ssotest provides fake identity providers for tests: an OpenID Connect issuer (discovery, JWKS, authorization and token endpoints, RS256 or ES256 signing) and GitHub's OAuth endpoints.
storage
Package storage is the bucket Conductor keeps off-machine state in: the session resume records, sealed checkpoints, and the control-plane database's WAL archive and base backups.
Package storage is the bucket Conductor keeps off-machine state in: the session resume records, sealed checkpoints, and the control-plane database's WAL archive and base backups.
systemd
Package systemd generates systemd user units that run the Conductor stack on machines with systemd: Postgres (Docker), the conductord control plane (binary), and optionally a local vLLM endpoint (Docker) for OpenCode.
Package systemd generates systemd user units that run the Conductor stack on machines with systemd: Postgres (Docker), the conductord control plane (binary), and optionally a local vLLM endpoint (Docker) for OpenCode.
taskcard
Package taskcard renders and parses the portable Markdown task card of DESIGN.md §21.
Package taskcard renders and parses the portable Markdown task card of DESIGN.md §21.
tracker
Package tracker syncs a team's issue tracker with Conductor's task ledger.
Package tracker syncs a team's issue tracker with Conductor's task ledger.
usage
Package usage turns what each harness records about its own model calls into a uniform token ledger, so Conductor can say how much a team's agents consume — by harness, by model, by person, by hour — without ever seeing a word of what was said.
Package usage turns what each harness records about its own model calls into a uniform token ledger, so Conductor can say how much a team's agents consume — by harness, by model, by person, by hour — without ever seeing a word of what was said.
version
Package version reports which build of Conductor is running.
Package version reports which build of Conductor is running.
web
Package web serves the Conductor dashboard.
Package web serves the Conductor dashboard.
wif
Package wif obtains provider-issued OIDC assertions for Claude workload federation.
Package wif obtains provider-issued OIDC assertions for Claude workload federation.
wireguard
Package wireguard prepares static WireGuard configuration templates.
Package wireguard prepares static WireGuard configuration templates.
worktree
Package worktree manages the isolated git workspaces that autonomous attempts run in (DESIGN.md §7.10, §11).
Package worktree manages the isolated git workspaces that autonomous attempts run in (DESIGN.md §7.10, §11).
scripts
wireguard-e2e command
Command wireguard-e2e exercises the native API from real WireGuard workers.
Command wireguard-e2e exercises the native API from real WireGuard workers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL