Run the worker
The worker is a single script you run on a machine that has your repo checked out. It claims feedback from the queue, triages it, writes fixes with your own agent — Claude Code, Codex, or Gemini, and opens draft PRs — all locally, with your own credentials.
Prerequisites
Each of these must be on the machine's PATH:
- node ≥ 18
- git
- gh — the GitHub CLI, authenticated (gh auth login)
- your agent CLI — at least one of claude (Claude Code), codex (OpenAI Codex), or gemini (Gemini CLI), logged in. You only need the one you use.
Choose an agent & model
Pick the vendor and model per phase (triage vs. code) in Account → Models. Triage is cheap and runs on every item, so a fast model is plenty; code is where quality matters. The worker runs whichever CLI you've installed — fdbck stores no keys.
| Agent | Models | Sign in |
|---|---|---|
| Claude Code | Haiku 4.5 · Sonnet 5 · Opus 4.8 · Fable 5 | claude (your Claude subscription) |
| Codex | GPT-5.6 Luna · GPT-5.6 Terra · GPT-5.6 Sol | codex login (your OpenAI/ChatGPT account) |
| Gemini | 3.5 Flash · 3.1 Pro (preview) · 2.5 Pro | GEMINI_API_KEY from AI Studio |
“Default” in the Models panel lets the CLI pick its own model. The worker runs Gemini with --yolo --skip-trust so it can edit files in the throwaway worktree unattended — set GEMINI_API_KEY in the worker's environment (the browser OAuth flow is unreliable for headless use).
Download
curl -fsSL https://fdbck.app/fdbck-worker.mjs -o fdbck-worker.mjs
Configure
The worker reads ~/.fdbck/worker.json. Create it with your worker token and a map from each repo to its local checkout.
{
"apiUrl": "https://fdbck.app",
"token": "wt_your_worker_token",
"repos": {
"your-org/your-repo": "/abs/path/to/checkout"
},
"vendor": "claude",
"model": "claude-sonnet-5"
}- apiUrl — where the worker polls. Almost always https://fdbck.app.
- token — your worker token (wt_…) from Account → Local worker. Keep it secret.
- repos — map of owner/repo → absolute checkout path. The worker only acts on repos listed here.
- vendor — optional fallback agent if the dashboard pref is unset: claude | codex | gemini. Per-phase vendor and model are normally set in the dashboard.
- model — optional. Pin the model; omit to use your agent's default.
- verify — optional. Run your repo's tests/build in the isolated worktree before opening a PR.
trueauto-detects frompackage.json; or be explicit:{ "test": "pnpm test", "build": "pnpm build" }. A failed verify still opens a draft PR (flagged), but is never auto-merged.
Power users can override the exact command per vendor with a commands map, e.g. "commands": { "codex": "codex exec --sandbox workspace-write --cd {dir} -m {model} {prompt}" } — placeholders {prompt} {dir} {model} are substituted.
How your feedback is kept safe. Each job runs in a throwaway git worktree off your target branch — your real checkout is never touched. The user's feedback text is written to a data file the agent reads, never spliced into its instructions, so a malicious report can't hijack the run. Keep ~/.fdbck/worker.json owner-only: chmod 600 ~/.fdbck/worker.json.
Check the setup
Run doctor before your first real run. It validates the whole chain — config, tools, auth, and repo paths — and tells you exactly what's missing.
$ node fdbck-worker.mjs doctor
✓ Node ≥ 18 v20.11.0
✓ git on PATH
✓ gh on PATH
✓ claude on PATH vendor: claude
✓ claude logged in responded to a test prompt
✓ claude auth source your Claude subscription (CLAUDE_CODE_OAUTH_TOKEN)
✓ gh authenticated
✓ config valid ~/.fdbck/worker.json
✓ checkout: your-org/your-repo /Users/you/code/repo
✓ fdbck reachable + token valid https://fdbck.app (HTTP 204)
All checks passed. Start the worker:
caffeinate -is node fdbck-worker.mjsKeep it running
The worker only picks up feedback while it's running. Pick the form that fits the machine. For a real always-on deployment — start-on-boot, restart-on-crash, and logs across launchd, systemd, Docker, a home-lab VM, or a cloud VPS — see Run the worker 24/7.
macOS
caffeinate keeps the machine awake while the worker runs.
caffeinate -is node fdbck-worker.mjs
Linux — quick
nohup node fdbck-worker.mjs >fdbck.log 2>&1 &
Linux — systemd (user unit)
For a worker that restarts on its own, write ~/.config/systemd/user/fdbck-worker.service:
[Unit] Description=fdbck worker After=network-online.target [Service] ExecStart=/usr/bin/node /home/you/fdbck-worker.mjs WorkingDirectory=/home/you Restart=always RestartSec=5 [Install] WantedBy=default.target
Then enable it:
systemctl --user enable --now fdbck-worker loginctl enable-linger "$USER" # keep running after logout
Windows
node fdbck-worker.mjs
Is it running?
Open Account → Local worker. The status pill goes green while the worker is connected, and doctor's last successful check bumps it too. If it's grey, the worker isn't reaching fdbck — start it, or run doctor to find out why.
Staying up to date
The worker can replace itself with the latest build in one command — the download is verified (node --check + version probe) before it atomically swaps in:
node fdbck-worker.mjs self-update
If your build ever falls below the server's minimum supported version (a release with a known-broken bug), fdbck stops handing it jobs; the worker then self-updates automatically, exits, and asks to be restarted. Set FDBCK_NO_SELF_UPDATE=1 to opt out. Running from a source checkout? Self-update refuses and tells you to git pull instead.
Short of that hard floor, a worker that's simply behind the latest release keeps running fine and prints a one-line update available nudge on startup — it never force-updates. Run self-update when you see it.
Commands & flags
Run node fdbck-worker.mjs help any time for the full reference. The essentials:
# commands
node fdbck-worker.mjs # start + poll for jobs (the default)
node fdbck-worker.mjs doctor # validate your setup, pass/fail report
node fdbck-worker.mjs self-update # pull the latest build over this file
node fdbck-worker.mjs version # print the version
# flags
--once drain the queue then exit 0 (CI / GitHub Actions)
--verbose extra diagnostic detail (worktree path, changed files)
# environment
FDBCK_LOG_FILE=/path/worker.log tee every line to a file (plain text) — tail -f it,
or read it after a run that went sideways
FDBCK_VERBOSE=1 same as --verbose
FDBCK_NO_SELF_UPDATE=1 block automatic self-update
NO_COLOR=1 / FDBCK_ASCII=1 plain / ASCII-only outputFDBCK_LOG_FILE is the one to reach for when a job does something you didn't expect: it captures the full run — timestamped, colour-free — so you can inspect exactly what the agent touched after the fact, or tail -f it live.
Claude auth: subscription or API key
Both modes are fully bring-your-own — fdbck never sees either credential:
Subscription token (default)
Run claude setup-token once and export CLAUDE_CODE_OAUTH_TOKEN in the shell that starts the worker (put it in ~/.zshenv so non-interactive shells see it too). Usage rides your Claude plan.
API key
Export ANTHROPIC_API_KEY instead — usage bills per-token at API rates. Handy for CI (below) or for isolating worker usage from your interactive plan. doctor shows which source claude will actually use; when both are set, claude prefers the API key.
Run it in CI (GitHub Actions)
Laptop closed ≠ pipeline down: run the worker on a schedule in your own GitHub Actions. Still entirely yours — your CI minutes, your tokens, your agent. The --once flag drains the queue and exits, so a run with no pending feedback finishes in seconds.
# .github/workflows/fdbck-worker.yml
name: fdbck worker
on:
schedule:
- cron: "*/15 * * * *" # every 15 minutes
workflow_dispatch:
permissions:
contents: write # push fix branches
pull-requests: write # open draft PRs
jobs:
fdbck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install claude CLI
run: npm i -g @anthropic-ai/claude-code
- name: Download the fdbck worker
run: curl -fsSL https://fdbck.app/fdbck-worker.mjs -o fdbck-worker.mjs
- name: Configure
run: |
mkdir -p ~/.fdbck
cat > ~/.fdbck/worker.json <<EOF
{
"apiUrl": "https://fdbck.app",
"token": "${{ secrets.FDBCK_WORKER_TOKEN }}",
"repos": { "${{ github.repository }}": "${{ github.workspace }}" }
}
EOF
chmod 600 ~/.fdbck/worker.json
- name: Drain the queue
run: node fdbck-worker.mjs --once
env:
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# or: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GH_TOKEN: ${{ github.token }}Secrets to add in the repo settings: FDBCK_WORKER_TOKEN (Account → Local worker) and CLAUDE_CODE_OAUTH_TOKEN (from claude setup-token) or an API key. The workflow's own github.token covers pushing branches and opening PRs in the same repo. The local daemon and CI mode coexist fine — whichever polls first claims the job.
Open by design — read it before you run it
The file you download is the worker's complete source — one readable script, deliberately not minified or obfuscated. We're asking you to run a process on a machine that has your private code checked out, so you should be able to see exactly what it does. Open fdbck-worker.mjs in an editor, or run node fdbck-worker.mjs doctor to see every check it makes. It's small, it has no dependencies to vet, and the worker script itself only ever talks to two hosts: fdbck.app (to claim jobs and report results) and GitHub (via your own gh). The agent CLI it spawns reaches your model provider directly (Anthropic / OpenAI / Google), on your own key.
What it does
- Polls fdbck for one queued job at a time.
- Runs your own agent CLI (Claude Code, Codex, or Gemini) on your code.
- Works in an isolated git worktree, never your live checkout.
- Opens a draft PR with your own gh / git.
- Reports the result (files changed, PR link) back to fdbck.
What it never does
- Send your source code, diffs, or repo to fdbck — the agent runs entirely on your machine.
- Store or transmit your agent or GitHub credentials — fdbck holds none of them.
- Push, merge, or open a PR without the guardrails you set (review mode, auto-merge limits).
- Reach any host other than fdbck.app and GitHub.
- Hide anything — the whole script is right there to audit.
The clever parts of fdbck — triage classification, the auto-PR and auto-merge gates, PII scrubbing, the learning loop — all run on fdbck.app, not in this file. The worker is a thin client that runs your agent and reports back; it holds no secrets and makes no product decisions on its own.
Run it somewhere isolated — the agent has real power on the host.
To actually write fixes, the worker launches your agent CLI with broad permissions on the machine it runs on — Claude Code with --permission-mode bypassPermissions, Codex with --sandbox workspace-write, Gemini with --yolo. That means it can read files and run commands as the user that started it. And the work it acts on includes feedback text submitted by your users, which is untrusted. fdbck hardens this — the reporter's text is written to a data file the model is told to treat as untrusted, never spliced into its instructions — but a prompt-injection fence is a mitigation, not a hard security boundary.
So treat the worker like any process that runs code on your behalf: give it a home of its own. Run it on a dedicated machine, VM, container, or CI runner — not your daily laptop with your whole SSH agent and cloud creds loaded. Scope its gh/git credentials to just the repos it needs, and keep unrelated secrets out of its environment. The deployment recipes (container, VM, CI) are all good isolated homes.
The worker runs each fix in an isolated git worktree, so it never disturbs your working copy. It uses your own gh, git, and your agent credentials — nothing is stored on fdbck.