@agentuity/cli 0.0.42 → 0.0.44

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 (249) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +1 -1
  3. package/bin/cli.ts +7 -5
  4. package/dist/api.d.ts +3 -3
  5. package/dist/api.d.ts.map +1 -1
  6. package/dist/auth.d.ts +10 -2
  7. package/dist/auth.d.ts.map +1 -1
  8. package/dist/banner.d.ts.map +1 -1
  9. package/dist/cli.d.ts.map +1 -1
  10. package/dist/cmd/auth/api.d.ts +4 -4
  11. package/dist/cmd/auth/api.d.ts.map +1 -1
  12. package/dist/cmd/auth/index.d.ts.map +1 -1
  13. package/dist/cmd/auth/login.d.ts.map +1 -1
  14. package/dist/cmd/auth/signup.d.ts.map +1 -1
  15. package/dist/cmd/auth/ssh/add.d.ts +2 -0
  16. package/dist/cmd/auth/ssh/add.d.ts.map +1 -0
  17. package/dist/cmd/auth/ssh/api.d.ts +16 -0
  18. package/dist/cmd/auth/ssh/api.d.ts.map +1 -0
  19. package/dist/cmd/auth/ssh/delete.d.ts +2 -0
  20. package/dist/cmd/auth/ssh/delete.d.ts.map +1 -0
  21. package/dist/cmd/auth/ssh/index.d.ts +3 -0
  22. package/dist/cmd/auth/ssh/index.d.ts.map +1 -0
  23. package/dist/cmd/auth/ssh/list.d.ts +2 -0
  24. package/dist/cmd/auth/ssh/list.d.ts.map +1 -0
  25. package/dist/cmd/auth/whoami.d.ts +2 -0
  26. package/dist/cmd/auth/whoami.d.ts.map +1 -0
  27. package/dist/cmd/bundle/ast.d.ts +14 -3
  28. package/dist/cmd/bundle/ast.d.ts.map +1 -1
  29. package/dist/cmd/bundle/ast.test.d.ts +2 -0
  30. package/dist/cmd/bundle/ast.test.d.ts.map +1 -0
  31. package/dist/cmd/bundle/bundler.d.ts +6 -1
  32. package/dist/cmd/bundle/bundler.d.ts.map +1 -1
  33. package/dist/cmd/bundle/file.d.ts.map +1 -1
  34. package/dist/cmd/bundle/fix-duplicate-exports.d.ts +2 -0
  35. package/dist/cmd/bundle/fix-duplicate-exports.d.ts.map +1 -0
  36. package/dist/cmd/bundle/fix-duplicate-exports.test.d.ts +2 -0
  37. package/dist/cmd/bundle/fix-duplicate-exports.test.d.ts.map +1 -0
  38. package/dist/cmd/bundle/index.d.ts +1 -1
  39. package/dist/cmd/bundle/index.d.ts.map +1 -1
  40. package/dist/cmd/bundle/plugin.d.ts +2 -0
  41. package/dist/cmd/bundle/plugin.d.ts.map +1 -1
  42. package/dist/cmd/cloud/deploy.d.ts.map +1 -0
  43. package/dist/cmd/cloud/domain.d.ts +17 -0
  44. package/dist/cmd/cloud/domain.d.ts.map +1 -0
  45. package/dist/cmd/cloud/index.d.ts.map +1 -0
  46. package/dist/cmd/cloud/resource/add.d.ts +2 -0
  47. package/dist/cmd/cloud/resource/add.d.ts.map +1 -0
  48. package/dist/cmd/cloud/resource/delete.d.ts +2 -0
  49. package/dist/cmd/cloud/resource/delete.d.ts.map +1 -0
  50. package/dist/cmd/cloud/resource/index.d.ts +3 -0
  51. package/dist/cmd/cloud/resource/index.d.ts.map +1 -0
  52. package/dist/cmd/cloud/resource/list.d.ts +2 -0
  53. package/dist/cmd/cloud/resource/list.d.ts.map +1 -0
  54. package/dist/cmd/cloud/scp/download.d.ts +2 -0
  55. package/dist/cmd/cloud/scp/download.d.ts.map +1 -0
  56. package/dist/cmd/cloud/scp/index.d.ts +3 -0
  57. package/dist/cmd/cloud/scp/index.d.ts.map +1 -0
  58. package/dist/cmd/cloud/scp/upload.d.ts +2 -0
  59. package/dist/cmd/cloud/scp/upload.d.ts.map +1 -0
  60. package/dist/cmd/cloud/ssh.d.ts +2 -0
  61. package/dist/cmd/cloud/ssh.d.ts.map +1 -0
  62. package/dist/cmd/dev/api.d.ts +18 -0
  63. package/dist/cmd/dev/api.d.ts.map +1 -0
  64. package/dist/cmd/dev/download.d.ts +11 -0
  65. package/dist/cmd/dev/download.d.ts.map +1 -0
  66. package/dist/cmd/dev/index.d.ts.map +1 -1
  67. package/dist/cmd/dev/templates.d.ts +3 -0
  68. package/dist/cmd/dev/templates.d.ts.map +1 -0
  69. package/dist/cmd/env/delete.d.ts +2 -0
  70. package/dist/cmd/env/delete.d.ts.map +1 -0
  71. package/dist/cmd/env/get.d.ts +2 -0
  72. package/dist/cmd/env/get.d.ts.map +1 -0
  73. package/dist/cmd/env/import.d.ts +2 -0
  74. package/dist/cmd/env/import.d.ts.map +1 -0
  75. package/dist/cmd/env/index.d.ts +2 -0
  76. package/dist/cmd/env/index.d.ts.map +1 -0
  77. package/dist/cmd/env/list.d.ts.map +1 -0
  78. package/dist/cmd/env/pull.d.ts +2 -0
  79. package/dist/cmd/env/pull.d.ts.map +1 -0
  80. package/dist/cmd/env/push.d.ts +2 -0
  81. package/dist/cmd/env/push.d.ts.map +1 -0
  82. package/dist/cmd/env/set.d.ts +2 -0
  83. package/dist/cmd/env/set.d.ts.map +1 -0
  84. package/dist/cmd/profile/show.d.ts.map +1 -1
  85. package/dist/cmd/project/create.d.ts.map +1 -1
  86. package/dist/cmd/project/delete.d.ts.map +1 -1
  87. package/dist/cmd/project/download.d.ts +1 -1
  88. package/dist/cmd/project/download.d.ts.map +1 -1
  89. package/dist/cmd/project/list.d.ts.map +1 -1
  90. package/dist/cmd/project/show.d.ts.map +1 -1
  91. package/dist/cmd/project/template-flow.d.ts +5 -1
  92. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  93. package/dist/cmd/secret/delete.d.ts +2 -0
  94. package/dist/cmd/secret/delete.d.ts.map +1 -0
  95. package/dist/cmd/secret/get.d.ts +2 -0
  96. package/dist/cmd/secret/get.d.ts.map +1 -0
  97. package/dist/cmd/secret/import.d.ts +2 -0
  98. package/dist/cmd/secret/import.d.ts.map +1 -0
  99. package/dist/cmd/secret/index.d.ts +2 -0
  100. package/dist/cmd/secret/index.d.ts.map +1 -0
  101. package/dist/cmd/secret/list.d.ts +2 -0
  102. package/dist/cmd/secret/list.d.ts.map +1 -0
  103. package/dist/cmd/secret/pull.d.ts +2 -0
  104. package/dist/cmd/secret/pull.d.ts.map +1 -0
  105. package/dist/cmd/secret/push.d.ts +2 -0
  106. package/dist/cmd/secret/push.d.ts.map +1 -0
  107. package/dist/cmd/secret/set.d.ts +2 -0
  108. package/dist/cmd/secret/set.d.ts.map +1 -0
  109. package/dist/cmd/version/index.d.ts.map +1 -1
  110. package/dist/config.d.ts +11 -3
  111. package/dist/config.d.ts.map +1 -1
  112. package/dist/crypto/box.d.ts +65 -0
  113. package/dist/crypto/box.d.ts.map +1 -0
  114. package/dist/crypto/box.test.d.ts +2 -0
  115. package/dist/crypto/box.test.d.ts.map +1 -0
  116. package/dist/download.d.ts.map +1 -1
  117. package/dist/env-util.d.ts +67 -0
  118. package/dist/env-util.d.ts.map +1 -0
  119. package/dist/env-util.test.d.ts +2 -0
  120. package/dist/env-util.test.d.ts.map +1 -0
  121. package/dist/index.d.ts +1 -1
  122. package/dist/index.d.ts.map +1 -1
  123. package/dist/schema-parser.d.ts.map +1 -1
  124. package/dist/steps.d.ts +4 -1
  125. package/dist/steps.d.ts.map +1 -1
  126. package/dist/terminal.d.ts.map +1 -1
  127. package/dist/tui.d.ts +32 -2
  128. package/dist/tui.d.ts.map +1 -1
  129. package/dist/types.d.ts +250 -127
  130. package/dist/types.d.ts.map +1 -1
  131. package/dist/utils/detectSubagent.d.ts +15 -0
  132. package/dist/utils/detectSubagent.d.ts.map +1 -0
  133. package/dist/utils/zip.d.ts +7 -0
  134. package/dist/utils/zip.d.ts.map +1 -0
  135. package/package.json +11 -3
  136. package/src/api-errors.md +2 -2
  137. package/src/api.ts +12 -7
  138. package/src/auth.ts +116 -7
  139. package/src/banner.ts +13 -6
  140. package/src/cli.ts +709 -36
  141. package/src/cmd/auth/api.ts +10 -16
  142. package/src/cmd/auth/index.ts +3 -1
  143. package/src/cmd/auth/login.ts +24 -8
  144. package/src/cmd/auth/signup.ts +15 -11
  145. package/src/cmd/auth/ssh/add.ts +263 -0
  146. package/src/cmd/auth/ssh/api.ts +94 -0
  147. package/src/cmd/auth/ssh/delete.ts +102 -0
  148. package/src/cmd/auth/ssh/index.ts +10 -0
  149. package/src/cmd/auth/ssh/list.ts +74 -0
  150. package/src/cmd/auth/whoami.ts +69 -0
  151. package/src/cmd/bundle/ast.test.ts +565 -0
  152. package/src/cmd/bundle/ast.ts +457 -44
  153. package/src/cmd/bundle/bundler.ts +255 -57
  154. package/src/cmd/bundle/file.ts +6 -12
  155. package/src/cmd/bundle/fix-duplicate-exports.test.ts +387 -0
  156. package/src/cmd/bundle/fix-duplicate-exports.ts +204 -0
  157. package/src/cmd/bundle/index.ts +11 -11
  158. package/src/cmd/bundle/patch/aisdk.ts +1 -1
  159. package/src/cmd/bundle/plugin.ts +373 -53
  160. package/src/cmd/cloud/deploy.ts +336 -0
  161. package/src/cmd/cloud/domain.ts +92 -0
  162. package/src/cmd/cloud/index.ts +11 -0
  163. package/src/cmd/cloud/resource/add.ts +56 -0
  164. package/src/cmd/cloud/resource/delete.ts +120 -0
  165. package/src/cmd/cloud/resource/index.ts +11 -0
  166. package/src/cmd/cloud/resource/list.ts +69 -0
  167. package/src/cmd/cloud/scp/download.ts +59 -0
  168. package/src/cmd/cloud/scp/index.ts +9 -0
  169. package/src/cmd/cloud/scp/upload.ts +62 -0
  170. package/src/cmd/cloud/ssh.ts +68 -0
  171. package/src/cmd/dev/api.ts +46 -0
  172. package/src/cmd/dev/download.ts +111 -0
  173. package/src/cmd/dev/index.ts +362 -34
  174. package/src/cmd/dev/templates.ts +84 -0
  175. package/src/cmd/env/delete.ts +47 -0
  176. package/src/cmd/env/get.ts +53 -0
  177. package/src/cmd/env/import.ts +102 -0
  178. package/src/cmd/env/index.ts +22 -0
  179. package/src/cmd/env/list.ts +56 -0
  180. package/src/cmd/env/pull.ts +80 -0
  181. package/src/cmd/env/push.ts +37 -0
  182. package/src/cmd/env/set.ts +71 -0
  183. package/src/cmd/index.ts +2 -2
  184. package/src/cmd/profile/show.ts +15 -6
  185. package/src/cmd/project/create.ts +7 -2
  186. package/src/cmd/project/delete.ts +75 -18
  187. package/src/cmd/project/download.ts +3 -3
  188. package/src/cmd/project/list.ts +8 -8
  189. package/src/cmd/project/show.ts +3 -7
  190. package/src/cmd/project/template-flow.ts +186 -48
  191. package/src/cmd/secret/delete.ts +40 -0
  192. package/src/cmd/secret/get.ts +54 -0
  193. package/src/cmd/secret/import.ts +64 -0
  194. package/src/cmd/secret/index.ts +22 -0
  195. package/src/cmd/secret/list.ts +56 -0
  196. package/src/cmd/secret/pull.ts +78 -0
  197. package/src/cmd/secret/push.ts +37 -0
  198. package/src/cmd/secret/set.ts +45 -0
  199. package/src/cmd/version/index.ts +2 -1
  200. package/src/config.ts +257 -27
  201. package/src/crypto/box.test.ts +431 -0
  202. package/src/crypto/box.ts +477 -0
  203. package/src/download.ts +1 -0
  204. package/src/env-util.test.ts +194 -0
  205. package/src/env-util.ts +290 -0
  206. package/src/index.ts +5 -1
  207. package/src/schema-parser.ts +2 -3
  208. package/src/steps.ts +144 -10
  209. package/src/terminal.ts +24 -23
  210. package/src/tui.ts +208 -68
  211. package/src/types.ts +292 -202
  212. package/src/utils/detectSubagent.ts +31 -0
  213. package/src/utils/zip.ts +38 -0
  214. package/dist/cmd/example/create-user.d.ts +0 -2
  215. package/dist/cmd/example/create-user.d.ts.map +0 -1
  216. package/dist/cmd/example/create.d.ts +0 -2
  217. package/dist/cmd/example/create.d.ts.map +0 -1
  218. package/dist/cmd/example/deploy.d.ts.map +0 -1
  219. package/dist/cmd/example/index.d.ts.map +0 -1
  220. package/dist/cmd/example/list.d.ts.map +0 -1
  221. package/dist/cmd/example/optional-auth.d.ts +0 -3
  222. package/dist/cmd/example/optional-auth.d.ts.map +0 -1
  223. package/dist/cmd/example/run-command.d.ts +0 -2
  224. package/dist/cmd/example/run-command.d.ts.map +0 -1
  225. package/dist/cmd/example/sound.d.ts +0 -3
  226. package/dist/cmd/example/sound.d.ts.map +0 -1
  227. package/dist/cmd/example/spinner.d.ts +0 -2
  228. package/dist/cmd/example/spinner.d.ts.map +0 -1
  229. package/dist/cmd/example/steps.d.ts +0 -2
  230. package/dist/cmd/example/steps.d.ts.map +0 -1
  231. package/dist/cmd/example/version.d.ts +0 -2
  232. package/dist/cmd/example/version.d.ts.map +0 -1
  233. package/dist/logger.d.ts +0 -24
  234. package/dist/logger.d.ts.map +0 -1
  235. package/src/cmd/example/create-user.ts +0 -38
  236. package/src/cmd/example/create.ts +0 -31
  237. package/src/cmd/example/deploy.ts +0 -36
  238. package/src/cmd/example/index.ts +0 -29
  239. package/src/cmd/example/list.ts +0 -32
  240. package/src/cmd/example/optional-auth.ts +0 -38
  241. package/src/cmd/example/run-command.ts +0 -45
  242. package/src/cmd/example/sound.ts +0 -14
  243. package/src/cmd/example/spinner.ts +0 -44
  244. package/src/cmd/example/steps.ts +0 -66
  245. package/src/cmd/example/version.ts +0 -13
  246. package/src/logger.ts +0 -235
  247. /package/dist/cmd/{example → cloud}/deploy.d.ts +0 -0
  248. /package/dist/cmd/{example → cloud}/index.d.ts +0 -0
  249. /package/dist/cmd/{example → env}/list.d.ts +0 -0
@@ -0,0 +1,47 @@
1
+ import { z } from 'zod';
2
+ import { createSubcommand } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { projectEnvDelete } from '@agentuity/server';
5
+ import {
6
+ findExistingEnvFile,
7
+ readEnvFile,
8
+ writeEnvFile,
9
+ filterAgentuitySdkKeys,
10
+ } from '../../env-util';
11
+
12
+ export const deleteSubcommand = createSubcommand({
13
+ name: 'delete',
14
+ aliases: ['del', 'remove', 'rm'],
15
+ description: 'Delete an environment variable',
16
+ requires: { auth: true, project: true, apiClient: true },
17
+ schema: {
18
+ args: z.object({
19
+ key: z.string().describe('the environment variable key to delete'),
20
+ }),
21
+ },
22
+
23
+ async handler(ctx) {
24
+ const { args, project, projectDir, apiClient } = ctx;
25
+
26
+ // Delete from cloud
27
+ await tui.spinner('Deleting environment variable from cloud', () => {
28
+ return projectEnvDelete(apiClient, {
29
+ id: project.projectId,
30
+ env: [args.key],
31
+ });
32
+ });
33
+
34
+ // Update local .env file (prefer .env.production, fallback to .env)
35
+ const envFilePath = await findExistingEnvFile(projectDir);
36
+ const currentEnv = await readEnvFile(envFilePath);
37
+ delete currentEnv[args.key];
38
+
39
+ // Filter out AGENTUITY_ keys before writing
40
+ const filteredEnv = filterAgentuitySdkKeys(currentEnv);
41
+ await writeEnvFile(envFilePath, filteredEnv);
42
+
43
+ tui.success(
44
+ `Environment variable '${args.key}' deleted successfully (cloud + ${envFilePath})`
45
+ );
46
+ },
47
+ });
@@ -0,0 +1,53 @@
1
+ import { z } from 'zod';
2
+ import { createSubcommand } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { projectGet } from '@agentuity/server';
5
+ import { maskSecret } from '../../env-util';
6
+
7
+ export const getSubcommand = createSubcommand({
8
+ name: 'get',
9
+ description: 'Get an environment variable value',
10
+ requires: { auth: true, project: true, apiClient: true },
11
+ schema: {
12
+ args: z.object({
13
+ key: z.string().describe('the environment variable key'),
14
+ }),
15
+ options: z.object({
16
+ mask: z
17
+ .boolean()
18
+ .default(false)
19
+ .describe('mask the value in output (default: true in TTY, false otherwise)'),
20
+ }),
21
+ },
22
+
23
+ async handler(ctx) {
24
+ const { args, opts, apiClient, project } = ctx;
25
+
26
+ // Fetch project with unmasked secrets
27
+ const projectData = await tui.spinner('Fetching environment variables', () => {
28
+ return projectGet(apiClient, { id: project.projectId, mask: false });
29
+ });
30
+
31
+ // Look for the key in env
32
+ const value = projectData.env?.[args.key];
33
+
34
+ if (value === undefined) {
35
+ tui.fatal(`Environment variable '${args.key}' not found`);
36
+ }
37
+
38
+ // Display the value, masked if requested
39
+ if (process.stdout.isTTY) {
40
+ if (opts?.mask) {
41
+ tui.success(`${args.key}=${maskSecret(value)}`);
42
+ } else {
43
+ tui.success(`${args.key}=${value}`);
44
+ }
45
+ } else {
46
+ if (opts?.mask) {
47
+ console.log(`${args.key}=${maskSecret(value)}`);
48
+ } else {
49
+ console.log(`${args.key}=${value}`);
50
+ }
51
+ }
52
+ },
53
+ });
@@ -0,0 +1,102 @@
1
+ import { z } from 'zod';
2
+ import { createSubcommand } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { projectEnvUpdate } from '@agentuity/server';
5
+ import {
6
+ findEnvFile,
7
+ readEnvFile,
8
+ writeEnvFile,
9
+ filterAgentuitySdkKeys,
10
+ mergeEnvVars,
11
+ splitEnvAndSecrets,
12
+ looksLikeSecret,
13
+ } from '../../env-util';
14
+ import { getCommand } from '../../command-prefix';
15
+
16
+ export const importSubcommand = createSubcommand({
17
+ name: 'import',
18
+ description: 'Import environment variables from a file to cloud and local .env.production',
19
+ requires: { auth: true, project: true, apiClient: true },
20
+ schema: {
21
+ args: z.object({
22
+ file: z.string().describe('path to the .env file to import'),
23
+ }),
24
+ },
25
+
26
+ async handler(ctx) {
27
+ const { args, apiClient, project, projectDir } = ctx;
28
+
29
+ // Read the import file
30
+ const importedEnv = await readEnvFile(args.file);
31
+
32
+ if (Object.keys(importedEnv).length === 0) {
33
+ tui.warning(`No environment variables found in ${args.file}`);
34
+ return;
35
+ }
36
+
37
+ // Filter out AGENTUITY_ prefixed keys
38
+ const filteredEnv = filterAgentuitySdkKeys(importedEnv);
39
+
40
+ if (Object.keys(filteredEnv).length === 0) {
41
+ tui.warning('No valid environment variables to import (all were AGENTUITY_ prefixed)');
42
+ return;
43
+ }
44
+
45
+ // Check for potential secrets in the imported variables
46
+ const potentialSecrets: string[] = [];
47
+ for (const [key, value] of Object.entries(filteredEnv)) {
48
+ if (looksLikeSecret(key, value)) {
49
+ potentialSecrets.push(key);
50
+ }
51
+ }
52
+
53
+ if (potentialSecrets.length > 0) {
54
+ tui.warning(
55
+ `Found ${potentialSecrets.length} variable(s) that look like they should be secrets:`
56
+ );
57
+ for (const key of potentialSecrets) {
58
+ tui.info(` • ${key}`);
59
+ }
60
+ tui.info(`\nSecrets should be stored using: ${getCommand('secret import <file>')}`);
61
+ tui.info('This keeps them more secure and properly masked in the cloud.');
62
+
63
+ const response = await tui.confirm(
64
+ 'Do you still want to import these as regular environment variables?',
65
+ false
66
+ );
67
+
68
+ if (!response) {
69
+ tui.info(
70
+ `Cancelled. Use "${getCommand('secret import')}" to store these as secrets instead.`
71
+ );
72
+ return;
73
+ }
74
+ }
75
+
76
+ // Split into env and secrets based on key naming conventions
77
+ const { env: normalEnv, secrets } = splitEnvAndSecrets(filteredEnv);
78
+
79
+ // Push to cloud
80
+ await tui.spinner('Importing environment variables to cloud', () => {
81
+ return projectEnvUpdate(apiClient, {
82
+ id: project.projectId,
83
+ env: normalEnv,
84
+ secrets: secrets,
85
+ });
86
+ });
87
+
88
+ // Merge with local .env.production file
89
+ const localEnvPath = await findEnvFile(projectDir);
90
+ const localEnv = await readEnvFile(localEnvPath);
91
+ const mergedEnv = mergeEnvVars(localEnv, filteredEnv);
92
+
93
+ await writeEnvFile(localEnvPath, mergedEnv, {
94
+ skipKeys: Object.keys(mergedEnv).filter((k) => k.startsWith('AGENTUITY_')),
95
+ });
96
+
97
+ const count = Object.keys(filteredEnv).length;
98
+ tui.success(
99
+ `Imported ${count} environment variable${count !== 1 ? 's' : ''} from ${args.file} to cloud and ${localEnvPath}`
100
+ );
101
+ },
102
+ });
@@ -0,0 +1,22 @@
1
+ import { createCommand } from '../../types';
2
+ import { pullSubcommand } from './pull';
3
+ import { pushSubcommand } from './push';
4
+ import { setSubcommand } from './set';
5
+ import { getSubcommand } from './get';
6
+ import { deleteSubcommand } from './delete';
7
+ import { importSubcommand } from './import';
8
+ import { listSubcommand } from './list';
9
+
10
+ export const command = createCommand({
11
+ name: 'env',
12
+ description: 'Manage environment variables for your project',
13
+ subcommands: [
14
+ listSubcommand,
15
+ pullSubcommand,
16
+ pushSubcommand,
17
+ setSubcommand,
18
+ getSubcommand,
19
+ deleteSubcommand,
20
+ importSubcommand,
21
+ ],
22
+ });
@@ -0,0 +1,56 @@
1
+ import { z } from 'zod';
2
+ import { createSubcommand } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { projectGet } from '@agentuity/server';
5
+ import { maskSecret } from '../../env-util';
6
+
7
+ export const listSubcommand = createSubcommand({
8
+ name: 'list',
9
+ aliases: ['ls'],
10
+ description: 'List all environment variables',
11
+ requires: { auth: true, project: true, apiClient: true },
12
+ schema: {
13
+ options: z.object({
14
+ mask: z
15
+ .boolean()
16
+ .default(false)
17
+ .describe('mask the values in output (default: false for env vars)'),
18
+ }),
19
+ },
20
+
21
+ async handler(ctx) {
22
+ const { opts, apiClient, project } = ctx;
23
+
24
+ // Fetch project with unmasked secrets
25
+ const projectData = await tui.spinner('Fetching environment variables', () => {
26
+ return projectGet(apiClient, { id: project.projectId, mask: false });
27
+ });
28
+
29
+ const env = projectData.env || {};
30
+
31
+ if (Object.keys(env).length === 0) {
32
+ tui.info('No environment variables found');
33
+ return;
34
+ }
35
+
36
+ // Display the variables
37
+ if (process.stdout.isTTY) {
38
+ tui.newline();
39
+ tui.info(`Environment Variables (${Object.keys(env).length}):`);
40
+ tui.newline();
41
+ }
42
+
43
+ const sortedKeys = Object.keys(env).sort();
44
+ // For env vars, masking should be explicitly opted-in (default false)
45
+ const shouldMask = opts?.mask === true;
46
+ for (const key of sortedKeys) {
47
+ const value = env[key];
48
+ const displayValue = shouldMask ? maskSecret(value) : value;
49
+ if (process.stdout.isTTY) {
50
+ console.log(`${tui.bold(key)}=${displayValue}`);
51
+ } else {
52
+ console.log(`${key}=${displayValue}`);
53
+ }
54
+ }
55
+ },
56
+ });
@@ -0,0 +1,80 @@
1
+ import { z } from 'zod';
2
+ import { join } from 'node:path';
3
+ import { createSubcommand } from '../../types';
4
+ import * as tui from '../../tui';
5
+ import { projectGet } from '@agentuity/server';
6
+ import {
7
+ findEnvFile,
8
+ findExistingEnvFile,
9
+ readEnvFile,
10
+ writeEnvFile,
11
+ mergeEnvVars,
12
+ } from '../../env-util';
13
+
14
+ export const pullSubcommand = createSubcommand({
15
+ name: 'pull',
16
+ description: 'Pull environment variables from cloud to local .env.production file',
17
+ requires: { auth: true, project: true, apiClient: true },
18
+ schema: {
19
+ options: z.object({
20
+ force: z.boolean().default(false).describe('overwrite local values with cloud values'),
21
+ }),
22
+ },
23
+
24
+ async handler(ctx) {
25
+ const { opts, apiClient, project, projectDir } = ctx;
26
+
27
+ // Fetch project with unmasked secrets
28
+ const projectData = await tui.spinner('Pulling environment variables from cloud', () => {
29
+ return projectGet(apiClient, { id: project.projectId, mask: false });
30
+ });
31
+
32
+ const cloudEnv = projectData.env || {};
33
+
34
+ // Read current local env from existing file (.env.production or .env)
35
+ const existingEnvPath = await findExistingEnvFile(projectDir);
36
+ const localEnv = await readEnvFile(existingEnvPath);
37
+
38
+ // Target file is always .env.production
39
+ const targetEnvPath = await findEnvFile(projectDir);
40
+
41
+ // Merge: cloud values override local if force=true, otherwise keep local
42
+ let mergedEnv: Record<string, string>;
43
+ if (opts?.force) {
44
+ // Cloud values take priority
45
+ mergedEnv = mergeEnvVars(localEnv, cloudEnv);
46
+ } else {
47
+ // Local values take priority (only add new keys from cloud)
48
+ mergedEnv = mergeEnvVars(cloudEnv, localEnv);
49
+ }
50
+
51
+ // Write to .env.production (skip AGENTUITY_ keys)
52
+ await writeEnvFile(targetEnvPath, mergedEnv, {
53
+ skipKeys: Object.keys(mergedEnv).filter((k) => k.startsWith('AGENTUITY_')),
54
+ });
55
+
56
+ // Write AGENTUITY_SDK_KEY to .env if present and missing locally
57
+ if (projectData.api_key) {
58
+ const dotEnvPath = join(projectDir, '.env');
59
+ const dotEnv = await readEnvFile(dotEnvPath);
60
+
61
+ if (!dotEnv.AGENTUITY_SDK_KEY) {
62
+ dotEnv.AGENTUITY_SDK_KEY = projectData.api_key;
63
+ await writeEnvFile(dotEnvPath, dotEnv, {
64
+ addComment: (key) => {
65
+ if (key === 'AGENTUITY_SDK_KEY') {
66
+ return 'AGENTUITY_SDK_KEY is a sensitive value and should not be committed to version control.';
67
+ }
68
+ return null;
69
+ },
70
+ });
71
+ tui.info(`Wrote AGENTUITY_SDK_KEY to ${dotEnvPath}`);
72
+ }
73
+ }
74
+
75
+ const count = Object.keys(cloudEnv).length;
76
+ tui.success(
77
+ `Pulled ${count} environment variable${count !== 1 ? 's' : ''} to ${targetEnvPath}`
78
+ );
79
+ },
80
+ });
@@ -0,0 +1,37 @@
1
+ import { createSubcommand } from '../../types';
2
+ import * as tui from '../../tui';
3
+ import { projectEnvUpdate } from '@agentuity/server';
4
+ import { findExistingEnvFile, readEnvFile, filterAgentuitySdkKeys } from '../../env-util';
5
+
6
+ export const pushSubcommand = createSubcommand({
7
+ name: 'push',
8
+ description: 'Push environment variables from local .env.production file to cloud',
9
+ requires: { auth: true, project: true, apiClient: true },
10
+
11
+ async handler(ctx) {
12
+ const { apiClient, project, projectDir } = ctx;
13
+
14
+ // Read local env file (prefer .env.production, fallback to .env)
15
+ const envFilePath = await findExistingEnvFile(projectDir);
16
+ const localEnv = await readEnvFile(envFilePath);
17
+
18
+ // Filter out AGENTUITY_ prefixed keys (don't push SDK keys)
19
+ const filteredEnv = filterAgentuitySdkKeys(localEnv);
20
+
21
+ if (Object.keys(filteredEnv).length === 0) {
22
+ tui.warning('No environment variables to push');
23
+ return;
24
+ }
25
+
26
+ // Push to cloud
27
+ await tui.spinner('Pushing environment variables to cloud', () => {
28
+ return projectEnvUpdate(apiClient, {
29
+ id: project.projectId,
30
+ env: filteredEnv,
31
+ });
32
+ });
33
+
34
+ const count = Object.keys(filteredEnv).length;
35
+ tui.success(`Pushed ${count} environment variable${count !== 1 ? 's' : ''} to cloud`);
36
+ },
37
+ });
@@ -0,0 +1,71 @@
1
+ import { z } from 'zod';
2
+ import { createSubcommand } from '../../types';
3
+ import * as tui from '../../tui';
4
+ import { projectEnvUpdate } from '@agentuity/server';
5
+ import {
6
+ findEnvFile,
7
+ readEnvFile,
8
+ writeEnvFile,
9
+ filterAgentuitySdkKeys,
10
+ looksLikeSecret,
11
+ } from '../../env-util';
12
+ import { getCommand } from '../../command-prefix';
13
+
14
+ export const setSubcommand = createSubcommand({
15
+ name: 'set',
16
+ description: 'Set an environment variable',
17
+ requires: { auth: true, project: true, apiClient: true },
18
+ schema: {
19
+ args: z.object({
20
+ key: z.string().describe('the environment variable key'),
21
+ value: z.string().describe('the environment variable value'),
22
+ }),
23
+ },
24
+
25
+ async handler(ctx) {
26
+ const { args, apiClient, project, projectDir } = ctx;
27
+
28
+ // Validate key doesn't start with AGENTUITY_
29
+ if (args.key.startsWith('AGENTUITY_')) {
30
+ tui.fatal('Cannot set AGENTUITY_ prefixed variables. These are reserved for system use.');
31
+ }
32
+
33
+ // Detect if this looks like a secret
34
+ if (looksLikeSecret(args.key, args.value)) {
35
+ tui.warning(`The variable '${args.key}' looks like it should be a secret.`);
36
+ tui.info(`Secrets should be stored using: ${getCommand('secret set <key> <value>')}`);
37
+ tui.info('This keeps them more secure and properly masked in the cloud.');
38
+
39
+ const response = await tui.confirm(
40
+ 'Do you still want to store this as a regular environment variable?',
41
+ false
42
+ );
43
+
44
+ if (!response) {
45
+ tui.info(
46
+ `Cancelled. Use "${getCommand('secret set')}" to store this as a secret instead.`
47
+ );
48
+ return;
49
+ }
50
+ }
51
+
52
+ // Set in cloud
53
+ await tui.spinner('Setting environment variable in cloud', () => {
54
+ return projectEnvUpdate(apiClient, {
55
+ id: project.projectId,
56
+ env: { [args.key]: args.value },
57
+ });
58
+ });
59
+
60
+ // Update local .env.production file
61
+ const envFilePath = await findEnvFile(projectDir);
62
+ const currentEnv = await readEnvFile(envFilePath);
63
+ currentEnv[args.key] = args.value;
64
+
65
+ // Filter out AGENTUITY_ keys before writing
66
+ const filteredEnv = filterAgentuitySdkKeys(currentEnv);
67
+ await writeEnvFile(envFilePath, filteredEnv);
68
+
69
+ tui.success(`Environment variable '${args.key}' set successfully (cloud + ${envFilePath})`);
70
+ },
71
+ });
package/src/cmd/index.ts CHANGED
@@ -27,8 +27,8 @@ export async function discoverCommands(): Promise<CommandDefinition[]> {
27
27
  description: subcommand.description,
28
28
  aliases: subcommand.aliases,
29
29
  hidden: true,
30
- requiresAuth: subcommand.requiresAuth,
31
- optionalAuth: subcommand.optionalAuth,
30
+ requires: subcommand.requires,
31
+ optional: subcommand.optional,
32
32
  schema: subcommand.schema,
33
33
  handler: subcommand.handler,
34
34
  };
@@ -1,6 +1,6 @@
1
1
  import { createSubcommand } from '../../types';
2
2
  import { z } from 'zod';
3
- import { getProfile, fetchProfiles } from '../../config';
3
+ import { getProfile, fetchProfiles, loadConfig } from '../../config';
4
4
  import { readFile } from 'node:fs/promises';
5
5
  import * as tui from '../../tui';
6
6
 
@@ -9,6 +9,9 @@ export const showCommand = createSubcommand({
9
9
  description: 'Show the configuration of a profile (defaults to current)',
10
10
  aliases: ['current'],
11
11
  schema: {
12
+ options: z.object({
13
+ json: z.boolean().optional().describe('Show the JSON config'),
14
+ }),
12
15
  args: z
13
16
  .object({
14
17
  name: z.string().optional().describe('Profile name to show (optional)'),
@@ -17,10 +20,11 @@ export const showCommand = createSubcommand({
17
20
  },
18
21
 
19
22
  async handler(ctx) {
20
- const { logger, args } = ctx;
23
+ const { logger, args, opts } = ctx;
21
24
 
22
25
  try {
23
26
  let profilePath: string;
27
+ let current = false;
24
28
 
25
29
  if (args.name) {
26
30
  // Find profile by name
@@ -33,16 +37,21 @@ export const showCommand = createSubcommand({
33
37
 
34
38
  profilePath = profile.filename;
35
39
  } else {
40
+ current = true;
36
41
  // Use current profile
37
42
  profilePath = await getProfile();
38
43
  }
39
44
 
40
- const content = await readFile(profilePath, 'utf-8');
41
-
42
45
  tui.info(`Profile: ${profilePath}`);
43
- tui.newline();
44
46
 
45
- console.log(content);
47
+ if (opts?.json) {
48
+ const content = await loadConfig(current ? undefined : profilePath);
49
+ console.log(JSON.stringify(content, null, 2));
50
+ } else {
51
+ tui.newline();
52
+ const content = await readFile(profilePath, 'utf-8');
53
+ console.log(content);
54
+ }
46
55
  } catch (error) {
47
56
  if (error instanceof Error) {
48
57
  logger.fatal(`Failed to show profile: ${error.message}`);
@@ -6,8 +6,10 @@ export const createProjectSubcommand = createSubcommand({
6
6
  name: 'create',
7
7
  description: 'Create a new project',
8
8
  aliases: ['new'],
9
+ banner: true,
9
10
  toplevel: true,
10
- optionalAuth: true,
11
+ optional: { auth: true, org: true, region: true },
12
+ requires: { apiClient: true },
11
13
  schema: {
12
14
  options: z.object({
13
15
  name: z.string().optional().describe('Project name'),
@@ -41,7 +43,7 @@ export const createProjectSubcommand = createSubcommand({
41
43
  },
42
44
 
43
45
  async handler(ctx) {
44
- const { logger, opts, auth, config } = ctx;
46
+ const { logger, opts, auth, config, apiClient, orgId, region } = ctx;
45
47
 
46
48
  await runCreateFlow({
47
49
  projectName: opts.name,
@@ -55,6 +57,9 @@ export const createProjectSubcommand = createSubcommand({
55
57
  logger,
56
58
  auth: opts.register === true ? auth : undefined,
57
59
  config: config!,
60
+ apiClient,
61
+ orgId,
62
+ region,
58
63
  });
59
64
  },
60
65
  });