Model or dataset
fabro-sh/fabro avatar
fabro-sh/fabro

Fabro puts the agent workflow in a Graphviz file, not in a prompt

⚒️ The open source dark software factory for expert engineers.

1,730 stars188 forksRustMIT

At a glance

What is it?
Fabro is a Rust tool that runs AI coding agents as nodes in a Graphviz DOT graph with human approval gates, per node model routing, Git checkpoints and cloud sandboxes. It is distributed as nightly builds with a version number still in the 0.38x range, and its own branding calls it a dark software factory.
Who is it for?
Adopt Fabro if your team already runs coding agents unattended and wants verification gates, model routing and git history around them, and you can accept a nightly release channel. Do not adopt it for one off local edits, since the value is in the durable run history rather than the generation.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The workflow is a DOT file you can review in a pull request

Fabro's central claim is that AI coding agents are powerful but unpredictable, and that the choice is between babysitting every step or reviewing a fifty file diff you do not trust. The middle path it offers is to define the process as a graph and let agents execute it.

The graph is Graphviz DOT, not a bespoke DSL or a YAML file. That choice has a practical consequence for a team: your workflow is diffable, reviewable and version controlled, and it can be compared line by line in a pull request like source code. The README describes nodes, transitions, variables, stylesheets and human gates, and links a DOT language reference for the full syntax.

The worked example in the README is a plan, approve, implement graph, and it is worth reading closely because it demonstrates three mechanisms at once:

dot
digraph PlanImplement {
    graph [
        goal="Plan, approve, implement, and simplify a change"
        model_stylesheet="
            *        { model: claude-haiku-4-5; reasoning_effort: low; }
            .coding  { model: claude-sonnet-4-5; reasoning_effort: high; }
        "
    ]

    start [shape=Mdiamond, label="Start"]
    plan      [label="Plan", prompt="Analyze the goal and codebase. Write a step-by-step plan.", reasoning_effort="high"]
    approve   [shape=hexagon, label="Approve Plan"]
    implement [label="Implement", class="coding", prompt="Read plan.md and implement every step."]

    approve -> implement [label="[A] Approve"]
    approve -> plan      [label="[R] Revise"]
}

Node shapes carry meaning: `Mdiamond` is the start, `Msquare` the exit, and a `hexagon` is a human gate that pauses for approval. The two outgoing edges from the gate, labelled Approve and Revise, give you a loop back to planning without a separate retry mechanism.

The graph attribute `goal` supplies the objective, and agents run as multi turn LLM sessions with tool access rather than as single prompts.

There is also a natural language path: the README lists specifying requirements as natural language specs and letting Fabro generate, and regenerate, implementations that conform to them.

Model routing is a stylesheet, so a cheap model change is one line

The `model_stylesheet` block above is the routing mechanism, and it is the feature most likely to change how a team spends money on agents.

The syntax is CSS-like. A `*` selector sets the default model and reasoning effort, and a class selector overrides it. In the example every node runs on `claude-haiku-4-5` with low reasoning effort unless it carries `class="coding"`, in which case it runs on `claude-sonnet-4-5` with high reasoning effort. Planning therefore runs cheap and implementation runs expensive.

The README frames the benefit in two ways. One is cost: route cheap tasks to fast inexpensive models and reserve frontier models for the steps that need them, with a CSS-like stylesheet making it a one line change. The other is combining models from different vendors, using one model to implement, another to cross critique and a third to condense the result, all inside a single workflow. Fallback chains are automatic.

Per node reasoning effort is set independently of the model, which the example shows by putting `reasoning_effort="high"` directly on the plan node while the stylesheet sets low for everything else. So a workflow can ask a cheap model to think hard, which is not the usual trade.

The feature table also lists human in the loop behaviour beyond the gate shape: approval gates that pause for human decisions, the ability to steer running agents mid turn, and interview steps that collect structured input. Steering mid turn is the piece that addresses the original complaint about babysitting, since it means you are not forced to choose between approving at a gate and watching every step.

Git branches per stage are the audit trail

The checkpointing model is the part that makes Fabro different from a shell script that calls an agent.

Every stage commits code changes and execution metadata to Git branches, according to the feature table, which means you can resume, revert or trace any change. That is the answer to the fifty file diff problem: instead of one untrusted diff, there is a branch per stage, so the implement step can be reverted without losing the plan step.

Observability sits alongside it. The README describes durable events, checkpoints, conclusions and stage outputs that make every run inspectable and exportable, and lists queryable run artifacts among the use cases. The web UI shows runs across Working, Pending, Verify and Merge stages, which is a hint that the pipeline has a verify stage where deterministic checks live.

Those deterministic checks are described as layered into the workflow graph: test suites, linters, type checkers and LLM-as-judge, with failures triggering fix loops automatically. A fix loop is a cycle in the graph, so it is written the same way as the approve and revise loop above rather than as special case code.

Sandboxing is the other isolation claim. Agents run in isolated Daytona cloud VMs with snapshot based setup, network controls and automatic cleanup, and you can shell into a running sandbox with `fabro sandbox ssh` or expose a port with `fabro sandbox preview` for live debugging. The stated motivation is keeping untrusted code off your laptop and out of your production environment.

That last point has a cost implication. Fabro documents Daytona cloud sandboxes, but does not identify the pricing or document a local sandbox backend.

Four install routes and a browser setup wizard

Installation offers one route per agent tool you might already use, which tells you who the project expects to be using it.

bash
# With Claude Code
curl -fsSL https://fabro.sh/install.md | claude

# With Codex
codex "$(curl -fsSL https://fabro.sh/install.md)"

# With Homebrew
brew install fabro-sh/tap/fabro-nightly

# With Bash
curl -fsSL https://fabro.sh/install.sh | bash

The first two hand the install instructions to your agent rather than running them, so the agent reads the script and executes it under your supervision. The Homebrew tap is named `fabro-nightly`, which matches the release channel.

Setup then goes through `fabro server start`, which opens a web wizard in your browser and exits when the wizard completes. On the next run it starts in the configured mode. So first run is interactive by design and there is no documented non interactive configuration path in the README.

The packaging is a single compiled Rust executable with no runtime dependencies: no Python, no Node, no Docker required, per the feature table. The repository contradicts that slightly in spirit, since the tree contains `package.json`, `bun.lock` and `bunfig.toml` alongside `apps/` and `lib/packages/`, so the web UI is a separate front end even though the shipped server is one binary with an embedded UI. `Cargo.toml` lists `lib/apps/*`, `lib/components/*` and `lib/foundation/*` as workspace members with `lib/apps/fabro-cli` as the default member, and pins the server stack to axum 0.8, sqlx 0.9 with bundled SQLite, tokio, reqwest with rustls, git2 with vendored libgit2 and OpenSSL, and `rmcp`.

The `install.md`, `install.sh` and `installer/` files are all in the repository root, so the curl pipeline can be read before you run it.

Nightly channel, port 32276, and a Docker socket in the container

Three operational details are worth settling before you deploy this.

First, the release channel. Every visible tag is a nightly build: v0.385.0-nightly.0 on 2026-10-13, v0.386.0-nightly.0 on 2026-10-14 and v0.387.0-nightly.0 on 2026-10-15. The version in `Cargo.toml` matches the newest tag exactly, and the project has not published a stable release in that window. A daily version bump means your installed binary identifies itself as a build date more than as a release, so pinning by version string alone is weak. Pin a tag when you need a fixed version.

Second, the server surface. The `Dockerfile` serves the HTTP API with the embedded web UI on `$PORT`, defaulting to 32276, persists state to `/storage` and runs as the unprivileged `fabro` user with uid and gid 1000. The compose file maps `${FABRO_PORT:-32276}:32276`, mounts a `fabro-storage` volume at `/storage`, mounts `/var/run/docker.sock`, and health checks `http://127.0.0.1:32276/health` every ten seconds with twelve retries and a twenty second start period. The env file is optional, declared with `required: false`.

That Docker socket mount is the one item to think hardest about. Mounting the host Docker socket into a container that runs agents capable of writing code gives that container host level container control. It is a common pattern and a common risk, and it is not something the README discusses. If you deploy this, treat the socket as privileged and put it behind whatever isolation your environment already uses.

Third, the licence is MIT with the text in `LICENSE.md` and the same identifier in the workspace package table. The repository is not archived and the last push was on 2026-10-16, so development is active. Contribution guidance is in `CONTRIBUTING.md`, and the root also carries `AGENTS.md` and `CLAUDE.md`, so the project expects agent driven work on itself.

Editorial conclusion

Adopt Fabro if your team already runs coding agents unattended and wants verification gates, model routing and git history around them, and you can accept a nightly release channel. Do not adopt it for one off local edits, since the value is in the durable run history rather than the generation. Verify first which model providers and sandbox backend you will pay for, that the Homebrew tap or curl installer matches your platform, and that the port 32276 API and its /health endpoint fit your deployment, since the compose file mounts the Docker socket into the container.

Frequently asked questions

How do I install fabro?

Use curl -fsSL https://fabro.sh/install.sh | bash, or brew install fabro-sh/tap/fabro-nightly, or hand https://fabro.sh/install.md to Claude Code or Codex. Then run fabro server start to finish setup in a browser wizard.

How are workflows defined in fabro?

In Graphviz DOT. Nodes carry prompts and reasoning effort, shapes mark the start, exit and human approval gates, and edges express transitions including loops such as an Approve or Revise branch. Full syntax is in the DOT language reference.

Does fabro let me use different models for different steps?

Yes. A CSS-like model_stylesheet in the graph sets a default model and reasoning effort with a * selector and overrides them per class, so planning can run on a cheap model while coding runs on a frontier one. Fallback chains are automatic.

Can fabro agents be isolated from my machine?

Agents run in isolated Daytona cloud VMs with snapshot based setup, network controls and automatic cleanup, and you can enter a sandbox with fabro sandbox ssh or expose ports with fabro sandbox preview. The compose file also mounts /var/run/docker.sock into the server container.

How does fabro version its releases?

Through nightly builds only in the visible window, with tags v0.385.0-nightly.0, v0.386.0-nightly.0 and v0.387.0-nightly.0 on consecutive days in October 2026. The Homebrew tap is named fabro-sh/tap/fabro-nightly to match.

Official sources

  1. fabro-sh/fabro on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/fabro-sh-fabro.svg)](https://hysenlabs.com/projects/fabro-sh-fabro)

Was this useful?