@keystrokehq/cli 0.1.49 → 0.1.51

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.mjs CHANGED
@@ -4809,11 +4809,11 @@ async function resolveProjectRef(platform, ref) {
4809
4809
  if (looksLikeUuid(ref)) try {
4810
4810
  return await platform.projects.get(ref);
4811
4811
  } catch (error) {
4812
- if (error instanceof PlatformError && error.status === 404) throw new Error(`Project ${ref} not found in the active organization. Run \`keystroke project list\`, then \`keystroke project link --project <slug>\`.`);
4812
+ if (error instanceof PlatformError && error.status === 404) throw new Error(`Project ${ref} not found in the active organization. Run \`keystroke projects list\`, then \`keystroke projects link --project <slug>\`.`);
4813
4813
  throw error;
4814
4814
  }
4815
4815
  const match = (await platform.projects.list()).find((project) => project.slug === ref);
4816
- if (!match) throw new Error(`Project "${ref}" not found in the active organization. Run \`keystroke project list\`.`);
4816
+ if (!match) throw new Error(`Project "${ref}" not found in the active organization. Run \`keystroke projects list\`.`);
4817
4817
  return match;
4818
4818
  }
4819
4819
  function resolveOrganizationRef(organizations, ref) {
@@ -5110,7 +5110,7 @@ async function resolveApiTarget(config, options = {}) {
5110
5110
  if (getEffectiveApiTarget(config) === "local") return resolveLocalTarget(options);
5111
5111
  if (!options.projectScoped) return resolveOrgPlatformTarget(config);
5112
5112
  const projectRef = options.projectId ?? readLinkedProjectConfig().project;
5113
- if (!projectRef) throw new Error("No project selected. Pass `--project <slug>` or run `keystroke project link --project <slug>`.");
5113
+ if (!projectRef) throw new Error("No project selected. Pass `--project <slug>` or run `keystroke projects link --project <slug>`.");
5114
5114
  return resolvePlatformTarget(config, projectRef);
5115
5115
  }
5116
5116
  //#endregion
@@ -5283,7 +5283,7 @@ async function requireAdminRole(config) {
5283
5283
  if (!active || active.role !== "owner" && active.role !== "admin") throw new Error("--admin requires org owner or admin");
5284
5284
  }
5285
5285
  //#endregion
5286
- //#region src/commands/agent/list.ts
5286
+ //#region src/commands/agents/list.ts
5287
5287
  function registerAgentListCommand(agent) {
5288
5288
  agent.command("list").description("List agents in the active organization").option("--admin", "List all org resources (org owner or admin only)").action((options) => runCliCommand("List agents failed", async () => {
5289
5289
  const config = createCliConfig();
@@ -5299,7 +5299,7 @@ function registerAgentListCommand(agent) {
5299
5299
  }, void 0, { orgScoped: true }));
5300
5300
  }
5301
5301
  //#endregion
5302
- //#region src/commands/agent/prompt.ts
5302
+ //#region src/commands/agents/prompt.ts
5303
5303
  function registerAgentPromptCommand(agent) {
5304
5304
  agent.command("prompt").description("Send a message to an agent (or follow up in an existing session)").argument("<agentId>", "Agent key / route id").requiredOption("--message <text>", "Message to send").option("--session-id <id>", "Existing session id for follow-up").action((agentId, options) => runProjectCliCommand("Agent prompt failed", async ({ client }) => {
5305
5305
  const result = await client.agents.prompt(agentId, {
@@ -5310,7 +5310,7 @@ function registerAgentPromptCommand(agent) {
5310
5310
  }));
5311
5311
  }
5312
5312
  //#endregion
5313
- //#region src/commands/project/run-project.ts
5313
+ //#region src/commands/projects/run-project.ts
5314
5314
  async function withActivePlatformClient(config, fn, fromDir = process.cwd(), applyLinkedOrganization = true) {
5315
5315
  if (applyLinkedOrganization) await ensureLinkedOrganization(config, fromDir);
5316
5316
  const platform = createCliPlatformClient(config);
@@ -5323,7 +5323,7 @@ function writeInactiveDeployHints(projects) {
5323
5323
  const bin = cliBinaryName();
5324
5324
  for (const project of projects) {
5325
5325
  if (project.status !== "inactive") continue;
5326
- process.stderr.write(`Project ${formatProjectLabel(project)} is inactive. Deploy with: ${bin} project link --project ${formatProjectLabel(project)}, then ${bin} deploy\n`);
5326
+ process.stderr.write(`Project ${formatProjectLabel(project)} is inactive. Deploy with: ${bin} projects link --project ${formatProjectLabel(project)}, then ${bin} deploy\n`);
5327
5327
  }
5328
5328
  }
5329
5329
  async function runProjectList(config, options = {}) {
@@ -5333,7 +5333,7 @@ async function runProjectList(config, options = {}) {
5333
5333
  process.stdout.write(`${JSON.stringify({ projects }, null, 2)}\n`);
5334
5334
  if (projects.length === 0) {
5335
5335
  const bin = cliBinaryName();
5336
- process.stderr.write(`No projects yet. Create one with: ${bin} project create --name "My project"\n`);
5336
+ process.stderr.write(`No projects yet. Create one with: ${bin} projects create --name "My project"\n`);
5337
5337
  return;
5338
5338
  }
5339
5339
  writeInactiveDeployHints(projects);
@@ -5380,15 +5380,15 @@ async function runProjectDelete(config, projectId) {
5380
5380
  });
5381
5381
  }
5382
5382
  //#endregion
5383
- //#region src/commands/agent/cancel-session.ts
5384
- async function runAgentSessionCancel(config, sessionId) {
5383
+ //#region src/commands/agents/cancel-session.ts
5384
+ async function runAgentSessionCancel(config, _agentId, sessionId) {
5385
5385
  await withActivePlatformClient(config, async (platform) => {
5386
5386
  const run = await platform.agents.cancelSession(sessionId);
5387
5387
  process.stdout.write(`${JSON.stringify(run, null, 2)}\n`);
5388
5388
  });
5389
5389
  }
5390
5390
  //#endregion
5391
- //#region src/commands/agent/sessions.ts
5391
+ //#region src/commands/agents/sessions.ts
5392
5392
  function registerAgentSessionsCommand(agent) {
5393
5393
  const sessions = agent.command("sessions").description("List and inspect agent sessions");
5394
5394
  sessions.command("list").description("List sessions for an agent").argument("<agentId>", "Agent key / route id").option("--limit <n>", "Page size (1–100)", "20").option("--cursor <cursor>", "Pagination cursor from a previous page").option("--status <status>", "Filter by status (running, completed, failed)").option("--source <source>", "Filter by source (api, gateway)").action((agentId, options) => runProjectCliCommand("List agent sessions failed", async ({ client }) => {
@@ -5404,10 +5404,10 @@ function registerAgentSessionsCommand(agent) {
5404
5404
  const result = await client.agents.getSession(agentId, sessionId, { include: options.include });
5405
5405
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5406
5406
  }));
5407
- sessions.command("cancel").description("Cancel a running agent session").argument("<sessionId>", "Agent session id").action(async (sessionId) => {
5407
+ sessions.command("cancel").description("Cancel a running agent session").argument("<agentId>", "Agent key / route id").argument("<sessionId>", "Agent session id").action(async (agentId, sessionId) => {
5408
5408
  const config = createCliConfig();
5409
5409
  try {
5410
- await runAgentSessionCancel(config, sessionId);
5410
+ await runAgentSessionCancel(config, agentId, sessionId);
5411
5411
  } catch (error) {
5412
5412
  process.stderr.write(`${formatCliError(error, "Cancel agent session failed", {
5413
5413
  serverUrl: getPlatformUrl(config),
@@ -5418,12 +5418,12 @@ function registerAgentSessionsCommand(agent) {
5418
5418
  });
5419
5419
  }
5420
5420
  //#endregion
5421
- //#region src/commands/agent/index.ts
5422
- function registerAgentCommand(program) {
5423
- const agent = program.command("agent").description("Invoke and inspect agents");
5424
- registerAgentListCommand(agent);
5425
- registerAgentPromptCommand(agent);
5426
- registerAgentSessionsCommand(agent);
5421
+ //#region src/commands/agents/index.ts
5422
+ function registerAgentsCommand(program) {
5423
+ const agents = program.command("agents").description("Invoke and inspect agents");
5424
+ registerAgentListCommand(agents);
5425
+ registerAgentPromptCommand(agents);
5426
+ registerAgentSessionsCommand(agents);
5427
5427
  }
5428
5428
  //#endregion
5429
5429
  //#region src/commands/api-key/run-api-key.ts
@@ -5482,7 +5482,7 @@ function registerApiKeyCommand(program) {
5482
5482
  });
5483
5483
  }
5484
5484
  //#endregion
5485
- //#region src/commands/app/action-hints.ts
5485
+ //#region src/commands/apps/action-hints.ts
5486
5486
  function toCamelCase(value) {
5487
5487
  const pascal = value.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
5488
5488
  return pascal.charAt(0).toLowerCase() + pascal.slice(1);
@@ -5501,15 +5501,15 @@ function actionImportHint(app, tool) {
5501
5501
  /** Next-step hint printed after listing an app's actions. */
5502
5502
  function listActionsHint(app) {
5503
5503
  const bin = cliBinaryName();
5504
- return `\nNext steps:\n Inspect a tool: ${bin} app action ${app} <TOOL_SLUG>\n Run a tool: ${bin} app execute ${app} <TOOL_SLUG> --input '{...}'\n`;
5504
+ return `\nNext steps:\n Inspect a tool: ${bin} apps actions get ${app} <TOOL_SLUG>\n Run a tool: ${bin} apps execute ${app} <TOOL_SLUG> --input '{...}'\n`;
5505
5505
  }
5506
5506
  /** Next-step hint printed after showing one action's schema. */
5507
5507
  function showActionHint(app, tool) {
5508
5508
  const bin = cliBinaryName();
5509
- return `\nNext steps:\n Run ad-hoc: ${bin} app execute ${app} ${tool} --input '{...}'\n Use in code: ${actionImportHint(app, tool)}\n Not connected? ${bin} connect ${app}\n`;
5509
+ return `\nNext steps:\n Run ad-hoc: ${bin} apps execute ${app} ${tool} --input '{...}'\n Use in code: ${actionImportHint(app, tool)}\n Not connected? ${bin} connect ${app}\n`;
5510
5510
  }
5511
5511
  //#endregion
5512
- //#region src/commands/app/run-app-catalog.ts
5512
+ //#region src/commands/apps/run-app-catalog.ts
5513
5513
  async function runAppSearch(client, query, options) {
5514
5514
  const trimmed = query.trim();
5515
5515
  if (!trimmed) throw new Error("Search query is required");
@@ -5546,21 +5546,10 @@ async function runAppAction(client, toolSlug) {
5546
5546
  return client.apps.getCatalogAction(trimmed);
5547
5547
  }
5548
5548
  //#endregion
5549
- //#region src/commands/app/action.ts
5550
- function registerAppActionCommand(app) {
5551
- app.command("action").description("Show a catalog action schema, plus how to run and import it").argument("<app>", "App slug (e.g. github)").argument("<tool>", "Tool slug (e.g. github_create_an_issue)").action((appSlug, toolSlug) => runCliCommand("App action failed", async () => {
5552
- const config = createCliConfig();
5553
- const client = createCliPlatformClient(config);
5554
- await ensureActiveOrganization(config);
5555
- const result = await runAppAction(client, toolSlug);
5556
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5557
- process.stderr.write(showActionHint(appSlug.trim().toLowerCase(), toolSlug.trim().toUpperCase()));
5558
- }, void 0, { orgScoped: true }));
5559
- }
5560
- //#endregion
5561
- //#region src/commands/app/actions.ts
5562
- function registerAppActionsCommand(app) {
5563
- app.command("actions [slug]").description("List or search a catalog app's actions (per app, or globally with --search)").option("--search <query>", "Search actions within the app or across all apps").option("--limit <n>", "Page size", (value) => Number.parseInt(value, 10)).option("--cursor <cursor>", "Pagination cursor").action((slug, options) => runCliCommand("App actions failed", async () => {
5549
+ //#region src/commands/apps/actions.ts
5550
+ function registerAppActionsCommands(app) {
5551
+ const actions = app.command("actions").description("List and inspect catalog app actions");
5552
+ actions.command("list").description("List or search a catalog app's actions").argument("[slug]", "App slug (omit for cross-app search with --search)").option("--search <query>", "Search actions within the app or across all apps").option("--limit <n>", "Page size", (value) => Number.parseInt(value, 10)).option("--cursor <cursor>", "Pagination cursor").action((slug, options) => runCliCommand("App actions list failed", async () => {
5564
5553
  const config = createCliConfig();
5565
5554
  const client = createCliPlatformClient(config);
5566
5555
  await ensureActiveOrganization(config);
@@ -5571,9 +5560,17 @@ function registerAppActionsCommand(app) {
5571
5560
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5572
5561
  if (slug?.trim()) process.stderr.write(listActionsHint(slug.trim().toLowerCase()));
5573
5562
  }, void 0, { orgScoped: true }));
5563
+ actions.command("get").description("Get a catalog action schema, plus how to run and import it").argument("<app>", "App slug (e.g. github)").argument("<tool>", "Tool slug (e.g. github_create_an_issue)").action((appSlug, toolSlug) => runCliCommand("App action get failed", async () => {
5564
+ const config = createCliConfig();
5565
+ const client = createCliPlatformClient(config);
5566
+ await ensureActiveOrganization(config);
5567
+ const result = await runAppAction(client, toolSlug);
5568
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5569
+ process.stderr.write(showActionHint(appSlug.trim().toLowerCase(), toolSlug.trim().toUpperCase()));
5570
+ }, void 0, { orgScoped: true }));
5574
5571
  }
5575
5572
  //#endregion
5576
- //#region src/commands/app/parse-custom-app-fields.ts
5573
+ //#region src/commands/apps/parse-custom-app-fields.ts
5577
5574
  function parseCustomAppFieldFlag(value) {
5578
5575
  const parts = value.split(":").map((part) => part.trim()).filter(Boolean);
5579
5576
  const key = parts[0];
@@ -5603,7 +5600,7 @@ function collectValues$1(value, previous) {
5603
5600
  return [...previous, value];
5604
5601
  }
5605
5602
  //#endregion
5606
- //#region src/commands/app/run-app-create.ts
5603
+ //#region src/commands/apps/run-app-create.ts
5607
5604
  async function runAppCreate(client, input, options) {
5608
5605
  if (options?.preview) return {
5609
5606
  preview: true,
@@ -5613,7 +5610,7 @@ async function runAppCreate(client, input, options) {
5613
5610
  return client.apps.create(input);
5614
5611
  }
5615
5612
  //#endregion
5616
- //#region src/commands/app/run-app-create-from-url.ts
5613
+ //#region src/commands/apps/run-app-create-from-url.ts
5617
5614
  async function discoverApp(client, source, url) {
5618
5615
  switch (source) {
5619
5616
  case "mcp": return client.apps.discoverMcp({ url });
@@ -5656,7 +5653,7 @@ async function runAppCreateFromUrl(client, input) {
5656
5653
  return client.apps.create(request);
5657
5654
  }
5658
5655
  //#endregion
5659
- //#region src/commands/app/create.ts
5656
+ //#region src/commands/apps/create.ts
5660
5657
  function resolveDiscoverSource(options) {
5661
5658
  const sources = [
5662
5659
  options.mcp ? {
@@ -5718,7 +5715,7 @@ function registerAppCreateCommand(app) {
5718
5715
  }, void 0, { orgScoped: true }));
5719
5716
  }
5720
5717
  //#endregion
5721
- //#region src/commands/app/run-app-execute.ts
5718
+ //#region src/commands/apps/run-app-execute.ts
5722
5719
  function isNotConnectedError(error) {
5723
5720
  if (!(error instanceof PlatformError) || error.status !== 404) return false;
5724
5721
  const body = error.body;
@@ -5749,7 +5746,7 @@ async function runAppExecute(client, appSlug, toolSlug, options) {
5749
5746
  }
5750
5747
  }
5751
5748
  //#endregion
5752
- //#region src/commands/app/execute.ts
5749
+ //#region src/commands/apps/execute.ts
5753
5750
  function registerAppExecuteCommand(app) {
5754
5751
  app.command("execute").description("Run a connected catalog action against the cloud (no local server)").argument("<app>", "App slug (e.g. github)").argument("<tool>", "Tool slug (e.g. github_get_the_authenticated_user)").option("--input <json>", "JSON arguments (defaults to {})", "{}").option("--version <version>", "Pinned toolkit version (defaults to the catalog value)").option("--credential <slug>", `Pin a specific credential by slug (see '${cliBinaryName()} credentials list'); overrides the default and is the only way to use a user credential`).addHelpText("after", `
5755
5752
  Credential resolution matches the runtime: project default → org default. User credentials are
@@ -5757,10 +5754,10 @@ never a default — reach one with --credential <slug>. Target a project with th
5757
5754
  --project <slug> flag; without it, only org credentials resolve.
5758
5755
 
5759
5756
  Examples:
5760
- ${cliBinaryName()} app execute github github_get_the_authenticated_user
5761
- ${cliBinaryName()} app execute github github_get_the_authenticated_user --project my-app
5762
- ${cliBinaryName()} app execute github github_get_the_authenticated_user --credential work-github
5763
- ${cliBinaryName()} app execute acculynx acculynx_add_job_appointment --input '{"jobId":"123","startDate":"2026-01-01T09:00:00Z","endDate":"2026-01-01T10:00:00Z"}'
5757
+ ${cliBinaryName()} apps execute github github_get_the_authenticated_user
5758
+ ${cliBinaryName()} apps execute github github_get_the_authenticated_user --project my-app
5759
+ ${cliBinaryName()} apps execute github github_get_the_authenticated_user --credential work-github
5760
+ ${cliBinaryName()} apps execute acculynx acculynx_add_job_appointment --input '{"jobId":"123","startDate":"2026-01-01T09:00:00Z","endDate":"2026-01-01T10:00:00Z"}'
5764
5761
  `).action((appSlug, toolSlug, options) => runCliCommand("App execute failed", async () => {
5765
5762
  const config = createCliConfig();
5766
5763
  const client = createCliPlatformClient(config);
@@ -5775,17 +5772,28 @@ Examples:
5775
5772
  });
5776
5773
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5777
5774
  }, { usage: {
5778
- command: `${cliBinaryName()} app execute ${appSlug} ${toolSlug}`,
5775
+ command: `${cliBinaryName()} apps execute ${appSlug} ${toolSlug}`,
5779
5776
  flag: "--input"
5780
5777
  } }, { orgScoped: true }));
5781
5778
  }
5782
5779
  //#endregion
5783
- //#region src/commands/app/run-app-list.ts
5780
+ //#region src/commands/apps/get.ts
5781
+ function registerAppGetCommand(app) {
5782
+ app.command("get").description("Get a Composio app from the live catalog").argument("<slug>", "App slug").action((slug) => runCliCommand("App get failed", async () => {
5783
+ const config = createCliConfig();
5784
+ const client = createCliPlatformClient(config);
5785
+ await ensureActiveOrganization(config);
5786
+ const result = await runAppShow(client, slug);
5787
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5788
+ }, void 0, { orgScoped: true }));
5789
+ }
5790
+ //#endregion
5791
+ //#region src/commands/apps/run-app-list.ts
5784
5792
  async function runAppList(client) {
5785
5793
  return client.apps.listCatalog();
5786
5794
  }
5787
5795
  //#endregion
5788
- //#region src/commands/app/list.ts
5796
+ //#region src/commands/apps/list.ts
5789
5797
  function registerAppListCommand(app) {
5790
5798
  app.command("list").description("List connectable apps in the active organization").action(() => runCliCommand("List apps failed", async () => {
5791
5799
  const config = createCliConfig();
@@ -5796,7 +5804,7 @@ function registerAppListCommand(app) {
5796
5804
  }, void 0, { orgScoped: true }));
5797
5805
  }
5798
5806
  //#endregion
5799
- //#region src/commands/app/search.ts
5807
+ //#region src/commands/apps/search.ts
5800
5808
  function registerAppSearchCommand(app) {
5801
5809
  app.command("search").description("Search the Composio app catalog (live)").argument("<query>", "Search query").option("--category <category>", "Filter by category").option("--limit <n>", "Page size", (value) => Number.parseInt(value, 10)).option("--cursor <cursor>", "Pagination cursor").action((query, options) => runCliCommand("App search failed", async () => {
5802
5810
  const config = createCliConfig();
@@ -5807,18 +5815,7 @@ function registerAppSearchCommand(app) {
5807
5815
  }, void 0, { orgScoped: true }));
5808
5816
  }
5809
5817
  //#endregion
5810
- //#region src/commands/app/show.ts
5811
- function registerAppShowCommand(app) {
5812
- app.command("show").description("Show a Composio app from the live catalog").argument("<slug>", "App slug").action((slug) => runCliCommand("App show failed", async () => {
5813
- const config = createCliConfig();
5814
- const client = createCliPlatformClient(config);
5815
- await ensureActiveOrganization(config);
5816
- const result = await runAppShow(client, slug);
5817
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
5818
- }, void 0, { orgScoped: true }));
5819
- }
5820
- //#endregion
5821
- //#region src/commands/app/generate-app-stub.ts
5818
+ //#region src/commands/apps/generate-app-stub.ts
5822
5819
  function slugPartToExportName(part) {
5823
5820
  return part.split(/[-_]+/).filter(Boolean).map((segment, index) => index === 0 ? segment.charAt(0).toLowerCase() + segment.slice(1) : segment.charAt(0).toUpperCase() + segment.slice(1)).join("");
5824
5821
  }
@@ -5840,7 +5837,7 @@ function generateAppStub(app) {
5840
5837
  return `import { defineApp } from "@keystrokehq/keystroke/app";
5841
5838
  import { z } from "zod";
5842
5839
 
5843
- /** Synced from platform app \`${app.slug}\`. Re-run \`keystroke app sync ${app.slug}\` after template changes. */
5840
+ /** Synced from platform app \`${app.slug}\`. Re-run \`keystroke apps sync ${app.slug}\` after template changes. */
5844
5841
  export const ${exportName} = defineApp({
5845
5842
  slug: ${JSON.stringify(app.slug)},
5846
5843
  auth: "api_key",
@@ -5851,7 +5848,7 @@ ${credentialLines}
5851
5848
  `;
5852
5849
  }
5853
5850
  //#endregion
5854
- //#region src/commands/app/run-app-sync.ts
5851
+ //#region src/commands/apps/run-app-sync.ts
5855
5852
  async function runAppSync(options) {
5856
5853
  const projectRoot = resolveKeystrokeConfigRoot(options.dir ?? process.cwd());
5857
5854
  if (!projectRoot) throw new Error("Not in a keystroke project (keystroke.config.ts not found)");
@@ -5863,7 +5860,7 @@ async function runAppSync(options) {
5863
5860
  return { outputPath };
5864
5861
  }
5865
5862
  //#endregion
5866
- //#region src/commands/app/sync.ts
5863
+ //#region src/commands/apps/sync.ts
5867
5864
  function registerAppSyncCommand(app) {
5868
5865
  app.command("sync").description("Sync a custom app credential template into src/apps/<name>/app.ts").argument("<slug>", "App slug, e.g. acme/internal-api").option("--dir <dir>", "Project root (defaults to cwd)").action((slug, options) => runCliCommand("Sync app failed", async () => {
5869
5866
  const config = createCliConfig();
@@ -5878,17 +5875,16 @@ function registerAppSyncCommand(app) {
5878
5875
  }, void 0, { orgScoped: true }));
5879
5876
  }
5880
5877
  //#endregion
5881
- //#region src/commands/app/index.ts
5882
- function registerAppCommand(program) {
5883
- const app = program.command("app").description("Discover and run connectable integrations");
5884
- registerAppListCommand(app);
5885
- registerAppSearchCommand(app);
5886
- registerAppShowCommand(app);
5887
- registerAppActionsCommand(app);
5888
- registerAppActionCommand(app);
5889
- registerAppExecuteCommand(app);
5890
- registerAppCreateCommand(app);
5891
- registerAppSyncCommand(app);
5878
+ //#region src/commands/apps/index.ts
5879
+ function registerAppsCommand(program) {
5880
+ const apps = program.command("apps").description("Discover and run connectable integrations");
5881
+ registerAppListCommand(apps);
5882
+ registerAppSearchCommand(apps);
5883
+ registerAppGetCommand(apps);
5884
+ registerAppActionsCommands(apps);
5885
+ registerAppExecuteCommand(apps);
5886
+ registerAppCreateCommand(apps);
5887
+ registerAppSyncCommand(apps);
5892
5888
  }
5893
5889
  //#endregion
5894
5890
  //#region src/auth/open-url.ts
@@ -6181,14 +6177,14 @@ function scopeTypeFromCli(scope) {
6181
6177
  }
6182
6178
  //#endregion
6183
6179
  //#region src/commands/credentials/rotate-key.ts
6184
- function registerCredentialsRotateKeyCommand(credentials) {
6185
- credentials.command("rotate-key").description("Rotate an api_key credential secret").argument("<id>", "Credential instance id").requiredOption("--set <field>", "Credential field as key=value or key=@env:VAR", collectSetValues$2, []).action((id, options) => runCredentialsCommand("Rotate credential key failed", async ({ platform, local }) => {
6180
+ function registerCredentialsRotateCommand(credentials) {
6181
+ credentials.command("rotate").description("Rotate an api_key credential secret").argument("<id>", "Credential instance id").requiredOption("--set <field>", "Credential field as key=value or key=@env:VAR", collectSetValues$2, []).action((id, options) => runCredentialsCommand("Rotate credential failed", async ({ platform, local }) => {
6186
6182
  const value = parseCredentialValueFields(options.set);
6187
- if (local) throw new Error("credentials rotate-key requires the platform API target (omit --local)");
6183
+ if (local) throw new Error("credentials rotate requires the platform API target (omit --local)");
6188
6184
  const patch = buildPlatformUpdatePatch({ value });
6189
6185
  const credential = await platform.credentials.update(id, patch);
6190
6186
  process.stdout.write(`${JSON.stringify({ credential }, null, 2)}\n`);
6191
- }));
6187
+ })).alias("rotate-key");
6192
6188
  }
6193
6189
  function collectSetValues$2(value, previous) {
6194
6190
  return previous.concat([value]);
@@ -6265,8 +6261,8 @@ function parseCredentialSetScopes(scopes, projectSlugs) {
6265
6261
  }
6266
6262
  //#endregion
6267
6263
  //#region src/commands/credentials/set.ts
6268
- function registerCredentialsSetCommand(credentials) {
6269
- credentials.command("set").description("Create a new api_key credential instance").argument("<key>", "Credential key or app id, e.g. exa").option("--scope <scope>", "org, user, or project (repeatable)", collectValues, []).option("--project-slug <slug>", "Project slug when scope includes project (repeatable)", collectValues, []).option("--slug <slug>", "Friendly credential slug within the scope").option("--name <name>", "Display name (used to derive slug when --slug is omitted)").option("--label <label>", "Alias for --name").option("--default", "Mark as default for this scope").option("--set <field>", "Credential field as key=value or key=@env:VAR (falls back to project .env when unset in shell)", collectSetValues$1, []).action((key, options) => runCredentialsCommand("Set credential failed", async ({ platform, local }) => {
6264
+ function registerCredentialsCreateCommand(credentials) {
6265
+ credentials.command("create").description("Create a new api_key credential instance").argument("<key>", "Credential key or app id, e.g. exa").option("--scope <scope>", "org, user, or project (repeatable)", collectValues, []).option("--project-slug <slug>", "Project slug when scope includes project (repeatable)", collectValues, []).option("--slug <slug>", "Friendly credential slug within the scope").option("--name <name>", "Display name (used to derive slug when --slug is omitted)").option("--label <label>", "Alias for --name").option("--default", "Mark as default for this scope").option("--set <field>", "Credential field as key=value or key=@env:VAR (falls back to project .env when unset in shell)", collectSetValues$1, []).action((key, options) => runCredentialsCommand("Set credential failed", async ({ platform, local }) => {
6270
6266
  const value = parseCredentialValueFields(options.set);
6271
6267
  const parsedScopes = parseCredentialSetScopes(options.scope, options.projectSlug);
6272
6268
  if (local) {
@@ -6316,7 +6312,7 @@ function registerCredentialsSetCommand(credentials) {
6316
6312
  return;
6317
6313
  }
6318
6314
  process.stdout.write(`${JSON.stringify({ credentials: created }, null, 2)}\n`);
6319
- }));
6315
+ })).alias("set");
6320
6316
  }
6321
6317
  function collectValues(value, previous) {
6322
6318
  return previous.concat([value]);
@@ -6376,9 +6372,9 @@ function registerCredentialsCommand(program) {
6376
6372
  const credentials = program.command("credentials").description("Manage platform app credentials and local api_key instances");
6377
6373
  registerCredentialsListCommand(credentials);
6378
6374
  registerCredentialsGetCommand(credentials);
6379
- registerCredentialsSetCommand(credentials);
6375
+ registerCredentialsCreateCommand(credentials);
6380
6376
  registerCredentialsUpdateCommand(credentials);
6381
- registerCredentialsRotateKeyCommand(credentials);
6377
+ registerCredentialsRotateCommand(credentials);
6382
6378
  registerCredentialsDeleteCommand(credentials);
6383
6379
  registerCredentialsAssignmentsCommands(credentials);
6384
6380
  registerCredentialsConsumersCommands(credentials);
@@ -6583,7 +6579,7 @@ function registerBuildCommand(program) {
6583
6579
  try {
6584
6580
  const root = resolveProjectRoot(options.dir);
6585
6581
  ensureSdkCurrent(root);
6586
- const { buildApp } = await import("./dist-DJFUIl5O.mjs");
6582
+ const { buildApp } = await import("./dist-BVw5-nbD.mjs");
6587
6583
  await buildApp({ root });
6588
6584
  process.stdout.write(`Built ${root}\n`);
6589
6585
  } catch (error) {
@@ -6706,7 +6702,7 @@ async function sleep(ms) {
6706
6702
  }
6707
6703
  async function buildDeployArchive(client, root, projectId, filter) {
6708
6704
  if (filter?.length) {
6709
- const { buildFilteredApp } = await import("./dist-DJFUIl5O.mjs");
6705
+ const { buildFilteredApp } = await import("./dist-BVw5-nbD.mjs");
6710
6706
  const filtered = await buildFilteredApp({
6711
6707
  root,
6712
6708
  filter,
@@ -6728,7 +6724,7 @@ async function buildDeployArchive(client, root, projectId, filter) {
6728
6724
  sourceFiles: filtered.sourceFiles
6729
6725
  };
6730
6726
  }
6731
- const { buildApp } = await import("./dist-DJFUIl5O.mjs");
6727
+ const { buildApp } = await import("./dist-BVw5-nbD.mjs");
6732
6728
  const { sourceFiles } = await buildApp({
6733
6729
  root,
6734
6730
  collectSources: true,
@@ -6788,7 +6784,7 @@ function registerDeployCommand(program) {
6788
6784
  config = createCliConfig();
6789
6785
  const root = resolveProjectRoot(options.dir);
6790
6786
  const projectId = await resolveActiveProjectId(config, root);
6791
- if (!projectId) throw new Error("Usage: keystroke deploy --project <slug> (or run `keystroke project link --project <slug>`)");
6787
+ if (!projectId) throw new Error("Usage: keystroke deploy --project <slug> (or run `keystroke projects link --project <slug>`)");
6792
6788
  await runDeploy({
6793
6789
  dir: options.dir,
6794
6790
  projectId,
@@ -6853,7 +6849,7 @@ function runtimeChildEnv(parentEnv, overrides) {
6853
6849
  //#region src/project/bootstrap-run.ts
6854
6850
  /** Node args + env for `@keystrokehq/build` bootstrap (shared by start + dev). */
6855
6851
  async function resolveBootstrapRun(options) {
6856
- const { resolveRuntimeBuildArtifact } = await import("./dist-DJFUIl5O.mjs");
6852
+ const { resolveRuntimeBuildArtifact } = await import("./dist-BVw5-nbD.mjs");
6857
6853
  const loader = pathToFileURL(resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/runtime-loader.mjs")).href;
6858
6854
  const bootstrap = resolveRuntimeBuildArtifact(options.runtimeNodeModules, "dist/standalone-bootstrap.mjs");
6859
6855
  const args = [`--import=${loader}`];
@@ -7002,7 +6998,7 @@ async function runDev(options) {
7002
6998
  process.on("SIGINT", shutdown);
7003
6999
  process.on("SIGTERM", shutdown);
7004
7000
  try {
7005
- const { watchApp } = await import("./dist-DJFUIl5O.mjs");
7001
+ const { watchApp } = await import("./dist-BVw5-nbD.mjs");
7006
7002
  await watchApp({
7007
7003
  root,
7008
7004
  clean: false,
@@ -7494,7 +7490,7 @@ function registerInitCommand(program) {
7494
7490
  process.stdout.write("\nNext steps:\n");
7495
7491
  process.stdout.write(` cd ${result.targetDir}\n`);
7496
7492
  process.stdout.write(" keystroke auth login # once\n");
7497
- if (!project) process.stdout.write(" keystroke project link --project <slug> # link this directory to a platform project\n");
7493
+ if (!project) process.stdout.write(" keystroke projects link --project <slug> # link this directory to a platform project\n");
7498
7494
  process.stdout.write(" keystroke deploy # lint + typecheck + build + ship dist/\n");
7499
7495
  } catch (error) {
7500
7496
  const message = error instanceof Error ? error.message : "Init failed";
@@ -7654,7 +7650,7 @@ function registerOrganizationCommand(program) {
7654
7650
  });
7655
7651
  }
7656
7652
  //#endregion
7657
- //#region src/commands/project/run-project-link.ts
7653
+ //#region src/commands/projects/run-project-link.ts
7658
7654
  async function runProjectLink(config, projectRef, fromDir = process.cwd()) {
7659
7655
  await withActivePlatformClient(config, async (platform) => {
7660
7656
  const project = await resolveProjectRef(platform, projectRef);
@@ -7668,7 +7664,7 @@ async function runProjectLink(config, projectRef, fromDir = process.cwd()) {
7668
7664
  }, fromDir, false);
7669
7665
  }
7670
7666
  //#endregion
7671
- //#region src/commands/project/run-project-members.ts
7667
+ //#region src/commands/projects/run-project-members.ts
7672
7668
  async function resolveMembersProject(platform) {
7673
7669
  const ref = resolveActiveProjectRef();
7674
7670
  if (!ref) throw new Error("Usage: keystroke --project <slug> project members <command>");
@@ -7714,7 +7710,7 @@ async function runProjectMembersLeave(config) {
7714
7710
  });
7715
7711
  }
7716
7712
  //#endregion
7717
- //#region src/commands/project/members.ts
7713
+ //#region src/commands/projects/members.ts
7718
7714
  function collectEmails(value, previous) {
7719
7715
  return [...previous, value];
7720
7716
  }
@@ -7775,7 +7771,7 @@ function registerProjectMembersCommand(project) {
7775
7771
  });
7776
7772
  }
7777
7773
  //#endregion
7778
- //#region src/commands/project/run-project-settings.ts
7774
+ //#region src/commands/projects/run-project-settings.ts
7779
7775
  async function resolveSettingsProject(platform) {
7780
7776
  const ref = resolveActiveProjectRef();
7781
7777
  if (!ref) throw new Error("Usage: keystroke --project <slug> project settings <command>");
@@ -7796,7 +7792,7 @@ async function runProjectSettingsUpdate(config, patch) {
7796
7792
  });
7797
7793
  }
7798
7794
  //#endregion
7799
- //#region src/commands/project/settings.ts
7795
+ //#region src/commands/projects/settings.ts
7800
7796
  function parseProjectRole(role) {
7801
7797
  if (role === "admin" || role === "builder") return role;
7802
7798
  throw new Error("Default role must be admin or builder");
@@ -7838,10 +7834,10 @@ function registerProjectSettingsCommand(project) {
7838
7834
  });
7839
7835
  }
7840
7836
  //#endregion
7841
- //#region src/commands/project/index.ts
7842
- function registerProjectCommand(program) {
7843
- const project = program.command("project").description("List, create, update, and delete platform projects");
7844
- project.command("list").description("List projects in the active organization").option("--admin", "List all org resources (org owner or admin only)").action(async (options) => {
7837
+ //#region src/commands/projects/index.ts
7838
+ function registerProjectsCommand(program) {
7839
+ const projects = program.command("projects").description("List, create, update, and delete platform projects");
7840
+ projects.command("list").description("List projects in the active organization").option("--admin", "List all org resources (org owner or admin only)").action(async (options) => {
7845
7841
  const config = createCliConfig();
7846
7842
  try {
7847
7843
  await runProjectList(config, { ...options.admin ? { admin: true } : {} });
@@ -7853,7 +7849,7 @@ function registerProjectCommand(program) {
7853
7849
  process.exitCode = 1;
7854
7850
  }
7855
7851
  });
7856
- project.command("metrics").description("List rollup metrics for projects in the active organization").option("--admin", "List all org resources (org owner or admin only)").action(async (options) => {
7852
+ projects.command("metrics").description("List rollup metrics for projects in the active organization").option("--admin", "List all org resources (org owner or admin only)").action(async (options) => {
7857
7853
  const config = createCliConfig();
7858
7854
  try {
7859
7855
  const projectRef = resolveActiveProjectRef();
@@ -7869,11 +7865,11 @@ function registerProjectCommand(program) {
7869
7865
  process.exitCode = 1;
7870
7866
  }
7871
7867
  });
7872
- project.command("deployments").description("View deployment history for platform projects").command("list").description("List deployment history for a project").action(async () => {
7868
+ projects.command("deployments").description("View deployment history for platform projects").command("list").description("List deployment history for a project").action(async () => {
7873
7869
  const config = createCliConfig();
7874
7870
  try {
7875
7871
  const projectRef = resolveActiveProjectRef();
7876
- if (!projectRef) throw new Error("Usage: keystroke project deployments list --project <slug> (or run `keystroke project link`)");
7872
+ if (!projectRef) throw new Error("Usage: keystroke projects deployments list --project <slug> (or run `keystroke projects link`)");
7877
7873
  await runProjectDeploymentsList(config, { projectRef });
7878
7874
  } catch (error) {
7879
7875
  process.stderr.write(`${formatCliError(error, "List deployments failed", {
@@ -7883,11 +7879,11 @@ function registerProjectCommand(program) {
7883
7879
  process.exitCode = 1;
7884
7880
  }
7885
7881
  });
7886
- project.command("link").description("Link this directory to a platform project in keystroke.config.ts").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
7882
+ projects.command("link").description("Link this directory to a platform project in keystroke.config.ts").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
7887
7883
  const config = createCliConfig();
7888
7884
  try {
7889
7885
  const projectRef = resolveActiveProjectRef(options.dir);
7890
- if (!projectRef) throw new Error("Usage: keystroke project link --project <slug> (see: keystroke project list)");
7886
+ if (!projectRef) throw new Error("Usage: keystroke projects link --project <slug> (see: keystroke projects list)");
7891
7887
  await runProjectLink(config, projectRef, options.dir);
7892
7888
  } catch (error) {
7893
7889
  process.stderr.write(`${formatCliError(error, "Link project failed", {
@@ -7897,7 +7893,7 @@ function registerProjectCommand(program) {
7897
7893
  process.exitCode = 1;
7898
7894
  }
7899
7895
  });
7900
- project.command("create").description("Create a platform project in the active organization").requiredOption("--name <name>", "Project name").option("--description <description>", "Project description").action(async (options) => {
7896
+ projects.command("create").description("Create a platform project in the active organization").requiredOption("--name <name>", "Project name").option("--description <description>", "Project description").action(async (options) => {
7901
7897
  const config = createCliConfig();
7902
7898
  try {
7903
7899
  await runProjectCreate(config, {
@@ -7912,11 +7908,11 @@ function registerProjectCommand(program) {
7912
7908
  process.exitCode = 1;
7913
7909
  }
7914
7910
  });
7915
- project.command("update").description("Update a platform project's name and/or description").option("--name <name>", "Project name").option("--description <description>", "Project description").action(async (options) => {
7911
+ projects.command("update").description("Update a platform project's name and/or description").option("--name <name>", "Project name").option("--description <description>", "Project description").action(async (options) => {
7916
7912
  const config = createCliConfig();
7917
7913
  try {
7918
7914
  const projectId = await resolveActiveProjectId(config);
7919
- if (!projectId) throw new Error("Usage: keystroke --project <slug> project update --name <name>");
7915
+ if (!projectId) throw new Error("Usage: keystroke --project <slug> projects update --name <name>");
7920
7916
  if (!options.name && options.description === void 0) throw new Error("At least one of --name or --description is required");
7921
7917
  await runProjectUpdate(config, {
7922
7918
  projectId,
@@ -7931,11 +7927,11 @@ function registerProjectCommand(program) {
7931
7927
  process.exitCode = 1;
7932
7928
  }
7933
7929
  });
7934
- project.command("delete").description("Delete a platform project").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
7930
+ projects.command("delete").description("Delete a platform project").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
7935
7931
  const config = createCliConfig();
7936
7932
  try {
7937
7933
  const projectId = await resolveActiveProjectId(config);
7938
- if (!projectId) throw new Error("Usage: keystroke --project <slug> project delete");
7934
+ if (!projectId) throw new Error("Usage: keystroke --project <slug> projects delete");
7939
7935
  if (!options.yes) throw new Error("Pass --yes to confirm project deletion");
7940
7936
  await runProjectDelete(config, projectId);
7941
7937
  } catch (error) {
@@ -7946,8 +7942,8 @@ function registerProjectCommand(program) {
7946
7942
  process.exitCode = 1;
7947
7943
  }
7948
7944
  });
7949
- registerProjectMembersCommand(project);
7950
- registerProjectSettingsCommand(project);
7945
+ registerProjectMembersCommand(projects);
7946
+ registerProjectSettingsCommand(projects);
7951
7947
  }
7952
7948
  //#endregion
7953
7949
  //#region src/commands/pull/run-pull.ts
@@ -8035,7 +8031,7 @@ async function runStart(options) {
8035
8031
  const apiPort = Number(new URL(serverUrl).port || 80);
8036
8032
  const runtimeNodeModules = resolveCliRuntimeNodeModules(resolveCliRoot(import.meta.url));
8037
8033
  ensureNativeDeps(runtimeNodeModules);
8038
- const { buildApp } = await import("./dist-DJFUIl5O.mjs");
8034
+ const { buildApp } = await import("./dist-BVw5-nbD.mjs");
8039
8035
  await buildApp({
8040
8036
  root,
8041
8037
  clean: false
@@ -8066,11 +8062,18 @@ function registerStartCommand(program) {
8066
8062
  });
8067
8063
  }
8068
8064
  //#endregion
8069
- //#region src/commands/trigger/list.ts
8065
+ //#region src/commands/triggers/list.ts
8066
+ /** Copy-ready pause/resume commands, printed to stderr so stdout JSON stays pipeable. */
8067
+ function writeToggleHints(triggers) {
8068
+ if (triggers.length === 0) return;
8069
+ process.stderr.write("\nPause/resume without redeploy (disabled state survives deploys):\n");
8070
+ for (const entry of triggers) process.stderr.write(` keystroke triggers disable ${entry.slug} # enable to resume; --workflow/--agent to narrow\n`);
8071
+ }
8070
8072
  function registerTriggerListCommand(trigger) {
8071
8073
  trigger.command("list").description("List discovered triggers").option("--endpoint <endpoint>", "Only webhook triggers on this shared endpoint").action((options) => runProjectCliCommand("List triggers failed", async ({ client }) => {
8072
8074
  const result = await client.triggers.list(options.endpoint ? { endpoint: options.endpoint } : void 0);
8073
8075
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
8076
+ writeToggleHints(result.triggers);
8074
8077
  }));
8075
8078
  }
8076
8079
  function registerTriggerGetCommand(trigger) {
@@ -8080,13 +8083,13 @@ function registerTriggerGetCommand(trigger) {
8080
8083
  }));
8081
8084
  }
8082
8085
  function registerTriggerUrlCommand(trigger) {
8083
- trigger.command("url").description("Print the webhook URL for a trigger").argument("<id>", "Attachment key or webhook route").action((id) => runProjectCliCommand("Resolve webhook URL failed", async ({ client }) => {
8086
+ trigger.command("url").description("Print the webhook URL for a trigger").argument("<triggerSlug>", "Trigger id or slug").action((id) => runProjectCliCommand("Resolve webhook URL failed", async ({ client }) => {
8084
8087
  const url = await client.triggers.webhookUrl(id);
8085
8088
  process.stdout.write(`${url}\n`);
8086
8089
  }));
8087
8090
  }
8088
8091
  //#endregion
8089
- //#region src/commands/trigger/poll.ts
8092
+ //#region src/commands/triggers/poll.ts
8090
8093
  function collect(value, previous) {
8091
8094
  return [...previous, value];
8092
8095
  }
@@ -8101,65 +8104,140 @@ function registerTriggerPollCommand(trigger) {
8101
8104
  }));
8102
8105
  }
8103
8106
  //#endregion
8104
- //#region src/commands/trigger/runs.ts
8105
- function registerTriggerRunsCommand(trigger) {
8106
- const runs = trigger.command("runs").description("List and inspect trigger runs");
8107
- runs.command("list").description("List runs for a trigger attachment").argument("<attachmentId>", "Trigger attachment key").option("--limit <n>", "Page size (1–100)", "20").option("--cursor <cursor>", "Pagination cursor from a previous page").option("--trigger-type <type>", "Filter by trigger type (cron, webhook, poll)").action((attachmentId, options) => runProjectCliCommand("List trigger runs failed", async ({ client }) => {
8108
- const result = await client.triggers.listRuns(attachmentId, {
8109
- limit: Number(options.limit),
8110
- ...options.cursor ? { cursor: options.cursor } : {},
8111
- ...options.triggerType ? { triggerType: options.triggerType } : {}
8112
- });
8113
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
8114
- }));
8115
- runs.command("get").description("Get full details for a trigger run").argument("<attachmentId>", "Trigger attachment key").argument("<runId>", "Trigger run id").option("--include <parts>", "Comma-separated: workflows, trace").action((attachmentId, runId, options) => runProjectCliCommand("Get trigger run failed", async ({ client }) => {
8116
- const result = await client.triggers.getRun(attachmentId, runId, { include: options.include });
8117
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
8118
- }));
8119
- }
8120
- //#endregion
8121
- //#region src/commands/trigger/resolve-trigger-attachment.ts
8122
- function findAssignment(assignments, attachmentRef) {
8123
- return assignments.find((entry) => entry.attachmentId === attachmentRef || entry.attachmentSlug === attachmentRef);
8124
- }
8125
- async function resolveTriggerAttachment(platform, triggerRef, attachmentRef) {
8107
+ //#region src/commands/triggers/resolve-trigger-attachment.ts
8108
+ async function loadTrigger(platform, triggerRef) {
8126
8109
  let trigger = await platform.triggers.get(triggerRef);
8127
8110
  if (!trigger) {
8128
8111
  const summary = (await platform.triggers.list()).find((entry) => entry.id === triggerRef || entry.slug === triggerRef) ?? null;
8129
8112
  if (summary) trigger = await platform.triggers.get(summary.id);
8130
8113
  }
8131
8114
  if (!trigger) throw new Error(`Trigger not found: ${triggerRef}`);
8132
- const assignment = findAssignment(trigger.assignments, attachmentRef);
8133
- if (!assignment) throw new Error(`Attachment not found on trigger ${trigger.slug}: ${attachmentRef}`);
8115
+ return trigger;
8116
+ }
8117
+ /**
8118
+ * Resolve which attachments a toggle applies to. With no target, every attachment on the
8119
+ * trigger is returned ("disable the trigger"). A `--workflow`/`--agent` target narrows to
8120
+ * the single binding for that workflow/agent — so callers never handle attachment ids.
8121
+ */
8122
+ async function resolveTriggerAttachments(platform, triggerRef, target) {
8123
+ const trigger = await loadTrigger(platform, triggerRef);
8124
+ if (!target) {
8125
+ if (trigger.assignments.length === 0) throw new Error(`Trigger ${trigger.slug} has no attachments`);
8126
+ return {
8127
+ trigger,
8128
+ attachments: trigger.assignments
8129
+ };
8130
+ }
8131
+ const match = trigger.assignments.find((entry) => entry.kind === target.kind && entry.slug === target.slug);
8132
+ if (!match) {
8133
+ const available = trigger.assignments.map((entry) => `${entry.kind} ${entry.slug}`).join(", ");
8134
+ throw new Error(`No ${target.kind} "${target.slug}" attached to trigger ${trigger.slug}` + (available ? ` (attached: ${available})` : ""));
8135
+ }
8134
8136
  return {
8135
- triggerId: trigger.id,
8136
- attachmentId: assignment.attachmentId,
8137
8137
  trigger,
8138
- assignment
8138
+ attachments: [match]
8139
+ };
8140
+ }
8141
+ /** Attachment slug passed to runtime trigger run APIs (one target required). */
8142
+ function attachmentSlugForRuns(attachments) {
8143
+ if (attachments.length === 1) return attachments[0].attachmentSlug;
8144
+ throw new Error(`Trigger has ${attachments.length} attachments — pass --workflow or --agent to list runs for one target`);
8145
+ }
8146
+ //#endregion
8147
+ //#region src/commands/triggers/runs.ts
8148
+ function resolveTarget$1(options) {
8149
+ if (options.workflow && options.agent) throw new Error("Pass only one of --workflow or --agent");
8150
+ if (options.workflow) return {
8151
+ kind: "workflow",
8152
+ slug: options.workflow
8139
8153
  };
8154
+ if (options.agent) return {
8155
+ kind: "agent",
8156
+ slug: options.agent
8157
+ };
8158
+ }
8159
+ async function resolveRunsAttachmentSlug(triggerRef, target) {
8160
+ const config = createCliConfig();
8161
+ let attachmentSlug = "";
8162
+ await withActivePlatformClient(config, async (platform) => {
8163
+ const { attachments } = await resolveTriggerAttachments(platform, triggerRef, target);
8164
+ attachmentSlug = attachmentSlugForRuns(attachments);
8165
+ });
8166
+ return attachmentSlug;
8167
+ }
8168
+ function registerTriggerRunsCommand(trigger) {
8169
+ const runs = trigger.command("runs").description("List and inspect trigger runs");
8170
+ runs.command("list").description("List runs for a trigger").argument("<triggerSlug>", "Trigger id or slug").option("--workflow <slug>", "Narrow to the attachment bound to this workflow").option("--agent <slug>", "Narrow to the attachment bound to this agent").option("--limit <n>", "Page size (1–100)", "20").option("--cursor <cursor>", "Pagination cursor from a previous page").option("--trigger-type <type>", "Filter by trigger type (cron, webhook, poll)").action(async (triggerSlug, options) => {
8171
+ const config = createCliConfig();
8172
+ try {
8173
+ const attachmentSlug = await resolveRunsAttachmentSlug(triggerSlug, resolveTarget$1(options));
8174
+ await runProjectCliCommand("List trigger runs failed", async ({ client }) => {
8175
+ const result = await client.triggers.listRuns(attachmentSlug, {
8176
+ limit: Number(options.limit),
8177
+ ...options.cursor ? { cursor: options.cursor } : {},
8178
+ ...options.triggerType ? { triggerType: options.triggerType } : {}
8179
+ });
8180
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
8181
+ });
8182
+ } catch (error) {
8183
+ process.stderr.write(`${formatCliError(error, "List trigger runs failed", {
8184
+ serverUrl: getPlatformUrl(config),
8185
+ webUrl: getWebUrl(config)
8186
+ })}\n`);
8187
+ process.exitCode = 1;
8188
+ }
8189
+ });
8190
+ runs.command("get").description("Get full details for a trigger run").argument("<triggerSlug>", "Trigger id or slug").argument("<runId>", "Trigger run id").option("--workflow <slug>", "Narrow to the attachment bound to this workflow").option("--agent <slug>", "Narrow to the attachment bound to this agent").option("--include <parts>", "Comma-separated: workflows, trace").action(async (triggerSlug, runId, options) => {
8191
+ const config = createCliConfig();
8192
+ try {
8193
+ const attachmentSlug = await resolveRunsAttachmentSlug(triggerSlug, resolveTarget$1(options));
8194
+ await runProjectCliCommand("Get trigger run failed", async ({ client }) => {
8195
+ const result = await client.triggers.getRun(attachmentSlug, runId, { include: options.include });
8196
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
8197
+ });
8198
+ } catch (error) {
8199
+ process.stderr.write(`${formatCliError(error, "Get trigger run failed", {
8200
+ serverUrl: getPlatformUrl(config),
8201
+ webUrl: getWebUrl(config)
8202
+ })}\n`);
8203
+ process.exitCode = 1;
8204
+ }
8205
+ });
8140
8206
  }
8141
8207
  //#endregion
8142
- //#region src/commands/trigger/run-attachment-enabled.ts
8143
- async function runTriggerAttachmentEnabled(config, options) {
8208
+ //#region src/commands/triggers/run-attachment-enabled.ts
8209
+ async function runTriggerEnabled(config, options) {
8144
8210
  await withActivePlatformClient(config, async (platform) => {
8145
- const resolved = await resolveTriggerAttachment(platform, options.triggerRef, options.attachmentRef);
8146
- const trigger = await platform.triggers.updateAttachment(resolved.triggerId, resolved.attachmentId, { enabled: options.enabled });
8147
- process.stdout.write(`${JSON.stringify(trigger, null, 2)}\n`);
8211
+ const { trigger, attachments } = await resolveTriggerAttachments(platform, options.triggerRef, options.target);
8212
+ let detail = trigger;
8213
+ for (const attachment of attachments) detail = await platform.triggers.updateAttachment(trigger.id, attachment.attachmentId, { enabled: options.enabled });
8214
+ process.stdout.write(`${JSON.stringify(detail, null, 2)}\n`);
8148
8215
  });
8149
8216
  }
8150
8217
  //#endregion
8151
- //#region src/commands/trigger/attachment.ts
8152
- function registerAttachmentToggleCommand(attachment, command, enabled) {
8153
- attachment.command(command).description(`${command === "enable" ? "Enable" : "Disable"} a trigger attachment`).argument("<triggerRef>", "Trigger id or slug").argument("<attachmentRef>", "Attachment id or slug (for example signup:signup-pipeline)").action(async (triggerRef, attachmentRef) => {
8218
+ //#region src/commands/triggers/toggle.ts
8219
+ function resolveTarget(options) {
8220
+ if (options.workflow && options.agent) throw new Error("Pass only one of --workflow or --agent");
8221
+ if (options.workflow) return {
8222
+ kind: "workflow",
8223
+ slug: options.workflow
8224
+ };
8225
+ if (options.agent) return {
8226
+ kind: "agent",
8227
+ slug: options.agent
8228
+ };
8229
+ }
8230
+ function registerToggle(trigger, command, enabled) {
8231
+ trigger.command(command).description(`${command === "enable" ? "Enable" : "Disable"} a trigger — all attachments by default, or one with --workflow/--agent`).argument("<trigger-slug>", "Trigger id or slug").option("--workflow <slug>", "Only the attachment bound to this workflow").option("--agent <slug>", "Only the attachment bound to this agent").action(async (triggerRef, options) => {
8154
8232
  const config = createCliConfig();
8155
8233
  try {
8156
- await runTriggerAttachmentEnabled(config, {
8234
+ await runTriggerEnabled(config, {
8157
8235
  triggerRef,
8158
- attachmentRef,
8236
+ target: resolveTarget(options),
8159
8237
  enabled
8160
8238
  });
8161
8239
  } catch (error) {
8162
- process.stderr.write(`${formatCliError(error, `${command} trigger attachment failed`, {
8240
+ process.stderr.write(`${formatCliError(error, `${command} trigger failed`, {
8163
8241
  serverUrl: getPlatformUrl(config),
8164
8242
  webUrl: getWebUrl(config)
8165
8243
  })}\n`);
@@ -8167,24 +8245,23 @@ function registerAttachmentToggleCommand(attachment, command, enabled) {
8167
8245
  }
8168
8246
  });
8169
8247
  }
8170
- function registerTriggerAttachmentCommand(trigger) {
8171
- const attachment = trigger.command("attachment").description("Enable or disable individual trigger attachments");
8172
- registerAttachmentToggleCommand(attachment, "disable", false);
8173
- registerAttachmentToggleCommand(attachment, "enable", true);
8248
+ function registerTriggerToggleCommands(trigger) {
8249
+ registerToggle(trigger, "disable", false);
8250
+ registerToggle(trigger, "enable", true);
8174
8251
  }
8175
8252
  //#endregion
8176
- //#region src/commands/trigger/index.ts
8177
- function registerTriggerCommand(program) {
8178
- const trigger = program.command("trigger").description("Invoke and inspect triggers");
8179
- registerTriggerListCommand(trigger);
8180
- registerTriggerGetCommand(trigger);
8181
- registerTriggerUrlCommand(trigger);
8182
- registerTriggerPollCommand(trigger);
8183
- registerTriggerRunsCommand(trigger);
8184
- registerTriggerAttachmentCommand(trigger);
8253
+ //#region src/commands/triggers/index.ts
8254
+ function registerTriggersCommand(program) {
8255
+ const triggers = program.command("triggers").description("Invoke and inspect triggers");
8256
+ registerTriggerListCommand(triggers);
8257
+ registerTriggerGetCommand(triggers);
8258
+ registerTriggerUrlCommand(triggers);
8259
+ registerTriggerPollCommand(triggers);
8260
+ registerTriggerRunsCommand(triggers);
8261
+ registerTriggerToggleCommands(triggers);
8185
8262
  }
8186
8263
  //#endregion
8187
- //#region src/commands/workflow/list.ts
8264
+ //#region src/commands/workflows/list.ts
8188
8265
  function registerWorkflowListCommand(workflow) {
8189
8266
  workflow.command("list").description("List workflows in the active organization").option("--admin", "List all org resources (org owner or admin only)").action((options) => runCliCommand("List workflows failed", async () => {
8190
8267
  const config = createCliConfig();
@@ -8200,32 +8277,32 @@ function registerWorkflowListCommand(workflow) {
8200
8277
  }, void 0, { orgScoped: true }));
8201
8278
  }
8202
8279
  //#endregion
8203
- //#region src/commands/workflow/run.ts
8280
+ //#region src/commands/workflows/run.ts
8204
8281
  function registerWorkflowRunCommand(workflow) {
8205
8282
  workflow.command("run").description("Invoke a workflow").argument("<workflowId>", "Workflow key / route id").option("--input <json>", "JSON request body (defaults to {})", "{}").addHelpText("after", `
8206
8283
  Examples:
8207
- ${cliBinaryName()} workflow run math --input '{"first":1,"second":2}'
8208
- ${cliBinaryName()} workflow run incoming-message --input '{"message":"Hi","sender":"you"}'
8284
+ ${cliBinaryName()} workflows run math --input '{"first":1,"second":2}'
8285
+ ${cliBinaryName()} workflows run incoming-message --input '{"message":"Hi","sender":"you"}'
8209
8286
  `).action((workflowId, options) => runProjectCliCommand("Workflow run failed", async ({ client }) => {
8210
8287
  const input = parseJsonOption(options.input, "--input");
8211
8288
  const result = await client.workflows.run(workflowId, input);
8212
8289
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
8213
- if (isQueuedRunResponse(result)) process.stderr.write(`Run queued. Track progress:\n ${cliBinaryName()} workflow runs get ${workflowId} ${result.runId} --include steps,trace\n`);
8290
+ if (isQueuedRunResponse(result)) process.stderr.write(`Run queued. Track progress:\n ${cliBinaryName()} workflows runs get ${workflowId} ${result.runId} --include steps,trace\n`);
8214
8291
  }, { usage: {
8215
- command: `${cliBinaryName()} workflow run ${workflowId}`,
8292
+ command: `${cliBinaryName()} workflows run ${workflowId}`,
8216
8293
  flag: "--input"
8217
8294
  } }));
8218
8295
  }
8219
8296
  //#endregion
8220
- //#region src/commands/workflow/cancel-run.ts
8221
- async function runWorkflowRunCancel(config, runId) {
8297
+ //#region src/commands/workflows/cancel-run.ts
8298
+ async function runWorkflowRunCancel(config, _workflowId, runId) {
8222
8299
  await withActivePlatformClient(config, async (platform) => {
8223
8300
  const run = await platform.workflows.cancelRun(runId);
8224
8301
  process.stdout.write(`${JSON.stringify(run, null, 2)}\n`);
8225
8302
  });
8226
8303
  }
8227
8304
  //#endregion
8228
- //#region src/commands/workflow/runs.ts
8305
+ //#region src/commands/workflows/runs.ts
8229
8306
  function registerWorkflowRunsCommand(workflow) {
8230
8307
  const runs = workflow.command("runs").description("List and inspect workflow runs");
8231
8308
  runs.command("list").description("List runs for a workflow").argument("<workflowId>", "Workflow key / route id").option("--limit <n>", "Page size (1–100)", "20").option("--cursor <cursor>", "Pagination cursor from a previous page").option("--status <status>", "Filter by status").option("--trigger <trigger>", "Filter by trigger kind").action((workflowId, options) => runProjectCliCommand("List workflow runs failed", async ({ client }) => {
@@ -8245,10 +8322,10 @@ function registerWorkflowRunsCommand(workflow) {
8245
8322
  const result = await client.workflows.listHooks(workflowId, runId);
8246
8323
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
8247
8324
  }));
8248
- runs.command("cancel").description("Cancel a running or queued workflow run").argument("<runId>", "Workflow run id").action(async (runId) => {
8325
+ runs.command("cancel").description("Cancel a running or queued workflow run").argument("<workflowId>", "Workflow key / route id").argument("<runId>", "Workflow run id").action(async (workflowId, runId) => {
8249
8326
  const config = createCliConfig();
8250
8327
  try {
8251
- await runWorkflowRunCancel(config, runId);
8328
+ await runWorkflowRunCancel(config, workflowId, runId);
8252
8329
  } catch (error) {
8253
8330
  process.stderr.write(`${formatCliError(error, "Cancel workflow run failed", {
8254
8331
  serverUrl: getPlatformUrl(config),
@@ -8259,15 +8336,15 @@ function registerWorkflowRunsCommand(workflow) {
8259
8336
  });
8260
8337
  }
8261
8338
  //#endregion
8262
- //#region src/commands/workflow/index.ts
8263
- function registerWorkflowCommand(program) {
8264
- const workflow = program.command("workflow").description("Invoke and inspect workflows");
8265
- registerWorkflowListCommand(workflow);
8266
- registerWorkflowRunCommand(workflow);
8267
- registerWorkflowRunsCommand(workflow);
8339
+ //#region src/commands/workflows/index.ts
8340
+ function registerWorkflowsCommand(program) {
8341
+ const workflows = program.command("workflows").description("Invoke and inspect workflows");
8342
+ registerWorkflowListCommand(workflows);
8343
+ registerWorkflowRunCommand(workflows);
8344
+ registerWorkflowRunsCommand(workflows);
8268
8345
  }
8269
8346
  //#endregion
8270
- //#region src/commands/channel/run-channel.ts
8347
+ //#region src/commands/channels/run-channel.ts
8271
8348
  async function runChannelPlatformsList(client) {
8272
8349
  return client.channels.listPlatforms();
8273
8350
  }
@@ -8290,7 +8367,7 @@ async function runChannelUnbind(client, projectId, input) {
8290
8367
  return client.channels.removeBinding(projectId, input);
8291
8368
  }
8292
8369
  //#endregion
8293
- //#region src/commands/channel/platforms.ts
8370
+ //#region src/commands/channels/platforms.ts
8294
8371
  function registerChannelPlatformsCommand(channel) {
8295
8372
  channel.command("platforms").description("Browse gateway-enabled apps").command("list").description("List apps that support agent external channels").action(() => runCliCommand("List channel platforms failed", async () => {
8296
8373
  const config = createCliConfig();
@@ -8301,17 +8378,17 @@ function registerChannelPlatformsCommand(channel) {
8301
8378
  }, void 0, { orgScoped: true }));
8302
8379
  }
8303
8380
  //#endregion
8304
- //#region src/commands/channel/resolve-channel-project.ts
8381
+ //#region src/commands/channels/resolve-channel-project.ts
8305
8382
  async function resolveChannelProjectId(config) {
8306
8383
  const platform = createCliPlatformClient(config);
8307
8384
  await ensureLinkedOrganization(config);
8308
8385
  await ensureActiveOrganization(config);
8309
8386
  const ref = resolveActiveProjectRef();
8310
- if (!ref) throw new Error("Project is required. Pass --project <slug> or run `keystroke project link --project <slug>`.");
8387
+ if (!ref) throw new Error("Project is required. Pass --project <slug> or run `keystroke projects link --project <slug>`.");
8311
8388
  return (await resolveProjectRef(platform, ref)).id;
8312
8389
  }
8313
8390
  //#endregion
8314
- //#region src/commands/channel/list.ts
8391
+ //#region src/commands/channels/list.ts
8315
8392
  function registerChannelAccountsCommand(channel) {
8316
8393
  channel.command("accounts").description("List available workspace accounts for a platform").requiredOption("--platform <key>", "Platform key (slack)").action(async (options) => runCliCommand("List channel accounts failed", async () => {
8317
8394
  const config = createCliConfig();
@@ -8343,13 +8420,13 @@ function registerChannelDirectoryCommand(channel) {
8343
8420
  }));
8344
8421
  }
8345
8422
  function registerChannelBindCommand(channel) {
8346
- channel.command("bind").description("Bind an agent to a channel").requiredOption("--agent <id>", "Agent id").requiredOption("--platform <key>", "Platform key (slack)").requiredOption("--account <id>", "Workspace account id (team id)").requiredOption("--channel <id>", "Provider channel id").option("--channel-name <name>", "Provider channel name").option("--mode <mode>", "Listen mode (mention, all, dm)", "mention").action(async (options) => runCliCommand("Bind channel failed", async () => {
8423
+ channel.command("bind").description("Bind an agent to a channel").argument("<agent>", "Agent id or slug").requiredOption("--platform <key>", "Platform key (slack)").requiredOption("--account <id>", "Workspace account id (team id)").requiredOption("--channel <id>", "Provider channel id").option("--channel-name <name>", "Provider channel name").option("--mode <mode>", "Listen mode (mention, all, dm)", "mention").action(async (agent, options) => runCliCommand("Bind channel failed", async () => {
8347
8424
  const config = createCliConfig();
8348
8425
  const projectId = await resolveChannelProjectId(config);
8349
8426
  const client = createCliPlatformClient(config);
8350
8427
  await ensureActiveOrganization(config);
8351
8428
  const connection = await runChannelBind(client, projectId, {
8352
- agentId: options.agent,
8429
+ agentId: agent,
8353
8430
  platform: options.platform,
8354
8431
  accountId: options.account,
8355
8432
  binding: {
@@ -8393,16 +8470,16 @@ function registerChannelUpdateBindingCommand(channel) {
8393
8470
  }));
8394
8471
  }
8395
8472
  //#endregion
8396
- //#region src/commands/channel/index.ts
8397
- function registerChannelCommand(program) {
8398
- const channel = program.command("channel").description("Manage agent external channel bindings");
8399
- registerChannelPlatformsCommand(channel);
8400
- registerChannelAccountsCommand(channel);
8401
- registerChannelListCommand(channel);
8402
- registerChannelDirectoryCommand(channel);
8403
- registerChannelBindCommand(channel);
8404
- registerChannelUnbindCommand(channel);
8405
- registerChannelUpdateBindingCommand(channel);
8473
+ //#region src/commands/channels/index.ts
8474
+ function registerChannelsCommand(program) {
8475
+ const channels = program.command("channels").description("Manage agent external channel bindings");
8476
+ registerChannelPlatformsCommand(channels);
8477
+ registerChannelAccountsCommand(channels);
8478
+ registerChannelListCommand(channels);
8479
+ registerChannelDirectoryCommand(channels);
8480
+ registerChannelBindCommand(channels);
8481
+ registerChannelUnbindCommand(channels);
8482
+ registerChannelUpdateBindingCommand(channels);
8406
8483
  }
8407
8484
  //#endregion
8408
8485
  //#region src/commands/config/preferences-patch.ts
@@ -8495,37 +8572,6 @@ function registerConfigCommand(program) {
8495
8572
  });
8496
8573
  }
8497
8574
  //#endregion
8498
- //#region src/commands/skill/index.ts
8499
- function registerSkillCommand(program) {
8500
- program.command("skill").description("Inspect platform skills").command("list").description("List skills in the active organization").option("--admin", "List all org resources (org owner or admin only)").action((options) => runCliCommand("List skills failed", async () => {
8501
- const config = createCliConfig();
8502
- const client = createCliPlatformClient(config);
8503
- await ensureActiveOrganization(config);
8504
- if (options.admin) await requireAdminRole(config);
8505
- const projectId = await resolveActiveProjectId(config);
8506
- const result = await client.skills.list({
8507
- ...projectId ? { projectId } : {},
8508
- ...options.admin ? { admin: true } : {}
8509
- });
8510
- process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
8511
- }, void 0, { orgScoped: true }));
8512
- }
8513
- //#endregion
8514
- //#region src/commands/skills.ts
8515
- function registerSkillsCommand(program) {
8516
- program.command("skills").description("Manage the scaffolded AGENTS guide").command("sync").description("Overwrite AGENTS.md with the CLI version").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
8517
- try {
8518
- const root = resolveProjectRoot(options.dir);
8519
- await scaffoldAgentsGuide(root);
8520
- process.stdout.write(`Synced AGENTS.md at ${root}\n`);
8521
- } catch (error) {
8522
- const message = error instanceof Error ? error.message : "AGENTS guide sync failed";
8523
- process.stderr.write(`${message}\n`);
8524
- process.exitCode = 1;
8525
- }
8526
- });
8527
- }
8528
- //#endregion
8529
8575
  //#region src/skills/sync-agents-guide.ts
8530
8576
  function commandPath(command) {
8531
8577
  const names = [];
@@ -8537,9 +8583,7 @@ function commandPath(command) {
8537
8583
  }
8538
8584
  function shouldSkipAutoSync(command) {
8539
8585
  if (process.env.CI === "true" || process.env.CI === "1") return true;
8540
- const path = commandPath(command);
8541
- if (path[0] === "init") return true;
8542
- if (path[0] === "skills") return true;
8586
+ if (commandPath(command)[0] === "init") return true;
8543
8587
  return false;
8544
8588
  }
8545
8589
  function resolveAutoSyncRoot(command) {
@@ -8576,14 +8620,12 @@ function createProgram() {
8576
8620
  registerConfigCommand(program);
8577
8621
  registerOrganizationCommand(program);
8578
8622
  registerApiKeyCommand(program);
8579
- registerProjectCommand(program);
8623
+ registerProjectsCommand(program);
8580
8624
  registerHistoryCommand(program);
8581
8625
  registerCredentialsCommand(program);
8582
8626
  registerHealthCommand(program);
8583
8627
  registerDocsCommand(program);
8584
8628
  registerInitCommand(program);
8585
- registerSkillsCommand(program);
8586
- registerSkillCommand(program);
8587
8629
  registerBuildCommand(program);
8588
8630
  registerLintCommand(program);
8589
8631
  registerTypecheckCommand(program);
@@ -8592,11 +8634,11 @@ function createProgram() {
8592
8634
  registerPullCommand(program);
8593
8635
  registerDevCommand(program);
8594
8636
  registerStartCommand(program);
8595
- registerAgentCommand(program);
8596
- registerChannelCommand(program);
8597
- registerAppCommand(program);
8598
- registerWorkflowCommand(program);
8599
- registerTriggerCommand(program);
8637
+ registerAgentsCommand(program);
8638
+ registerChannelsCommand(program);
8639
+ registerAppsCommand(program);
8640
+ registerWorkflowsCommand(program);
8641
+ registerTriggersCommand(program);
8600
8642
  return program;
8601
8643
  }
8602
8644
  async function runCli(argv) {