Skip to main content
Fracta runs in three deployment modes. All modes share the same thin-client architecture: the CLI and MCP server always connect to the control plane via HTTP. Modes differ in where components run and what infrastructure is needed. To start a project in any mode, run fracta init --scaffold <mode> from your own git repository. The scaffold drops a complete deployment tree under deployment/ plus a top-level fracta.yaml — see the fracta init reference and the per-mode guides linked below.

Mode Summary

One mode per project. fracta init --scaffold refuses to re-scaffold an existing project as a different mode (the resulting tree would be incoherent). See Switching modes below.

Thin-Client Architecture

All deployment modes share the same client boundary:
The CLI and MCP server never construct orchestrators, backends, or state stores. They send HTTP requests to the control plane API. LocalControlPlaneClient runs only inside the control plane process.

1. Local Daemon Mode

The simplest mode. A local daemon process runs the full control plane. Agents are local subprocesses with git-worktree isolation.

Scaffold

Produces:

Architecture

Runtime Mechanics

Local daemon mode has two different fracta MCP surfaces:
  • fracta serve is the host-facing MCP server. Claude/Codex/OpenCode on the developer machine starts it over stdio. It is a thin client that forwards lifecycle calls to the control plane API.
  • fracta serve --gateway-mode is the agent-facing HTTP MCP gateway. Spawned agents connect to it at gateway.url, usually http://localhost:8080/agents/<agent>/mcp.
The startup chain is:
After fracta serve has confirmed that the control plane is healthy, it no longer waits on the daemon. The long-running ownership tree is:
gateway.url must be set in fracta.yaml (e.g. gateway.url: http://localhost:8080) for spawned agents to discover gateway-proxied MCP tools.

Config

The scaffolded fracta.yaml works out of the box for local development. The relevant fields:

Auto-start and config forwarding

fracta serve auto-starts the daemon if not running. The --config flag is forwarded to the daemon process. If no config is found, the daemon starts with bare defaults (no queue, no logging, no connections) and logs a warning. You can also manage the daemon explicitly:

Prerequisites

  • FalkorDB running locally (redis://localhost:6379).
  • Any MCP backend tools you reference in your config available locally (often via podman or uvx).
  • Environment variables for secrets (typically via op run --env-file, doppler run, or similar).

When to use

  • Day-to-day development.
  • Debugging agent behavior with local logs.
  • When git-worktree merge semantics are needed.
  • When container/K8s infrastructure isn’t needed.
See the full local-process guide.

2. Docker Compose Mode

Same architecture, containerized. Uses DirectoryWorkspace (not git) with the host project bind-mounted at /workspace.

Scaffold

Produces:

Architecture

Start

Secrets

Inject API credentials and other secrets into the compose stack with whatever secret manager you already use. Compose interpolates ${VAR} from the host environment, so any tool that sets env vars works (1Password op run, Doppler, Vault Agent, sops, plain .env for dev):

Auth helpers

Edit (or replace) deployment/auth-helpers/fetch-token-example to fetch a token for your provider. The file’s header comments include reference snippets for AWS Bedrock STS, Vertex AI via gcloud, mounted Anthropic API keys, and custom HTTP token proxies. The compose file bind-mounts ./deployment/auth-helpers/ into every fracta service container at /opt/fracta/auth-helpers/, so resolver command: references find your helper on PATH.

Workspace Semantics

Compose uses DirectoryWorkspace (not GitWorkspace). The host project directory is bind-mounted into containers at /workspace. Agent subprocesses create per-agent subdirectories under /workspace/agents/<id>. Merge/integration and base-branch semantics are disabled. For git-based workflows, use local daemon mode.

When to use

  • Testing the full multi-service architecture locally.
  • When you want Postgres state without K8s.
  • CI/CD environments that support Docker Compose.
  • Sharing a reproducible dev environment.
See the full docker-compose guide.

3. Kubernetes Mode

The orchestrator runs as an in-cluster Deployment. Agents run as K8s Jobs. The control plane is exposed as a Kubernetes Service on :9090; the host’s thin client talks HTTP to that Service. The golden path is to run fracta serve on the host as an MCP server in your AI CLI’s config — your CLI talks MCP to it, it talks HTTP to the in-cluster control plane Service. The same thin client also works from the command line (fracta spawn, fracta list, …).

Scaffold

Produces:

Architecture

Config

The scaffolded fracta.yaml is the host-side thin-client config:
The in-cluster control plane and gateway configs live inside ConfigMaps in deployment/k8s/manifests/fracta-controlplane.yaml and deployment/k8s/manifests/fracta-gateway.yaml.

Reaching the control plane Service from the host

The host needs to reach the in-cluster fracta-controlplane Service on :9090. The transport depends on your cluster:
On Docker Desktop with type: LoadBalancer, the Service may already be directly accessible at localhost:9090. For real clusters, expose the Service via an Ingress and point control_plane_api.url in fracta.yaml at that address. None of these change the architecture — they’re just transports for the same host → Service :9090 hop.

Deploy

Or apply the whole tree:

Auth helpers

Edit (or replace) deployment/auth-helpers/fetch-token-example, then package the directory into the fracta-auth-helpers ConfigMap:
The controlplane’s runtime.kubernetes.extra_volumes block (already in the scaffolded ConfigMap) mounts that ConfigMap into every spawned agent pod at /opt/fracta/auth-helpers/, so command: references resolve on PATH. See Kubernetes runtime configuration for the full ConfigMap workflow.

Agent Permissions

Agent tool permissions are controlled by project.allowed_tools in the controlplane config (deployment/k8s/manifests/fracta-controlplane.yaml), not the host-side thin-client fracta.yaml. This is because the controlplane owns agent lifecycle — it bakes permissions into each pod’s .claude/settings.json at spawn time.
For Claude agents, these are merged with a hardcoded PermissionBaseline (git, go, ls, cat, find, grep). Without explicit allowed_tools, agents only get the baseline. For Codex agents, permissions are managed by Codex’s own --full-auto sandbox policy. For OpenCode agents, permissions are written to opencode.json with "task":"deny" by default. See runtime configuration for details. Permissions are independent per project — each fracta.yaml (or controlplane ConfigMap, in k8s mode) declares its own allowed_tools.

Auth

Auth is runtime-specific. Each runtime references a credential profile defined in the controlplane ConfigMap. See authentication & credentials for the full guide. The scaffolded controlplane config ships an example profile that points at fetch-token-example — replace it with profiles for your real auth provider (Bedrock STS, Vertex, Anthropic API key, etc.). RBAC: the controlplane Deployment uses serviceAccountName: fracta-agent with permissions for configmaps, secrets, jobs, and pods (defined in deployment/k8s/manifests/rbac.yaml).

When to use

  • Production-like local testing.
  • When you need K8s Job isolation for agents.
  • When iterating on agent/gateway behavior without rebuilding the orchestrator.
See the full Kubernetes guide and the Kubernetes runbook.

Comparison: What Runs Where


Switching modes

fracta init --scaffold is single-mode per project. A given project declares one runtime.backend in fracta.yaml and ships one deployment/ tree (matching that mode). fracta init refuses to re-scaffold a project as a different mode, because the result would be a tree where the manifests, configs, and fracta.yaml disagree about what’s running. If you try, you’ll see:
If you genuinely need multiple modes side by side:
  1. Separate projects — one repo per mode. fracta.yaml and deployment/ live independently. Organizations often factor out the shared config into a custom scaffold and pull both projects from --source github:org/my-app-scaffolds@v1.
  2. Separate worktrees — same git repo, different branches per mode. Less ceremony than separate repos, but CI must be aware that different branches deploy to different targets.

Migration Path

The three modes form a progression:
Each step moves more responsibility into containers/cluster while keeping the same domain model and thin-client boundary. The client attachment is identical across all modes: RemoteControlPlaneClient → HTTP → control plane API. To migrate, scaffold a fresh project at the new mode (in a separate directory or branch) and copy over your agents.agent_runtimes, auth.credentials.profiles, and project.allowed_tools settings.