Skip to content
Skillv1.0.0

setup

Set up and maintain Bitfab tracing for AI features. TRIGGER when: user wants to set up Bitfab, instrument code, add tracing/observability for LLM or agent calls, observe AI calls, add evaluation, trac

by Project-White-Rabbit(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from Project-White-Rabbit/bitfab-amp-plugin (skills/setup/SKILL.md). Install upstream with npx skills add Project-White-Rabbit/bitfab-amp-plugin --skill setup. Copyright stays with the author.

Bitfab Setup

When the flow branches, always present the options clearly and wait for the user's answer before proceeding. Number or letter the options so the user can pick by reference. Rules:

  • Recommend an option first, explain why in one line
  • Present 2-5 concrete options
  • One decision per question, never batch

Execution style (applies to every phase). Default to terse, action-first turns:

  • During mechanical phases (detecting language, searching code, reading files), run the tools and report only what you found. Do not narrate each command or pre-announce what you are about to do.
  • Batch read-only probing: combine related shell checks into one command (separate them with ;, not && (a no-match grep exits non-zero and would abort an && chain, skipping later probes)), and read multiple files in a single batch rather than one file per turn. Adaptive follow-up greps that depend on a prior result are expected and fine; the goal is to collapse only the fixed, independent probes.
  • Keep prose between tool calls to one line or none. Save fuller explanation for decision points and the workflow summaries the user acts on.
  • Surfacing a risk, ambiguity, or unexpected finding is never the narration to suppress: raise it immediately, even mid-probe (e.g. unserializable inputs, a shim with lazy init, an ambiguous project root).

Studio recovery (applies to every Studio-opening command). Any command that opens or navigates Studio (openTracePlan.js, startTemplatePreview.js, etc.) emits {"event":"not-responding","sessionId":"..."} and exits non-zero when a Studio session is recorded but its window can't be reached (a crash, sleep, or a close no process witnessed). It will NOT open a duplicate window. Do not retry this blindly. Recommend the user refresh or reopen the Studio tab, then ask the user with two options: Try again (re-run the same command, the record is still on disk, so a window that came back gets reused) or Open a new Studio (run node "${BITFAB_PLUGIN_DIR}/dist/commands/clearStudioSession.js", then re-run the command, which now opens a fresh window). Only run node "${BITFAB_PLUGIN_DIR}/dist/commands/clearStudioSession.js" after the user approves. Some commands (e.g. login) also expose a --force flag for a user at a terminal to recover the same way; never run --force yourself, surface the recovery to the user instead.

Describe this to the user in terms of their browser window, never the plumbing. The words in the paragraph above (session, pointer, record, stale, not-responding, sessionId) are for you, not for them: a user has a Studio tab open, they do not have a session pointer, and naming one tells them nothing they can act on. Say what they can see and what you want them to do, and offer a cause they can check rather than a diagnosis you can't make: the browser may have backgrounded the window (behind another window, minimized, or on another desktop or space), so send them looking for it before you offer a new one. E.g. "The Studio tab I opened earlier isn't responding. Your browser may have backgrounded it. Try switching to it and refreshing it, and if you can't find it I'll open a new one." Same rule for every other internal term you might be tempted to echo (agent session, monitor event file, exec session, daemon): describe the effect, not the mechanism.

Studio URL surfacing (applies to every fresh Studio open). If any Studio-opening command emits {"event":"window-open-requested","url":"..."}, immediately surface that URL to the user in a normal chat message (for example, Opening Studio: <url>. Click it if a window doesn't appear) so it is copyable from the transcript. This event means the open was requested (the browser launch was called), not that a window is confirmed on screen: on a remote/SSH session or with no supported default browser, nothing may surface, so the link is the reliable fallback. Surface it every time the event appears; do not leave the URL only in shell/tool output. If instead the command emits {"event":"open-failed","reason":"...","url":"..."}, the browser process did not even launch (e.g. rate-limited, spawn-failed): tell the user Studio couldn't open a browser (give the reason) and to click the link to open it (<url>); the session is live and the command keeps polling, so a manual click connects.

Studio reuse: never close-then-reopen to switch pages (applies to every Studio-opening command). Every Studio-opening command (openTracePlan.js, startDataset.js, startTemplatePreview.js, login.js, etc.) resolves the active session and navigates the live tab in place (emitting {"event":"navigated",...}); it opens a fresh window only when no session is active. So to change what Studio is showing, open a different dataset, a different trace plan, or a different page, just run the relevant open command again with the new target. Never call node "${BITFAB_PLUGIN_DIR}/dist/commands/closeStudio.js" just to switch: closing and reopening churns the tab, can orphan windows, and is never the way to change pages. Reserve node "${BITFAB_PLUGIN_DIR}/dist/commands/closeStudio.js" for genuine end-of-flow cleanup (the cleanup step already handles that) or when the user explicitly asks for the Studio tab to be closed.

🚨 Blocking-process rule (applies to any plugin command described as "blocks until the user does X"): When you launch a plugin CLI that blocks on a Studio interaction (login.js, startDataset.js, openTracePlan.js, etc.), you MUST keep the exec session alive and keep polling it until the process exits on its own.

  • The process opens Studio (or navigates an existing Studio session) and polls for the user's action via agent session events. It exits only after the user completes the action in Studio (or after the timeout).
  • After launching the command, keep polling the live shell/exec session every few seconds with your normal "read more output" tool. Do not idle waiting for a user message.
  • The user's confirmation does NOT come back as a chat message; it comes back as the plugin process exiting with output on stdout.
  • Stop polling only when: (a) the process exits 0 with its completion summary, (b) the process exits non-zero, or (c) the user explicitly cancels.
  • When the process exits, immediately continue with the next step, do not wait for another user message.
  • Exception, openTracePlan.js only. Its trace-plan steps (build-trace-plan, present-diff) run it in the background AND ask the user "Continue instrumenting?" in the same turn, because reviewing the plan in Studio is optional there. Keep polling the exec session as above, but a terminal-side answer is a second, equally valid way for that step to finish. Everything else in this rule still holds: never idle on a chat message alone, and when the process exits, act on its stdout, which outranks a stale answer.

This skill has twelve phases: explain, login, session-logs, instrument, modify, inspect, switch-org, view, replay, db-snapshot, templates, and analyze-repo. Run individually or through setup (wizard runs login β†’ instrument; explain is a standalone read-only overview that requires no login; session-logs is standalone and does not require login; modify is only invoked explicitly or as a branch from Instrument's existing-SDK-usage menu; inspect is a standalone diagnostic (with optional one-shot fixes) invoked explicitly; switch-org is a standalone account action (requires auth) invoked explicitly; view is only invoked explicitly; db-snapshot is only invoked explicitly; templates is only invoked explicitly; analyze-repo is a standalone, non-interactive batch action (requires auth) invoked explicitly: it scans, picks the top few candidates, and uploads a draft trace plan for each, asking nothing and editing no code).

Natural-language aliases (these reuse an existing mode, not a separate one): "explain Bitfab" / "what is Bitfab" β†’ explain; "trace a new workflow" / "instrument a new flow" / "create a trace plan" / "give me the trace plan" / "give me the trace plan for " / "show me the trace plan" / "bitfab create a plan" / "instrument the second/next/other one" / "instrument another function" β†’ instrument (a bare bitfab:setup with one of these phrasings routes to Instrument, NOT the full wizard); "update-setup" / "update my tracing setup" / "adjust what's captured" β†’ modify (NOT a plugin/SDK version bump, that's bitfab:update); "debug-setup" / "debug my tracing setup" / "inspect my tracing" / "why aren't my traces showing up" / "what's instrumented" β†’ inspect (for output-quality debugging use bitfab:assistant instead); "switch org" / "change org" / "switch to the org" / "I'm in the wrong org" β†’ switch-org; "set up db snapshots" / "set up db branching" / "replay against my database" / "replay against the database at trace time" / "database snapshots for replay" β†’ db-snapshot; "analyze the repo" / "analyze-repo" / "scan the codebase and draft trace plans" / "find the top things to instrument and upload plans for them" β†’ analyze-repo (non-interactive: never prompts, never edits code, just uploads draft plans).

When instrumenting a workflow, its instrumentation and replay pipeline are written together in the same cycle once the trace plan is confirmed (see Instrument's write-instrumentation step). The standalone replay mode remains available for coverage-verification and backfill.

Before running plugin commands below, resolve BITFAB_PLUGIN_DIR in the shell. Amp does not inject a plugin-root env var, so you must determine it. Copy and run this block verbatim, it auto-detects whichever install is active:

if [ -z "$BITFAB_PLUGIN_DIR" ]; then
  project_root=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
  for candidate in "$project_root/.amp/plugins/bitfab" "${XDG_CONFIG_HOME:-$HOME/.config}/amp/plugins/bitfab"; do
    if [ -f "$candidate/dist/commands/status.js" ]; then
      BITFAB_PLUGIN_DIR="$candidate"
      break
    fi
  done
  export BITFAB_PLUGIN_DIR
fi
test -n "$BITFAB_PLUGIN_DIR" || { echo "ERROR: Bitfab plugin not installed"; exit 1; }

If the block prints ERROR: Bitfab plugin not installed, the user hasn't installed the plugin yet, stop and tell them to install it. Otherwise proceed. The commands live at $BITFAB_PLUGIN_DIR/dist/commands/*.js.

SDK reference: https://docs.bitfab.ai is the source of truth for SDK install, initialization, API surface, and replay. Every docs path below ends in .md: that suffix returns the page as plain markdown (no HTML chrome), so fetch the URLs exactly as written. Fetch in this order before writing any code, do not improvise from memory:

  • Canonical API surface (preferred for agents): the dense reference pages at /reference/typescript.md, /reference/python.md, /reference/ruby.md, /reference/go.md. These list every public export, signature, type, default, and error semantic, no tutorials, no prose. Read these first.
  • The client exposes three instrumentation primitives, not one. Spans are the oldest, not the only one: TypeScript has withSpan/span, withTrace/trace, and withNode/node; Python has @client.span, @client.trace, and @client.node; Ruby and Go have spans only. trace records a root plus every first-party call beneath it without decorating them (TypeScript needs a bitfab-transform adapter, Python needs 3.12+), and node applies naming, typing, capture, and mockOnReplay/mock_on_replay policy to one call discovered inside that subtree. Name all three when you fetch a reference page. The fetch answers the question you asked, so asking only about withSpan/@span returns a page that reads as though spans are the whole API.
  • Cross-SDK shared semantics: /reference/overview.md (invariants), /reference/span-types.md (the SpanType enum), /reference/http.md (wire protocol).
  • Framework integrations (fetch when a framework is detected in step 1 of Instrument): /frameworks/langgraph.md, /frameworks/openai-agents.md, /frameworks/claude-agent-sdk.md, /frameworks/baml.md, /frameworks/vercel-ai-sdk.md. Each page documents the SDK's native handler/processor/wrapper for that framework, which is usually preferable to hand-wrapping every node/agent call with withSpan/@span.
  • Tutorials / walkthroughs / replay registry module template: the language-specific guide pages (/typescript-sdk.md, /python-sdk.md, /ruby-sdk.md, /go-sdk.md). Use these for the copy-pasteable replay registry module and the replay output contract. During Instrument, fetch the Replay section before Instrument's write-instrumentation step so the replay registry module can be written alongside the instrumentation in the same cycle without re-fetching.

MCP tools: This skill uses get_bitfab_api_key, save_trace_plan, get_trace_plan, list_trace_plans, and cancel_trace_plan (login / instrument / modify / view / analyze-repo), list_trace_functions and search_traces (inspect, templates, and the exact-trace smoke test in db-snapshot), list_organizations (switch-org), get_database_connection_status (db-snapshot only), and, for the templates mode only, get_template_reference, get_template, and save_template. All are registered by the Bitfab plugin under these bare names.

CLI commands available via Bash (all paths relative to ${BITFAB_PLUGIN_DIR}/dist/commands/):

Command Description
status.js Check plugin authentication and connection status
login.js Authenticate for setup/instrumentation; standalone browser OAuth (blocks). Studio, dataset, and experiment flows log in inline and need no pre-login.
switchOrg.js [<clerkOrganizationId>] List the user's Bitfab orgs (no args), or switch the plugin's active org and replace the local API key (with a arg)
openTracePlan.js <planId> Open the trace plan review UI in Studio (stays alive until the user closes or updates the plan)
openStudioTo.js <path> Navigate the active Studio session to a path (opens a window when none is active)
startTemplatePreview.js <functionKey> Open the template editor preview in Studio (blocks until user clicks Done)
closeStudio.js [message] Close the active Studio session (tab + background event process); no-op when nothing is open
clearStudioSession.js Start a fresh Studio window on the next open
update.js <mode> Check plugin + SDK versions and install the latest (used by inspect to detect and fix staleness)
`sessionLogConsent.js [get set true

Modes

Read the user's request first. If its first token is exactly one of the mode names below, run that mode. Otherwise, when this skill documents how to route the remaining arguments (see its intro), follow that; if it doesn't, run wizard and treat the user's request as its input. Run only that mode's section below and skip the others.

Mode Trigger What it does
wizard wizard (default) Run login, then instrument workflows until the user is done.
explain explain Explain what Bitfab is and what each mode does (read-only, no login).
login login Authenticate for setup/instrumentation (Studio/assistant flows log in inline, no pre-login).
session-logs session-logs Opt in or out of session log collection (no login required).
instrument instrument Instrument AI workflows with Bitfab tracing.
modify modify Modify an existing trace setup (add context, change depth, or move the root).
inspect inspect Diagnose (and offer to fix) your tracing setup: auth, what's instrumented, plugin/SDK freshness, replay coverage, trace arrival.
switch-org switch-org Switch which Bitfab org the plugin reads and writes (replaces the local API key).
view view Open the trace planner UI for an existing trace function (read-only).
replay replay Create or update replay registry modules for instrumented workflows.
db-snapshot db-snapshot Set up per-trace database snapshots so replay runs against the DB state at trace time (TypeScript, Python, Ruby).
templates templates Iterate on the span-rendering templates for one trace function.
analyze-repo analyze-repo Non-interactively scan the repo, pick the top workflows to trace (default 5, or limit=<n>; optional free-text guidance: steers what to focus on), and upload a draft trace plan for each (no prompts, no code changes).

Login

Run only when mode is wizard, login or instrument.

Authenticate with Bitfab and retrieve the API key.

  1. Run the status check:

    node "${BITFAB_PLUGIN_DIR}/dist/commands/status.js"

    If the output includes v<X> available, run ... to update, surface that line verbatim to the user once before proceeding; do not block on it.

    If already authenticated, skip to step 3.

  2. If "not authenticated", run the login script yourself, do NOT ask the user to run it manually:

    node "${BITFAB_PLUGIN_DIR}/dist/commands/login.js"

    Run with 600000ms (10 minute) timeout. This opens Studio to the sign-in page and polls the server until the user completes authentication in the browser. The process exits when authentication succeeds or the 10-minute timeout fires.

    If the browser fails to open, login.js prints the Studio sign-in URL. Surface it to the user verbatim so they can open it manually; do not rely on shell/tool output being visible. The polling loop stays active for the full 10-minute timeout regardless of whether auto-launch worked.

    Per the Blocking-process rule at the top: after login.js opens Studio, keep polling the live exec session until it exits. Do not send a "waiting for you to sign in" message and then idle; the user's sign-in will NOT arrive as a chat message; it arrives as login.js exiting with Logged in as <email> on stdout.

    If login.js exits non-zero or the 10-minute timeout elapsed, report the error to the user and stop.

  3. Call get_bitfab_api_key to retrieve the API key, NEVER print or log the full key. Stored at ~/.config/bitfab/credentials.json, used for the BITFAB_API_KEY environment variable.

    If get_bitfab_api_key is not available in this session, the Bitfab plugin did not load, so its tools never registered. Say so and hand the user the fix below; do not diagnose further, and do not fall back to drafting anything by hand.

    Tell them to run plugins: reload from the command palette (Ctrl-O), or restart Amp, then re-run this skill. amp plugins list shows whether the Bitfab plugin loaded and, if not, why.

    Then stop, the same way a failed login stops. Do not fall through to the remaining steps: every phase after this one needs these tools, so continuing only moves the failure further from its cause.

  4. Check whether session log consent has already been recorded:

    node "${BITFAB_PLUGIN_DIR}/dist/commands/sessionLogConsent.js" get

    If the output is already true or false, skip the prompt and continue. If the output is null, ask the user:

    • Question: "Allow Bitfab to collect session logs?"
    • Description: Used to diagnose issues and improve the product.
    • Options: "Allow" / "Don't allow"

    Save the answer (replace CONSENT with true or false):

    node "${BITFAB_PLUGIN_DIR}/dist/commands/sessionLogConsent.js" set CONSENT

Explain

Run only when mode is wizard or explain.

Teach the two primitives the user has to instrument with. Read-only, no code changes, no Studio. Runs inside wizard (right after Login, before the approach question) and standalone via bitfab:setup explain (or natural-language asks like "what is Bitfab" / "explain Bitfab"), which needs no authentication.

  1. Render the block below verbatim as a single message, as formatted markdown (do not wrap it in a code fence, do not reword it, and do not add a summary or an ASCII diagram). This is the education the rest of setup depends on: a user who does not understand withSpan and replay cannot make the per-method decisions instrumentation asks of them. Do not authenticate, scan the codebase, ask any questions, or edit anything here, in either mode.

    **Purpose**
    
    Bitfab's SDK captures each instrumented method's inputs, outputs, and surrounding context as a trace at runtime. During development, developers and coding agents can inject captured trace data and modify code execution at the per-method level to test AI features end-to-end.
    
    **How to instrument**
    
    Bitfab provides you a way to capture traces and replay them safely during development. The core primitives from the Bitfab SDK are:
    
    - `withSpan(...)`
    - `replay(...)`
    
    `withSpan` captures traces and sends them to Bitfab by default. It serializes the inputs, outputs, and metadata of the method it wraps (or decorates) and sends them over the OTEL transport layer.
    
    `replay` calls into your code and modifies the behavior of `withSpan` for each method it wraps (or decorates) in one of five ways:
    
    1. Execute as normal
    2. Pass in inputs from the recorded trace
    3. Pass in modified inputs from the recorded trace
    4. Skip execution and return outputs from the recorded trace
    5. Skip execution and return modified outputs from the recorded trace

    If the user asks about a framework (or once one is detected later in setup), follow up by explaining how that framework maps onto the five cases above. The principles do not change; only the way it gets instrumented does.

    Unless the mode is explain:

    Stop there and continue to the Approach section. Do not render the mode menu below: mid-setup, a menu of other modes is noise.

    Only when the mode is explain:

    Follow the block above with this one, as a code block, exactly as laid out:

    What you can run
      bitfab:setup            Login, then instrument workflows until done
      bitfab:setup explain    This overview (read-only)
      bitfab:setup login      Authenticate with Bitfab
      bitfab:setup instrument Wrap a new AI workflow with tracing
      bitfab:setup modify     Adjust what an existing trace captures
      bitfab:setup inspect    Diagnose + fix setup: auth, what's instrumented, SDK/plugin current, replay coverage, traces arriving
      bitfab:setup switch-org Switch which org the plugin reads and writes
      bitfab:setup view       Open one trace function's plan in the browser (read-only)
      bitfab:setup replay     Create or update replay registry modules
      bitfab:setup templates  Change how a trace function's spans render
      bitfab:setup session-logs  Opt in/out of session log collection
    

    then close with one line: to start tracing, run bitfab:setup; to debug an existing setup, run bitfab:setup inspect. Then stop.

Approach

Run only when mode is wizard.

Settle who does the instrumenting before any code is read or written. Runs once, in wizard mode only, after Login.

  1. The user is authenticated now. Ask the user to settle who does the instrumenting:

    • Question: "Want me to walk you through instrumenting, or would you rather do it yourself?"

    A) Walk me through it: I drive the instrumentation end to end, checking with you at each decision (recommended) β†’ step 2 B) I'll instrument myself: hand over the docs and stop, no scanning, no code changes β†’ step 3

    Recommend A and say why in one line: it is the whole flow (SDK install, trace plan, spans, replay registry module) with a confirmation before anything is written. Ask this once; do not re-ask it later in the session.

  2. The user asked to be walked through it. Before anything else (before dispatching to the Instrument section, before a single probe or file read), render the content of the block below verbatim as formatted markdown: no code fence, no rewording, no additions.

    **What's about to happen next**
    
    - This wizard will guide Amp on how to use the Bitfab plugin to analyze your repository. Amp will then instrument your AI features and write a `replay` script using the Bitfab SDK.
    - Whenever Amp needs your input, it will prompt you
    - Setup takes about 10 - 17 minutes depending on how many features you want to instrument and how complex your AI features are.

    This is the user's only warning about what the skill is about to do to their repository and how long it takes. It has to reach them between saying "walk me through it" and the next question they get asked, so nothing, not the language detection, not the existing-usage report, may come first.

    Then go to the Instrument section and start at its first step. The guided path ends here: do not continue into the self-serve handoff that follows, which belongs to option B and tells you to stop.

  3. The user is instrumenting on their own. Give them the pointers below in one short message, then stop: do not scan the codebase, read files, or edit anything.

    • Docs: https://docs.bitfab.ai, start with the SDK guide for their language (/typescript-sdk, /python-sdk, /ruby-sdk, /go-sdk); each one covers install, initialization, wrapping a workflow, and (outside Go) the replay registry module. Name the language's page directly if the project's language is already obvious from the conversation; do not go read the repo to find out.
    • API key: their app needs BITFAB_API_KEY set in the environment it runs in before any trace will arrive. Tell them to get the key from the Bitfab MCP's get_bitfab_api_key tool. Do not call it yourself, and never print a key.
    • Coming back: bitfab:setup picks this flow back up, and bitfab:setup inspect diagnoses an instrumentation they wrote themselves (auth, what's instrumented, whether traces are arriving).

    Then go to the Cleanup section and end the run there. Option B is a full stop: do not read on into the sections that follow, the Instrument section included, and do not scan or edit anything on the way out.

Session Logs

Run only when mode is session-logs.

Opt in or out of session log collection. Does not require authentication.

  1. Check whether session log consent has already been recorded:

    node "${BITFAB_PLUGIN_DIR}/dist/commands/sessionLogConsent.js" get

    If the output is true, tell the user session logs are currently enabled. If false, tell the user session logs are currently disabled. If null, tell the user no preference is recorded yet. Then ask the user:

    • Question: "Allow Bitfab to collect session logs?"
    • Description: Session logs help us diagnose issues and improve the product. They include prompts, responses, and tool calls from sessions where Bitfab tools are used.
    • Options: "Allow" / "Don't allow"

    Save the answer (replace CONSENT with true or false):

    node "${BITFAB_PLUGIN_DIR}/dist/commands/sessionLogConsent.js" set CONSENT

    Confirm the change to the user.

Instrument

Run only when mode is wizard or instrument.

Instrument the codebase with Bitfab tracing. Requires authentication (run Login first if needed).

Bitfab captures every AI function call, inputs, outputs, and errors, so you can see exactly what your AI is doing and discover what's going wrong. The goal is to have enough context in each trace to tell whether a call succeeded or failed, and why.

Detection and search below are mechanical: run the probes and report what you found, without narrating each command. Combine related read-only checks into one command (separate them with ;, not &&, since a no-match grep exits non-zero and would abort an && chain) and read multiple files in a single batch; adaptive follow-up greps that depend on a prior result are expected. A risk, ambiguity, or unexpected finding (unserializable inputs, a shim with lazy init, an ambiguous root) is never the narration to suppress: raise it immediately, even mid-probe.

  1. Detect the project language (TypeScript, Python, Ruby, or Go). In a monorepo, identify which directories are applications (services, APIs, agents) vs libraries (SDKs, shared packages). Focus on application directories. The only output of this step is that language-and-framework verdict; finding the AI workflows to instrument comes later, at step 7, so a grep hit here is a framework signal, not a workflow to read and characterize. Also scan imports and package manifests for supported framework signals, and note which framework each application directory uses, step 5 fetches the matching framework page alongside the language reference:

    • LangGraph / LangChain: TS: @langchain/langgraph, @langchain/core; Python: langgraph, langchain, langchain_core
    • OpenAI Agents SDK: TS: @openai/agents, setTraceProcessors; Python: agents (from agents import ...)
    • Claude Agent SDK: TS: @anthropic-ai/claude-agent-sdk, query(; Python: claude_agent_sdk, ClaudeSDKClient, query(
    • BAML: TS: @boundaryml/baml, baml_client import; Python: baml-py, from baml_client import b
    • Vercel AI SDK: TS: ai, wrapLanguageModel, streamText, generateText (TypeScript only)
  2. Search for existing SDK usage (withSpan, @span, bitfab_span, client.Span, getFunction, get_function, etc.). In a monorepo, search each application directory separately: a root-level search can miss subdirectories.

    • If found: ask the user, listing the existing trace function keys inside the question's own text (<key> Β· its root function, or its handler registration site for handler-only keys), so the user picks against the actual list instead of a message scrolled above the prompt:

    A) Search for more workflows: find workflows that aren't traced yet (recommended) β†’ step 3 B) I'll name the workflow to instrument: type the file, function, or directory and I read only that, no codebase scan β†’ step 3 C) Change what an existing trace captures: adjust what one of the keys above records; type its key to go straight to it β†’ step 1 of the Modify phase

    B and C are both free-text options, and this is the earliest point either answer can land. Say so in the question: they can type a workflow to instrument, or the key of an existing trace to change, instead of picking anything.

    • B (a target to instrument): carry that target through the SDK install and doc steps and treat the discovery question at step 7 as already answered by it, then read just that location at step 10. Without this option a user who already knows their target has to answer "search" here, sit through the install, and then answer the same question again four steps later, which is asking them to repeat themselves.
    • C (an existing key to change): the keys are right there in the question, so a named key routes to the Modify phase with the target already settled, and Modify is told to skip both the search you just ran and its own which-function question when it arrives holding a key. Only a bare C leaves Modify to ask.

    There is deliberately no "done, finish setup" option here. The user invoked setup and nothing has been instrumented this session, so an exit offered as a peer of the two real options invites them to undo the thing they just asked for. A user who genuinely wants out says so in free text, which is the last of the runtime routes below; do not manufacture a menu item for it.

    Routes that are conditions rather than options:

    • no existing SDK usage found: continue β†’ step 3
    • the user says in free text that they are done and want no changes: continue β†’ step 1 of the Cleanup phase
    • If usage routes through a project-local shim (a wrapper file that re-exports withSpan / @span / bitfab_span / getCurrentTrace / getCurrentSpan with custom init, often named lib/bitfab.* or after a predecessor SDK such as lib/simforge.*), audit the shim before instrumenting anything new. The shim must (a) construct the SDK client (new Bitfab(...), bitfab_init(), Bitfab::Client.new, etc.) at module load, synchronously, never lazily inside the wrapped function; and (b) hand off to the SDK call synchronously, with no await between the user's entry to the shim and client.withSpan(...) / @bitfab.span(...). Lazy or async client init (e.g. await getOrCreateTraceFunction(key) inside the wrapped body) breaks the SDK's nesting context (TypeScript AsyncLocalStorage, Python contextvars) under any parallel fan-out (Promise.all, Promise.allSettled, asyncio.gather, parallel workers): every span becomes its own top-level trace instead of nesting inside its caller. Fix the shim before instrumenting anything new. (Direct callers of the SDK with no shim already satisfy this rule, skip the audit.)
    • If not found: proceed to step 3: no SDK usage does NOT mean nothing to instrument, it means the SDK hasn't been installed yet. NEVER conclude "nothing to instrument" before completing step 6.
  3. Use the API key from the Login phase (or retrieve it now if already authenticated)

  4. Say one line before you install anything. This is the deliberate exception to the "do not pre-announce" execution-style rule, and the only one in this phase: the next few steps install a package, write to the project's env files, and fetch docs, which is the wizard touching the user's repo before it has asked them a single thing about what they want traced. Name what happens now, and end the line with whatever comes next on the route the user is actually on, since step 7 only asks when nothing has settled it yet. Promising a question the flow then skips is worse than saying nothing:

    • They named a target at step 2: name it back ("Installing the SDK and setting your API key, then reading the SDK docs, then I'll instrument <target>"). This confirms you heard them and keeps the target in view across the install and the doc fetches, the stretch where a held answer is easiest to lose.
    • They chose to search there: say the scan is next ("...then I'll find the workflows worth tracing").
    • Nothing settled yet (this step was reached without that menu, because no existing SDK usage was found): promise the question ("...then I'll ask what you want to instrument").

    One line, nothing around it, then get on with it.

    Install the SDK now. Detect the project's package manager from its manifest (pyproject.toml β†’ uv/poetry; package.json β†’ pnpm/npm/yarn/bun; Gemfile β†’ bundle; go.mod β†’ go get; requirements.txt β†’ edit file + pip install -r) and run its canonical add command, do NOT stop to ask about version pinning or dep groups. Prefer uv add/poetry add over bare pip install (bare pip install doesn't persist to pyproject.toml). In monorepos, scope to the correct workspace (e.g. pnpm add --filter <pkg>, or cd into the app directory first), running from the repo root will install into the wrong package. Default to a runtime dep for applications; a dev dep for libraries/SDKs where a runtime dep would propagate to downstream users. Then set the BITFAB_API_KEY environment variable.

    Tell the user what you did. Pick the env-handling approach that fits the project's existing convention. Whatever you do, surface it explicitly: name the file (with absolute path) or mechanism you used, so the user knows where the key now lives. Do not print the key value itself. If the key landed in a .env-style file, additionally tell the user that any already-running dev server, REPL, or test runner may need a restart to pick it up, since most file watchers reload code on save but not env files.

  5. Read the SDK reference. Fetch the dense canonical reference page first (/reference/typescript.md, /reference/python.md, /reference/ruby.md, or /reference/go.md) for every signature, type, default, and error semantic you need (initialization, withSpan / @span / bitfab_span / client.Span, the subtree primitives withTrace / trace and withNode / node in TypeScript and Python, getFunction / get_function / GetFunction / bitfab_function, SpanType, getCurrentSpan/getCurrentTrace, wrapBAML/wrap_baml). Ask the page for all three primitives by name, not just spans: the fetch returns an answer to your prompt rather than the page, so a prompt about withSpan/@span alone comes back documenting spans alone, and you will instrument without ever learning that trace (a root that captures every first-party call beneath it, no decorators) and node (naming, typing, capture, and replay-mock policy for one call inside that subtree) exist. If step 1 detected a framework in this application directory, also fetch the matching framework page; it documents the handler/processor/wrapper the SDK exposes for that framework, which is usually preferable to hand-wrapping every node/agent call with withSpan/@span: LangGraph / LangChain β†’ /frameworks/langgraph.md (getLangGraphCallbackHandler / get_langgraph_callback_handler; in a LangChain-only project, prefer the identical aliases getLangChainCallbackHandler / get_langchain_callback_handler so the code reads naturally; Experimental (alpha) tool replay: getLangGraphIntegration / get_langgraph_integration with createInvoker / create_invoker / create_async_invoker); OpenAI Agents SDK β†’ /frameworks/openai-agents.md (getOpenAiTracingProcessor / get_openai_tracing_processor, plus the replayable run wrapper getOpenAiAgentHandler / get_openai_agent_handler (drop-in for the run call)); Claude Agent SDK β†’ /frameworks/claude-agent-sdk.md (getClaudeAgentHandler / get_claude_agent_handler); BAML β†’ /frameworks/baml.md (wrapBAML / wrap_baml); Vercel AI SDK β†’ /frameworks/vercel-ai-sdk.md (getVercelAiMiddleware). Then fetch the language guide (/typescript-sdk.md, /python-sdk.md, /ruby-sdk.md, /go-sdk.md), including the Replay section for non-Go projects, for the install command, the multi-file project layout example, the BAML auto-instrumentation walkthrough, and the replay registry module template. Read the replay section upfront (not later) because step 14 reuses it to write the replay pipeline in the same cycle, and it should not re-fetch these pages. Fetch those pages (via web-fetch capability, in one batch since they are independent URLs, or ask the user to share them). Do not improvise instrumentation from memory: the API has moved and guessing will produce broken code.

  6. Instrumentation must produce a replayable trace. There are exactly two ways to get one: (1) the root span has serializable inputs, or (2) the workflow runs on a supported framework integration that records a replayable root (LangGraph / LangChain, OpenAI Agents SDK, Claude Agent SDK, or Vercel AI SDK), which captures the framework's own serializable input as the root. Establish one of these before writing any instrumentation. Trace-processor integrations (OpenAI Agents SDK) are a special case: the processor auto-captures the agent run, but on its own records a root span with an empty input (verified against a live run: the OpenAI Agents agent span is the root and carries no recorded input), so the processor ALONE is NOT replayable. Pair it with its run wrapper (getOpenAiAgentHandler / get_openai_agent_handler), a drop-in for the run call that opens a keyed root carrying the run input as a serializable argument, with the processor's spans nesting underneath, which turns it into case (1). A hand-written withSpan/@span root that takes the run input works too.

    The root exists so the replay harness can re-invoke it as a plain lambda with serialized inputs: that's what makes traces searchable (a coherent unit of behavior) and replayable (runnable against current code). The root must own its state setup, not consume a pre-built stateful object the replay registry module can't reconstruct. Frameworks are the sharpest case (LangGraph compiled graphs, Claude Agent SDK clients, LangChain chains all require constructors + special setup), but the rule generalizes to anything stateful, configured SDK clients, prepared models, cached routers, DB sessions. For manually wrapped workflows, the root is therefore the outer workflow function that builds the framework / stateful object + invokes it + processes the output (API handler, message processor, job runner, pipeline coordinator), almost never the SDK's run() / invoke() itself. For callback-handler integrations that already record a replayable root (LangGraph / LangChain, Claude Agent SDK, or Vercel AI SDK), do not turn this into a mandatory manual outer span: the handler-created framework invocation root is enough when the production workflow is just the graph/chain/agent invocation. The replay callable is where you rebuild the framework/stateful object around the recorded root input. Add a same-key withSpan/@span outer root only when there is meaningful production work around the framework call (input prep, non-framework retrieval, post-processing, persistence, downstream service calls) that should be visible in the trace.

    Wrap the code path that runs the real workload (serves traffic, processes the actual jobs), not an entrypoint that exists only to test or explore locally. The test is role, not form: a cron-driven batch script or an ETL job is production and worth wrapping; a dev CLI or notebook that exists only to poke at the workflow is not. Instrument the real path even when you'll run it in dev to generate traces.

    Hard constraint: every wrapped function's inputs and outputs must be serializable by the SDK's tracing layer so traces can be replayed. Every span input and output gets serialized into the trace using the SDK's language-native serialization (TypeScript/JSON, Python/JSON via Pydantic, Ruby/to_json, Go/json.Marshal). If a wrapped function takes live runtime objects that don't round-trip through that serialization, the trace can't be replayed, and badly-failing inputs can drop the entire span on the floor (not just garble the input field). Examples of unserializable inputs:

    • browser objects (MediaStream, RTCPeerConnection, WebSocket, DOM refs)
    • HTTP Request / Response, stream writers, open sockets
    • framework request contexts whose content is genuinely opaque (not reconstructible from headers + user id)
    • live SDK client instances passed as arguments (LLM clients like OpenAI / Anthropic / Bedrock, configured agents, DB connection objects, HTTP agents): class instances whose internals carry circular references, function members, or platform handles all sink superjson and JSON.stringify. Watch especially for an options/config bag (e.g. options.llmProvider, ctx.db) that smuggles a live client into an otherwise-serializable signature.

    Unserializable OUTPUTS (live streams) are a separate case from unserializable inputs, and in the TypeScript SDK they do NOT require a refactor. A function whose inputs are serializable but which returns a live stream the caller consumes directly (a Vercel AI SDK streamText result, a ReadableStream, an SSE / streaming Response) is the common shape for chat and agent endpoints. Serializing that object as-is captures nothing replayable, and awaiting it to completion before returning would break streaming and first-byte latency. Record a drained, serializable view of the stream as the span output instead:

    • TypeScript: use the withSpan finalize option (withSpan(key, { type, finalize }, fn)). The wrapped function returns the live stream to the caller unchanged; the span records await finalize(result) (e.g. { text, usage, toolCalls }). Pass the prebuilt finalizers.aiSdk for the Vercel AI SDK, or finalizers.readableStream for a raw ReadableStream (reading the AI SDK result's promises does not disturb the caller's stream, since it tees internally). This is purely-additive instrumentation, NOT a refactor: do it in the write-instrumentation step with no second confirmation. The trace stays replayable as long as the function's inputs are serializable. Never push the user into a structural rewrite of a streaming endpoint when finalize covers it.
    • Python: also use the finalize option (@client.span(key, type=..., finalize=...)). The idiomatic, non-destructive shape is an async generator that yields its chunks (the caller still receives every chunk); finalize then receives the collected chunks and returns a serializable summary. Pass finalizers.openai_chunks for OpenAI streaming or finalizers.anthropic_events for Anthropic. Same rule: purely-additive, NOT a refactor, no second confirmation. (Python streams are single-consumer, so prefer the async-generator form over draining a returned stream object.)
    • Ruby / Go (no finalize yet): introduce a serializable completion. Trace a core that runs the turn to completion and returns { text, usage, ... }, with the streaming wired around it (the structural refactor below).

    Module-level dependencies (DB clients, env vars, config loaders, LLM clients) do not count when accessed via module scope or closure: replay resolves them from the app's runtime wiring instead of serializing them as span inputs. The same client passed as a function argument IS captured as input and WILL fail. The fix when an SDK client is the only unserializable piece is usually trivial: hoist it to module scope (or capture via closure) and drop it from the argument list, leaving the wrapped function's serializable args (issue, request, options-without-the-client) intact. When the natural outer boundary still has unserializable inputs after that, do one of the following before writing code:

    • Instrument via the framework handler or processor (preferred whenever the workflow runs on a supported framework: LangGraph / LangChain via getLangGraphCallbackHandler / get_langgraph_callback_handler, OpenAI Agents SDK via getOpenAiTracingProcessor / get_openai_tracing_processor, Claude Agent SDK via getClaudeAgentHandler / get_claude_agent_handler, Vercel AI SDK via getVercelAiMiddleware). These split into two replayability cases, do not conflate them:
      • Integrations that record a replayable root (LangGraph / LangChain, OpenAI Agents SDK, Claude Agent SDK, or Vercel AI SDK) are replayable as-is, via one of two mechanisms. Callback handlers (LangGraph / LangChain, Claude Agent SDK, or Vercel AI SDK) record the framework invocation itself as the root span, with the framework's own serializable input (LangGraph initial state, agent prompt) as the recorded root input. Trace processors (OpenAI Agents SDK) don't record the input themselves, so their run wrapper (getOpenAiAgentHandler / get_openai_agent_handler) does it: a drop-in for the run call that records a keyed root carrying the run input, with the processor's auto-captured spans nesting underneath. Either way, the unserializable arguments above it (live dependency objects, billing callbacks, request contexts) never enter the trace, and no decorated root function needs to exist in the app code: the replay registry module passes the key to replay() with a plain callable that re-invokes the same framework entrypoint production calls with the recorded root input plus reconstructed runtime wiring (framework config and dependencies); the SDK wraps the callable internally. Unsafe calls made by that wiring still need replay-mockable marked spans; use no-op values only for replay-only callback slots with no recorded call to mock. On SDKs that predate explicit-key replay, wrap the callable under the same key yourself (Python @bitfab.span("<key>"), TS getFunction(key).withSpan(...)). The pattern is documented in the SDK docs' Replay section (handler subsection) and wired up in step 14 11b. Never report one of these workflows as "not replayable" because no @span-decorated function exists in production code.
      • A bare trace processor (OpenAI Agents SDK) with neither its run wrapper nor a manual root is NOT replayable. The processor captures the run, but its root span records an empty input (verified against a live run: the OpenAI Agents agent span is the root and carries no recorded input). Pair it with the run wrapper (getOpenAiAgentHandler / get_openai_agent_handler), the drop-in for the run call above, or a hand-written withSpan/@span root that takes the run input: the processor's auto-captured spans nest under that root, and replay runs against the root's serializable input. Do not treat a bare processor-only trace as replayable.
    • Move the trace boundary inward to the first function whose inputs are serializable (e.g. trace processTurn(transcript, context) instead of handleSession(stream, peerConnection)). This is not a refactor.
    • Refactor so a function with serializable inputs exists. Two flavors, chosen per case in the refactor plan:
      • Visibility refactor (common): the logic that takes serializable inputs already exists inline but isn't importable (embedded in a route handler, not exported). Extract it into a named, exported function at module scope. No semantic change.
      • Structural refactor (rare overall, mostly realtime/browser apps): no function with serializable inputs exists yet. Introduce one: a pure core whose parameters are serializable, with callers constructing them. A real rewrite. (This flavor is for missing serializable-input cores. A streaming output in the TypeScript and Python SDKs is handled by the finalize option above, not a structural refactor; only fall back here for streaming on Ruby/Go.)

    Raise this with the user in step 11 (not later); never instrument a root with unserializable inputs and try to fix it in the Replay phase.

  7. First, check for reusable draft plans. Call list_trace_plans with { source: "analyze_repo", status: "awaiting" } (it returns only this org's unconfirmed, non-expired bitfab:setup analyze-repo drafts, newest first). This is a silent probe, do not narrate the call itself.

    If drafts came back, print them for the user before asking, so they can choose which to wire up. List every draft as a numbered item (this is the menu they will pick from in step 8), each showing enough to decide on, straight from the list_trace_plans output:

    • root name and its trace function key
    • the root file
    • frameworks detected in the plan (when any)
    • recommended capture: N of M nodes
    • how long ago it was drafted

    Evaluate these two routes before you ask anything. Step 2 may already have settled this question, and re-asking several steps and an SDK install later is asking the user to repeat themselves:

    • the existing-SDK-usage menu already chose to search for more workflows, and the draft probe returned nothing: skip the question and scan β†’ step 9
    • the existing-SDK-usage menu already named a target to instrument, and the draft probe returned nothing: skip the question and read the named target β†’ step 10

    Awaiting drafts override both, because they are new information the user has not seen: when the probe returns any, ask instead, and say in one line what their earlier answer was so the re-ask reads as an update rather than a memory lapse.

    When neither route fires, ask the user what to instrument:

    A) Reuse an analyze-repo draft plan: only shown when drafts exist: pick from the printed drafts and wire them up one at a time (recommended) β†’ step 8 B) Find workflows for me: scan the codebase for every AI call, agent, and LLM-driven decision β†’ step 9 C) I'll name the target: type the file, function, or directory and I read only that, no codebase scan β†’ step 10

    Option C is a free-text option, not a promise of a second question. Say in the question's own text that they can type the file, function, or directory instead of picking anything, so a user who already knows their target answers in the same breath and never sees a follow-up prompt. The scan (B) is the only option that spends real time, which is why it is worth a fork at all. An answer that names a file, function, or directory IS option C, whether it arrives as typed free text, as a note on a selection, or as the label plus a name: route it to C and take the name, never re-ask because no option came back selected.

    Option A (reuse the drafts) is only present when list_trace_plans returned at least one draft. When drafts exist, offer A first and recommend it, wiring up an existing draft is the whole point of having run analyze-repo first. When there are no drafts, omit A entirely and present only the scan and point-to-target options (the plain two-way choice, with no mention of trace plans); in that case recommend the scan option instead.

    If they pick A, go to step 8 to wire up the picked drafts (a draft is a starting point, not a commitment: it is still presented for review and can be adjusted or cancelled before any code is written). If they pick B, do the full codebase scan in step 9.

    If they pick C, they have just told you they know what they want; the only thing you are missing is its name, and it usually arrives with the answer. If they named it anywhere (the free text they typed on this question, their original invocation, or earlier in the session), take that and go straight to step 10. Only when C comes back bare, with no target named, do you ask in plain chat and wait for their next message, one line, e.g. "Which file, function, or directory should I instrument?". Do NOT turn it into an options question (the answer is free-form, and options would only stand between the user and typing it), and do NOT read, grep, or list the codebase to assemble candidate targets to offer them. Scanning for candidates is option B, the option they just declined, and a menu of the three roots you happened to find is worse than an empty prompt: the target they have in mind may not be on it, and offering it reads as ignoring their answer. Once they name it, go to step 10 to read just that location, skipping the broad scan.

  8. You reached this step by choosing to reuse a saved trace plan: either option A at step 7 (the first pass) or the saved-plan option at step 16 (a later loop, after instrumenting something). Both arrive here to wire up drafts one at a time.

    If you do not currently hold an unprocessed batch queue (a fresh arrival from either step), ask the user which of the awaiting drafts you just listed to instrument (they may pick one or several) and hold the selected plan ids as an ordered batch queue. If you already hold a queue with unprocessed drafts left (you looped back here from a skip below), do not ask again, just take the next unprocessed draft. Process them one at a time, exactly like the discovery loop instruments one workflow per cycle, never several at once. Only once a queue you were actively processing is fully consumed (every selected draft processed or skipped) do you leave to step 16 to pick the next move, never bounce back there without a fresh selection.

    For the current draft, reconcile it against the CURRENT code, a draft is a snapshot from analyze-repo time and the code may have moved on (a prior draft in this same batch, a manual wrap, or an earlier session may already have instrumented this workflow; the root may also have been renamed, moved, or deleted). Reconcile now, before you present or open the plan, so you never surface a plan the user can't act on: presenting a plan you're about to abandon (already instrumented, or stale) just wastes their time on a moot review.

    • Read the draft's tree with get_trace_plan { planId } (this reads the draft without confirming it).
    • Read the plan's root file at its recorded file/line, and grep the root and captured-node locations for existing SDK instrumentation, the plan's own trace function key (getFunction("<key>") / get_function / bitfab_function / WithFunctionName) and span wrappers (withSpan / @span / bitfab_span / client.Span).
    • Cross-check the key against list_trace_functions: a key that already appears there is live and sending traces.
    • While you are in these files, also Read every captured node's signature (the plan carries file, line, signature on each node) and note the plan's replay dependencies (captured external_read / side_effect nodes), so that if this draft proceeds you carry into step 14 the same context a discovery cycle would have held (its mock / DB-snapshot follow-ups included), and steps 13 and 14 do not have to re-read the code.

    Then take the branch that matches what you found, do not blindly wrap: wrapping a root that is already instrumented would duplicate the trace, you would create a second root span over the same call and the workflow would report twice.

    A) Wire up this draft: the normal case: present the draft, confirm it, then instrument (recommended) β†’ step 13 B) Already instrumented, retire the draft: re-wrapping would duplicate the root span; cancel the draft, offer setup modify, move to the next draft β†’ step 8 C) Refresh this draft in place: rebuild the tree from current code, save it onto the same plan id, then present it β†’ step 13 D) Workflow gone, retire the draft: nothing left to instrument; cancel the draft and move to the next one β†’ step 8

    A is the normal reuse case: it carries the existing draft plan id into step 13, which presents the already-built draft (no re-build) and opens/confirms it exactly like a freshly built plan.

    C repairs the draft instead of throwing it away. The workflow still exists, the draft just describes where it used to be, so rebuild its tree from the current code (the same reconcile rules bitfab:setup modify uses: keep a node's id, samples, and analysis where its implementation identity is clear, mint new ids for genuinely new nodes, and backfill sampleInput / sampleOutput / analysis on anything you added or changed), then save it back onto the SAME draft with save_trace_plan { planId, tree, capturedNodeIds }. A structural update may replace tree.rootId, so a moved or renamed boundary is a refresh, not a reason for a second plan. Carry that same plan id and your refreshed tree into step 13. Say in one line what moved. Never leave a stale draft in the reuse list for a later session to pick up, and never create a competing plan for a key that already has one.

    B and D retire this draft with cancel_trace_plan and loop back here for the next queued draft, so a moot draft never reaches the user and never resurfaces in a later probe. Cancelling is final, whic

*Truncated - read the full file at https://github.com/Project-White-Rabbit/bitfab-amp-plugin/blob/75b0b1b0caa1dff6d8ea6f6fdd27563a2e7e8c8d/skills/setup/SKILL.md.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/project-white-rabbit-bitfab-amp-plugin-setup/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

project-white-rabbit-bitfab-amp-plugin-setup.ocm.jsonjson
{
  "ocm": "1",
  "id": "project-white-rabbit-bitfab-amp-plugin-setup",
  "kind": "skill",
  "name": "setup",
  "description": "Set up and maintain Bitfab tracing for AI features. TRIGGER when: user wants to set up Bitfab, instrument code, add tracing/observability for LLM or agent calls, observe AI calls, add evaluation, trace LLM functions, trace a new workflow, change what an existing trace captures, re-instrument an existing traced function (move a database read or other side effect in or out of a span, change what a span records as its input/output), inspect or debug their tracing setup (what's instrumented, why traces aren't showing up), or understand what Bitfab is; or says anything like 'instrument', 'add tracing', 'trace my code', 'set up observability', 'hook up Bitfab', 'start tracking my AI workflow', 'trace a new workflow', 'create a trace plan', 'bitfab create a plan', 'give me the trace plan', 'give me the trace plan for <function>', 'show me the trace plan', 'update my tracing setup', 're-instrument', 're-instrument <function>', 'move the database read out of the span', 'make this trace replayable without a database', ",
  "publisher": "Project-White-Rabbit",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "github"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Set up and maintain Bitfab tracing for AI features. TRIGGER when: user wants to set up Bitfab, instrument code, add tracing/observability for LLM or agent calls, observe AI calls, add evaluation, trace LLM functions, trace a new workflow, change what an existing trace captures, re-instrument an existing traced function (move a database read or other side effect in or out of a span, change what a span records as its input/output), inspect or debug their tracing setup (what's instrumented, why traces aren't showing up), or understand what Bitfab is; or says anything like 'instrument', 'add tracing', 'trace my code', 'set up observability', 'hook up Bitfab', 'start tracking my AI workflow', 'trace a new workflow', 'create a trace plan', 'bitfab create a plan', 'give me the trace plan', 'give me the trace plan for <function>', 'show me the trace plan', 'update my tracing setup', 're-instrument', 're-instrument <function>', 'move the database read out of the span', 'make this trace replayable without a database', "
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "github",
      "repository": "https://github.com/Project-White-Rabbit/bitfab-amp-plugin",
      "path": "skills/setup/SKILL.md",
      "ref": "75b0b1b0caa1dff6d8ea6f6fdd27563a2e7e8c8d",
      "url": "https://github.com/Project-White-Rabbit/bitfab-amp-plugin/blob/75b0b1b0caa1dff6d8ea6f6fdd27563a2e7e8c8d/skills/setup/SKILL.md",
      "key": "Project-White-Rabbit/bitfab-amp-plugin/skills/setup/SKILL.md"
    }
  },
  "instructions": "# Bitfab Setup\n\n**When the flow branches, always present the options clearly and wait for the user's answer before proceeding.** Number or letter the options so the user can pick by reference. Rules:\n- Recommend an option first, explain why in one line\n- Present 2-5 concrete options\n- One decision per question, never batch\n\n**Execution style (applies to every phase).** Default to terse, action-first turns:\n- During mechanical phases (detecting language, searching code, reading files), run the tools and report only what you found. Do not narrate each command or pre-announce what you are about t",
  "cost": {
    "context_tokens": 60199
  }
}

Fetch it by URL: GET /api/v1/registry/project-white-rabbit-bitfab-amp-plugin-setup/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.