@cubis/foundry 0.3.13 → 0.3.14

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.
@@ -12,7 +12,7 @@ Before proceeding, validate that the user has completed the following steps befo
12
12
 
13
13
  ## Step 1
14
14
 
15
- Prompt the user to configure their own Postman API key for authentication. They can either set it as an environment variable named POSTMAN_API_KEY on their system, or hardcode it directly into the user level MCP configuration file (usually at ~/.kiro/settings/mcp.json) in the power section. To obtain an API key, they log into their Postman account, navigate to Settings API Keys, and generate a new key with appropriate permissions for workspace, collection, and environment management. The key will be automatically used by the MCP server to authenticate all API requests to Postman's services.
15
+ Generate and maintain `postman_setting.json` as the primary Postman configuration. Use env-first authentication by default: keep `apiKey` as `null`, set `apiKeyEnvVar` to `POSTMAN_API_KEY`, and read the key from environment variables. Only store `apiKey` inline when the user explicitly requests file-based key storage. Keep `defaultWorkspaceId` nullable (`null` when unknown) so workflows can run without a preselected workspace.
16
16
 
17
17
  ## Step 2
18
18
 
@@ -68,7 +68,7 @@ Create a hook that runs anytime the source code or configuration file has been c
68
68
 
69
69
  Automate API testing and collection management with Postman. Create workspaces, collections, environments, and run tests programmatically.
70
70
 
71
- **Authentication**: Requires Postman API key (Settings API Keys at postman.com)
71
+ **Authentication**: Env-first via `postman_setting.json` + `POSTMAN_API_KEY`; inline `apiKey` is optional.
72
72
 
73
73
  ## Available MCP Servers
74
74
 
@@ -10,7 +10,7 @@ Before proceeding, validate that the user has completed the following steps befo
10
10
 
11
11
  ## Step 1
12
12
 
13
- Prompt the user to configure their own Postman API key for authentication. They can either set it as an environment variable named POSTMAN_API_KEY on their system, or hardcode it directly into the user level MCP configuration file (usually at ~/.kiro/settings/mcp.json) in the power section. To obtain an API key, they log into their Postman account, navigate to Settings API Keys, and generate a new key with appropriate permissions for workspace, collection, and environment management. The key will be automatically used by the MCP server to authenticate all API requests to Postman's services.
13
+ Generate and maintain `postman_setting.json` as the primary Postman configuration. Use env-first authentication by default: keep `apiKey` as `null`, set `apiKeyEnvVar` to `POSTMAN_API_KEY`, and read the key from environment variables. Only store `apiKey` inline when the user explicitly requests file-based key storage. Keep `defaultWorkspaceId` nullable (`null` when unknown) so workflows can run without a preselected workspace.
14
14
 
15
15
  ## Step 2
16
16
 
@@ -66,7 +66,7 @@ Create a hook that runs anytime the source code or configuration file has been c
66
66
 
67
67
  Automate API testing and collection management with Postman. Create workspaces, collections, environments, and run tests programmatically.
68
68
 
69
- **Authentication**: Requires Postman API key (Settings API Keys at postman.com)
69
+ **Authentication**: Env-first via `postman_setting.json` + `POSTMAN_API_KEY`; inline `apiKey` is optional.
70
70
 
71
71
  ## Available MCP Servers
72
72
 
@@ -12,7 +12,7 @@ Before proceeding, validate that the user has completed the following steps befo
12
12
 
13
13
  ## Step 1
14
14
 
15
- Prompt the user to configure their own Postman API key for authentication. They can either set it as an environment variable named POSTMAN_API_KEY on their system, or hardcode it directly into the user level MCP configuration file (usually at ~/.kiro/settings/mcp.json) in the power section. To obtain an API key, they log into their Postman account, navigate to Settings API Keys, and generate a new key with appropriate permissions for workspace, collection, and environment management. The key will be automatically used by the MCP server to authenticate all API requests to Postman's services.
15
+ Generate and maintain `postman_setting.json` as the primary Postman configuration. Use env-first authentication by default: keep `apiKey` as `null`, set `apiKeyEnvVar` to `POSTMAN_API_KEY`, and read the key from environment variables. Only store `apiKey` inline when the user explicitly requests file-based key storage. Keep `defaultWorkspaceId` nullable (`null` when unknown) so workflows can run without a preselected workspace.
16
16
 
17
17
  ## Step 2
18
18
 
@@ -68,7 +68,7 @@ Create a hook that runs anytime the source code or configuration file has been c
68
68
 
69
69
  Automate API testing and collection management with Postman. Create workspaces, collections, environments, and run tests programmatically.
70
70
 
71
- **Authentication**: Requires Postman API key (Settings API Keys at postman.com)
71
+ **Authentication**: Env-first via `postman_setting.json` + `POSTMAN_API_KEY`; inline `apiKey` is optional.
72
72
 
73
73
  ## Available MCP Servers
74
74
 
@@ -239,4 +239,4 @@ for (const collection of collections) {
239
239
 
240
240
  **Full mode (112 tools):** Change URL to `https://mcp.postman.com/full`
241
241
 
242
- **API Key Permissions:** Workspace management, collection read/write, environment read/write, collection runs
242
+ **API Key Permissions:** Workspace management, collection read/write, environment read/write, collection runs
@@ -10,7 +10,7 @@ Before proceeding, validate that the user has completed the following steps befo
10
10
 
11
11
  ## Step 1
12
12
 
13
- Prompt the user to configure their own Postman API key for authentication. They can either set it as an environment variable named POSTMAN_API_KEY on their system, or hardcode it directly into the user level MCP configuration file (usually at ~/.kiro/settings/mcp.json) in the power section. To obtain an API key, they log into their Postman account, navigate to Settings API Keys, and generate a new key with appropriate permissions for workspace, collection, and environment management. The key will be automatically used by the MCP server to authenticate all API requests to Postman's services.
13
+ Generate and maintain `postman_setting.json` as the primary Postman configuration. Use env-first authentication by default: keep `apiKey` as `null`, set `apiKeyEnvVar` to `POSTMAN_API_KEY`, and read the key from environment variables. Only store `apiKey` inline when the user explicitly requests file-based key storage. Keep `defaultWorkspaceId` nullable (`null` when unknown) so workflows can run without a preselected workspace.
14
14
 
15
15
  ## Step 2
16
16
 
@@ -66,7 +66,7 @@ Create a hook that runs anytime the source code or configuration file has been c
66
66
 
67
67
  Automate API testing and collection management with Postman. Create workspaces, collections, environments, and run tests programmatically.
68
68
 
69
- **Authentication**: Requires Postman API key (Settings API Keys at postman.com)
69
+ **Authentication**: Env-first via `postman_setting.json` + `POSTMAN_API_KEY`; inline `apiKey` is optional.
70
70
 
71
71
  ## Available MCP Servers
72
72
 
@@ -3,7 +3,7 @@ name: backend-specialist
3
3
  description: Expert backend architect for Node.js, Python, and modern serverless/edge systems. Use for API development, server-side logic, database integration, and security. Triggers on backend, server, api, endpoint, database, auth.
4
4
  tools: Read, Grep, Glob, Bash, Edit, Write
5
5
  model: inherit
6
- skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
6
+ skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, openapi-docs, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
7
7
  ---
8
8
 
9
9
  # Backend Development Architect
@@ -14,4 +14,14 @@ Use this workflow when backend architecture or implementation is primary.
14
14
  1. Ask `@backend-specialist` for solution outline.
15
15
  2. Validate API contracts, data model, and failure handling.
16
16
  3. Implement backend changes with tests and observability.
17
- 4. Return summary including migration and rollout notes.
17
+ 4. Always update API docs: OpenAPI spec, Swagger UI route, and Stoplight Elements route/component.
18
+ 5. Return summary including migration and rollout notes.
19
+
20
+ ## Output Contract
21
+ - API/contract changes
22
+ - OpenAPI spec path
23
+ - Swagger UI route
24
+ - Stoplight route/component status
25
+ - Migration impact
26
+ - Reliability/security notes
27
+ - Verification evidence
@@ -3,7 +3,7 @@ name: backend-specialist
3
3
  description: Expert backend architect for Node.js, Python, and modern serverless/edge systems. Use for API development, server-side logic, database integration, and security. Triggers on backend, server, api, endpoint, database, auth.
4
4
  tools: Read, Grep, Glob, Bash, Edit, Write
5
5
  model: inherit
6
- skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
6
+ skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, openapi-docs, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
7
7
  ---
8
8
 
9
9
  # Backend Development Architect
@@ -16,10 +16,14 @@ Use this when backend architecture or service logic is primary.
16
16
  1. Ask specialist(s) for design and risk assessment.
17
17
  2. Validate contracts, data model, and failure handling.
18
18
  3. Implement backend changes with observability.
19
- 4. Run targeted tests and summarize rollout notes.
19
+ 4. Always update API docs: OpenAPI spec, Swagger UI route, and Stoplight Elements route/component.
20
+ 5. Run targeted tests and summarize rollout notes.
20
21
 
21
22
  ## Output Contract
22
23
  - API/contract changes
24
+ - OpenAPI spec path
25
+ - Swagger UI route
26
+ - Stoplight route/component status
23
27
  - Migration impact
24
28
  - Reliability/security notes
25
29
  - Verification evidence
@@ -2,7 +2,7 @@
2
2
  name: backend-specialist
3
3
  description: Expert backend architect for Node.js, Python, and modern serverless/edge systems. Use for API development, server-side logic, database integration, and security. Triggers on backend, server, api, endpoint, database, auth.
4
4
  tools: Read, Grep, Glob, Bash, Edit, Write
5
- skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
5
+ skills: clean-code, nodejs-best-practices, python-patterns, api-patterns, openapi-docs, database-design, database-optimizer, database-skills, mcp-builder, lint-and-validate, powershell-windows, bash-linux, rust-pro, api-designer, architecture-designer, typescript-pro, nestjs-expert, fastapi-expert, secure-code-guardian, test-master
6
6
  ---
7
7
 
8
8
  # Backend Development Architect
@@ -16,10 +16,14 @@ Use this when backend architecture or service logic is primary.
16
16
  1. Ask specialist(s) for design and risk assessment.
17
17
  2. Validate contracts, data model, and failure handling.
18
18
  3. Implement backend changes with observability.
19
- 4. Run targeted tests and summarize rollout notes.
19
+ 4. Always update API docs: OpenAPI spec, Swagger UI route, and Stoplight Elements route/component.
20
+ 5. Run targeted tests and summarize rollout notes.
20
21
 
21
22
  ## Output Contract
22
23
  - API/contract changes
24
+ - OpenAPI spec path
25
+ - Swagger UI route
26
+ - Stoplight route/component status
23
27
  - Migration impact
24
28
  - Reliability/security notes
25
29
  - Verification evidence
package/README.md CHANGED
@@ -34,10 +34,13 @@ cbx workflows doctor codex
34
34
  cbx workflows platforms
35
35
  cbx workflows install --platform antigravity --dry-run
36
36
  cbx workflows install --platform antigravity --terminal-integration --terminal-verifier codex
37
+ cbx workflows install --platform codex --postman
38
+ cbx workflows install --platform codex --postman --postman-workspace-id null
37
39
  ```
38
40
 
39
41
  Install bootstrap behavior:
40
42
  - `cbx workflows install` now also bootstraps `ENGINEERING_RULES.md` and `TECH.md` (creates when missing; keeps existing files unless explicitly regenerated).
43
+ - Optional `--postman` bootstrap creates `postman_setting.json` and installs/configures the Postman skill.
41
44
  - Use `cbx rules init --platform <platform> --overwrite` to force-regenerate both files.
42
45
 
43
46
  `rules` manages strict engineering policy and a generated codebase tech map:
@@ -112,6 +115,7 @@ Routing behavior:
112
115
  - Antigravity/Copilot: workflow + agent markdown can be routed by platform conventions.
113
116
  - Codex: use generated callable wrapper skills (`$workflow-*`, `$agent-*`).
114
117
  - Example for backend intent in Codex: `$workflow-backend` or `$agent-backend-specialist`.
118
+ - Backend workflow policy: always include OpenAPI updates plus Swagger UI and Stoplight Elements status in output.
115
119
 
116
120
  ### Codex Runtime Mode
117
121
 
package/bin/cubis.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { confirm, select } from "@inquirer/prompts";
3
+ import { confirm, input, select } from "@inquirer/prompts";
4
4
  import { Command } from "commander";
5
5
  import { existsSync } from "node:fs";
6
6
  import {
@@ -122,6 +122,12 @@ const CODEX_WORKFLOW_SKILL_PREFIX = "workflow-";
122
122
  const CODEX_AGENT_SKILL_PREFIX = "agent-";
123
123
  const TERMINAL_VERIFIER_PROVIDERS = ["codex", "gemini"];
124
124
  const DEFAULT_TERMINAL_VERIFIER = "codex";
125
+ const POSTMAN_API_KEY_ENV_VAR = "POSTMAN_API_KEY";
126
+ const POSTMAN_MCP_URL = "https://mcp.postman.com/minimal";
127
+ const POSTMAN_SKILL_ID = "postman";
128
+ const POSTMAN_SETTINGS_FILENAME = "postman_setting.json";
129
+ const POSTMAN_API_KEY_MISSING_WARNING =
130
+ `Postman API key is not configured. Set ${POSTMAN_API_KEY_ENV_VAR} or update ${POSTMAN_SETTINGS_FILENAME}.`;
125
131
  const TECH_SCAN_MAX_FILES = 5000;
126
132
  const TECH_SCAN_IGNORED_DIRS = new Set([
127
133
  ".git",
@@ -231,6 +237,13 @@ function normalizeTerminalVerifier(value) {
231
237
  return TERMINAL_VERIFIER_ALIASES[normalized] || null;
232
238
  }
233
239
 
240
+ function normalizePostmanWorkspaceId(value) {
241
+ if (value === undefined || value === null) return null;
242
+ const normalized = String(value).trim();
243
+ if (!normalized || normalized.toLowerCase() === "null") return null;
244
+ return normalized;
245
+ }
246
+
234
247
  function defaultState() {
235
248
  return {
236
249
  schemaVersion: 1,
@@ -1872,6 +1885,237 @@ async function writeGeneratedArtifact({ destination, content, dryRun = false })
1872
1885
  return { action: exists ? "replaced" : "installed", path: destination };
1873
1886
  }
1874
1887
 
1888
+ function resolvePostmanSettingsPath({ scope, cwd = process.cwd() }) {
1889
+ if (scope === "global") {
1890
+ return path.join(os.homedir(), ".cbx", POSTMAN_SETTINGS_FILENAME);
1891
+ }
1892
+ const workspaceRoot = findWorkspaceRoot(cwd);
1893
+ return path.join(workspaceRoot, POSTMAN_SETTINGS_FILENAME);
1894
+ }
1895
+
1896
+ function buildPostmanMcpConfig({ apiKey = null, mcpUrl = POSTMAN_MCP_URL }) {
1897
+ const authHeader = apiKey
1898
+ ? `Bearer ${apiKey}`
1899
+ : `Bearer \${${POSTMAN_API_KEY_ENV_VAR}}`;
1900
+ return {
1901
+ mcpServers: {
1902
+ postman: {
1903
+ url: mcpUrl,
1904
+ headers: {
1905
+ Authorization: authHeader
1906
+ }
1907
+ }
1908
+ },
1909
+ disabled: false
1910
+ };
1911
+ }
1912
+
1913
+ function getPostmanApiKeySource({ apiKey, envApiKey }) {
1914
+ if (apiKey) return "inline";
1915
+ if (envApiKey) return "env";
1916
+ return "unset";
1917
+ }
1918
+
1919
+ function normalizePostmanApiKey(value) {
1920
+ if (value === undefined || value === null) return null;
1921
+ const normalized = String(value).trim();
1922
+ return normalized || null;
1923
+ }
1924
+
1925
+ async function ensureGitIgnoreEntry({
1926
+ filePath,
1927
+ entry,
1928
+ dryRun = false
1929
+ }) {
1930
+ const exists = await pathExists(filePath);
1931
+ const original = exists ? await readFile(filePath, "utf8") : "";
1932
+ const lines = original.split(/\r?\n/).map((line) => line.trim());
1933
+ const alreadyPresent = lines.includes(entry);
1934
+
1935
+ if (alreadyPresent) {
1936
+ return { action: "unchanged", filePath };
1937
+ }
1938
+
1939
+ if (dryRun) {
1940
+ return {
1941
+ action: exists ? "would-patch" : "would-create",
1942
+ filePath
1943
+ };
1944
+ }
1945
+
1946
+ const suffix = original.endsWith("\n") || original.length === 0 ? "" : "\n";
1947
+ const nextContent = `${original}${suffix}${entry}\n`;
1948
+ await mkdir(path.dirname(filePath), { recursive: true });
1949
+ await writeFile(filePath, nextContent, "utf8");
1950
+ return {
1951
+ action: exists ? "patched" : "created",
1952
+ filePath
1953
+ };
1954
+ }
1955
+
1956
+ async function resolvePostmanInstallSelection({
1957
+ scope,
1958
+ options,
1959
+ cwd = process.cwd()
1960
+ }) {
1961
+ const hasApiKeyOption = options.postmanApiKey !== undefined;
1962
+ const hasWorkspaceOption = options.postmanWorkspaceId !== undefined;
1963
+ const enabled = Boolean(options.postman) || hasApiKeyOption || hasWorkspaceOption;
1964
+ if (!enabled) return { enabled: false };
1965
+
1966
+ const explicitApiKey = hasApiKeyOption ? String(options.postmanApiKey || "").trim() : "";
1967
+ let apiKey = explicitApiKey || null;
1968
+ const envApiKey = String(process.env[POSTMAN_API_KEY_ENV_VAR] || "").trim();
1969
+ let defaultWorkspaceId = hasWorkspaceOption
1970
+ ? normalizePostmanWorkspaceId(options.postmanWorkspaceId)
1971
+ : null;
1972
+ const warnings = [];
1973
+
1974
+ const canPrompt = !options.yes && process.stdin.isTTY;
1975
+ if (canPrompt && !hasApiKeyOption && !apiKey && !envApiKey) {
1976
+ const promptedApiKey = String(
1977
+ await input({
1978
+ message: `Postman API key (optional, leave blank to keep ${POSTMAN_API_KEY_ENV_VAR} env mode):`,
1979
+ default: ""
1980
+ })
1981
+ ).trim();
1982
+ if (promptedApiKey) {
1983
+ apiKey = promptedApiKey;
1984
+ }
1985
+ }
1986
+
1987
+ if (canPrompt && !hasWorkspaceOption) {
1988
+ const promptedWorkspaceId = await input({
1989
+ message: "Default Postman workspace ID (optional, leave blank for null):",
1990
+ default: ""
1991
+ });
1992
+ defaultWorkspaceId = normalizePostmanWorkspaceId(promptedWorkspaceId);
1993
+ }
1994
+
1995
+ const apiKeySource = getPostmanApiKeySource({ apiKey, envApiKey });
1996
+ if (apiKeySource === "unset") {
1997
+ warnings.push(POSTMAN_API_KEY_MISSING_WARNING);
1998
+ }
1999
+
2000
+ const settingsPath = resolvePostmanSettingsPath({ scope, cwd });
2001
+ const settings = {
2002
+ apiKey: apiKey || null,
2003
+ apiKeyEnvVar: POSTMAN_API_KEY_ENV_VAR,
2004
+ apiKeySource,
2005
+ defaultWorkspaceId: defaultWorkspaceId ?? null,
2006
+ mcpUrl: POSTMAN_MCP_URL,
2007
+ generatedBy: "cbx workflows install --postman",
2008
+ generatedAt: new Date().toISOString()
2009
+ };
2010
+
2011
+ return {
2012
+ enabled: true,
2013
+ apiKey,
2014
+ apiKeySource,
2015
+ defaultWorkspaceId: defaultWorkspaceId ?? null,
2016
+ warnings,
2017
+ settings,
2018
+ settingsPath
2019
+ };
2020
+ }
2021
+
2022
+ async function configurePostmanInstallArtifacts({
2023
+ scope,
2024
+ profilePaths,
2025
+ postmanSelection,
2026
+ overwrite = false,
2027
+ dryRun = false,
2028
+ cwd = process.cwd()
2029
+ }) {
2030
+ if (!postmanSelection?.enabled) return null;
2031
+
2032
+ let warnings = postmanSelection.warnings.filter((warning) => warning !== POSTMAN_API_KEY_MISSING_WARNING);
2033
+ const settingsContent = `${JSON.stringify(postmanSelection.settings, null, 2)}\n`;
2034
+ const settingsResult = await writeTextFile({
2035
+ targetPath: postmanSelection.settingsPath,
2036
+ content: settingsContent,
2037
+ overwrite,
2038
+ dryRun
2039
+ });
2040
+
2041
+ let effectiveApiKey = normalizePostmanApiKey(postmanSelection.settings.apiKey);
2042
+ let effectiveDefaultWorkspaceId = postmanSelection.defaultWorkspaceId ?? null;
2043
+ let effectiveMcpUrl = postmanSelection.settings.mcpUrl || POSTMAN_MCP_URL;
2044
+
2045
+ if (settingsResult.action === "skipped" || settingsResult.action === "would-skip") {
2046
+ try {
2047
+ const existingSettingsRaw = await readFile(postmanSelection.settingsPath, "utf8");
2048
+ const existingSettings = JSON.parse(existingSettingsRaw);
2049
+ effectiveApiKey = normalizePostmanApiKey(existingSettings?.apiKey);
2050
+ effectiveDefaultWorkspaceId = normalizePostmanWorkspaceId(existingSettings?.defaultWorkspaceId);
2051
+ const existingMcpUrl = String(existingSettings?.mcpUrl || "").trim();
2052
+ if (existingMcpUrl) {
2053
+ effectiveMcpUrl = existingMcpUrl;
2054
+ }
2055
+ } catch {
2056
+ warnings.push(
2057
+ `Existing ${POSTMAN_SETTINGS_FILENAME} could not be parsed. Using install-time Postman values for MCP config.`
2058
+ );
2059
+ }
2060
+ }
2061
+
2062
+ const envApiKey = normalizePostmanApiKey(process.env[POSTMAN_API_KEY_ENV_VAR]);
2063
+ const effectiveApiKeySource = getPostmanApiKeySource({
2064
+ apiKey: effectiveApiKey,
2065
+ envApiKey
2066
+ });
2067
+ if (effectiveApiKeySource === "unset") {
2068
+ warnings.push(POSTMAN_API_KEY_MISSING_WARNING);
2069
+ }
2070
+
2071
+ let gitIgnoreResult = null;
2072
+ if (scope === "project") {
2073
+ const workspaceRoot = findWorkspaceRoot(cwd);
2074
+ const gitIgnorePath = path.join(workspaceRoot, ".gitignore");
2075
+ gitIgnoreResult = await ensureGitIgnoreEntry({
2076
+ filePath: gitIgnorePath,
2077
+ entry: POSTMAN_SETTINGS_FILENAME,
2078
+ dryRun
2079
+ });
2080
+ }
2081
+
2082
+ const postmanSkillDir = path.join(profilePaths.skillsDir, POSTMAN_SKILL_ID);
2083
+ const postmanMcpPath = path.join(postmanSkillDir, "mcp.json");
2084
+ let mcpResult = null;
2085
+ const postmanSkillExists = await pathExists(postmanSkillDir);
2086
+ if (!dryRun && !postmanSkillExists) {
2087
+ mcpResult = {
2088
+ action: "missing-postman-skill",
2089
+ path: postmanMcpPath
2090
+ };
2091
+ } else {
2092
+ const mcpConfigContent = `${JSON.stringify(
2093
+ buildPostmanMcpConfig({
2094
+ apiKey: effectiveApiKey,
2095
+ mcpUrl: effectiveMcpUrl
2096
+ }),
2097
+ null,
2098
+ 2
2099
+ )}\n`;
2100
+ mcpResult = await writeGeneratedArtifact({
2101
+ destination: postmanMcpPath,
2102
+ content: mcpConfigContent,
2103
+ dryRun
2104
+ });
2105
+ }
2106
+
2107
+ return {
2108
+ enabled: true,
2109
+ apiKeySource: effectiveApiKeySource,
2110
+ defaultWorkspaceId: effectiveDefaultWorkspaceId,
2111
+ warnings,
2112
+ settingsPath: postmanSelection.settingsPath,
2113
+ settingsResult,
2114
+ gitIgnoreResult,
2115
+ mcpResult
2116
+ };
2117
+ }
2118
+
1875
2119
  async function installAntigravityTerminalIntegrationArtifacts({
1876
2120
  profilePaths,
1877
2121
  provider,
@@ -2032,6 +2276,7 @@ async function installBundleArtifacts({
2032
2276
  platform,
2033
2277
  scope,
2034
2278
  overwrite,
2279
+ extraSkillIds = [],
2035
2280
  terminalVerifierSelection = null,
2036
2281
  dryRun = false,
2037
2282
  cwd = process.cwd()
@@ -2092,7 +2337,8 @@ async function installBundleArtifacts({
2092
2337
  else installed.push(destination);
2093
2338
  }
2094
2339
 
2095
- const skillIds = Array.isArray(platformSpec.skills) ? platformSpec.skills : [];
2340
+ const manifestSkillIds = Array.isArray(platformSpec.skills) ? platformSpec.skills : [];
2341
+ const skillIds = unique([...manifestSkillIds, ...extraSkillIds.filter(Boolean)]);
2096
2342
  for (const skillId of skillIds) {
2097
2343
  const source = path.join(agentAssetsRoot(), "skills", skillId);
2098
2344
  const destination = path.join(profilePaths.skillsDir, skillId);
@@ -2389,6 +2635,32 @@ function printInstallSummary({
2389
2635
  }
2390
2636
  }
2391
2637
 
2638
+ function printPostmanSetupSummary({ postmanSetup }) {
2639
+ if (!postmanSetup?.enabled) return;
2640
+
2641
+ console.log("\nPostman setup:");
2642
+ console.log(`- Settings file: ${postmanSetup.settingsResult.action} (${postmanSetup.settingsPath})`);
2643
+ console.log(`- API key source: ${postmanSetup.apiKeySource}`);
2644
+ console.log(
2645
+ `- Default workspace ID: ${postmanSetup.defaultWorkspaceId === null ? "null" : postmanSetup.defaultWorkspaceId}`
2646
+ );
2647
+ if (postmanSetup.gitIgnoreResult) {
2648
+ console.log(
2649
+ `- .gitignore (${postmanSetup.gitIgnoreResult.filePath}): ${postmanSetup.gitIgnoreResult.action}`
2650
+ );
2651
+ }
2652
+ if (postmanSetup.mcpResult) {
2653
+ console.log(`- Postman MCP config (${postmanSetup.mcpResult.path}): ${postmanSetup.mcpResult.action}`);
2654
+ }
2655
+
2656
+ if (postmanSetup.warnings.length > 0) {
2657
+ console.log("- Warnings:");
2658
+ for (const warning of postmanSetup.warnings) {
2659
+ console.log(` - ${warning}`);
2660
+ }
2661
+ }
2662
+ }
2663
+
2392
2664
  function printRemoveSummary({
2393
2665
  platform,
2394
2666
  scope,
@@ -2694,6 +2966,18 @@ function withInstallOptions(command) {
2694
2966
  return withWorkflowBaseOptions(command)
2695
2967
  .option("-b, --bundle <bundle>", "bundle id (default: agent-environment-setup)")
2696
2968
  .option("--overwrite", "overwrite existing files")
2969
+ .option(
2970
+ "--postman",
2971
+ "optional: install Postman skill and generate postman_setting.json"
2972
+ )
2973
+ .option(
2974
+ "--postman-api-key <key>",
2975
+ "optional: set Postman API key inline for generated postman_setting.json and installed Postman MCP config"
2976
+ )
2977
+ .option(
2978
+ "--postman-workspace-id <id|null>",
2979
+ "optional: set default Postman workspace ID (use 'null' for no default)"
2980
+ )
2697
2981
  .option(
2698
2982
  "--terminal-integration",
2699
2983
  "Antigravity only: enable terminal verification integration (prompts for verifier when interactive)"
@@ -2854,6 +3138,11 @@ async function runWorkflowInstall(options) {
2854
3138
  platform,
2855
3139
  options
2856
3140
  });
3141
+ const postmanSelection = await resolvePostmanInstallSelection({
3142
+ scope,
3143
+ options,
3144
+ cwd: process.cwd()
3145
+ });
2857
3146
 
2858
3147
  const installResult = await installBundleArtifacts({
2859
3148
  bundleId,
@@ -2861,6 +3150,7 @@ async function runWorkflowInstall(options) {
2861
3150
  platform,
2862
3151
  scope,
2863
3152
  overwrite: Boolean(options.overwrite),
3153
+ extraSkillIds: postmanSelection.enabled ? [POSTMAN_SKILL_ID] : [],
2864
3154
  terminalVerifierSelection,
2865
3155
  dryRun,
2866
3156
  cwd: process.cwd()
@@ -2890,6 +3180,14 @@ async function runWorkflowInstall(options) {
2890
3180
  skipTech: false,
2891
3181
  cwd: process.cwd()
2892
3182
  });
3183
+ const postmanSetupResult = await configurePostmanInstallArtifacts({
3184
+ scope,
3185
+ profilePaths: installResult.profilePaths,
3186
+ postmanSelection,
3187
+ overwrite: Boolean(options.overwrite),
3188
+ dryRun,
3189
+ cwd: process.cwd()
3190
+ });
2893
3191
 
2894
3192
  const terminalVerificationRuleResult =
2895
3193
  platform === "antigravity" && installResult.terminalIntegration
@@ -2930,6 +3228,9 @@ async function runWorkflowInstall(options) {
2930
3228
  engineeringResults: engineeringArtifactsResult.engineeringResults,
2931
3229
  techResult: engineeringArtifactsResult.techResult
2932
3230
  });
3231
+ printPostmanSetupSummary({
3232
+ postmanSetup: postmanSetupResult
3233
+ });
2933
3234
  if (dryRun) {
2934
3235
  console.log("\nDry-run complete. Re-run without `--dry-run` to apply changes.");
2935
3236
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cubis/foundry",
3
- "version": "0.3.13",
3
+ "version": "0.3.14",
4
4
  "description": "Cubis Foundry CLI for workflow-first AI agent environments",
5
5
  "type": "module",
6
6
  "bin": {