fabrik
Health Gecti
- License — License: Apache-2.0
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 11 GitHub stars
Code Gecti
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Drive Claude Code through an SDLC pipeline on your GitHub Project board — Specify → Research → Plan → Implement → Review → Validate. Human in the loop, or on it. A Go CLI for automated, issue-driven development. Docs → fabrik.handarbeit.io
Fabrik
Automated Claude Code SDLC driver powered by GitHub Issues and Projects.
Fabrik watches a GitHub Project board and drives Claude Code through configurable
workflow stages. Issues are the unit of work — the issue body is the spec, comments
are user input, and the board columns define the workflow.
📖 Documentation, guides, and examples → fabrik.handarbeit.io
Quick Start
Requires Go 1.26.1+, the Claude Code CLI, and a GitHub token with repo and project scopes.
# Install
go install github.com/handarbeit/fabrik@latest
# Initialize stage configs, plugin, and project config template
# Pass your GitHub Project URL to auto-populate owner, project, and owner_type:
fabrik init --user you https://github.com/orgs/your-org/projects/5
# Or run without a URL for full interactive prompts (TTY) / blank template (non-TTY)
fabrik init
# Creates .fabrik/stages/, .fabrik/plugin/, and .fabrik/config.yaml
# Edit .fabrik/config.yaml with your project settings (commit this file)
# Add your GitHub token to a gitignored .env:
echo 'FABRIK_TOKEN=ghp_...' >> .env
echo '.env' >> .gitignore
# Run (settings come from .fabrik/config.yaml)
fabrik
# Or override specific values with flags
fabrik --stages ./.fabrik/stages --yolo
Configuration summary:
.fabrik/config.yaml— non-secret project settings (commit to git).env— secrets only (FABRIK_TOKEN/GITHUB_TOKEN; must be gitignored)- Precedence:
CLI flag > env var > .env > config.yaml > defaults
Auto-upgrade
Use --auto-upgrade to have Fabrik self-upgrade at startup and when idle:
fabrik --auto-upgrade ...
At startup and after 2 idle polls, Fabrik upgrades itself automatically and re-execs:
- Release binaries: checks GitHub Releases for a newer version and downloads it.
- Dev builds (built from source via
go build): detects local or remote commits
ahead of the running binary and rebuilds in place fromorigin/main.
When Fabrik is upgraded, it also compares your .fabrik/stages/*.yaml files against the embedded defaults and prints a startup warning for any stage file that is missing fields added in the newer binary. Run fabrik refresh-stages --apply to add the missing keys, then review with git diff and commit. See Stage YAML Drift Warning in the User Guide for details.
Fabrik PM Plugin (Claude Code Companion)
Don't want to install the binary yet? You can still get value from Fabrik by installing the Fabrik PM plugin in your interactive Claude Code session. It gives Claude ambient awareness of your Fabrik-managed project so you can ask things like "what's on the board?", "why is #42 stuck?", or "what's in progress?" without leaving your editor.
Run these in any Claude Code session:
/plugin marketplace add handarbeit/fabrik
/plugin install fabrik@fabrik
/reload-plugins
After install you get:
fabrik:fabrikskill — auto-activates when.fabrik/is detected or Fabrik is mentioned. Provides ambient PM awareness of the board, stages, and stuck items.fabrik:fabrik-setupskill — one-time onboarding walkthrough for setting up Fabrik from scratch./fabrik:statuscommand — board snapshot: what's in each pipeline stage, which workers are running, which worktrees have uncommitted changes.
The PM plugin is independent of the engine — install it on its own to chat about a Fabrik-managed repo, or pair it with the binary for the full experience. See Install the Fabrik PM Plugin in the User Guide for details and upgrade instructions.
Distinct from
fabrik-workflows: the engine's stage skills are embedded in the binary and deployed automatically to.fabrik/plugin/byfabrik init. You do not — and should not — installfabrik-workflowsmanually.
How It Works
GitHub Project Board (source of truth)
| GraphQL poll
Fabrik (Go CLI, runs locally)
| stage config match
Claude Code (invoked per stage, in isolated worktree)
| output
GitHub Issue comments + labels + body updates
- Poll — Fabrik fetches the entire project board via a single GitHub GraphQL query.
- Match — Each issue's board status is matched to a stage config (YAML file).
- Worktree — An isolated git worktree is created for each issue (
fabrik/issue-Nbranch). - Invoke — Claude Code runs in the worktree with the stage's prompt, model, and tool configuration.
- Complete — When Claude signals completion, the issue is labeled
stage:<name>:complete. - Advance — In yolo mode, the issue auto-advances to the next stage. Otherwise, a human moves it.
Big-board efficiency (v0.0.57): On large project boards, the per-poll GraphQL cost drops ~5–10× via a lightweight
updatedAt-only probe that gates the full deep-fetch — only items that changed since the last poll trigger a full query. Terminal items (issues in a cleanup/Done column withstage:<name>:completeand no active lifecycle labels) are skipped entirely from both the probe and deep-fetch evaluation.Cold-start optimization (v0.0.58): On startup, closed Done items are seeded from probe data as terminal without a deep-fetch, reducing cold-start GraphQL cost by ~80–90%. Combined with probe-driven polling, this makes running two Fabrik instances on a single token budget practical.
Webhook Mode (Optional)
Fabrik can receive GitHub events in near-real-time (within ~2 seconds) instead of waiting for the next poll tick by spawning gh webhook forward as a background subprocess. Enable with --webhooks. With the default in-memory board cache active, the webhook stream also drives a reconcile-based health check (default every 3 minutes) that reduces full-board polling to at most once every 60 minutes.
Single-user constraint: GitHub allows only one active
gh webhook forwardsubscription per repository or organization at a time. Coordinate across your team so only one Fabrik instance runs with--webhooks; other instances can run without it and will still process issues via polling. See §10 of the User Guide for full setup, configuration, and troubleshooting details.
Merge Train & Merge Queue (Optional)
On a repo with strict branch protection, landing several ready PRs serially produces an O(N²) rebase-and-retest cascade — each merge invalidates every other ready PR's "up-to-date + green" status, forcing a rebase and a full required-check re-run before the next one can land. Fabrik solves this by batching ready PRs and validating the combined result once instead of retesting each one against every prior merge.
Two landing engines share one Queued board column, and Fabrik picks per repo:
- GitHub's native merge queue (ADR-058) — used automatically when the repo has one enabled (Enterprise Cloud or org-owned public repos). Kill-switch:
--merge-queue off. - Fabrik's internal merge train (ADR-059) — the plan- and host-agnostic fallback for private Team and personal-account repos where GitHub's native queue isn't available. It stages a trial branch per repo, runs one combined Validate, and lands the batch atomically; a red batch is isolated via halving bisection so a single poisoner doesn't block the rest. It is opt-in via
--merge-train on,FABRIK_MERGE_TRAIN=on, ormerge_train: onin.fabrik/config.yaml.
Native queue routing defaults to auto (it only engages on repos where GitHub's native queue is already enabled); the merge train defaults to off. Both leave the existing serial auto-merge path untouched unless explicitly turned on. See Merge Queue and Merge Train / Queued in the User Guide for setup (including the required Queued board column) and tuning knobs.
Comment Processing
When anyone comments on an issue in an active stage:
- Fabrik reacts with :eyes: to each new comment (marks as "in review")
- Adds
fabrik:editinglabel to lock the issue - Invokes Claude with a stage-specific comment review prompt
- Claude performs any requested actions (e.g., linking PRs, running commands)
- If the issue body needs updating, parses the updated body from Claude's output
- Updates the issue body on GitHub (or posts output as a comment)
- Removes
fabrik:editinglabel - Reacts with :rocket: to each processed comment (also used to skip already-processed comments on restart)
Comments from all authors trigger processing — human colleagues, code-review bots
(Copilot, Gemini), and other Fabrik instances alike. Only two categories are skipped:
comments that start with 🏭 **Fabrik (Fabrik's own output) and comments that already
carry a 🚀 rocket reaction (already processed).
This allows iterative refinement — comment to answer questions, provide feedback,
or steer the work, and Fabrik incorporates the input into the issue.
Review and Fix
Stages with post_to_pr: true (like the default Review stage) post detailed
output on the linked PR and a brief summary on the issue. The Review stage
also rebases onto the configured base branch and resolves merge conflicts before reviewing,
keeping the PR branch clean.
The Review and Validate stages ship with wait_for_reviews: true enabled by
default. When this option is set, Fabrik uses a three-phase reviewer gate
(re-invocation fires unconditionally; auto-advancement to the next stage still
requires auto-advance to be active):
- Always-gate: On stage completion, Fabrik adds
fabrik:awaiting-review
and holds auto-advance until the gate clears. - Gate evaluation: On each subsequent poll, Fabrik checks the dual
condition: no requested reviewers are outstanding and at least one
review has been submitted (this catches bot reviewers like Copilot and
Gemini that self-trigger via webhook without appearing in the formal
reviewer list). If the condition isn't met and the per-cycle timeout
expires, the issue pauses withfabrik:awaiting-input. - Re-invocation: When the gate clears and there are unresolved PR
review thread comments, Fabrik re-invokes the stage agent to address that
inline feedback and push a new commit, then waits for the next review
round. Reviews with no inline thread comments—including reviews with only
top-level review text (for example, bot approvals or summary-only
comments)—do not trigger re-invocation, and the issue advances normally.
After each re-invocation cycle, Fabrik posts a PR summary comment with a
per-thread footer listing how each inline review thread was addressed.
Configuration:
--max-review-cycles/FABRIK_MAX_REVIEW_CYCLES(default5)
caps the number of re-invocation cycles per session.--review-wait-timeout/FABRIK_REVIEW_WAIT_TIMEOUT(default15minutes) sets the per-cycle wait before
pausing. The env var is only consulted when the corresponding CLI flag is absent; if--review-wait-timeout=0or--max-review-cycles=0is explicitly passed, the
built-in default is used and the env var is bypassed. See
USER_GUIDE.md §10 for details.
The Validate stage also ships with wait_for_ci: true enabled by default. Fabrik gates auto-advance and, when applicable, auto-merge on CI checks passing; if checks fail, it re-invokes the stage agent with a structured CI-fix report to address new-regression failures. Non-required check_run failures do not block the gate — Fabrik trusts GitHub's mergeable_state as the authoritative merge-readiness signal, so only failures that branch protection itself considers blocking will prevent auto-merge.
If a stage doesn't complete (e.g., unfixable issues found), it retries after
a cooldown period rather than being permanently skipped.
Steering with Comments
Fabrik responds to natural language. Comment on an issue to steer the work:
- "Please link the PR to this issue" — Claude performs the action
- "Please process PR feedback on PR #18" — Claude reads the PR reviews and fixes the code
- "Let's use approach B instead" — Claude updates the plan accordingly
Each stage sees the full conversation history — previous stage outputs, user
comments, and all — so context carries forward through the pipeline.
Awaiting Input Notifications
When a stage needs user input (FABRIK_BLOCKED_ON_INPUT), Fabrik posts a🏭 **Fabrik** — @<user>: comment so GitHub delivers a mobile push notification
to the configured operator. For pushes to arrive, Fabrik must run as a different
account than the user being @mentioned — see
USER_GUIDE.md §Stages Waiting for Input
for setup details and the self-mention caveat.
In-Place Restart
Sending SIGHUP to the Fabrik process drains in-flight Claude runs, then
re-execs the binary in place — no terminal disruption, no lost state. Use it
to pick up a new binary after go install without restarting the session.
The terminal alt-screen is properly restored on signal-driven exit, so noreset is needed after a SIGINT, SIGTERM, or SIGHUP. Plugin-skills are checked and
refreshed non-interactively during restart when no local customizations are detected —
the process never hangs waiting for a prompt. When local customizations are present,
the refresh is skipped to preserve your edits and the [u] custom workflow badge
appears on next TUI startup instead, so operator customizations are never silently
overwritten. See
USER_GUIDE.md §Recovering from Wedged State
for the full escape-hatch procedure.
Default Pipeline
The example stages implement a full SDLC pipeline:
| Stage | Purpose |
|---|---|
| Backlog | Parking lot (no processing) |
| Specify | Refine rough issues into clear, unambiguous specs (Q&A with user) |
| Research | Explore codebase, identify scope, surface questions |
| Plan | Design approach, break into tasks, document decisions |
| Implement | Write code, tests, commit to issue branch |
| Review | Rebase, review, fix, and push to PR |
| Validate | Run tests, verify requirements met |
| Done | Terminal state (no processing) |
Stage Configuration
Each stage is a YAML file in your stages directory:
name: Research # Must match a Project board column name
order: 1 # Processing order (lower = earlier)
skill: fabrik-research # Plugin skill (recommended; alternative to inline prompt)
prompt: | # Inline prompt (used when skill is not set)
You are a research agent...
comment_skill: fabrik-research-comment # Skill for comment review (overrides comment_prompt)
comment_prompt: | # Inline comment-review prompt (used when comment_skill is not set)
You are reviewing user comments...
model: sonnet # Optional: claude model to use
max_turns: 50 # Optional: max conversation turns per stage invocation
comment_max_turns: 15 # Optional: max turns when processing user comments (default: min(max_turns,15))
read_only: false # Optional: stash/restore worktree; use for analysis stages (Specify, Research)
post_to_pr: true # Optional: post output on linked PR instead of issue
create_draft_pr: true # Optional: push branch and create draft PR before Claude runs
mark_pr_ready_on_complete: true # Optional: mark PR ready after stage completes
auto_advance: false # Optional: override global yolo setting for this stage
# true = always auto-advance; false = never; omit = inherit yolo
cleanup_worktree: false # Optional: remove worktree instead of invoking Claude (terminal stages)
disable_adaptive_thinking: true # Optional: disable Claude Code's adaptive thinking budget (default: true)
effort_level: high # Optional: Claude thinking effort: low, medium, high, max (default: high)
allowed_tools: # Optional: replaces the default tool set — not additive
- Read
- Grep
- Glob
completion:
type: claude # "claude" (default and only supported type)
Permission Posture
Every Claude Code invocation receives --permission-mode dontAsk and an explicit --allowedTools list. Tools outside the allowed set are silently denied — no interactive prompts. This means Fabrik works correctly in headless and shared environments without requiring users to pre-configure permissions in ~/.claude/settings.json.
When a stage omits allowed_tools, Fabrik uses a built-in default covering file operations, git, GitHub CLI, common build systems, and shell utilities. See §7 Permissions in the User Guide for the full list.
When allowed_tools is set, it replaces the default set entirely — it is not additive. Only the listed tools are permitted for that stage.
The fabrik:unrestricted label bypasses this posture entirely, passing --dangerously-skip-permissions instead. Use only when a stage needs tools outside the default set.
Configuration
Fabrik resolves settings in this order (highest to lowest priority):
CLI flag > shell env var > .env file > .fabrik/config.yaml > built-in default
Run fabrik init to generate .fabrik/config.yaml in your project. This file holds
all non-secret project settings and should be committed to git. See the
Configuration Reference in the User
Guide for a full field-by-field description with examples and defaults.
Secrets (GitHub tokens) belong in a gitignored .env file only:
# .env (gitignored — keep secrets here)
FABRIK_TOKEN=ghp_... # Preferred
GITHUB_TOKEN=ghp_... # Fallback
Safety: When a .git/ directory is present, Fabrik refuses to start if .env exists but is not listed in .gitignore (prevents accidental token leaks). In directories without .git/ — containers, CI workspaces, or bare directories — this check is skipped and .env is loaded normally.
Flags
| Flag | Description | Default |
|---|---|---|
--owner |
GitHub repo owner | required |
--repo |
GitHub repo name; omit for multi-repo mode | optional |
--project |
GitHub project number | required |
--user |
Your GitHub username | required |
--token |
GitHub token | $GITHUB_TOKEN |
--stages |
Stage configs directory | ./.fabrik/stages |
--yolo |
Auto-advance issues through stages without human approval; also auto-merges the linked PR when Validate completes | false |
--convergence-budget |
Wall-clock budget for post-Validate yolo PR convergence (Go duration: 30m, 1h; 0 disables the budget entirely; also FABRIK_CONVERGENCE_BUDGET) |
30m |
--auto-merge-strategy |
Merge method for GitHub native auto-merge on yolo PRs: MERGE, SQUASH, or REBASE (also FABRIK_AUTO_MERGE_STRATEGY) |
MERGE |
--auto-upgrade |
Self-upgrade from handarbeit/fabrik GitHub Releases at startup and when idle (after 2 idle polls) | false |
--poll |
Poll interval in seconds | 30 |
--notui |
Disable the interactive TUI dashboard | TUI on by default |
--max-concurrent |
Maximum number of concurrent issue workers | 5 |
--max-retries |
Max failed stage attempts before pausing the issue (0 = unlimited) | 3 |
--claude-wait-delay |
Seconds to wait after Claude exits before recovering buffered output when grandchild processes hold stdout pipe open (0 = use built-in default of 30 sec; env: FABRIK_CLAUDE_WAIT_DELAY). Prevents worker goroutines from blocking indefinitely when Claude uses run_in_background or the Monitor tool. |
0 (30 sec) |
--review-wait-timeout |
Minutes to wait per reviewer-gate cycle before pausing. Explicitly passing 0 uses the built-in default of 15 and bypasses FABRIK_REVIEW_WAIT_TIMEOUT. When absent, FABRIK_REVIEW_WAIT_TIMEOUT is consulted first; falls back to 15 if unset. |
0 |
--max-review-cycles |
Max re-invocation cycles per reviewer-gate session. Explicitly passing 0 uses the built-in default of 5 and bypasses FABRIK_MAX_REVIEW_CYCLES. When absent, FABRIK_MAX_REVIEW_CYCLES is consulted first; falls back to 5 if unset. |
0 |
--max-rebase-cycles |
Maximum rebase re-invocation cycles per issue before pausing (0 = default 3; also FABRIK_MAX_REBASE_CYCLES) |
0 (3 cycles) |
--max-enqueue-cycles |
Maximum merge-queue re-enqueue cycles per issue before pausing (0 = default 5; also FABRIK_MAX_ENQUEUE_CYCLES) |
0 (5 cycles) |
--merge-queue |
Merge queue routing for the yolo path: auto (enqueue when the repo requires GitHub's native merge queue) or off (skip enqueue; direct merge may fail on queue-required repos; also FABRIK_MERGE_QUEUE) |
auto |
--merge-train |
Fabrik-internal merge train (ADR-059): on advances yolo Validate completions into the Queued column for batched landing with a single combined Validate, or off to keep the existing per-PR auto-merge path (also FABRIK_MERGE_TRAIN) |
off |
--max-train-trials-per-window |
Merge-train runaway guard: maximum trial-branch creations with zero successful lands within the window before pausing all Queued members (0 = default 20; also FABRIK_MAX_TRAIN_TRIALS_PER_WINDOW) |
0 (20) |
--train-trial-window |
Merge-train runaway guard: rolling window in minutes over which --max-train-trials-per-window is measured (0 = default 60; also FABRIK_TRAIN_TRIAL_WINDOW) |
0 (60 min) |
--debug-output |
Save Claude stage output to .fabrik/debug/ for debugging |
false |
--symlink-env |
Create a relative symlink at <worktree>/.env pointing to the fabrikDir .env at worktree setup time. Enables stage code to read project secrets without copying them. Also FABRIK_SYMLINK_ENV. |
false |
--plugin-dir |
Path to Fabrik plugin directory (overrides installed plugin) | "" |
--webhooks |
Enable real-time webhook event delivery via gh webhook forward (requires cli/gh-webhook extension; also FABRIK_WEBHOOKS) |
false |
--reconcile-interval |
Seconds between periodic light-reconcile health checks when webhooks are enabled (0 = default 180; also FABRIK_RECONCILE_INTERVAL) |
0 (180 s) |
Prerequisite for yolo auto-merge: GitHub's
allow_auto_mergesetting must be enabled on the repository before Fabrik can enable native auto-merge on yolo PRs. Enable it under Settings → General → Pull Requests → "Allow auto-merge", or run:gh api -X PATCH repos/{owner}/{repo} -F allow_auto_merge=trueFabrik emits a
[startup] WARNINGif this setting is disabled on any managed repo.
Releases: New releases are announced in the handarbeit/fabrik Discussions "Announcements" category after each successful release.
Subcommands
| Command | Description |
|---|---|
fabrik init |
Initialize .fabrik/stages/, .fabrik/plugin/, and .fabrik/config.yaml in the current repo |
fabrik watch <issue-number> |
Open a real-time TUI for a single issue — live Claude output, stage history, PR/CI status |
fabrik stream-filter |
Read NDJSON Claude output from stdin and render it as human-readable text |
fabrik resume <issue-number> |
Resume an interrupted Claude session for an issue |
fabrik upgrade |
Self-update the Fabrik binary (release builds) and refresh plugin skills in .fabrik/plugin/ from embedded defaults. Plain fabrik upgrade errors when local customizations are detected; use --force to overwrite unconditionally or --reconcile for a guided merge prompt. See the User Guide for details. |
Built-in Skills
Fabrik ships two user-invocable Claude Code skills (type /skill-name in any Claude Code session in the Fabrik repo):
| Skill | Description |
|---|---|
/cut-release |
Pre-flight checks, curated release notes, commit/tag/push, and auto-files a doc-update issue — see §5 of the User Guide |
/audit-documentation |
Scans recently shipped issues, identifies documentation gaps, closes covered issues, and files new gap issues — see §5 of the User Guide |
Operator customizations to built-in skills are protected — upgrades detect local edits and offer guided reconciliation rather than silently overwriting. See Upgrade protection for customized skills.
The main Fabrik dashboard (enabled by default; disable with --notui) shows a live turn counter ([N/M turns]) for each active job in the In Progress pane.
fabrik watch
Monitor a single issue in real time without running the engine:
fabrik watch 42
# or with explicit credentials if not in .fabrik/config.yaml:
fabrik watch 42 --owner myorg --repo myrepo
The watch TUI displays: issue title and labels, live Claude output (streamed from the log file), stage history with duration and cost, linked PR status, CI check results, and comment count. Press i to open an interactive Claude session in the issue's worktree (resumes the current stage's session). Press q to exit.
Labels
Fabrik uses labels to track state:
| Label | Purpose |
|---|---|
fabrik:locked:<user> |
Issue is being processed by this user's Fabrik instance |
fabrik:editing |
Issue body is being updated (prevents concurrent processing) |
fabrik:paused |
Issue is skipped entirely — no stage processing or comment processing occurs |
fabrik:awaiting-input |
Stage is paused waiting for user input; auto-clears when a new comment from the configured user (--user) is received |
fabrik:blocked |
Issue is waiting for one or more blocking issues to close; managed automatically by the engine |
fabrik:awaiting-review |
Applied optimistically by the engine whenever a wait_for_reviews: true stage completes (reviewer request data may still be stale at that moment); removed when no requested reviewers are outstanding and at least one review has been submitted (the dual condition catches bot reviewers like Copilot and Gemini that self-trigger via webhook without appearing in the formal reviewer list), or when the reviewer-wait timeout elapses as a fallback (--review-wait-timeout / FABRIK_REVIEW_WAIT_TIMEOUT), at which point the issue is paused with fabrik:awaiting-input |
fabrik:awaiting-ci |
Applied immediately when a wait_for_ci: true stage emits FABRIK_STAGE_COMPLETE; means "CI gate active" and covers both pending and failed CI states; stage:X:complete is deferred until CI passes (conjunctive gate). Triggers cache bypass so CI results are re-evaluated on every poll. Cleared when all checks pass or the CI wait timeout elapses, at which point the issue is paused with fabrik:awaiting-input |
fabrik:rebase-needed |
Applied when GitHub reports the linked PR as mergeable: false on a wait_for_ci: true stage (usually triggered by another PR merging into the base branch while this branch sits in the CI-await window); the engine dispatches a rebase re-invocation for Claude to resolve the conflict, and the label is cleared when the rebase lands and the PR becomes mergeable again |
stage:<name>:complete |
Stage has been completed |
stage:<name>:in_progress |
Stage is actively running |
stage:<name>:failed |
Stage hit max retries and was paused |
model:<name> |
Use this model for the issue (e.g. model:opus overrides the stage YAML default) |
effort:<level> |
Override thinking effort for this issue only — valid values: low, medium, high, max; precedence: max > high > medium > low. Complements model: label. |
fabrik:yolo |
Force auto-advance even when auto_advance: false; also triggers auto-merge of the linked PR when Validate completes |
fabrik:auto-merge-enabled |
Applied when Fabrik enables GitHub's native auto-merge on a yolo PR after Validate completes; serves as the idempotency guard and convergence-budget start anchor; removed when the PR merges or is closed |
fabrik:cruise |
Auto-advances through all stages like fabrik:yolo but stops at Validate — no auto-merge, no move to Done. If both fabrik:cruise and fabrik:yolo are present, fabrik:yolo takes precedence. |
fabrik:unrestricted |
Pass --dangerously-skip-permissions to Claude Code for this issue only, bypassing the default --permission-mode dontAsk posture and the entire tool allowlist. Use only when a stage needs tools outside the default set (e.g. deno, bun, or other non-standard toolchains). Caution: removes all tool restrictions. |
fabrik:extend-turns |
Pre-grant 2× max_turns budget for the next invocation; auto-extends to 3× when stage progress is detected; auto-removed on successful stage completion. |
fabrik:revalidate |
Force re-entry of the Validate stage — the engine clears stage:Validate:complete, stage:Validate:failed, fabrik:paused, fabrik:awaiting-input, fabrik:awaiting-ci, fabrik:auto-merge-enabled, and itself, then re-runs Validate on the current HEAD SHA. Use as a one-action recovery for stuck-Validate, or as the manual fallback for items that completed Validate before SHA-change auto-revalidation was deployed. |
base:<branch> |
Override the base branch for this issue — Fabrik forks from, rebases onto, and targets PRs at <branch> instead of the repository default. Must be set before Research. If the branch does not exist on the remote, Fabrik falls back to the default branch and posts a comment. |
Multi-User
Multiple people can run Fabrik against the same project board. Stage work is scoped
to each instance's --user — an instance only picks up and runs stages for issues
locked to its configured user. Comment processing, however, is any-author: comments
from colleagues, bots, and other Fabrik instances all trigger processing regardless
of who wrote them. Labels provide lightweight locking to prevent conflicts.
Git Worktrees
Fabrik always bare-clones each managed repository on first access. Run Fabrik from any directory — no need to be inside a git checkout of a managed repo:
- Repos are discovered lazily from project board items
- Each repo is bare-cloned to
.fabrik/repos/<owner>-<repo>.giton first access - Each issue gets an isolated worktree at
.fabrik/worktrees/<owner>-<repo>/issue-N/on branchfabrik/issue-N - One worktree manager per discovered repository handles its own lifecycle
This means:
- Multiple issues can be worked on simultaneously without conflicts
- Each issue's changes are on their own branch, ready for PR
- Worktrees persist across polls for Claude session continuity
mkdir my-fabrik-dir && cd my-fabrik-dir
fabrik init
fabrik --owner myorg --project 5 --user me
# Fabrik bare-clones each repo as needed into .fabrik/repos/
Omitting --repo (or leaving repo: commented out in .fabrik/config.yaml) enables multi-repo mode — Fabrik processes all repos discovered on the board. Pass --repo owner/repo to restrict processing to a single repository.
.fabrik/repos/ is gitignored by default — bare clone directories are large and should not be committed.
SSH vs HTTPS
By default, Fabrik bare-clones repos using HTTPS. To use SSH instead ([email protected]:<owner>/<repo>.git), pass --ssh or set git_ssh: true in .fabrik/config.yaml. The FABRIK_GIT_SSH=true environment variable is also supported.
If no git credential helper is configured, Fabrik prints an advisory warning at startup (non-fatal) directing you to configure one or switch to SSH. Existing bare clones are not re-cloned when you change this setting — only new clones are affected.
See USER_GUIDE §3 — Git Clone Protocol (HTTPS vs SSH) for full details.
Formations
Fabrik supports dependency-based sequencing of issues using GitHub's native "Blocked by" relationships. A formation is a coordinated set of issues that execute in parallel where possible and respect ordering constraints automatically — no polling, no manual unblocking.
When all blocking issues are closed, Fabrik guarantees re-evaluation of a blocked issue within ~10× the poll interval (~5 minutes at default settings), then resumes it automatically once dependencies are satisfied. The fabrik:blocked label is managed entirely by the engine (created on first use, no pre-creation needed). The first stage (Specify) always runs regardless of blockers, so an entire formation can be fully specified before execution begins.
Recipe: file issues → add blocked-by edges in GitHub → label all fabrik:yolo → move to Specify → watch it run.
Plan can also decompose an oversized issue autonomously. It emits FABRIK_SPAWN_CHILD_BEGIN/END blocks in its output declaring each sub-issue to create; when the parent advances to Implement, the engine's preImplement step creates each child issue in its target repo, adds it to the board, and links it as a blockedBy dependency of the parent. The sub-issues then flow as a formation automatically.
Validated on the Ambient project: 9 issues, 4 parallel starts, 7 dependency edges — all pipeline constraints respected automatically, ~88 minutes wall-clock, $31 total cost.
See the USER_GUIDE §3 — Dependency-Based Sequencing (Formations) for the full recipe, diagram, and behavior callouts.
When an issue reaches Done, it remains on the board in the Done column. Auto-archive is currently disabled — it was removing items from the board before users could see them. It will be re-enabled once the timing logic is reworked to track actual Done stage completion time.
The Self-Evolving Factory
Fabrik is used to develop Fabrik. Issues filed against this repo go through
the same Specify → Research → Plan → Implement → Review → Validate pipeline that Fabrik
orchestrates. When we filed an issue to add PR comment processing, Fabrik
researched its own codebase, planned the GraphQL changes, and will eventually
implement the feature that lets it read PR comments — gaining a capability it
needs by building it for itself. Ouroboros-as-a-service.
The human's role is product manager, architect, and UX designer all in one:
file issues, answer questions when the Research stage surfaces them, drag cards
across the board, and occasionally comment "please process PR feedback" when
Copilot has opinions. The factory does the rest.
Migration from ./stages
If you used Fabrik before v0.2, your stage configs were in ./stages (the old default)
or ./stages/mystages/ if you used that convention.
mkdir -p .fabrik/stages
# If you used the default ./stages path:
cp ./stages/*.yaml .fabrik/stages/
# If you used ./stages/mystages/:
cp ./stages/mystages/*.yaml .fabrik/stages/
# Or keep the old path by setting FABRIK_STAGES in your .env:
# FABRIK_STAGES=./stages
Documentation
- User Guide — full configuration reference for the pre-v0.2
./stagesworkflow (see "Quick Start" and "Migration from./stages" above for the current./.fabrik/stagesdefault), workflow patterns, stage details, labels, and troubleshooting - State Machine — authoritative spec for engine state transitions, label semantics, and review gate behavior
- Troubleshooting — common issues: plugin conflicts, PID lock, merge conflicts, max turns, and more
Architecture Decision Records
See adrs/ for documented decisions and their rationale. Of particular note:
- ADR-058: GitHub Merge Queue Integration — native queue auto-detection and routing, killing the O(N²) rebase-and-retest cascade on queue-enabled repos.
- ADR-059: Fabrik-Internal Merge Train — the plan/host-agnostic batched-landing fallback for repos where GitHub's native queue is unavailable.
Requirements
- Go 1.26.1+
- Claude Code CLI installed and authenticated
- GitHub classic personal access token (
ghp_...) withrepo,project, andworkflowscopes- Fine-grained tokens (
github_pat_...) are not supported — GitHub Projects v2 GraphQL requires a classic PAT - Create one at: https://github.com/settings/tokens (select "Tokens (classic)")
- Fine-grained tokens (
- A GitHub Project (v2) with board columns matching your stage names
License
Apache License 2.0. Contributions are accepted under the same license (see CONTRIBUTING.md) — no CLA required.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi