Installation
CLI (recommended)
One command installs the plugin, opens your browser to log in, and launches/bitfab:setup:
--prompt (or -p) to send it straight to the agent:
claude auth login first.
For the experimental terminal-native flow, run
npx bitfab-cli init --v2 instead. It keeps setup choices and tool permissions in the CLI and uses the Claude Agent SDK directly. Set ANTHROPIC_API_KEY or configure a supported Agent SDK cloud provider first. Use npx bitfab-cli setup --v2 instrument to run one setup mode, or add --diagram to print its declarative state graph without starting the agent.Plugin installation
To do the same three things yourself:1
Add the Bitfab plugin marketplace
A plugin marketplace is a catalog of plugins you can browse and install into Claude Code. Add Bitfab’s so the
bitfab plugin is available to install.- Terminal
- Claude Code
2
Install the plugin
Install
bitfab from the marketplace you just added.- Terminal
- Claude Code
3
Run setup
Start Claude Code and run setup to log in and instrument your codebase. If you installed from inside Claude Code and the summary asks for it, run
/reload-plugins first.What the Plugin Does
Automatic Setup
The/bitfab:setup command runs a multi-phase workflow:
- Login — Opens your browser for OAuth authentication, saves credentials securely
- Explain — Walks through opt-out
withTrace/trace,withNode/node, supportedwithSpanfallbacks, and replay, including the five ways replay can change a method’s execution. Everything after this asks you to make per-method decisions, so it comes first - Approach — Asks whether the agent should walk you through instrumenting or hand you the docs so you can do it yourself
- Instrument + Replay (in parallel, per workflow) — Reads your codebase, finds all AI workflows (LLM calls, agents, AI-driven decisions), and presents them as a numbered list. You choose which to instrument, or name a file, function, or directory yourself and it reads only that instead of scanning. Either way it adds tracing with minimal diffs and creates a registry module for the replay command shipped with the SDK
MixedTracingError as a reason to stay opt-in. Before converting a shared helper, it checks every production caller so existing opt-in callers keep a separate surface; TypeScript node wrappers also use named functions as required by withNode. A TypeScript client that uses a dedicated organization or environment key also gates captureEnabled on that key being present, so an empty value cannot fall back to an unrelated BITFAB_API_KEY.
You can run individual phases:
Assistant
The/bitfab:assistant command turns production traces into code improvements, whether the goal is correctness (improving pass rates) or efficiency (cutting token usage and cost). Your agent will do the mechanical work and collaborate with you on three steps:
- Build a dataset from production traces — search for failures, label them with expected outcomes
- Experiment against that dataset — make isolated code changes, replay, compare results
- Hill climb — repeat until the best change is found, then present results
Building the Dataset
Your coding agent does the data wrangling — it searches production traces for failures, reads full inputs and outputs, and identifies edge cases. It then presents edge cases for your judgment: is this a failure (and what should the output be), correct, or irrelevant? This labeled dataset becomes the benchmark for all experiments. The plugin opens a rich UI for navigating and labeling the dataset, then brings you back to your coding agent so you stay in flow. You can label every trace yourself, or label a few and let the agent classify the rest based on the patterns you’ve established.Running Experiments
The command reads your code, diagnoses failure patterns, and categorizes proposed changes:- Code fixes — deterministic bugs, bundled into one experiment as a foundation
- Judgment-based fixes — prompt changes, search tuning, output formatting — each gets its own experiment
- Infrastructure proposals — larger changes noted for future work, not experimented on
Results
After each round, you see which traces now match expected outcomes, which still diverge, and whether any regressions occurred. The assistant works through the planned experiments in turn without pausing to ask whether to keep going, then wraps up once the plan is complete. The final summary shows pass rate improvement and all files changed, uncommitted in your working tree for review.MCP Tools
The plugin registers MCP tools that Claude Code can call during conversations. These let you inspect traces, manage datasets and labels, run experiments, and improve your code without leaving the editor. If a tool call includes a parameter that the installed plugin does not support, Bitfab ignores only that parameter and continues the call with the supported ones. The result includes a warning that names each ignored parameter and the receiving plugin version. Update the plugin before relying on those parameters.Core
get_bitfab_api_key
Retrieve your API key for SDK initialization and environment variable configuration.
get_api_key_context
Returns which Bitfab org the plugin reads/writes to (it can differ from the project’s BITFAB_API_KEY and from the org open in Bitfab). Call before the first plugin write of a session, or when data you wrote isn’t visible in Bitfab.
list_organizations
List the Bitfab organizations available to the signed-in user, marking the current plugin org.
list_organization_members
List the people in the current organization with their names and emails. Read it before save_trace_assertions when routing an assertion to a reviewer, so assigneeEmail carries an address someone actually holds: an email belonging to nobody in the organization fails that call.
get_database_connection_status
Reports whether the org has a database connected for per-trace replay branching (none, checking, connected, or failed) and identifies it as direct Neon or a managed Postgres mirror. For direct Neon connections, the response also includes the pinned project name and ID. Used by /bitfab:setup db-snapshot to tell when the branchable copy is ready.
Trace Inspection
list_trace_functions
List all traced functions in your organization.
search_traces
Search and filter traces with full-text search, date ranges, status filters, regex matching, environment, and label filters. Find a trace by the title your code gave it with name (matching its words in order) or nameContains (matching any fragment of at least 3 characters), and by the key and value pairs setMetadata recorded with callerMetadata (matching exactly, up to 10 pairs). All three ignore case and combine with every other filter. Supports drill-down to narrow results progressively. Replay traces are excluded by default; set includeReplays to include them, or filter by experimentId to scope to a specific experiment’s replay traces and enable them automatically. Filter by datasetId to scope to a specific dataset, or by hasDbSnapshot to scope to traces that captured (or lack) a database snapshot reference.
get_traces
Read one or more traces by ID with the trace environment plus summary (truncated) or full span details (input, output, reasoning, context, errors, per-span duration, tokens, and model).
Spans come back 50 per trace at a time, and the whole response stays under a fixed size so it fits in your agent’s context. When a trace has more spans than that, the response lists every span name and span type with how often each appears and says where the next page starts. By default, any span field over 10,000 characters is left out and replaced by its size, so read it with get_span_field. Pass spanNames to see only the spans you care about, spanTypes to see only spans of some types (["llm"] for the model calls), spanFields to see only some fields (an empty list gives just each span’s name, ID, and timing), and spanOffset / spanLimit to page.
get_trace_labels
Read just the labels for one or more traces by ID: each trace’s pass/fail verdict, annotation, saved { spanId, text } evidence, and whether the label is human-validated, followed by one indented line per scored assertion carrying that assertion’s own verdict, annotation, evidence, confidence, and author. A verdict written per assertion reads back per assertion, not as a tally. No span content is loaded, so one call accepts up to 100 IDs, ideal for loading a whole dataset’s verdicts at once.
generate_label_evidence
Discover suggested evidence for an assertion on a selected original or replay trace. The assertion must belong to that trace or be inherited through its replay lineage. The selected trace is narrowed to relevant spans before each candidate is enriched with spanId, text, spanName, signature-only parameters (names and runtime types, never values), spanType, and isMocked. Saved { spanId, text } evidence remains available through get_trace_labels.
get_grader_labels
Read the individual verdicts each grader recorded, one row per grader per trace, with the grader’s reason, its failure diagnostic, the confidence, and whether the verdict came from a human, a grader Bitfab ran, or an external grader. Pass trace IDs to see every grader’s verdict on those traces, or a grader ID to see that grader’s most recent verdicts across traces.
save_grader_labels
Post pass/fail verdicts for external graders: graders you run yourself, in your own eval harness, CI, or review queue, that Bitfab never runs. Each verdict names the grader, the trace, and pass or fail, with an optional reason, failure diagnostic, and confidence. The verdicts show up in dataset and experiment pass rates exactly like a grader Bitfab ran. Create the grader first with save_grader and external: true.
get_span_field
Fetch the complete, untruncated value of a single span field (input, output, reasoning, content, errors, or contexts) when get_traces truncated it or left it out. Pass the trace ID, the span’s [ID: ...], and the field name. A field longer than 32,000 characters comes back in parts: each response says which offset reads the next one.
get_span
Read one span from its span ID alone, with no trace ID. Pass Bitfab’s span ID or the span ID your code’s SDK sent. The response names the trace and traced function the span belongs to and shows the span’s output. A span it cannot find names the organization it searched, since a span recorded in another organization reads as not found.
Labeling and Datasets
save_agent_labels
Set, skip, abstain on, or archive the agent’s pass/fail verdict on a trace’s assertions. An abstention (abstain: true) says the evidence does not show the part of the run the assertion checks; it counts as a fail in every pass rate but reads back apart from one, as judge coverage. Supports confidence levels (VeryLow through VeryHigh), annotations shown to human reviewers, and optional { spanId, text } evidence grounded in the evaluated trace. Every verdict and skip scores one approved assertion and carries its assertionId; labels are never written directly on a trace, so a trace with no approved assertions needs assertions before it can be labeled. An archive may omit assertionId to clear an old whole-trace agent verdict. A verdict counts as soon as it is written; there is no approval step, and a person can override it with their own label.
save_human_labels
Write a validated human pass/fail verdict on one or more of a trace’s approved assertions, with an annotation and optional { spanId, text } evidence grounded in the evaluated trace. Every entry carries the assertionId it scores, one verdict per assertion; labels are never written directly on a trace. Unlike save_agent_labels, these labels count as validated the instant they’re written. Used by assistant fix, which first adds and approves an assertion for the bug when the trace has none, before adding the failing trace to a dataset once the fix is verified.
save_trace_assertions
Record what a trace SHOULD do the next time it is replayed. Each assertion is one statement of the answer the trace settles, with its real names, dates, times, and amounts, never a condition such as “if the meeting is booked” or a pointer such as “the times the user approved”. It comes with optional pass/fail criteria, an optional target scoping the check to the trace’s output or to a single span by name, and an optional people-only humanNote, and an optional assigneeEmail naming the member who should review it. The note can be created or edited through this tool but is never assessment evidence. Assigning routes the assertion to a person without deciding anything, so it leaves the approval state alone. A new assertion is saved awaiting review, so nothing checks it yet; once a person approves it in Bitfab, every later replay of the trace is judged against it. Distinct from a verdict, which judges a run that already happened: a trace holds at most one verdict per author and any number of assertions.
approvalState records a review decision on an assertion that already exists: approved, rejected, or pending, which reads as not reviewed. Deciding one is { id, approvalState } on its own, because omitting assertion preserves the stored wording. A decision needs that id, so it is refused on a new assertion: putting a claim into force is never the same call that wrote it. Approval is what decides whether replays check the assertion at all, so read the assertion and the spans it cites before deciding. Rewording an assertion, or changing its criteria, target, or category, returns it to not reviewed unless the same call decides it. The approver recorded is the owner of the API key the call was made with, so an approval means a second author looked, never that a person did.
generate_trace_assertions
Generate assertion drafts from one original trace and the organization’s existing categories. Pass optional guidance, such as a root cause analysis, to focus the evidence and produce smaller assertions, and categoryIds to limit generation to those assertion categories. Generation runs on Bitfab and the tool waits up to four minutes for it. If it is still running after that, the tool says so, and calling it again checks on it without starting a second generation. The first generation saves drafts awaiting human review. Later calls reuse that result unless regenerate is true, which archives the prior generated drafts and replaces them without touching human-authored assertions. get_trace_assertions also reports each trace’s generation status. Read the drafts back with get_trace_assertions and approvalStates: ["pending"].
get_trace_assertions
Read the assertions on up to 100 traces by ID, with no span content. By default only assertions a person has approved come back, because only those are checked on a replay; a trace whose assertions are all still awaiting review reads the same as one with none. Pass approvalStates to read other review states: pending for drafts awaiting review, including the ones generate_trace_assertions saved, and rejected for ones turned down. Each unapproved assertion is marked as not checked on replays. Reads include each people-only human note so an agent can preserve or edit it, but the note is never assessment evidence, and each assertion’s assignee. Call it before judging a replay so the verdict is measured against what the user actually asked for. A replay carrying none of its own reads its original trace’s assertions and is told which trace they came from.
list_trace_assertions
Find assertions across traces by review state, optionally narrowed to one traced function or one category, without knowing which traces carry them. Pass approvalStates: ["pending"] to read the review queue, including drafts generate_trace_assertions saved. Each result names its trace and carries the same fields get_trace_assertions returns. Results come newest first, one page at a time, and the first page reports how many assertions are in each review state. The cursor holds its place, so approving or rejecting the assertions on a page before reading the next never skips any.
archive_trace_assertions
Retire one or more assertions on a trace so later replays stop checking them. Archiving is non-destructive: the row is hidden from reads and kept for audit, and verdicts already recorded against it are untouched. The call is all-or-nothing, so one unknown, already-archived, or wrong-trace id fails it and archives nothing.
get_scenario
Read one scenario, found by scenarioId or by a traceId it was built from (send one, not both): the situation the trace function’s run was in, as the trigger that started the run and the data available when it arrived, with a name and a description. It describes the situation only, never what the run did or should do. Returns the trigger and data summaries, then the actual outcome when one was saved, then the name, description, trigger, data, and actualOutcome as JSON in exactly the shape save_scenario accepts. Call it before save_scenario so an edit starts from what is saved.
save_scenario
Create or update one scenario.
To save the records your own system holds for a run, send its traceId with records, or with recordsPath naming a local JSON file (an array of records, or an object with a records array). The plugin reads the file and sends its records, so they never pass through the conversation. Each record is { kind, ref, at, asOf, title, text, quote }. Create the scenario first by sending records as an empty list: Bitfab builds only the trigger from the trace, and the data starts empty, with no records. The data holds only what you send afterwards, because a trace shows what happened in the run, not all the data your system held when it ran. So far it builds scenarios only for traces of Noah’s noah-agent-turn function, and refuses any other trace with no scenario. Check that the returned trigger is not empty before sending records. Records that are not empty are refused for a trace with no scenario yet, and for a scenario whose trigger is empty. Bitfab looks for each record’s quote, and failing that its text, in the inputs and outputs of the trace’s spans. A record found in a span cites that span and can back an assertion; a record found in no span is kept as context the run never saw. To say where the records came from, send sources beside records: { frameAt, capturedAt, windows, coverage }, the block Noah’s scenario builder writes. When the recordsPath file is an object holding those fields, the plugin sends them as sources for you. coverage gives each kind of data its capture status (rewound-to-frame is as of the run, current-at-capture is as of capture, not-recorded and unavailable mean not captured) and filledColumns, the columns the capture predates. The scenario page and get_scenario then show, for each kind, how many records were kept and whether it was read in full as of the run, cut by a window, captured as of capture, missing columns, or not captured at all. Drafted assertions never treat a record missing from a kind that was not read in full as proof it did not exist.
Records and their sources replace the saved ones whole (records sent without sources clear the saved sources), need traceId rather than scenarioId, and cannot be sent with any other field. A trace that is a replay is refused.
To edit a scenario that already exists, find it by scenarioId or by a traceId it was built from (send one, not both), for example to add history the run had available, record data it was missing, or correct the trigger. name, description, trigger, and data each replace the saved value whole, and fields left out are kept. To add to the data without resending it, use appendData instead of data: its history entries go after the saved ones and its missing items after the saved missing items, and appends made at the same time all land. Send data or appendData, not both. A history entry’s source names the span its text came from, on any trace linked to the scenario (including the traceId you sent); leave it out when the text is not in such a trace, and a source naming a span on any other trace is refused. The trigger and data summaries are rebuilt from what is saved. An edit to a trace with no scenario, or to an unknown scenarioId, is refused. Returns the saved scenario. To record what the run actually did, send actualOutcome as { summary, actions, source }: a summary in a few sentences and the actions it took, in order, each { name, details, result, failed, at }, read from the trace. It is shown below the trigger as one example, never as what the run should have done. Bitfab never fills it, and null clears it.
generate_scenario_assertions
Turn a person’s label on one scenario, found by scenarioId or by a traceId it was built from, into up to four assertions, saved as pending agent assertions for review on the trace the scenario was built from. Create the scenario with save_scenario and check it first. note says what the run got right or wrong, and verdict says whether it was right overall. Each assertion cites the spans that settle its values, from the scenario’s trigger, history, and the records the run saw; records the run never saw are context only. A note that gives nothing a reviewer could check against a replay yields no assertions. A trace with no scenario, a scenario id that does not exist, or a scenario built from a replay is refused.
save_dataset
Create a named dataset for a traced function. Datasets are buckets of traces that humans review and that experiments replay against. Pass a dataset’s datasetId with a new name and/or description to rename it or change its description in place; its id, traces, and graders are kept. An empty description clears it, and a name another dataset on the same traced function already uses is refused.
list_datasets
List all datasets for a traced function with IDs, names, descriptions, trace counts, and assigned graders.
add_traces_to_dataset / remove_traces_from_dataset
Add or remove traces from a dataset (idempotent, up to 100 per call). Removing a trace from a dataset does not delete the trace itself.
add_graders_to_dataset / remove_graders_from_dataset
Assign or remove graders from a dataset (idempotent, up to 100 per call). Assignments are restricted to graders in the same organization and trace function as the dataset. Removing an assignment does not delete the grader.
save_grader / list_graders
Create or edit a grader (a pass/fail check) for a traced function, or list the graders defined for one. By default a grader is an LLM-as-judge that Bitfab runs. Pass external: true when creating it to make an external grader instead: Bitfab never runs it, you post its verdicts with save_grader_labels, and the setting can’t change later. save_grader upserts by grader id or by name, supports renaming, clearing pass/fail criteria, archive/restore, and selecting the judge model for graders Bitfab runs (Gemini 2.5 Flash by default, or GPT-5.6 Sol/Terra, Claude Opus 4.8, or Gemini 3.1 Pro). list_graders returns each grader’s name, status, evaluation focus, and criteria, and marks external graders; supports case-insensitive name search; and paginates newest-first with 20 results by default, up to 50 per page. Pass the returned cursor to retrieve the next page. Archived graders are hidden by default.
Experiments
save_experiment_group
Create or reuse a group across selected experiments, optionally giving it a human-readable name and notes. To update an existing group, pass its id and a new name and/or notes; editing never changes which experiments belong to the group.
list_experiment_groups
List recent experiment groups with their names, notes, creation times, and member experiment ids.
get_experiment_group
Get one experiment group by id with its name, notes, creation and update times, plus each member experiment’s id, name, status, and creation time.
save_experiment
Update an existing experiment’s human-readable name, notes, or experiment group. Omitted fields keep their current values; an empty notes string clears the notes, an experiment group id moves the experiment into that existing group, and null removes it from its group.
Set status when a replay stopped without finishing. completed marks the experiment finished and grades the traces that already landed, leaving out the ones that never ran, and it can no longer be resumed after that. interrupted marks a pending experiment as stopped, so it shows as interrupted and can be resumed later. Marking a completed experiment interrupted leaves it completed.
rerun_graders_on_dataset / rerun_graders_on_experiment
Re-score a dataset’s traces, or an experiment’s completed replays, with the graders already attached to them, overwriting the previous verdicts. This is how traces added before a grader existed get scored, and how everything gets re-scored after a grader’s criteria change: attaching a grader does not itself grade anything. Defaults to every attached grader; name a subset to narrow it, and ids that are not attached are rejected rather than skipped. Waits up to 90 seconds and reports how many traces were graded; a repeat call reports the running job instead of starting a second one.
add_graders_to_experiment_group
Assign one or more graders directly to every experiment currently in a group. Completed experiments queue any missing evaluations immediately; pending experiments use the graders when they complete. Because assignments live on experiments rather than the group, experiments added later do not inherit them automatically.
remove_graders_from_experiment_group
Detach one or more graders from every experiment currently in a group, undoing add_graders_to_experiment_group. Graders that are not assigned are ignored, the graders themselves are not deleted, and archived graders can still be detached.
list_experiments
List experiments newest first, with name, notes, status, pass/fail totals, delta (fixed, regressed, still passing, still failing), and the git state each ran from. The filters are all optional and can be combined: traced function, git branch, and dataset. With no filters it lists your organization’s most recent experiments.
get_experiment
Get a single experiment by experiment ID with its name, notes, status, pass/fail totals, delta, experiment group, and grader results: the aggregate passing/failing checks and pass rate, plus a per-grader breakdown of each assigned grader’s own passing/failing on the run. Use it when you already have an experiment id, instead of paging the whole function’s history with list_experiments.
list_experiment_traces
Get individual trace results for an experiment, including each replay trace’s verdict by comparing against the original trace’s label, plus token usage (input, output, cached, total) for the replay and the paired original.
add_graders_to_experiment / remove_graders_from_experiment
Attach or detach graders directly on an experiment so they run against its replay traces (idempotent, up to 100 per call). Attachments are restricted to active graders in the same organization and trace function as the experiment. The effective grader set at completion is the union of these direct attachments and the dataset’s current runnable graders. Detaching does not delete the grader. Its effect depends on run state: for an in-progress experiment a detached grader that is also a dataset grader is re-added from the dataset at completion (so it still runs), while for an already-completed experiment the grader set is a finalized snapshot with no dataset re-union, so detaching permanently drops that grader from the run’s results. Attaching to an already-completed experiment persists the assignment but does not immediately grade its existing replay traces; those traces are graded only the next time the experiment runs completion again (e.g. an SDK replay retry) or a fresh replay runs.
get_replay_status
Read the current replay status of an experiment, including the mapping from local replay trace IDs to server trace IDs while a replay is still running.
It also reports how many trace attempts finished (finishedCount) and how many remain (remainingCount), and whether the experiment can be resumed (resumable). When a dataset replay crashes after its experiment was created, the assistant skill reads this first. If the experiment is resumable, it tells you how many traces already finished and how many are left, then reruns with --resume <experimentId> so the finished traces are kept rather than replayed again.
Templates
get_template_reference
Read the agent-facing reference for Bitfab span templates: the Nunjucks engine, render-context schema, registered filters, and common patterns. Call once per session before editing templates.
get_template
Read the rendering template for a span type (llm, agent, function, guardrail, handoff, custom), scoped to a trace function key or org-global.
save_template
Upsert a rendering template for a span type. Controls how span input/output renders in the Bitfab UI.
Instrumentation
get_sim_plan
Read a trace function’s sim plan (alpha): its span nodes overlaid from recent traces, each with its span type, call count, average payload, estimated monthly cost, share of traces, and whether its content (inputs and outputs) is captured. Use it to learn the exact node names before save_sim_plan, or to answer what a workflow records today. A node is its span name inside the trace function key.
save_sim_plan
Turn content capture off or on for span nodes of one trace function (alpha). A span with capture off is no longer sent. The trace’s root, a span recorded by a framework integration, and a span that recorded an error are still sent without inputs and outputs, and a node declared in code always keeps its content. A node recorded by a framework integration (OpenAI Agents, LangGraph, Claude Agent SDK, Vercel AI SDK), a node that is the root of its traces, a node imported from another platform, or a node named by Bitfab rather than the SDK keeps its content, and turning it off is refused with the reason. Turning a node off also turns content off for every node beneath it in the sim plan; a node beneath it that keeps its content stays on, and a node named in the same call keeps the value given to it. Turning a node back on leaves the nodes beneath it as they are. Takes the nodes to change by span name and returns the updated sim plan, so a decision made here shows up on the Sim plan page as set by agent.
Slash Commands
Session Notifications
The plugin runs a hook on every session start and resume that checks:- Authentication: If you’re not logged in, it reminds you to run
/bitfab:setup - Updates: If a new plugin version is available, it tells you how to update (or auto-updates if you’ve enabled it)
Example Workflows
Instrument a new project
Diagnose and fix a failing function
Ask Claude Code naturally:search_traces and get_traces to inspect failing traces, then suggests code fixes directly.
For a specific failing trace, run /bitfab:assistant fix <trace-id>. The agent diagnoses the failure, confirms why the original trace is wrong before editing when the trace or conversation does not already make that clear, makes the focused code fix, and replays only that trace first. Once the fix passes, it adds that trace to a dataset with a validated failing label, then branches: inspect the before/after in Bitfab, re-run the full dataset (in Bitfab or terminal-only), keep iterating, or stop. If that full-dataset re-run reveals real regressions (previously-passing traces the fix broke), it reports them and keeps the target trace saved as a red test to revisit. If the replay still fails, it offers to keep iterating or save the trace as a failing test instead.
Iterate on a trace function
Replay after a code change
After updating a function, pass your registry module to the replay command installed by the SDK:.bitfab/replays/<run-id>/items/ folder and referenced from .bitfab/replays/<run-id>/events.jsonl. If the replay command succeeds but its local result cannot be captured, the plugin reports the outcome as unverified instead of failed, then checks the experiment on the server to recover the final result.
Configuration
Credentials
Credentials are stored in.bitfab/credentials.local.json when that project-local file exists, otherwise in ~/.config/bitfab/credentials.json (created by /bitfab:setup login with owner-readable permissions).
Environment Variables
Troubleshooting
Not authenticated
If you see “Not authenticated” on session start:- Run
/bitfab:setup loginto authenticate via browser - Check that
~/.config/bitfab/credentials.jsonexists and contains your API key - If using an environment variable, verify
BITFAB_API_KEYis set
MCP tools not available
If Claude Code can’t access the Bitfab tools:- Run
/bitfab:statusto check connection status - Run
/mcpand check whether Bitfab is disabled. Turning an MCP server off is remembered per project, so it survives reinstalling the plugin and restarting Claude Code. Enable it there and the tools load into the running session. - Verify the plugin is installed: check
/plugin list
claude mcp list is not a reliable check here: it health-checks the server in a separate
process and reports Connected even when the current session has it disabled.
Stale session
The plugin automatically detects and recovers from stale MCP sessions. If tools stop working mid-conversation, they’ll reconnect on the next call.Plugin updates
Run/bitfab:status to check for updates, then /bitfab:update to install the latest version. Restart Claude Code after updating.