bitfab-cli 0.2.398 → 0.2.400

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +50 -25
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -26022,14 +26022,17 @@ Run ${platform2.loginHint} to re-authenticate.`);
26022
26022
  }
26023
26023
 
26024
26024
  // ../bitfab-plugin-lib/dist/commands/switchOrg.js
26025
- async function requestSwitch(serviceUrl, apiKey, clerkOrganizationId) {
26025
+ async function requestSwitch(serviceUrl, apiKey, authOrganizationId) {
26026
26026
  const res = await fetch(`${serviceUrl}/api/plugin/organizations/switch`, {
26027
26027
  method: "POST",
26028
26028
  headers: {
26029
26029
  Authorization: `Bearer ${apiKey}`,
26030
26030
  "Content-Type": "application/json"
26031
26031
  },
26032
- body: JSON.stringify({ clerkOrganizationId })
26032
+ body: JSON.stringify({
26033
+ authOrganizationId,
26034
+ clerkOrganizationId: authOrganizationId
26035
+ })
26033
26036
  });
26034
26037
  if (!res.ok) {
26035
26038
  throw new Error(`Failed to switch organization (HTTP ${res.status})`);
@@ -26038,9 +26041,9 @@ async function requestSwitch(serviceUrl, apiKey, clerkOrganizationId) {
26038
26041
  }
26039
26042
  var ARGS = [
26040
26043
  {
26041
- name: "clerkOrganizationId",
26044
+ name: "authOrganizationId",
26042
26045
  required: false,
26043
- description: "Clerk organization ID to make active. Discover IDs with the list_organizations MCP tool."
26046
+ description: "Organization ID to make active. Discover IDs with the list_organizations MCP tool."
26044
26047
  }
26045
26048
  ];
26046
26049
  async function runSwitchOrg(platform2) {
@@ -26049,21 +26052,21 @@ async function runSwitchOrg(platform2) {
26049
26052
  })[0] ?? null;
26050
26053
  const { apiKey, serviceUrl } = requireAuth(platform2.loginHint);
26051
26054
  if (!target) {
26052
- console.error("Usage: switchOrg <clerkOrganizationId>");
26055
+ console.error("Usage: switchOrg <authOrganizationId>");
26053
26056
  console.error("Discover org ids with the list_organizations MCP tool, then pass one here.");
26054
26057
  process.exit(1);
26055
26058
  }
26056
26059
  try {
26057
26060
  const result = await requestSwitch(serviceUrl, apiKey, target);
26058
26061
  if (result.status === "not-member") {
26059
- emitJson({ event: "not-member", clerkOrganizationId: target });
26062
+ emitJson({ event: "not-member", authOrganizationId: target });
26060
26063
  return;
26061
26064
  }
26062
26065
  saveCredentials(result.apiKey);
26063
26066
  emitJson({
26064
26067
  event: "switched",
26065
26068
  status: result.status,
26066
- clerkOrganizationId: result.clerkOrganizationId,
26069
+ authOrganizationId: result.authOrganizationId ?? result.clerkOrganizationId ?? target,
26067
26070
  organizationName: result.organizationName,
26068
26071
  apiKey: result.apiKey
26069
26072
  });
@@ -26805,6 +26808,9 @@ var Flow = external_exports.object({
26805
26808
  * `split-chain` (a dispatch edge back to an earlier sub-skill renders
26806
26809
  * like any other), which the sequential `split` orchestrator cannot
26807
26810
  * express.
26811
+ * Codex writes non-inline phases to ordinary `references/<phase>.md`
26812
+ * files and routes by reading them, keeping phase names out of skill
26813
+ * discovery. Other targets emit phase sub-skills.
26808
26814
  *
26809
26815
  * `mode` is per-target (the standard default-plus-override form), so split
26810
26816
  * can roll out one target at a time: `{ default: "monolith", claude:
@@ -27526,9 +27532,25 @@ function escapeMermaidLabel(s2) {
27526
27532
  function s(value, target, label) {
27527
27533
  return resolveTargetableString(value, target, label);
27528
27534
  }
27535
+ function usesPhaseReferences(flow, target) {
27536
+ return target.name === "codex" && resolvePerTarget(flow.compile.mode, target.name) === "split-chain";
27537
+ }
27529
27538
  function dispatchSkillRef(target, skillName) {
27530
27539
  return target.dispatchRef?.(skillName) ?? `\`${skillName}\``;
27531
27540
  }
27541
+ function phaseDestination(flow, target, phaseId, unitPhases) {
27542
+ if (!usesPhaseReferences(flow, target)) {
27543
+ return `the ${dispatchSkillRef(target, `${flow.id}-${phaseId}`)} skill`;
27544
+ }
27545
+ const phase = flow.phases.find((candidate) => candidate.id === phaseId);
27546
+ if (phase === void 0) {
27547
+ throw new Error(`Unknown phase "${phaseId}" in flow "${flow.id}"`);
27548
+ }
27549
+ const fromReference = [...unitPhases].some((id) => !flow.compile.inlinePhases.includes(id));
27550
+ const prefix = fromReference ? "./" : "references/";
27551
+ const title = s(phase.title, target.name, `phase[${phaseId}].title`);
27552
+ return `the [${title}](${prefix}${phaseId}.md) reference`;
27553
+ }
27532
27554
  function resolveArgumentHint(flow, target) {
27533
27555
  const argumentHint = flow.frontmatter.argumentHint;
27534
27556
  if (argumentHint === void 0) {
@@ -27632,7 +27654,7 @@ function applyFlowPlaceholders(text2, flow, target, unitPhases) {
27632
27654
  const title = s(phase.title, target.name, `phase[${phaseId}].title`);
27633
27655
  return `the *${title}* section`;
27634
27656
  }
27635
- return `the ${dispatchSkillRef(target, `${flow.id}-${phaseId}`)} skill`;
27657
+ return phaseDestination(flow, target, phaseId, unitPhases);
27636
27658
  });
27637
27659
  result = result.replace(/\{\{dispatch-ref:([a-z0-9-]+)\}\}/g, (_match, phaseId) => {
27638
27660
  const phase = flow.phases.find((p9) => p9.id === phaseId);
@@ -27644,8 +27666,8 @@ function applyFlowPlaceholders(text2, flow, target, unitPhases) {
27644
27666
  const title = s(phase.title, target.name, `phase[${phaseId}].title`);
27645
27667
  return `the *${title}* section`;
27646
27668
  }
27647
- const skill = dispatchSkillRef(target, `${flow.id}-${phaseId}`);
27648
- return `the ${skill} skill with the current mode, forwarding \`${target.argsToken}\` minus the leading mode keyword (if the user typed one)`;
27669
+ const destination = phaseDestination(flow, target, phaseId, unitPhases);
27670
+ return `${destination} with the current mode, forwarding \`${target.argsToken}\` minus the leading mode keyword (if the user typed one)`;
27649
27671
  });
27650
27672
  const stepNumbers = computeStepNumbers(flow, target.name, unitPhases === void 0 && flow.compile.continuousStepNumbers === true);
27651
27673
  result = result.replace(/\{\{step:([a-z0-9-]+\/[a-z0-9-]+)\}\}/g, (_match, ref) => {
@@ -27827,6 +27849,9 @@ function destinationRenderer(flow, target, unitPhases) {
27827
27849
  }
27828
27850
  const phaseId = ref.split("/")[0];
27829
27851
  if (unitPhases !== void 0 && !unitPhases.has(phaseId)) {
27852
+ if (usesPhaseReferences(flow, target)) {
27853
+ return phaseDestination(flow, target, phaseId, unitPhases);
27854
+ }
27830
27855
  return `the \`${flow.id}-${phaseId}\` skill`;
27831
27856
  }
27832
27857
  if (phaseId === sourcePhaseId) {
@@ -31198,8 +31223,8 @@ var setupFlow = Flow.parse({
31198
31223
  description: "Open a sign-in window and wait for authentication. Relay the printed sign-in link as a fallback."
31199
31224
  },
31200
31225
  switchOrg: {
31201
- description: "List the user's Bitfab orgs (no args), or switch the plugin's active org and replace the local API key (with a <clerkOrganizationId> arg)",
31202
- args: "[<clerkOrganizationId>]"
31226
+ description: "List the user's Bitfab orgs (no args), or switch the plugin's active org and replace the local API key (with a <authOrganizationId> arg)",
31227
+ args: "[<authOrganizationId>]"
31203
31228
  },
31204
31229
  startTemplatePreview: {
31205
31230
  description: "Print a template preview link and exit.",
@@ -31358,9 +31383,9 @@ Never modify existing code on a refactor path without completing this three-step
31358
31383
  kind: "action",
31359
31384
  title: "Inspect the replay environment",
31360
31385
  toolCalls: ["bash", "read", "glob", "grep", "ask"],
31361
- body: `Read the existing GitHub Actions, runtime manifests, lockfiles, replay registry, gitignore, and environment-variable NAMES. Never read or print secret values. Check git origin, Python 3.10+, and gh authentication. Local dispatch supports macOS/Linux and github.com. Inspect all push-triggered workflows and deployment integrations. Temporary branches use bitfab-replay/** and can trigger those systems. Ask before changing existing CI or deployment behavior. Do not set pushTriggersReviewed until these triggers have been reviewed with the user.
31386
+ body: `Read the existing GitHub Actions, runtime manifests, lockfiles, replay registry, gitignore, and environment-variable NAMES. Never read or print secret values. Check git origin, Python 3.10+, and gh authentication. Local dispatch supports macOS/Linux and github.com. Inspect all push-triggered workflows and deployment integrations. Temporary branches use bitfab-replay/** and can trigger those systems. Offer the usual fixes: a push workflow can add bitfab-replay/** to branches-ignore, and a Vercel project can skip those branches with git.deploymentEnabled {"bitfab-replay/**": false} in its vercel.json or an Ignored Build Step in the dashboard. Ask before changing existing CI or deployment behavior. Do not set pushTriggersReviewed until these triggers have been reviewed with the user.
31362
31387
 
31363
- Choose one existing replay pipeline and reproduce its runtime, dependency installation, build steps, working directory, caches, and required services from CI. Use the installed SDK's cloud-capable CLI. TypeScript/Python/Ruby registry imports happen on the runner only. Go must dispatch cloud flags before building its registry or initializing the application. A private database needs runner network access or a replay-safe service fixture. Do not silently give replay production side effects. Submodules/gitlinks and credential-like tracked files are rejected by the snapshot helper. Surface blockers instead of claiming the environment is ready.
31388
+ Choose one existing replay registry and reproduce its runtime, dependency installation, build steps, working directory, caches, and required services from CI. Cover what every pipeline in that registry needs, since cloud replay allows all of them by default. Use the installed SDK's cloud-capable CLI: run its bitfab-replay --cloud --help now. If it does not print the cloud options, the project's SDK predates cloud replay, so upgrade it through bitfab:update before continuing. Never give the user .bitfab/cloudReplay.py as the command to run; the SDK command starts it. TypeScript/Python/Ruby registry imports happen on the runner only. Go must dispatch cloud flags before building its registry or initializing the application. For database reads, prefer database branching. When the Bitfab organization has a database connected, each replay item gets a branch at its trace's captured instant, and the runner needs no database secret. That works only when every registry entry that reads the database sets dbBranch, and the application takes its connection per call from the replay branch URL (getCurrentReplayBranch().databaseUrl, or the Python, Ruby, or Go equivalent), falling back to its normal URL. A pool or engine created once at import from DATABASE_URL never sees the branch, and the SDK does not change DATABASE_URL, so check how the application builds its database client. When either piece is missing, offer to run db-snapshot mode first. Without branching, a private database needs runner network access or a replay-safe service fixture. Do not silently give replay production side effects. Submodules/gitlinks and credential-like tracked files are rejected by the snapshot helper. A gitlink with no .gitmodules entry is usually a nested repository committed by accident: offer to untrack it with git rm --cached and ignore its folder. Surface blockers instead of claiming the environment is ready.
31364
31389
 
31365
31390
  Present the proposed workflow, fixed replay command, required secret/variable names, and any required CI trigger exclusions. Ask only about unresolved project choices. Never ask for secret values in chat.`,
31366
31391
  next: "cloud/install"
@@ -31370,15 +31395,15 @@ Present the proposed workflow, fixed replay command, required secret/variable na
31370
31395
  kind: "action",
31371
31396
  title: "Install the repository-owned runner",
31372
31397
  toolCalls: ["bash", "read", "write", "edit"],
31373
- body: `Create a reviewed JSON setup specification containing version: 1, provider: "github", workflow: "bitfab-replay.yml", workingDirectory (repository-relative), registry (repository-relative path or null for Go), pipeline, command (a JSON argv array without the pipeline argument or cloud flags), pushTriggersReviewed: true, setupSteps (GitHub Actions step objects), secrets (names including BITFAB_API_KEY), and variables (names only). Optional secretPrefix (uppercase, ending in an underscore) names the GitHub secret each one is read from without changing the environment variable the replay sees; it defaults to BITFAB_CLOUD_, and only an explicit empty string turns prefixing off. Optional runsOn, services, and environment match the existing CI. Prefer a GitHub Environment with required reviewers when replay code receives sensitive credentials. Pin third-party actions to reviewed commit SHAs. Ensure Python 3.10+ exists on the runner. Commands run in workingDirectory. Registry in the command must be relative to that directory. Set step working-directory explicitly where needed. Do not copy deployment steps, local env values, or API keys into the specification.
31398
+ body: `Create a reviewed JSON setup specification containing version: 1, provider: "github", workflow: "bitfab-replay.yml", workingDirectory (repository-relative), registry (repository-relative path or null for Go), pipeline (null allows every pipeline in the registry and is the default; a name restricts replay to that one pipeline, for when the others need credentials or services the runner should not have), command (a JSON argv array without the pipeline argument or cloud flags), pushTriggersReviewed: true, setupSteps (GitHub Actions step objects), secrets (names including BITFAB_API_KEY), and variables (names only). The runner always provides BITFAB_API_KEY. Find the variable the registry's Bitfab client actually reads its key from, and when it is another name, map it in the command, for example ["sh", "-c", "APP_KEY_NAME=\\"$BITFAB_API_KEY\\" exec <command> \\"$@\\"", "sh"]. Optional secretPrefix (uppercase, ending in an underscore) names the GitHub secret each one is read from without changing the environment variable the replay sees; it defaults to BITFAB_CLOUD_, and only an explicit empty string turns prefixing off. Optional runsOn, services, and environment match the existing CI. Prefer a GitHub Environment with required reviewers when replay code receives sensitive credentials. Pin third-party actions to reviewed commit SHAs. Ensure Python 3.10+ exists on the runner. Commands run in workingDirectory. Registry in the command must be relative to that directory. Set step working-directory explicitly where needed. Do not copy deployment steps, local env values, or API keys into the specification.
31374
31399
 
31375
31400
  Run python3 "{{pluginRoot}}/scripts/cloudReplay.py" init --config <specification-path>. This creates .bitfab/cloud.json, .bitfab/cloudReplay.py, and .github/workflows/bitfab-replay.yml. The generated workflow is JSON, which is valid YAML. Existing files are never overwritten. For an existing setup, review the diff and edit project configuration deliberately. Remove only your temporary specification after successful installation. If .bitfab is ignored, propose a narrow gitignore exception for these two files. Never force-add secrets or arbitrary ignored files.
31376
31401
 
31377
- Tell the user which repository or Environment secrets to create in GitHub Settings \u2192 Secrets and variables \u2192 Actions. BITFAB_API_KEY belongs to their intended Bitfab organization. Other names come from their application, such as OPENAI_API_KEY. BITFAB_SERVICE_URL is optional. Do not override the SDK's default with an empty GitHub variable. Runtime secrets belong on the replay step. Any install-time credentials need explicit references on the relevant setup step. Local gh authentication is separate from these runner secrets. Do not create a Bitfab cloud target, install a GitHub App, or request a repository connection.
31402
+ Tell the user which repository or Environment secrets to create in GitHub Settings \u2192 Secrets and variables \u2192 Actions. BITFAB_API_KEY belongs to the Bitfab organization that holds the registry's traces; confirm that with the user, because a key from another organization finds none of them. Other names come from their application, such as OPENAI_API_KEY. BITFAB_SERVICE_URL is optional. Do not override the SDK's default with an empty GitHub variable. Runtime secrets belong on the replay step. Any install-time credentials need explicit references on the relevant setup step. Local gh authentication is separate from these runner secrets. Do not create a Bitfab cloud target, install a GitHub App, or request a repository connection.
31378
31403
 
31379
31404
  Init records the secret names and the resolved prefix in .bitfab/cloud.json, so later lifecycle commands reuse them without being told again. Runner secrets are prefixed BITFAB_CLOUD_ unless the user asks otherwise, so the runner reads BITFAB_CLOUD_OPENAI_API_KEY and exposes it to the replay as OPENAI_API_KEY. Replay credentials then never collide with secrets the repository already uses, and can carry narrower scopes or a different Bitfab organization than production. Pass a different prefix, or an empty string to reuse the repository's existing bare-named secrets, only when the user wants that. Report the prefixed names from requiredSecrets as the ones to create.
31380
31405
 
31381
- When the project keeps local environment files, list the NAMES each required secret could come from and ask whether to copy those local values into GitHub. Never read, print, or compare the values, and ask once for the whole set rather than per secret. On a yes, run python3 .bitfab/cloudReplay.py secrets --env-file <file> [--env-file <file>] [--environment <name>], which reads the recorded names and prefix, parses quoted, multi-line, and JSON values correctly, and pipes each value to gh on standard input so it never appears in arguments, process listings, or shell history. Never hand-extract a value with grep, cut, or a shell variable, and never pass one through gh secret set --body. Use --dry-run first to report which names the files define. The command reports set, missing, and empty names only; create the missing ones by hand. A name your files define as blank is skipped rather than uploaded, because an empty secret replaces a working default with nothing. Warn before copying a value whose own configuration points somewhere a runner cannot reach, such as a localhost service URL, or that grants more than the replay needs, and let the user decide. Setting secrets requires the same explicit authorization as any other remote write, and a wrong value only surfaces when the first real replay runs, since the dry run never calls the application.`,
31406
+ When the project keeps local environment files, list the NAMES each required secret could come from and ask whether to copy those local values into GitHub. Never read, print, or compare the values, and ask once for the whole set rather than per secret. On a yes, run python3 .bitfab/cloudReplay.py secrets --env-file <file> [--env-file <file>] [--environment <name>], which reads the recorded names and prefix, parses quoted, multi-line, and JSON values correctly, and pipes each value to gh on standard input so it never appears in arguments, process listings, or shell history. Never hand-extract a value with grep, cut, or a shell variable, and never pass one through gh secret set --body. Use --dry-run first to report which names the files define. The command reports set, missing, and empty names only; create the missing ones by hand. A name your files define as blank is skipped rather than uploaded, because an empty secret replaces a working default with nothing. Warn before copying a value whose own configuration points somewhere a runner cannot reach, such as a localhost service URL, or that grants more than the replay needs, and let the user decide. When the value for BITFAB_API_KEY lives locally under the client's other name, or only a development key sits under BITFAB_API_KEY, leave it out of the copy and have the user set it. Environment secrets need the Environment to exist: check with gh api repos/<owner>/<repo>/environments, and when it is missing, ask before creating it with gh api -X PUT repos/<owner>/<repo>/environments/<name>, offering the user as a required reviewer. Setting secrets requires the same explicit authorization as any other remote write, and a wrong value only surfaces when the first real replay runs, since the dry run never calls the application.`,
31382
31407
  next: "cloud/verify"
31383
31408
  },
31384
31409
  {
@@ -31388,7 +31413,7 @@ When the project keeps local environment files, list the NAMES each required sec
31388
31413
  toolCalls: ["bash", "read", "ask"],
31389
31414
  body: `Validate workflow syntax (actionlint when available) and run the installed SDK CLI with --cloud --help. The workflow must land on the default branch once before workflow_dispatch can run it on temporary branches. Explain the required commit/merge. Do not push, merge, change repository permissions, or set secrets without authorization.
31390
31415
 
31391
- After the setup files are tracked, run bitfab-replay --cloud <pipeline> --trace-ids <real-trace-uuid> --cloud-dry-run using the selected SDK command. It reports changed tracked files and omitted new files. Include new source files explicitly with repeated --cloud-include <repository-relative-file>. Review the entire snapshot for credentials. Filename screening is not a secret scanner. Then, only when remote replay is authorized, run without --cloud-dry-run. The helper creates a commit through an isolated index, pushes bitfab-replay/<UUID>, dispatches that branch, waits, retrieves the test-run identity, and deletes the branch with an exact-SHA lease. HEAD, staged changes, and working files stay untouched. Never reset or undo the user's work.
31416
+ After the setup files are tracked (until then, pass each one with --cloud-include; the helper names any that are missing), run bitfab-replay --cloud <pipeline> --trace-ids <real-trace-uuid> --cloud-dry-run using the selected SDK command. It reports changed tracked files and omitted new files. Include new source files explicitly with repeated --cloud-include <repository-relative-file>. Review the entire snapshot for credentials. Filename screening is not a secret scanner. Then, only when remote replay is authorized, run without --cloud-dry-run. The helper creates a commit through an isolated index, pushes bitfab-replay/<UUID>, dispatches that branch, waits, retrieves the test-run identity, and deletes the branch with an exact-SHA lease. HEAD, staged changes, and working files stay untouched. Never reset or undo the user's work.
31392
31417
 
31393
31418
  Use --cloud-detach to return immediately. Explain --cloud-status, --cloud-watch, --cloud-cancel, and --cloud-cleanup with the printed execution UUID. Records live under this worktree's Git directory. Interrupted/lost-response submissions must be recovered, not blindly dispatched again. Cancel requests do not imply the job stopped. Watch/status confirms completion before deleting the branch. Detached jobs do not automatically clean themselves without a later local lifecycle command. Report separately whether files are generated, secrets configured, workflow merged, dry-run verified, and an actual remote replay completed. Never call a mock smoke run a real replay.`,
31394
31419
  next: "cleanup/finish"
@@ -32208,7 +32233,7 @@ Then, for anything not healthy, name the most likely cause and the fix:
32208
32233
  - **Root not replayable**, two failure modes, with the fix matched to each: **(a) the root takes unserializable inputs** (live SDK/DB clients, HTTP req/res, streams, opaque contexts), with or without a replay registry module: move the trace boundary inward to a serializable-input function or refactor to introduce one; **(b) a bare trace-processor-only key** ({{traceProcessorNames}}) whose root is the processor's empty-input span: add a \`withTrace\`/\`trace\` root that wraps the run and takes its input in a supported subtree runtime, or route the run through the run wrapper ({{traceProcessorRootWrappers}}). Use a manual \`withSpan\`/\`@span\` root only when opt-out is technically unavailable. Either way, re-instrument via \`{{cmd}}setup modify\` (or \`{{cmd}}setup instrument\` for a fresh boundary). This is a code change, recommended here, not applied blanket.
32209
32234
  - **Opt-out roots without subtree capture**: every trace is the root alone, so tracing looks healthy and the traces are useless for per-step diagnosis, replay mocking, and prompt iteration. For TypeScript, use the installed SDK and wire the matching adapter into the build behind the server entrypoint, preserving existing config wrappers such as Sentry. For Python, this is a runtime upgrade to 3.12+; report it rather than attempting it.
32210
32235
  - **Instrumented but no traces**: the app hasn't run with tracing enabled, or \`BITFAB_API_KEY\` isn't set in the run environment. Run the app with the key loaded.
32211
- - **Key set but traces aren't visible in the browser**: the API key is bound to a different Clerk org/tenant than the browser session. A key resolves \`API key \u2192 organization_id \u2192 clerk_organization_id \u2192 Clerk tenant\` at creation time; browser visibility requires both to be the same tenant.
32236
+ - **Key set but traces aren't visible in the browser**: the API key belongs to a different organization than the one the browser is showing. A key is bound to one organization when it is created, and the browser shows the signed-in user's active organization. Have the user pick the key's organization in the in-app org switcher; if it isn't listed, the signed-in user isn't a member of it.
32212
32237
  - **Nothing instrumented**: run \`{{cmd}}setup instrument\`.
32213
32238
  - **Want to change what's captured**: run \`{{cmd}}setup modify\`.
32214
32239
 
@@ -32272,7 +32297,7 @@ For unusual monorepos or private registries, defer to \`{{cmd}}update\`. Report
32272
32297
  stepStyle: "list",
32273
32298
  intro: `Switch which Bitfab organization the plugin reads and writes. Triggered explicitly by \`{{cmd}}setup switch-org\` (or natural-language asks like "switch org" / "change org" / "switch to the <name> org" / "I'm in the wrong org"). The plugin's org is set by the API key in \`~/.config/bitfab/credentials.json\`; this lists the user's orgs, switches to the chosen one, and replaces that local key. Requires authentication. Does **not** open Bitfab.
32274
32299
 
32275
- **The live browser does not follow on its own.** Switching persists the new active org server-side (so future sign-ins default to it) and replaces the plugin's key, but a browser tab that's already signed in keeps showing the old org until its session is re-minted. The org actually flips in the browser on the **next** Bitfab open (a fresh session whose org check runs Clerk's client-side \`setActive\`) or when the user picks the org from the in-app org switcher.
32300
+ **The live browser does not follow on its own.** Switching persists the new active org server-side (so future sign-ins default to it) and replaces the plugin's key, but a browser tab that's already signed in keeps showing the old org until its session is re-minted. The org actually flips in the browser on the **next** Bitfab open (a fresh session whose org check sets the active organization in the browser) or when the user picks the org from the in-app org switcher.
32276
32301
 
32277
32302
  **The plugin key and the app's runtime key are separate.** Switching replaces only the plugin's credential in \`~/.config/bitfab/credentials.json\`. The \`BITFAB_API_KEY\` your application reads at runtime (from a \`.env\`-style file) is untouched, so traces your code sends keep landing in the **old** org until that key is updated too. The last step offers to do that.`,
32278
32303
  steps: [
@@ -32305,7 +32330,7 @@ If **already authenticated**, continue to step {{step:switch-org/pick-org}}. If
32305
32330
  kind: "branch",
32306
32331
  toolCalls: ["listOrganizations", "ask"],
32307
32332
  title: "List the orgs and choose a target",
32308
- body: `Call {{tool:listOrganizations}} to list the organizations the signed-in user belongs to. Each entry has a name, the user's role, an \`id:\` (the \`clerkOrganizationId\`), and the org the plugin uses now is marked \`[current]\`.
32333
+ body: `Call {{tool:listOrganizations}} to list the organizations the signed-in user belongs to. Each entry has a name, the user's role, an \`id:\` (the \`authOrganizationId\`), and the org the plugin uses now is marked \`[current]\`.
32309
32334
 
32310
32335
  Choose the target org:
32311
32336
  - **If the user already named an org** (in their request), match it case-insensitively by name against the list and use that org's \`id\`. If the name matches none, or matches more than one, fall through to asking.
@@ -32330,15 +32355,15 @@ Only ever use an \`id\` value returned by {{tool:listOrganizations}}; never inve
32330
32355
  toolCalls: ["bash"],
32331
32356
  commandCalls: ["switchOrg"],
32332
32357
  title: "Switch and confirm",
32333
- body: `Switch to the chosen org by passing its \`clerkOrganizationId\`:
32358
+ body: `Switch to the chosen org by passing its \`authOrganizationId\`:
32334
32359
 
32335
32360
  \`\`\`bash
32336
- {{command:switchOrg}} <clerkOrganizationId>
32361
+ {{command:switchOrg}} <authOrganizationId>
32337
32362
  \`\`\`
32338
32363
 
32339
32364
  The command prints one JSON line; act on it:
32340
- - \`{"event":"switched","status":"switched"|"already-aligned","clerkOrganizationId":"...","organizationName":"...","apiKey":"..."}\`: success. The plugin now reads and writes that org and its API key has been replaced locally. Tell the user in one line: the plugin is now connected to **<organizationName>**. Then tell them to select **<organizationName>** with the in-app org switcher to align their browser with the plugin. Opening a plugin page link does not change the browser's active organization. Hold on to the \`apiKey\` value from this JSON; the next step uses it to sync the app's local key, and you must never echo that value to the user.
32341
- - \`{"event":"not-member","clerkOrganizationId":"..."}\`: the user isn't a member of that org. Report it; do not retry.
32365
+ - \`{"event":"switched","status":"switched"|"already-aligned","authOrganizationId":"...","organizationName":"...","apiKey":"..."}\`: success. The plugin now reads and writes that org and its API key has been replaced locally. Tell the user in one line: the plugin is now connected to **<organizationName>**. Then tell them to select **<organizationName>** with the in-app org switcher to align their browser with the plugin. Opening a plugin page link does not change the browser's active organization. Hold on to the \`apiKey\` value from this JSON; the next step uses it to sync the app's local key, and you must never echo that value to the user.
32366
+ - \`{"event":"not-member","authOrganizationId":"..."}\`: the user isn't a member of that org. Report it; do not retry.
32342
32367
  - \`{"event":"error","reason":"..."}\`: report the reason.
32343
32368
 
32344
32369
  Do not print or ask for the API key, and do not surface the \`apiKey\` value to the user; the command replaces the plugin's copy for you and hands you that value solely for the next step.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitfab-cli",
3
- "version": "0.2.398",
3
+ "version": "0.2.400",
4
4
  "description": "Install and configure the Bitfab plugin in Claude Code, Codex, or Cursor, or the Bitfab skill pack in Amp (Alpha).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",