agent-shim 8.28.0 → 8.30.0

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.
package/dist/index.cjs CHANGED
@@ -5333,10 +5333,113 @@ function createRcCredentialStore(fs12, dir) {
5333
5333
  // src/frontdoor/rcApi.ts
5334
5334
  var import_client = require("@orpc/client");
5335
5335
  var import_fetch = require("@orpc/client/fetch");
5336
+ var import_openapi = require("@orpc/openapi");
5337
+ var import_node = require("@orpc/openapi/node");
5336
5338
  var import_server2 = require("@orpc/server");
5337
- var import_node = require("@orpc/server/node");
5339
+ var import_node2 = require("@orpc/server/node");
5338
5340
  var import_undici = require("undici");
5339
5341
 
5342
+ // package.json
5343
+ var package_default = {
5344
+ name: "agent-shim",
5345
+ version: "8.30.0",
5346
+ description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
5347
+ license: "MIT",
5348
+ author: "Joseph Mearman <joseph@mearman.co.uk>",
5349
+ repository: {
5350
+ type: "git",
5351
+ url: "git+https://github.com/ExaDev/agent-shim.git"
5352
+ },
5353
+ homepage: "https://github.com/ExaDev/agent-shim#readme",
5354
+ bugs: "https://github.com/ExaDev/agent-shim/issues",
5355
+ keywords: [
5356
+ "claude-code",
5357
+ "claude",
5358
+ "cli"
5359
+ ],
5360
+ packageManager: "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
5361
+ type: "module",
5362
+ engines: {
5363
+ node: "^22.18 || >=24"
5364
+ },
5365
+ bin: {
5366
+ "agent-shim": "dist/cli.cjs",
5367
+ "claude-use": "dist/cli.cjs"
5368
+ },
5369
+ files: [
5370
+ "dist/cli.cjs",
5371
+ "dist/index.mjs",
5372
+ "dist/index.cjs",
5373
+ "dist/types"
5374
+ ],
5375
+ scripts: {
5376
+ prepare: "husky && node scripts/build.mts --bundle-only",
5377
+ typecheck: "turbo run _typecheck",
5378
+ _typecheck: "tsc --noEmit",
5379
+ lint: "turbo run _lint",
5380
+ _lint: "eslint . --cache --cache-location .eslintcache --max-warnings 0",
5381
+ test: "turbo run _test",
5382
+ _test: "vitest run",
5383
+ "test:coverage": "turbo run _test:coverage",
5384
+ "_test:coverage": "vitest run --coverage",
5385
+ knip: "turbo run _knip",
5386
+ _knip: "knip --cache",
5387
+ build: "turbo run _build",
5388
+ _build: "node scripts/build.mts",
5389
+ "build:bundle": "node scripts/build.mts --bundle-only",
5390
+ prepublishOnly: "pnpm build:bundle",
5391
+ schema: "node scripts/gen-schema.mts"
5392
+ },
5393
+ dependencies: {
5394
+ "@clack/prompts": "^1.8.0",
5395
+ "@orpc/client": "1.15.4",
5396
+ "@orpc/openapi": "1.15.4",
5397
+ "@orpc/server": "1.15.4",
5398
+ commander: "^15.0.0",
5399
+ cosmiconfig: "^10.0.1",
5400
+ picomatch: "^4.0.7",
5401
+ undici: "7.29.1",
5402
+ zod: "^4.6.1"
5403
+ },
5404
+ devDependencies: {
5405
+ "@commitlint/cli": "^21.2.2",
5406
+ "@commitlint/config-conventional": "^21.2.2",
5407
+ "@exadev/eslint-config": "2.12.1",
5408
+ "@semantic-release/changelog": "^7.0.0",
5409
+ "@semantic-release/git": "^11.0.1",
5410
+ "@semantic-release/npm": "^13.1.5",
5411
+ "@types/node": "^26.5.1",
5412
+ "@types/picomatch": "^4.0.3",
5413
+ "@vitest/coverage-v8": "^4.1.11",
5414
+ "conventional-changelog-conventionalcommits": "^10.4.0",
5415
+ esbuild: "^0.28.2",
5416
+ eslint: "^10.10.0",
5417
+ globals: "^17.12.0",
5418
+ husky: "^9.1.7",
5419
+ jiti: "^2.7.0",
5420
+ knip: "^6.35.1",
5421
+ "lint-staged": "^17.5.0",
5422
+ rollup: "4.64.0",
5423
+ "rollup-plugin-dts": "6.5.1",
5424
+ "semantic-release": "^25.0.9",
5425
+ turbo: "^2.11.5",
5426
+ typescript: "^6.0.3",
5427
+ "typescript-eslint": "^8.70.0",
5428
+ vitest: "^4.1.11"
5429
+ },
5430
+ main: "dist/index.cjs",
5431
+ module: "dist/index.mjs",
5432
+ types: "dist/types/index.d.ts",
5433
+ exports: {
5434
+ ".": {
5435
+ types: "./dist/types/index.d.ts",
5436
+ import: "./dist/index.mjs",
5437
+ require: "./dist/index.cjs"
5438
+ },
5439
+ "./package.json": "./package.json"
5440
+ }
5441
+ };
5442
+
5340
5443
  // src/frontdoor/rcSchemas.ts
5341
5444
  var import_zod4 = require("zod");
5342
5445
  var RcPermissionModeSchema = import_zod4.z.enum(RC_PERMISSION_MODES);
@@ -5498,18 +5601,23 @@ var RcAnswerOutputSchema = import_zod4.z.strictObject({
5498
5601
 
5499
5602
  // src/frontdoor/rcApi.ts
5500
5603
  var RC_ORPC_PATH_PREFIX = "/__agent-shim/orpc";
5604
+ var RC_OPENAPI_DOC_PATH = "/openapi.json";
5501
5605
  var RC_SUBSCRIBER_BUFFER_EVENTS = 100;
5606
+ function doorApiBearer(headers) {
5607
+ const presented = headers.authorization;
5608
+ const bearerPrefix = "bearer ".length;
5609
+ return typeof presented === "string" && presented.slice(0, bearerPrefix).toLowerCase() === "bearer " ? presented.slice(bearerPrefix) : void 0;
5610
+ }
5502
5611
  function doorApiAuth(expectedToken) {
5503
5612
  return import_server2.os.$context().use(({ context, next }) => {
5504
- const presented = context.headers.authorization;
5505
- const bearerPrefix = "bearer ".length;
5506
- const token = typeof presented === "string" && presented.slice(0, bearerPrefix).toLowerCase() === "bearer " ? presented.slice(bearerPrefix) : void 0;
5613
+ const token = doorApiBearer(context.headers);
5507
5614
  if (token === void 0 || !isLiveCapability(token, [expectedToken])) {
5508
5615
  throw new import_client.ORPCError("UNAUTHORIZED", { message: "the front door's typed API demands this generation's control token as a Bearer credential" });
5509
5616
  }
5510
5617
  return next();
5511
5618
  });
5512
5619
  }
5620
+ var RC_API_TAG = "remote-control";
5513
5621
  function createRcApiRouter(deps) {
5514
5622
  const authed = doorApiAuth(deps.expectedToken);
5515
5623
  const delivered = (sessionId, result) => {
@@ -5529,41 +5637,41 @@ function createRcApiRouter(deps) {
5529
5637
  };
5530
5638
  return {
5531
5639
  rc: {
5532
- list: authed.output(RcListOutputSchema).handler(() => ({ sessions: deps.list() })),
5533
- status: authed.input(RcSessionQuerySchema).output(RcStatusOutputSchema).handler(({ input }) => {
5640
+ list: authed.route({ method: "GET", path: "/rest/rc/sessions", summary: "List the observed Remote Control sessions", tags: [RC_API_TAG] }).output(RcListOutputSchema).handler(() => ({ sessions: deps.list() })),
5641
+ status: authed.route({ method: "GET", path: "/rest/rc/status", summary: "Read session status, one session's when named", tags: [RC_API_TAG] }).input(RcSessionQuerySchema).output(RcStatusOutputSchema).handler(({ input }) => {
5534
5642
  const statuses = deps.statusOf(input.session);
5535
5643
  if (input.session !== void 0 && !statuses.some((entry) => entry.id === input.session)) {
5536
5644
  throw new import_client.ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
5537
5645
  }
5538
5646
  return { statuses };
5539
5647
  }),
5540
- pending: authed.input(RcSessionQuerySchema).output(RcPendingOutputSchema).handler(({ input }) => {
5648
+ pending: authed.route({ method: "GET", path: "/rest/rc/pending", summary: "Read the control requests awaiting an answer", tags: [RC_API_TAG] }).input(RcSessionQuerySchema).output(RcPendingOutputSchema).handler(({ input }) => {
5541
5649
  const pending = deps.pendingOf(input.session);
5542
5650
  if (input.session !== void 0 && deps.statusOf(input.session).length === 0) {
5543
5651
  throw new import_client.ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
5544
5652
  }
5545
5653
  return { pending };
5546
5654
  }),
5547
- send: authed.input(RcSendInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.inject(input.session, input.text)) })),
5548
- answer: authed.input(RcAnswerInputSchema).output(RcAnswerOutputSchema).handler(async ({ input }) => {
5655
+ send: authed.route({ method: "POST", path: "/rest/rc/send", summary: "Send one message into a session", tags: [RC_API_TAG] }).input(RcSendInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.inject(input.session, input.text)) })),
5656
+ answer: authed.route({ method: "POST", path: "/rest/rc/answer", summary: "Answer one pending control request", tags: [RC_API_TAG] }).input(RcAnswerInputSchema).output(RcAnswerOutputSchema).handler(async ({ input }) => {
5549
5657
  const decision = { approve: input.approve, message: input.approve || input.text === void 0 ? void 0 : input.text };
5550
5658
  return { session: input.session, request: input.request, sequenceNums: delivered(input.session, await deps.answer(input.session, input.request, decision)) };
5551
5659
  }),
5552
- interrupt: authed.input(RcInterruptInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.interrupt(input.session)) })),
5553
- setModel: authed.input(RcSetModelInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setModel(input.session, input.model)) })),
5554
- setPermissionMode: authed.input(RcSetPermissionModeInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setPermissionMode(input.session, input.mode)) })),
5555
- endSession: authed.input(RcEndSessionInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.endSession(input.session, input.reason)) })),
5556
- getUsage: authed.input(RcGetUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getUsage(input.session, input.skipBehaviors)) })),
5557
- getContextUsage: authed.input(RcGetContextUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getContextUsage(input.session, input.detail)) })),
5558
- readFile: authed.input(RcReadFileInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.readFile(input.session, input.path, { ...input.maxBytes === void 0 ? {} : { maxBytes: input.maxBytes }, ...input.encoding === void 0 ? {} : { encoding: input.encoding } })) })),
5559
- fileSuggestions: authed.input(RcFileSuggestionsInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.fileSuggestions(input.session, input.query)) })),
5560
- keepAlive: authed.input(RcKeepAliveInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.keepAlive(input.session)) })),
5561
- mcpStatus: authed.input(RcMcpStatusInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpStatus(input.session)) })),
5562
- mcpReconnect: authed.input(RcMcpReconnectInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpReconnect(input.session, input.serverName)) })),
5563
- mcpAuthenticate: authed.input(RcMcpAuthenticateInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpAuthenticate(input.session, input.serverName, input.redirectUri)) })),
5564
- mcpOAuthCallbackUrl: authed.input(RcMcpOAuthCallbackUrlInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpOAuthCallbackUrl(input.session, input.serverName, input.callbackUrl)) })),
5565
- teleport: authed.input(RcTeleportInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.teleport(input.session, input.marker)) })),
5566
- subscribe: authed.input(RcSessionQuerySchema).output((0, import_server2.eventIterator)(RcStreamEventSchema)).handler(async function* ({ input, signal }) {
5660
+ interrupt: authed.route({ method: "POST", path: "/rest/rc/interrupt", summary: "Interrupt a session's running turn", tags: [RC_API_TAG] }).input(RcInterruptInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.interrupt(input.session)) })),
5661
+ setModel: authed.route({ method: "POST", path: "/rest/rc/set-model", summary: "Switch a session's model", tags: [RC_API_TAG] }).input(RcSetModelInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setModel(input.session, input.model)) })),
5662
+ setPermissionMode: authed.route({ method: "POST", path: "/rest/rc/set-permission-mode", summary: "Switch a session's permission mode", tags: [RC_API_TAG] }).input(RcSetPermissionModeInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setPermissionMode(input.session, input.mode)) })),
5663
+ endSession: authed.route({ method: "POST", path: "/rest/rc/end-session", summary: "End a session", tags: [RC_API_TAG] }).input(RcEndSessionInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.endSession(input.session, input.reason)) })),
5664
+ getUsage: authed.route({ method: "POST", path: "/rest/rc/get-usage", summary: "Ask a session for its usage snapshot", tags: [RC_API_TAG] }).input(RcGetUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getUsage(input.session, input.skipBehaviors)) })),
5665
+ getContextUsage: authed.route({ method: "POST", path: "/rest/rc/get-context-usage", summary: "Ask a session for its context usage", tags: [RC_API_TAG] }).input(RcGetContextUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getContextUsage(input.session, input.detail)) })),
5666
+ readFile: authed.route({ method: "POST", path: "/rest/rc/read-file", summary: "Ask a session to read one file", tags: [RC_API_TAG] }).input(RcReadFileInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.readFile(input.session, input.path, { ...input.maxBytes === void 0 ? {} : { maxBytes: input.maxBytes }, ...input.encoding === void 0 ? {} : { encoding: input.encoding } })) })),
5667
+ fileSuggestions: authed.route({ method: "POST", path: "/rest/rc/file-suggestions", summary: "Ask a session for file-path suggestions", tags: [RC_API_TAG] }).input(RcFileSuggestionsInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.fileSuggestions(input.session, input.query)) })),
5668
+ keepAlive: authed.route({ method: "POST", path: "/rest/rc/keep-alive", summary: "Keep a session's bridge alive", tags: [RC_API_TAG] }).input(RcKeepAliveInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.keepAlive(input.session)) })),
5669
+ mcpStatus: authed.route({ method: "POST", path: "/rest/rc/mcp-status", summary: "Ask a session for its MCP servers' status", tags: [RC_API_TAG] }).input(RcMcpStatusInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpStatus(input.session)) })),
5670
+ mcpReconnect: authed.route({ method: "POST", path: "/rest/rc/mcp-reconnect", summary: "Ask a session to reconnect one MCP server", tags: [RC_API_TAG] }).input(RcMcpReconnectInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpReconnect(input.session, input.serverName)) })),
5671
+ mcpAuthenticate: authed.route({ method: "POST", path: "/rest/rc/mcp-authenticate", summary: "Start OAuth for one MCP server on a session", tags: [RC_API_TAG] }).input(RcMcpAuthenticateInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpAuthenticate(input.session, input.serverName, input.redirectUri)) })),
5672
+ mcpOAuthCallbackUrl: authed.route({ method: "POST", path: "/rest/rc/mcp-oauth-callback-url", summary: "Hand a completed MCP OAuth callback to a session", tags: [RC_API_TAG] }).input(RcMcpOAuthCallbackUrlInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpOAuthCallbackUrl(input.session, input.serverName, input.callbackUrl)) })),
5673
+ teleport: authed.route({ method: "POST", path: "/rest/rc/teleport", summary: "Teleport a session to a conversation marker", tags: [RC_API_TAG] }).input(RcTeleportInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.teleport(input.session, input.marker)) })),
5674
+ subscribe: authed.route({ method: "GET", path: "/rest/rc/events", summary: "Stream a session's Remote Control events (SSE)", tags: [RC_API_TAG] }).input(RcSessionQuerySchema).output((0, import_server2.eventIterator)(RcStreamEventSchema)).handler(async function* ({ input, signal }) {
5567
5675
  const queue = [];
5568
5676
  let wake;
5569
5677
  const detach = deps.fanout.subscribe(input.session, (event) => {
@@ -5600,15 +5708,44 @@ function createRcApiRouter(deps) {
5600
5708
  }
5601
5709
  };
5602
5710
  }
5603
- function doorApiNodeHandlerOf(router) {
5604
- const handler = new import_node.RPCHandler(router, { plugins: [new import_node.BodyLimitPlugin({ maxBodySize: CONTROL_BODY_CAP_BYTES })] });
5711
+ function doorApiNodeHandlerOf(router, expectedToken) {
5712
+ const plugins = [new import_node2.BodyLimitPlugin({ maxBodySize: CONTROL_BODY_CAP_BYTES })];
5713
+ const rpcHandler = new import_node2.RPCHandler(router, { plugins });
5714
+ const restHandler = new import_node.OpenAPIHandler(router, { plugins });
5715
+ let document;
5716
+ const documentOf = async () => document ??= new import_openapi.OpenAPIGenerator().generate(router, { info: { title: "agent-shim front door API", version: package_default.version } });
5605
5717
  return {
5606
5718
  pathPrefix: RC_ORPC_PATH_PREFIX,
5607
- handle: async (request4, response) => await handler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX })
5719
+ handle: async (request4, response) => {
5720
+ if (request4.method === "GET" && request4.url === `${RC_ORPC_PATH_PREFIX}${RC_OPENAPI_DOC_PATH}`) {
5721
+ const token = doorApiBearer(request4.headers);
5722
+ if (token === void 0 || !isLiveCapability(token, [expectedToken])) {
5723
+ const refusal = new import_client.ORPCError("UNAUTHORIZED", { message: "the front door's OpenAPI document demands this generation's control token as a Bearer credential" });
5724
+ response.writeHead(HTTP_STATUS.unauthorized, { "content-type": "application/json" });
5725
+ response.end(JSON.stringify(refusal.toJSON()));
5726
+ return { matched: true };
5727
+ }
5728
+ try {
5729
+ const doc = await documentOf();
5730
+ response.writeHead(HTTP_STATUS.ok, { "content-type": "application/json" });
5731
+ response.end(JSON.stringify(doc));
5732
+ } catch (error) {
5733
+ const refusal = new import_client.ORPCError("INTERNAL_SERVER_ERROR", { message: `the OpenAPI document could not be generated from the door's own router: ${error instanceof Error ? error.message : String(error)}` });
5734
+ response.writeHead(HTTP_STATUS.internalServerError, { "content-type": "application/json" });
5735
+ response.end(JSON.stringify(refusal.toJSON()));
5736
+ }
5737
+ return { matched: true };
5738
+ }
5739
+ const rest = await restHandler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX });
5740
+ if (rest.matched) {
5741
+ return rest;
5742
+ }
5743
+ return await rpcHandler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX });
5744
+ }
5608
5745
  };
5609
5746
  }
5610
5747
  function createRcApiNodeHandler(deps) {
5611
- return doorApiNodeHandlerOf(createRcApiRouter(deps));
5748
+ return doorApiNodeHandlerOf(createRcApiRouter(deps), deps.expectedToken);
5612
5749
  }
5613
5750
  function frontDoorApiLink(port, ca, token) {
5614
5751
  const dispatcher = new import_undici.Agent({ connect: { ca } });
@@ -10043,6 +10180,10 @@ var CheckRunInputSchema = import_zod19.z.strictObject({
10043
10180
  path: import_zod19.z.string().min(1),
10044
10181
  identity: import_zod19.z.string().min(1).optional()
10045
10182
  }).refine((input) => import_node_path27.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
10183
+ var PoolPickInputSchema = import_zod19.z.strictObject({
10184
+ pool: import_zod19.z.string().min(1),
10185
+ path: import_zod19.z.string().min(1)
10186
+ }).refine((input) => import_node_path27.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
10046
10187
  var DoctorFindingSchema = import_zod19.z.strictObject({
10047
10188
  section: import_zod19.z.enum(DOCTOR_SECTIONS),
10048
10189
  subject: import_zod19.z.string().optional(),
@@ -10080,11 +10221,12 @@ var LaunchLifecycleEventSchema = import_zod20.z.strictObject({
10080
10221
  });
10081
10222
 
10082
10223
  // src/frontdoor/eventsApi.ts
10224
+ var EVENTS_API_TAG = "events";
10083
10225
  function createEventsApiRouter(deps) {
10084
10226
  const authed = doorApiAuth(deps.expectedToken);
10085
10227
  return {
10086
10228
  events: {
10087
- subscribe: authed.input(DoorEventSourceQuerySchema).output((0, import_server3.eventIterator)(DoorEventSchema)).handler(async function* ({ input, signal }) {
10229
+ subscribe: authed.route({ method: "GET", path: "/rest/events", summary: "Stream the door's every event source (SSE)", tags: [EVENTS_API_TAG] }).input(DoorEventSourceQuerySchema).output((0, import_server3.eventIterator)(DoorEventSchema)).handler(async function* ({ input, signal }) {
10088
10230
  if (input.sources !== void 0) {
10089
10231
  const live = deps.events.sources();
10090
10232
  const unknown = input.sources.filter((source) => !live.includes(source));
@@ -10117,12 +10259,17 @@ function createEventsApiRouter(deps) {
10117
10259
  }
10118
10260
 
10119
10261
  // src/frontdoor/controlApi.ts
10262
+ var USAGE_API_TAG = "usage";
10263
+ var FRONTDOOR_API_TAG = "frontdoor";
10264
+ var CHECK_API_TAG = "check";
10265
+ var DOCTOR_API_TAG = "doctor";
10266
+ var POOL_API_TAG = "pool";
10120
10267
  function createControlApiRouter(deps) {
10121
10268
  const authed = doorApiAuth(deps.expectedToken);
10122
10269
  return {
10123
10270
  usage: {
10124
- list: authed.output(UsageListOutputSchema).handler(() => ({ snapshots: deps.usageSnapshots() })),
10125
- effectiveWindow: authed.input(UsageWindowsInputSchema).output(UsageWindowsOutputSchema).handler(({ input }) => {
10271
+ list: authed.route({ method: "GET", path: "/rest/usage/snapshots", summary: "List every identity's usage snapshot", tags: [USAGE_API_TAG] }).output(UsageListOutputSchema).handler(() => ({ snapshots: deps.usageSnapshots() })),
10272
+ effectiveWindow: authed.route({ method: "GET", path: "/rest/usage/windows", summary: "Read one identity's effective quota windows", tags: [USAGE_API_TAG] }).input(UsageWindowsInputSchema).output(UsageWindowsOutputSchema).handler(({ input }) => {
10126
10273
  const snapshot = deps.usageSnapshotOf(input.identity);
10127
10274
  if (snapshot === void 0) {
10128
10275
  throw new import_client3.ORPCError("NOT_FOUND", { message: `identity ${input.identity} has no usage snapshot yet, so no quota window has been observed for it` });
@@ -10139,7 +10286,7 @@ function createControlApiRouter(deps) {
10139
10286
  ...unified?.sevenDay === void 0 ? {} : { sevenDay: effectiveWindow(unified.sevenDay, now) }
10140
10287
  };
10141
10288
  }),
10142
- live: authed.input(RcSessionQuerySchema).output(UsageLiveOutputSchema).handler(({ input }) => {
10289
+ live: authed.route({ method: "GET", path: "/rest/usage/live", summary: "Read the live rate-limit observations the event backbone files", tags: [USAGE_API_TAG] }).input(RcSessionQuerySchema).output(UsageLiveOutputSchema).handler(({ input }) => {
10143
10290
  const sessions = deps.liveRateLimits(input.session);
10144
10291
  if (input.session !== void 0 && sessions.length === 0) {
10145
10292
  if (deps.list().some((session) => session.id === input.session)) {
@@ -10151,15 +10298,27 @@ function createControlApiRouter(deps) {
10151
10298
  })
10152
10299
  },
10153
10300
  frontdoor: {
10154
- status: authed.output(FrontDoorStatusOutputSchema).handler(() => deps.frontDoorStatus()),
10155
- sessions: authed.output(FrontDoorSessionsOutputSchema).handler(() => ({ sessions: deps.frontDoorStatus().sessions }))
10301
+ status: authed.route({ method: "GET", path: "/rest/frontdoor/status", summary: "Read the front door's status", tags: [FRONTDOOR_API_TAG] }).output(FrontDoorStatusOutputSchema).handler(() => deps.frontDoorStatus()),
10302
+ sessions: authed.route({ method: "GET", path: "/rest/frontdoor/sessions", summary: "Read the front door's session registry", tags: [FRONTDOOR_API_TAG] }).output(FrontDoorSessionsOutputSchema).handler(() => ({ sessions: deps.frontDoorStatus().sessions }))
10156
10303
  },
10157
10304
  check: {
10158
10305
  // The report's own JSON shape is the contract (the same one `check --json` prints and `checkReportSchema.ts` defines), so the procedure returns exactly that conversion.
10159
- run: authed.input(CheckRunInputSchema).output(CheckReportJsonSchema).handler(({ input }) => checkReportToJson(deps.checkReport(input.path, input.identity)))
10306
+ run: authed.route({ method: "GET", path: "/rest/check", summary: "Run the check report for one directory", tags: [CHECK_API_TAG] }).input(CheckRunInputSchema).output(CheckReportJsonSchema).handler(({ input }) => checkReportToJson(deps.checkReport(input.path, input.identity)))
10160
10307
  },
10161
10308
  doctor: {
10162
- run: authed.output(DoctorRunOutputSchema).handler(() => deps.doctorReport())
10309
+ run: authed.route({ method: "GET", path: "/rest/doctor", summary: "Run the doctor report", tags: [DOCTOR_API_TAG] }).output(DoctorRunOutputSchema).handler(() => deps.doctorReport())
10310
+ },
10311
+ pool: {
10312
+ pick: authed.route({ method: "GET", path: "/rest/pool/pick", summary: "Rank one pool exactly as a launch from a directory would right now", tags: [POOL_API_TAG] }).input(PoolPickInputSchema).output(PoolPickReportSchema).handler(({ input }) => {
10313
+ const report = deps.poolPick(input.pool, input.path);
10314
+ if (report === void 0) {
10315
+ const live = deps.poolNames();
10316
+ throw new import_client3.ORPCError("NOT_FOUND", {
10317
+ message: live.length === 0 ? `no pools are configured, so none is named ${input.pool}` : `no pool is named ${input.pool}; the live pools are ${live.map((name) => `"${name}"`).join(", ")}`
10318
+ });
10319
+ }
10320
+ return report;
10321
+ })
10163
10322
  }
10164
10323
  };
10165
10324
  }
@@ -10167,7 +10326,7 @@ function createDoorApiRouter(deps) {
10167
10326
  return { ...createRcApiRouter(deps), ...createControlApiRouter(deps), ...createEventsApiRouter(deps) };
10168
10327
  }
10169
10328
  function createDoorApiNodeHandler(deps) {
10170
- return doorApiNodeHandlerOf(createDoorApiRouter(deps));
10329
+ return doorApiNodeHandlerOf(createDoorApiRouter(deps), deps.expectedToken);
10171
10330
  }
10172
10331
  function frontDoorApiClient(port, ca, token) {
10173
10332
  return (0, import_client3.createORPCClient)(frontDoorApiLink(port, ca, token));
@@ -12253,106 +12412,6 @@ function removeDirectoryRule(paths, rulePath) {
12253
12412
  var import_node_crypto10 = require("node:crypto");
12254
12413
  var import_node_path30 = __toESM(require("node:path"), 1);
12255
12414
 
12256
- // package.json
12257
- var package_default = {
12258
- name: "agent-shim",
12259
- version: "8.28.0",
12260
- description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
12261
- license: "MIT",
12262
- author: "Joseph Mearman <joseph@mearman.co.uk>",
12263
- repository: {
12264
- type: "git",
12265
- url: "git+https://github.com/ExaDev/agent-shim.git"
12266
- },
12267
- homepage: "https://github.com/ExaDev/agent-shim#readme",
12268
- bugs: "https://github.com/ExaDev/agent-shim/issues",
12269
- keywords: [
12270
- "claude-code",
12271
- "claude",
12272
- "cli"
12273
- ],
12274
- packageManager: "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
12275
- type: "module",
12276
- engines: {
12277
- node: "^22.18 || >=24"
12278
- },
12279
- bin: {
12280
- "agent-shim": "dist/cli.cjs",
12281
- "claude-use": "dist/cli.cjs"
12282
- },
12283
- files: [
12284
- "dist/cli.cjs",
12285
- "dist/index.mjs",
12286
- "dist/index.cjs",
12287
- "dist/types"
12288
- ],
12289
- scripts: {
12290
- prepare: "husky && node scripts/build.mts --bundle-only",
12291
- typecheck: "turbo run _typecheck",
12292
- _typecheck: "tsc --noEmit",
12293
- lint: "turbo run _lint",
12294
- _lint: "eslint . --cache --cache-location .eslintcache --max-warnings 0",
12295
- test: "turbo run _test",
12296
- _test: "vitest run",
12297
- "test:coverage": "turbo run _test:coverage",
12298
- "_test:coverage": "vitest run --coverage",
12299
- knip: "turbo run _knip",
12300
- _knip: "knip --cache",
12301
- build: "turbo run _build",
12302
- _build: "node scripts/build.mts",
12303
- "build:bundle": "node scripts/build.mts --bundle-only",
12304
- prepublishOnly: "pnpm build:bundle",
12305
- schema: "node scripts/gen-schema.mts"
12306
- },
12307
- dependencies: {
12308
- "@clack/prompts": "^1.8.0",
12309
- "@orpc/client": "1.15.4",
12310
- "@orpc/server": "1.15.4",
12311
- commander: "^15.0.0",
12312
- cosmiconfig: "^10.0.1",
12313
- picomatch: "^4.0.7",
12314
- undici: "7.29.1",
12315
- zod: "^4.6.1"
12316
- },
12317
- devDependencies: {
12318
- "@commitlint/cli": "^21.2.2",
12319
- "@commitlint/config-conventional": "^21.2.2",
12320
- "@exadev/eslint-config": "2.12.1",
12321
- "@semantic-release/changelog": "^7.0.0",
12322
- "@semantic-release/git": "^11.0.1",
12323
- "@semantic-release/npm": "^13.1.5",
12324
- "@types/node": "^26.5.1",
12325
- "@types/picomatch": "^4.0.3",
12326
- "@vitest/coverage-v8": "^4.1.11",
12327
- "conventional-changelog-conventionalcommits": "^10.4.0",
12328
- esbuild: "^0.28.2",
12329
- eslint: "^10.10.0",
12330
- globals: "^17.12.0",
12331
- husky: "^9.1.7",
12332
- jiti: "^2.7.0",
12333
- knip: "^6.35.1",
12334
- "lint-staged": "^17.5.0",
12335
- rollup: "4.64.0",
12336
- "rollup-plugin-dts": "6.5.1",
12337
- "semantic-release": "^25.0.9",
12338
- turbo: "^2.11.5",
12339
- typescript: "^6.0.3",
12340
- "typescript-eslint": "^8.70.0",
12341
- vitest: "^4.1.11"
12342
- },
12343
- main: "dist/index.cjs",
12344
- module: "dist/index.mjs",
12345
- types: "dist/types/index.d.ts",
12346
- exports: {
12347
- ".": {
12348
- types: "./dist/types/index.d.ts",
12349
- import: "./dist/index.mjs",
12350
- require: "./dist/index.cjs"
12351
- },
12352
- "./package.json": "./package.json"
12353
- }
12354
- };
12355
-
12356
12415
  // src/launcher/argv.ts
12357
12416
  var ConflictingIdentityError = class extends UsageError {
12358
12417
  constructor(positional, flag) {