@imbrace/cli 0.1.0 → 0.3.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.
Files changed (58) hide show
  1. package/README.md +443 -0
  2. package/dist/commands/ai-agent/create.d.ts +5 -0
  3. package/dist/commands/ai-agent/create.js +11 -0
  4. package/dist/commands/ai-agent/list-files.d.ts +10 -0
  5. package/dist/commands/ai-agent/list-files.js +40 -0
  6. package/dist/commands/ai-agent/list-folders.d.ts +10 -0
  7. package/dist/commands/ai-agent/list-folders.js +39 -0
  8. package/dist/commands/ai-agent/list-providers.js +1 -1
  9. package/dist/commands/ai-agent/update.d.ts +5 -0
  10. package/dist/commands/ai-agent/update.js +16 -0
  11. package/dist/commands/docs.d.ts +10 -0
  12. package/dist/commands/docs.js +39 -0
  13. package/dist/commands/workflow/conn/create.d.ts +15 -0
  14. package/dist/commands/workflow/conn/create.js +69 -0
  15. package/dist/commands/workflow/conn/delete.d.ts +13 -0
  16. package/dist/commands/workflow/conn/delete.js +39 -0
  17. package/dist/commands/workflow/conn/get.d.ts +12 -0
  18. package/dist/commands/workflow/conn/get.js +42 -0
  19. package/dist/commands/workflow/conn/list.d.ts +9 -0
  20. package/dist/commands/workflow/conn/list.js +37 -0
  21. package/dist/commands/workflow/create.d.ts +1 -0
  22. package/dist/commands/workflow/create.js +4 -0
  23. package/dist/commands/workflow/disable.d.ts +12 -0
  24. package/dist/commands/workflow/disable.js +30 -0
  25. package/dist/commands/workflow/enable.d.ts +12 -0
  26. package/dist/commands/workflow/enable.js +34 -0
  27. package/dist/commands/workflow/folder/create.d.ts +12 -0
  28. package/dist/commands/workflow/folder/create.js +43 -0
  29. package/dist/commands/workflow/folder/delete.d.ts +13 -0
  30. package/dist/commands/workflow/folder/delete.js +39 -0
  31. package/dist/commands/workflow/folder/get.d.ts +12 -0
  32. package/dist/commands/workflow/folder/get.js +38 -0
  33. package/dist/commands/workflow/folder/list.d.ts +9 -0
  34. package/dist/commands/workflow/folder/list.js +35 -0
  35. package/dist/commands/workflow/folder/update.d.ts +13 -0
  36. package/dist/commands/workflow/folder/update.js +30 -0
  37. package/dist/commands/workflow/list.d.ts +1 -0
  38. package/dist/commands/workflow/list.js +7 -1
  39. package/dist/commands/workflow/mcp/create.d.ts +12 -0
  40. package/dist/commands/workflow/mcp/create.js +44 -0
  41. package/dist/commands/workflow/mcp/delete.d.ts +13 -0
  42. package/dist/commands/workflow/mcp/delete.js +39 -0
  43. package/dist/commands/workflow/mcp/get.d.ts +12 -0
  44. package/dist/commands/workflow/mcp/get.js +40 -0
  45. package/dist/commands/workflow/mcp/list.d.ts +9 -0
  46. package/dist/commands/workflow/mcp/list.js +36 -0
  47. package/dist/commands/workflow/mcp/rotate-token.d.ts +13 -0
  48. package/dist/commands/workflow/mcp/rotate-token.js +46 -0
  49. package/dist/commands/workflow/move.d.ts +13 -0
  50. package/dist/commands/workflow/move.js +35 -0
  51. package/dist/commands/workflow/node/add-raw.d.ts +15 -0
  52. package/dist/commands/workflow/node/add-raw.js +70 -0
  53. package/dist/commands/workflow/publish.d.ts +12 -0
  54. package/dist/commands/workflow/publish.js +30 -0
  55. package/dist/commands/workflow/run.d.ts +14 -0
  56. package/dist/commands/workflow/run.js +50 -0
  57. package/llms.txt +625 -0
  58. package/package.json +12 -2
@@ -0,0 +1,39 @@
1
+ import { Command, Flags } from "@oclif/core";
2
+ import { readFileSync, existsSync } from "node:fs";
3
+ import { fileURLToPath } from "node:url";
4
+ import { dirname, resolve } from "node:path";
5
+ export default class Docs extends Command {
6
+ static description = "Print the bundled llms.txt — a comprehensive command reference designed to be fed into a coding agent's context (Claude, Cursor, ...). Pipe to a file: `imbrace docs > llms.txt`.";
7
+ static examples = [
8
+ "imbrace docs # print full llms.txt to stdout",
9
+ "imbrace docs --path # print absolute path to bundled llms.txt",
10
+ "imbrace docs > /tmp/imbrace-llms.txt # save for an AI agent's context",
11
+ ];
12
+ static flags = {
13
+ path: Flags.boolean({ description: "Print only the absolute path to llms.txt (don't print contents)" }),
14
+ json: Flags.boolean({ description: "Output as JSON: { path, content }" }),
15
+ };
16
+ async run() {
17
+ const { flags } = await this.parse(Docs);
18
+ const here = dirname(fileURLToPath(import.meta.url));
19
+ const candidates = [
20
+ resolve(here, "../../llms.txt"),
21
+ resolve(here, "../llms.txt"),
22
+ resolve(here, "../../../llms.txt"),
23
+ ];
24
+ const llmsPath = candidates.find((p) => existsSync(p));
25
+ if (!llmsPath) {
26
+ this.error(`llms.txt not found. Looked in:\n${candidates.map((p) => ` - ${p}`).join("\n")}\n\nReinstall the package or fetch from https://github.com/imbraceltd/imbrace-cli/blob/main/llms.txt`);
27
+ }
28
+ if (flags.path && !flags.json) {
29
+ this.log(llmsPath);
30
+ return;
31
+ }
32
+ const content = readFileSync(llmsPath, "utf8");
33
+ if (flags.json) {
34
+ this.log(JSON.stringify({ path: llmsPath, content }, null, 2));
35
+ return;
36
+ }
37
+ this.log(content);
38
+ }
39
+ }
@@ -0,0 +1,15 @@
1
+ import { BaseCommand } from "../../../base-command.js";
2
+ export default class WorkflowConnCreate extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ piece: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ type: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
+ value: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ "display-name": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ "external-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ "id-only": import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ }
@@ -0,0 +1,69 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../../base-command.js";
3
+ import { apiRequest } from "../../../http.js";
4
+ export default class WorkflowConnCreate extends BaseCommand {
5
+ static description = "Create a connection (save credential for an external service)";
6
+ static examples = [
7
+ 'imbrace workflow conn create --piece slack --type SECRET_TEXT --value "xoxb-..." --json',
8
+ 'imbrace workflow conn create --piece openai --type SECRET_TEXT --value "sk-..." --display-name "Production OpenAI" --json',
9
+ ];
10
+ static flags = {
11
+ piece: Flags.string({
12
+ description: "Piece name (e.g. 'slack' or '@activepieces/piece-slack')",
13
+ required: true,
14
+ }),
15
+ type: Flags.string({
16
+ description: "Auth type",
17
+ options: ["SECRET_TEXT", "OAUTH2", "CLOUD_OAUTH2", "BASIC_AUTH", "CUSTOM_AUTH"],
18
+ required: true,
19
+ }),
20
+ value: Flags.string({
21
+ description: "Credential value. For SECRET_TEXT: the raw token. For other types: JSON string with type-specific fields.",
22
+ required: true,
23
+ }),
24
+ "display-name": Flags.string({ description: "Human-readable name (default: auto-generated)" }),
25
+ "external-id": Flags.string({ description: "Unique external ID (default: auto-generated cli_<timestamp>)" }),
26
+ json: Flags.boolean({ description: "Output as JSON" }),
27
+ "id-only": Flags.boolean({ description: "Print only the new connection ID" }),
28
+ };
29
+ async run() {
30
+ const { flags } = await this.parse(WorkflowConnCreate);
31
+ // For non-SECRET_TEXT types, parse value as JSON
32
+ let value = flags.value;
33
+ if (flags.type !== "SECRET_TEXT") {
34
+ try {
35
+ value = JSON.parse(flags.value);
36
+ }
37
+ catch (e) {
38
+ this.error(`--value must be valid JSON for type ${flags.type}: ${e.message}`);
39
+ }
40
+ }
41
+ const body = {
42
+ piece: flags.piece,
43
+ type: flags.type,
44
+ value,
45
+ };
46
+ if (flags["display-name"])
47
+ body.displayName = flags["display-name"];
48
+ if (flags["external-id"])
49
+ body.externalId = flags["external-id"];
50
+ try {
51
+ const res = await apiRequest("/workflow/conn/create", { method: "POST", body });
52
+ if (flags["id-only"]) {
53
+ this.log(res.data?.id ?? "");
54
+ return;
55
+ }
56
+ if (flags.json) {
57
+ this.log(JSON.stringify(res, null, 2));
58
+ return;
59
+ }
60
+ this.log(`\n✅ ${res.message}`);
61
+ if (res.data?.id)
62
+ this.log(` ID: ${res.data.id}`);
63
+ this.log("");
64
+ }
65
+ catch (error) {
66
+ this.error(`Failed: ${error.message}`);
67
+ }
68
+ }
69
+ }
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from "../../../base-command.js";
2
+ export default class WorkflowConnDelete extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ connId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,39 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../../base-command.js";
3
+ import { confirm } from "@inquirer/prompts";
4
+ import { apiRequest } from "../../../http.js";
5
+ export default class WorkflowConnDelete extends BaseCommand {
6
+ static description = "Delete a connection";
7
+ static examples = [
8
+ "imbrace workflow conn delete <connId> --yes",
9
+ "imbrace workflow conn delete <connId> --yes --json",
10
+ ];
11
+ static args = {
12
+ connId: Args.string({ description: "Connection ID", required: true }),
13
+ };
14
+ static flags = {
15
+ yes: Flags.boolean({ char: "y", description: "Skip confirmation" }),
16
+ json: Flags.boolean({ description: "Output as JSON" }),
17
+ };
18
+ async run() {
19
+ const { args, flags } = await this.parse(WorkflowConnDelete);
20
+ if (!flags.yes && !flags.json) {
21
+ const ok = await confirm({ message: `Delete connection ${args.connId}?`, default: false });
22
+ if (!ok) {
23
+ this.log("Cancelled.");
24
+ return;
25
+ }
26
+ }
27
+ try {
28
+ const res = await apiRequest(`/workflow/conn/${args.connId}`, { method: "DELETE" });
29
+ if (flags.json) {
30
+ this.log(JSON.stringify(res, null, 2));
31
+ return;
32
+ }
33
+ this.log(`\n✅ ${res.message}\n`);
34
+ }
35
+ catch (error) {
36
+ this.error(`Failed: ${error.message}`);
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from "../../../base-command.js";
2
+ export default class WorkflowConnGet extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ connId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,42 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../../base-command.js";
3
+ import { input } from "@inquirer/prompts";
4
+ import { apiRequest } from "../../../http.js";
5
+ export default class WorkflowConnGet extends BaseCommand {
6
+ static description = "Get details of a single connection (credential metadata, status, piece info)";
7
+ static examples = [
8
+ "imbrace workflow conn get <connId>",
9
+ "imbrace workflow conn get <connId> --json",
10
+ ];
11
+ static args = {
12
+ connId: Args.string({ description: "Connection ID" }),
13
+ };
14
+ static flags = {
15
+ json: Flags.boolean({ description: "Output as JSON" }),
16
+ };
17
+ async run() {
18
+ const { args, flags } = await this.parse(WorkflowConnGet);
19
+ const connId = args.connId ?? (flags.json ? this.error("Connection ID is required") : await input({ message: "Connection ID:" }));
20
+ try {
21
+ const res = await apiRequest(`/workflow/conn/${connId}`);
22
+ if (flags.json) {
23
+ this.log(JSON.stringify(res, null, 2));
24
+ return;
25
+ }
26
+ const c = res.data || {};
27
+ this.log(`\n ID: ${c.id || ""}`);
28
+ this.log(` Display name: ${c.displayName || ""}`);
29
+ this.log(` External ID: ${c.externalId || ""}`);
30
+ this.log(` Piece: ${c.pieceName || ""}`);
31
+ this.log(` Type: ${c.type || ""}`);
32
+ this.log(` Status: ${c.status || ""}`);
33
+ this.log(` Project ID: ${c.projectId || ""}`);
34
+ this.log(` Created: ${c.created || ""}`);
35
+ this.log(` Updated: ${c.updated || ""}`);
36
+ this.log("");
37
+ }
38
+ catch (error) {
39
+ this.error(`Failed: ${error.message}`);
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from "../../../base-command.js";
2
+ export default class WorkflowConnList extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,37 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../../base-command.js";
3
+ import { apiRequest } from "../../../http.js";
4
+ export default class WorkflowConnList extends BaseCommand {
5
+ static description = "List all connections (saved credentials for external services)";
6
+ static examples = [
7
+ "imbrace workflow conn list",
8
+ "imbrace workflow conn list --json",
9
+ ];
10
+ static flags = {
11
+ json: Flags.boolean({ description: "Output as JSON" }),
12
+ };
13
+ async run() {
14
+ const { flags } = await this.parse(WorkflowConnList);
15
+ try {
16
+ const res = await apiRequest("/workflow/conn/list");
17
+ if (flags.json) {
18
+ this.log(JSON.stringify(res, null, 2));
19
+ return;
20
+ }
21
+ this.log(`\n Found ${res.count} connection(s):\n`);
22
+ this.log(" ID DISPLAY NAME PIECE TYPE");
23
+ this.log(" ─────────────────────────────────────────────────────────────────────────────────────────────");
24
+ for (const c of res.data || []) {
25
+ const id = (c.id || "").padEnd(31);
26
+ const name = (c.displayName || "").padEnd(28);
27
+ const piece = (c.pieceName || "").padEnd(28);
28
+ const type = c.type || "";
29
+ this.log(` ${id} ${name} ${piece} ${type}`);
30
+ }
31
+ this.log("");
32
+ }
33
+ catch (error) {
34
+ this.error(`Failed: ${error.message}`);
35
+ }
36
+ }
37
+ }
@@ -5,6 +5,7 @@ export default class WorkflowCreate extends BaseCommand {
5
5
  static flags: {
6
6
  name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
7
  "project-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ "folder-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
9
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
10
  "id-only": import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
11
  };
@@ -7,10 +7,12 @@ export default class WorkflowCreate extends BaseCommand {
7
7
  static examples = [
8
8
  'imbrace workflow create --name "My Flow" --json',
9
9
  'imbrace workflow create --name "Slack Bot" --id-only',
10
+ 'imbrace workflow create --name "Lead handler" --folder-id <folderId>',
10
11
  ];
11
12
  static flags = {
12
13
  name: Flags.string({ char: "n", description: "Workflow display name (required)" }),
13
14
  "project-id": Flags.string({ description: "Project ID. Auto-discovered from existing flows if omitted." }),
15
+ "folder-id": Flags.string({ description: "Place the flow in this folder (use 'imbrace workflow folder list' to discover)." }),
14
16
  json: Flags.boolean({ description: "Output as JSON" }),
15
17
  "id-only": Flags.boolean({ description: "Print only the new workflow ID (pipe-friendly)" }),
16
18
  };
@@ -21,6 +23,8 @@ export default class WorkflowCreate extends BaseCommand {
21
23
  const body = { name };
22
24
  if (flags["project-id"])
23
25
  body.projectId = flags["project-id"];
26
+ if (flags["folder-id"])
27
+ body.folderId = flags["folder-id"];
24
28
  try {
25
29
  const res = await apiRequest("/workflow/create", { method: "POST", body });
26
30
  if (flags["id-only"]) {
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class WorkflowDisable extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ flowId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,30 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../base-command.js";
3
+ import { apiRequest } from "../../http.js";
4
+ export default class WorkflowDisable extends BaseCommand {
5
+ static description = "Stop auto-trigger on a workflow (keeps published version intact)";
6
+ static examples = [
7
+ "imbrace workflow disable <flowId>",
8
+ "imbrace workflow disable <flowId> --json",
9
+ ];
10
+ static args = {
11
+ flowId: Args.string({ description: "Workflow ID", required: true }),
12
+ };
13
+ static flags = {
14
+ json: Flags.boolean({ description: "Output as JSON" }),
15
+ };
16
+ async run() {
17
+ const { args, flags } = await this.parse(WorkflowDisable);
18
+ try {
19
+ const res = await apiRequest(`/workflow/${args.flowId}/disable`, { method: "POST", body: {} });
20
+ if (flags.json) {
21
+ this.log(JSON.stringify(res, null, 2));
22
+ return;
23
+ }
24
+ this.log(`\n✅ ${res.message}\n`);
25
+ }
26
+ catch (error) {
27
+ this.error(`Failed: ${error.message}`);
28
+ }
29
+ }
30
+ }
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from "../../base-command.js";
2
+ export default class WorkflowEnable extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ flowId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,34 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../base-command.js";
3
+ import { apiRequest } from "../../http.js";
4
+ export default class WorkflowEnable extends BaseCommand {
5
+ static description = "Enable auto-trigger on a workflow. Requires `workflow publish` first.";
6
+ static examples = [
7
+ "imbrace workflow enable <flowId>",
8
+ "imbrace workflow enable <flowId> --json",
9
+ ];
10
+ static args = {
11
+ flowId: Args.string({ description: "Workflow ID", required: true }),
12
+ };
13
+ static flags = {
14
+ json: Flags.boolean({ description: "Output as JSON" }),
15
+ };
16
+ async run() {
17
+ const { args, flags } = await this.parse(WorkflowEnable);
18
+ try {
19
+ const res = await apiRequest(`/workflow/${args.flowId}/enable`, { method: "POST", body: {} });
20
+ if (flags.json) {
21
+ this.log(JSON.stringify(res, null, 2));
22
+ return;
23
+ }
24
+ this.log(`\n✅ ${res.message}\n`);
25
+ }
26
+ catch (error) {
27
+ // Common error: trying to enable before publish
28
+ if (/publishedFlowVersionId/.test(error.message || "")) {
29
+ this.error(`Cannot enable an unpublished workflow. Run 'imbrace workflow publish ${args.flowId}' first.`);
30
+ }
31
+ this.error(`Failed: ${error.message}`);
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from "../../../base-command.js";
2
+ export default class WorkflowFolderCreate extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ "project-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
+ "id-only": import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,43 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../../base-command.js";
3
+ import { input } from "@inquirer/prompts";
4
+ import { apiRequest } from "../../../http.js";
5
+ export default class WorkflowFolderCreate extends BaseCommand {
6
+ static description = "Create a new folder for organizing workflows";
7
+ static examples = [
8
+ 'imbrace workflow folder create --name "Sales Automations" --json',
9
+ 'imbrace workflow folder create --name "Internal Tools" --id-only',
10
+ ];
11
+ static flags = {
12
+ name: Flags.string({ char: "n", description: "Folder name (required)" }),
13
+ "project-id": Flags.string({ description: "Project ID. Auto-discovered if omitted." }),
14
+ json: Flags.boolean({ description: "Output as JSON" }),
15
+ "id-only": Flags.boolean({ description: "Print only the new folder ID (pipe-friendly)" }),
16
+ };
17
+ async run() {
18
+ const { flags } = await this.parse(WorkflowFolderCreate);
19
+ const nonInteractive = flags.json || flags["id-only"];
20
+ const name = flags.name ?? (nonInteractive ? this.error("--name is required with --json or --id-only") : await input({ message: "Folder name:" }));
21
+ const body = { name };
22
+ if (flags["project-id"])
23
+ body.projectId = flags["project-id"];
24
+ try {
25
+ const res = await apiRequest("/workflow/folder/create", { method: "POST", body });
26
+ if (flags["id-only"]) {
27
+ this.log(res.data?.id ?? "");
28
+ return;
29
+ }
30
+ if (flags.json) {
31
+ this.log(JSON.stringify(res, null, 2));
32
+ return;
33
+ }
34
+ this.log(`\n✅ ${res.message}`);
35
+ if (res.data?.id)
36
+ this.log(` ID: ${res.data.id}`);
37
+ this.log("");
38
+ }
39
+ catch (error) {
40
+ this.error(`Failed: ${error.message}`);
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from "../../../base-command.js";
2
+ export default class WorkflowFolderDelete extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ folderId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }
@@ -0,0 +1,39 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../../base-command.js";
3
+ import { confirm } from "@inquirer/prompts";
4
+ import { apiRequest } from "../../../http.js";
5
+ export default class WorkflowFolderDelete extends BaseCommand {
6
+ static description = "Delete a folder. Flows inside the folder are NOT deleted — they become unfiled.";
7
+ static examples = [
8
+ "imbrace workflow folder delete <folderId> --yes",
9
+ "imbrace workflow folder delete <folderId> --yes --json",
10
+ ];
11
+ static args = {
12
+ folderId: Args.string({ description: "Folder ID", required: true }),
13
+ };
14
+ static flags = {
15
+ yes: Flags.boolean({ char: "y", description: "Skip confirmation" }),
16
+ json: Flags.boolean({ description: "Output as JSON" }),
17
+ };
18
+ async run() {
19
+ const { args, flags } = await this.parse(WorkflowFolderDelete);
20
+ if (!flags.yes && !flags.json) {
21
+ const ok = await confirm({ message: `Delete folder ${args.folderId}?`, default: false });
22
+ if (!ok) {
23
+ this.log("Cancelled.");
24
+ return;
25
+ }
26
+ }
27
+ try {
28
+ const res = await apiRequest(`/workflow/folder/${args.folderId}`, { method: "DELETE" });
29
+ if (flags.json) {
30
+ this.log(JSON.stringify(res, null, 2));
31
+ return;
32
+ }
33
+ this.log(`\n✅ ${res.message}\n`);
34
+ }
35
+ catch (error) {
36
+ this.error(`Failed: ${error.message}`);
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,12 @@
1
+ import { BaseCommand } from "../../../base-command.js";
2
+ export default class WorkflowFolderGet extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ folderId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,38 @@
1
+ import { Args, Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../../base-command.js";
3
+ import { input } from "@inquirer/prompts";
4
+ import { apiRequest } from "../../../http.js";
5
+ export default class WorkflowFolderGet extends BaseCommand {
6
+ static description = "Get details of a single folder";
7
+ static examples = [
8
+ "imbrace workflow folder get <folderId>",
9
+ "imbrace workflow folder get <folderId> --json",
10
+ ];
11
+ static args = {
12
+ folderId: Args.string({ description: "Folder ID" }),
13
+ };
14
+ static flags = {
15
+ json: Flags.boolean({ description: "Output as JSON" }),
16
+ };
17
+ async run() {
18
+ const { args, flags } = await this.parse(WorkflowFolderGet);
19
+ const folderId = args.folderId ?? (flags.json ? this.error("Folder ID is required") : await input({ message: "Folder ID:" }));
20
+ try {
21
+ const res = await apiRequest(`/workflow/folder/${folderId}`);
22
+ if (flags.json) {
23
+ this.log(JSON.stringify(res, null, 2));
24
+ return;
25
+ }
26
+ const f = res.data || {};
27
+ this.log(`\n ID: ${f.id || ""}`);
28
+ this.log(` Name: ${f.displayName || ""}`);
29
+ this.log(` Project ID: ${f.projectId || ""}`);
30
+ this.log(` Created: ${f.created || ""}`);
31
+ this.log(` Updated: ${f.updated || ""}`);
32
+ this.log("");
33
+ }
34
+ catch (error) {
35
+ this.error(`Failed: ${error.message}`);
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from "../../../base-command.js";
2
+ export default class WorkflowFolderList extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ };
8
+ run(): Promise<void>;
9
+ }
@@ -0,0 +1,35 @@
1
+ import { Flags } from "@oclif/core";
2
+ import { BaseCommand } from "../../../base-command.js";
3
+ import { apiRequest } from "../../../http.js";
4
+ export default class WorkflowFolderList extends BaseCommand {
5
+ static description = "List all folders (used to organize workflows)";
6
+ static examples = [
7
+ "imbrace workflow folder list",
8
+ "imbrace workflow folder list --json",
9
+ ];
10
+ static flags = {
11
+ json: Flags.boolean({ description: "Output as JSON" }),
12
+ };
13
+ async run() {
14
+ const { flags } = await this.parse(WorkflowFolderList);
15
+ try {
16
+ const res = await apiRequest("/workflow/folder/list");
17
+ if (flags.json) {
18
+ this.log(JSON.stringify(res, null, 2));
19
+ return;
20
+ }
21
+ this.log(`\n Found ${res.count} folder(s):\n`);
22
+ this.log(" ID NAME");
23
+ this.log(" ─────────────────────────────────────────────────────");
24
+ for (const f of res.data || []) {
25
+ const id = (f.id || "").padEnd(24);
26
+ const name = f.displayName || "";
27
+ this.log(` ${id} ${name}`);
28
+ }
29
+ this.log("");
30
+ }
31
+ catch (error) {
32
+ this.error(`Failed: ${error.message}`);
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from "../../../base-command.js";
2
+ export default class WorkflowFolderUpdate extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ folderId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ name: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }