@agentuity/cli 0.0.43 → 0.0.45

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 (209) hide show
  1. package/AGENTS.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/api.d.ts +3 -3
  4. package/dist/api.d.ts.map +1 -1
  5. package/dist/auth.d.ts +10 -2
  6. package/dist/auth.d.ts.map +1 -1
  7. package/dist/banner.d.ts.map +1 -1
  8. package/dist/cli.d.ts.map +1 -1
  9. package/dist/cmd/auth/api.d.ts +4 -4
  10. package/dist/cmd/auth/api.d.ts.map +1 -1
  11. package/dist/cmd/auth/index.d.ts.map +1 -1
  12. package/dist/cmd/auth/login.d.ts.map +1 -1
  13. package/dist/cmd/auth/signup.d.ts.map +1 -1
  14. package/dist/cmd/auth/ssh/add.d.ts +2 -0
  15. package/dist/cmd/auth/ssh/add.d.ts.map +1 -0
  16. package/dist/cmd/auth/ssh/api.d.ts +16 -0
  17. package/dist/cmd/auth/ssh/api.d.ts.map +1 -0
  18. package/dist/cmd/auth/ssh/delete.d.ts +2 -0
  19. package/dist/cmd/auth/ssh/delete.d.ts.map +1 -0
  20. package/dist/cmd/auth/ssh/index.d.ts +3 -0
  21. package/dist/cmd/auth/ssh/index.d.ts.map +1 -0
  22. package/dist/cmd/auth/ssh/list.d.ts +2 -0
  23. package/dist/cmd/auth/ssh/list.d.ts.map +1 -0
  24. package/dist/cmd/auth/whoami.d.ts.map +1 -1
  25. package/dist/cmd/bundle/ast.d.ts +14 -3
  26. package/dist/cmd/bundle/ast.d.ts.map +1 -1
  27. package/dist/cmd/bundle/ast.test.d.ts +2 -0
  28. package/dist/cmd/bundle/ast.test.d.ts.map +1 -0
  29. package/dist/cmd/bundle/bundler.d.ts +6 -1
  30. package/dist/cmd/bundle/bundler.d.ts.map +1 -1
  31. package/dist/cmd/bundle/file.d.ts.map +1 -1
  32. package/dist/cmd/bundle/fix-duplicate-exports.d.ts +2 -0
  33. package/dist/cmd/bundle/fix-duplicate-exports.d.ts.map +1 -0
  34. package/dist/cmd/bundle/fix-duplicate-exports.test.d.ts +2 -0
  35. package/dist/cmd/bundle/fix-duplicate-exports.test.d.ts.map +1 -0
  36. package/dist/cmd/bundle/plugin.d.ts +2 -0
  37. package/dist/cmd/bundle/plugin.d.ts.map +1 -1
  38. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  39. package/dist/cmd/cloud/domain.d.ts +17 -0
  40. package/dist/cmd/cloud/domain.d.ts.map +1 -0
  41. package/dist/cmd/cloud/index.d.ts.map +1 -1
  42. package/dist/cmd/cloud/resource/add.d.ts +2 -0
  43. package/dist/cmd/cloud/resource/add.d.ts.map +1 -0
  44. package/dist/cmd/cloud/resource/delete.d.ts +2 -0
  45. package/dist/cmd/cloud/resource/delete.d.ts.map +1 -0
  46. package/dist/cmd/cloud/resource/index.d.ts +3 -0
  47. package/dist/cmd/cloud/resource/index.d.ts.map +1 -0
  48. package/dist/cmd/cloud/resource/list.d.ts +2 -0
  49. package/dist/cmd/cloud/resource/list.d.ts.map +1 -0
  50. package/dist/cmd/cloud/scp/download.d.ts +2 -0
  51. package/dist/cmd/cloud/scp/download.d.ts.map +1 -0
  52. package/dist/cmd/cloud/scp/index.d.ts +3 -0
  53. package/dist/cmd/cloud/scp/index.d.ts.map +1 -0
  54. package/dist/cmd/cloud/scp/upload.d.ts +2 -0
  55. package/dist/cmd/cloud/scp/upload.d.ts.map +1 -0
  56. package/dist/cmd/cloud/ssh.d.ts +2 -0
  57. package/dist/cmd/cloud/ssh.d.ts.map +1 -0
  58. package/dist/cmd/dev/api.d.ts +18 -0
  59. package/dist/cmd/dev/api.d.ts.map +1 -0
  60. package/dist/cmd/dev/download.d.ts +11 -0
  61. package/dist/cmd/dev/download.d.ts.map +1 -0
  62. package/dist/cmd/dev/index.d.ts.map +1 -1
  63. package/dist/cmd/dev/templates.d.ts +3 -0
  64. package/dist/cmd/dev/templates.d.ts.map +1 -0
  65. package/dist/cmd/env/delete.d.ts.map +1 -1
  66. package/dist/cmd/env/get.d.ts.map +1 -1
  67. package/dist/cmd/env/import.d.ts.map +1 -1
  68. package/dist/cmd/env/list.d.ts.map +1 -1
  69. package/dist/cmd/env/pull.d.ts.map +1 -1
  70. package/dist/cmd/env/push.d.ts.map +1 -1
  71. package/dist/cmd/env/set.d.ts.map +1 -1
  72. package/dist/cmd/profile/show.d.ts.map +1 -1
  73. package/dist/cmd/project/create.d.ts.map +1 -1
  74. package/dist/cmd/project/delete.d.ts.map +1 -1
  75. package/dist/cmd/project/list.d.ts.map +1 -1
  76. package/dist/cmd/project/show.d.ts.map +1 -1
  77. package/dist/cmd/project/template-flow.d.ts +4 -0
  78. package/dist/cmd/project/template-flow.d.ts.map +1 -1
  79. package/dist/cmd/secret/delete.d.ts.map +1 -1
  80. package/dist/cmd/secret/get.d.ts.map +1 -1
  81. package/dist/cmd/secret/import.d.ts.map +1 -1
  82. package/dist/cmd/secret/list.d.ts.map +1 -1
  83. package/dist/cmd/secret/pull.d.ts.map +1 -1
  84. package/dist/cmd/secret/push.d.ts.map +1 -1
  85. package/dist/cmd/secret/set.d.ts.map +1 -1
  86. package/dist/config.d.ts +9 -3
  87. package/dist/config.d.ts.map +1 -1
  88. package/dist/crypto/box.d.ts +65 -0
  89. package/dist/crypto/box.d.ts.map +1 -0
  90. package/dist/crypto/box.test.d.ts +2 -0
  91. package/dist/crypto/box.test.d.ts.map +1 -0
  92. package/dist/download.d.ts.map +1 -1
  93. package/dist/steps.d.ts +4 -1
  94. package/dist/steps.d.ts.map +1 -1
  95. package/dist/terminal.d.ts.map +1 -1
  96. package/dist/tui.d.ts +31 -1
  97. package/dist/tui.d.ts.map +1 -1
  98. package/dist/types.d.ts +249 -126
  99. package/dist/types.d.ts.map +1 -1
  100. package/dist/utils/detectSubagent.d.ts +15 -0
  101. package/dist/utils/detectSubagent.d.ts.map +1 -0
  102. package/dist/utils/zip.d.ts +7 -0
  103. package/dist/utils/zip.d.ts.map +1 -0
  104. package/package.json +11 -3
  105. package/src/api-errors.md +2 -2
  106. package/src/api.ts +12 -7
  107. package/src/auth.ts +116 -7
  108. package/src/banner.ts +13 -6
  109. package/src/cli.ts +695 -63
  110. package/src/cmd/auth/api.ts +10 -16
  111. package/src/cmd/auth/index.ts +2 -1
  112. package/src/cmd/auth/login.ts +24 -8
  113. package/src/cmd/auth/signup.ts +15 -11
  114. package/src/cmd/auth/ssh/add.ts +263 -0
  115. package/src/cmd/auth/ssh/api.ts +94 -0
  116. package/src/cmd/auth/ssh/delete.ts +102 -0
  117. package/src/cmd/auth/ssh/index.ts +10 -0
  118. package/src/cmd/auth/ssh/list.ts +74 -0
  119. package/src/cmd/auth/whoami.ts +13 -13
  120. package/src/cmd/bundle/ast.test.ts +565 -0
  121. package/src/cmd/bundle/ast.ts +457 -44
  122. package/src/cmd/bundle/bundler.ts +255 -57
  123. package/src/cmd/bundle/file.ts +6 -12
  124. package/src/cmd/bundle/fix-duplicate-exports.test.ts +387 -0
  125. package/src/cmd/bundle/fix-duplicate-exports.ts +204 -0
  126. package/src/cmd/bundle/index.ts +9 -9
  127. package/src/cmd/bundle/patch/aisdk.ts +1 -1
  128. package/src/cmd/bundle/plugin.ts +373 -53
  129. package/src/cmd/cloud/deploy.ts +300 -93
  130. package/src/cmd/cloud/domain.ts +92 -0
  131. package/src/cmd/cloud/index.ts +4 -1
  132. package/src/cmd/cloud/resource/add.ts +56 -0
  133. package/src/cmd/cloud/resource/delete.ts +120 -0
  134. package/src/cmd/cloud/resource/index.ts +11 -0
  135. package/src/cmd/cloud/resource/list.ts +69 -0
  136. package/src/cmd/cloud/scp/download.ts +59 -0
  137. package/src/cmd/cloud/scp/index.ts +9 -0
  138. package/src/cmd/cloud/scp/upload.ts +62 -0
  139. package/src/cmd/cloud/ssh.ts +68 -0
  140. package/src/cmd/dev/api.ts +46 -0
  141. package/src/cmd/dev/download.ts +111 -0
  142. package/src/cmd/dev/index.ts +360 -34
  143. package/src/cmd/dev/templates.ts +84 -0
  144. package/src/cmd/env/delete.ts +5 -20
  145. package/src/cmd/env/get.ts +5 -18
  146. package/src/cmd/env/import.ts +5 -20
  147. package/src/cmd/env/list.ts +5 -18
  148. package/src/cmd/env/pull.ts +10 -23
  149. package/src/cmd/env/push.ts +5 -23
  150. package/src/cmd/env/set.ts +5 -20
  151. package/src/cmd/index.ts +2 -2
  152. package/src/cmd/profile/show.ts +15 -6
  153. package/src/cmd/project/create.ts +7 -2
  154. package/src/cmd/project/delete.ts +75 -18
  155. package/src/cmd/project/download.ts +2 -2
  156. package/src/cmd/project/list.ts +8 -8
  157. package/src/cmd/project/show.ts +3 -7
  158. package/src/cmd/project/template-flow.ts +170 -72
  159. package/src/cmd/secret/delete.ts +5 -20
  160. package/src/cmd/secret/get.ts +5 -18
  161. package/src/cmd/secret/import.ts +5 -20
  162. package/src/cmd/secret/list.ts +5 -18
  163. package/src/cmd/secret/pull.ts +10 -23
  164. package/src/cmd/secret/push.ts +5 -23
  165. package/src/cmd/secret/set.ts +5 -20
  166. package/src/config.ts +224 -24
  167. package/src/crypto/box.test.ts +431 -0
  168. package/src/crypto/box.ts +477 -0
  169. package/src/download.ts +1 -0
  170. package/src/env-util.test.ts +1 -1
  171. package/src/steps.ts +65 -6
  172. package/src/terminal.ts +24 -23
  173. package/src/tui.ts +192 -61
  174. package/src/types.ts +291 -201
  175. package/src/utils/detectSubagent.ts +31 -0
  176. package/src/utils/zip.ts +38 -0
  177. package/dist/cmd/example/create-user.d.ts +0 -2
  178. package/dist/cmd/example/create-user.d.ts.map +0 -1
  179. package/dist/cmd/example/create.d.ts +0 -2
  180. package/dist/cmd/example/create.d.ts.map +0 -1
  181. package/dist/cmd/example/deploy.d.ts +0 -2
  182. package/dist/cmd/example/deploy.d.ts.map +0 -1
  183. package/dist/cmd/example/index.d.ts +0 -2
  184. package/dist/cmd/example/index.d.ts.map +0 -1
  185. package/dist/cmd/example/list.d.ts +0 -2
  186. package/dist/cmd/example/list.d.ts.map +0 -1
  187. package/dist/cmd/example/optional-auth.d.ts +0 -3
  188. package/dist/cmd/example/optional-auth.d.ts.map +0 -1
  189. package/dist/cmd/example/run-command.d.ts +0 -2
  190. package/dist/cmd/example/run-command.d.ts.map +0 -1
  191. package/dist/cmd/example/sound.d.ts +0 -3
  192. package/dist/cmd/example/sound.d.ts.map +0 -1
  193. package/dist/cmd/example/spinner.d.ts +0 -2
  194. package/dist/cmd/example/spinner.d.ts.map +0 -1
  195. package/dist/cmd/example/steps.d.ts +0 -2
  196. package/dist/cmd/example/steps.d.ts.map +0 -1
  197. package/dist/cmd/example/version.d.ts +0 -2
  198. package/dist/cmd/example/version.d.ts.map +0 -1
  199. package/src/cmd/example/create-user.ts +0 -38
  200. package/src/cmd/example/create.ts +0 -31
  201. package/src/cmd/example/deploy.ts +0 -36
  202. package/src/cmd/example/index.ts +0 -29
  203. package/src/cmd/example/list.ts +0 -32
  204. package/src/cmd/example/optional-auth.ts +0 -38
  205. package/src/cmd/example/run-command.ts +0 -45
  206. package/src/cmd/example/sound.ts +0 -14
  207. package/src/cmd/example/spinner.ts +0 -44
  208. package/src/cmd/example/steps.ts +0 -66
  209. package/src/cmd/example/version.ts +0 -13
@@ -2,8 +2,6 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../types';
3
3
  import * as tui from '../../tui';
4
4
  import { projectEnvDelete } from '@agentuity/server';
5
- import { getAPIBaseURL, APIClient } from '../../api';
6
- import { loadProjectConfig } from '../../config';
7
5
  import {
8
6
  findExistingEnvFile,
9
7
  readEnvFile,
@@ -15,39 +13,26 @@ export const deleteSubcommand = createSubcommand({
15
13
  name: 'delete',
16
14
  aliases: ['del', 'remove', 'rm'],
17
15
  description: 'Delete an environment variable',
18
- requiresAuth: true,
16
+ requires: { auth: true, project: true, apiClient: true },
19
17
  schema: {
20
18
  args: z.object({
21
19
  key: z.string().describe('the environment variable key to delete'),
22
20
  }),
23
- options: z.object({
24
- dir: z.string().optional().describe('project directory (default: current directory)'),
25
- }),
26
21
  },
27
22
 
28
23
  async handler(ctx) {
29
- const { args, opts, config } = ctx;
30
- const dir = opts?.dir ?? process.cwd();
31
-
32
- // Load project config to get project ID
33
- const projectConfig = await loadProjectConfig(dir);
34
- if (!projectConfig) {
35
- tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
36
- }
37
-
38
- const apiUrl = getAPIBaseURL(config);
39
- const client = new APIClient(apiUrl, config);
24
+ const { args, project, projectDir, apiClient } = ctx;
40
25
 
41
26
  // Delete from cloud
42
27
  await tui.spinner('Deleting environment variable from cloud', () => {
43
- return projectEnvDelete(client, {
44
- id: projectConfig.projectId,
28
+ return projectEnvDelete(apiClient, {
29
+ id: project.projectId,
45
30
  env: [args.key],
46
31
  });
47
32
  });
48
33
 
49
34
  // Update local .env file (prefer .env.production, fallback to .env)
50
- const envFilePath = await findExistingEnvFile(dir);
35
+ const envFilePath = await findExistingEnvFile(projectDir);
51
36
  const currentEnv = await readEnvFile(envFilePath);
52
37
  delete currentEnv[args.key];
53
38
 
@@ -2,20 +2,17 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../types';
3
3
  import * as tui from '../../tui';
4
4
  import { projectGet } from '@agentuity/server';
5
- import { getAPIBaseURL, APIClient } from '../../api';
6
- import { loadProjectConfig } from '../../config';
7
5
  import { maskSecret } from '../../env-util';
8
6
 
9
7
  export const getSubcommand = createSubcommand({
10
8
  name: 'get',
11
9
  description: 'Get an environment variable value',
12
- requiresAuth: true,
10
+ requires: { auth: true, project: true, apiClient: true },
13
11
  schema: {
14
12
  args: z.object({
15
13
  key: z.string().describe('the environment variable key'),
16
14
  }),
17
15
  options: z.object({
18
- dir: z.string().optional().describe('project directory (default: current directory)'),
19
16
  mask: z
20
17
  .boolean()
21
18
  .default(false)
@@ -24,25 +21,15 @@ export const getSubcommand = createSubcommand({
24
21
  },
25
22
 
26
23
  async handler(ctx) {
27
- const { args, opts, config } = ctx;
28
- const dir = opts?.dir ?? process.cwd();
29
-
30
- // Load project config to get project ID
31
- const projectConfig = await loadProjectConfig(dir);
32
- if (!projectConfig) {
33
- tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
34
- }
35
-
36
- const apiUrl = getAPIBaseURL(config);
37
- const client = new APIClient(apiUrl, config);
24
+ const { args, opts, apiClient, project } = ctx;
38
25
 
39
26
  // Fetch project with unmasked secrets
40
- const project = await tui.spinner('Fetching environment variables', () => {
41
- return projectGet(client, { id: projectConfig.projectId, mask: false });
27
+ const projectData = await tui.spinner('Fetching environment variables', () => {
28
+ return projectGet(apiClient, { id: project.projectId, mask: false });
42
29
  });
43
30
 
44
31
  // Look for the key in env
45
- const value = project.env?.[args.key];
32
+ const value = projectData.env?.[args.key];
46
33
 
47
34
  if (value === undefined) {
48
35
  tui.fatal(`Environment variable '${args.key}' not found`);
@@ -2,8 +2,6 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../types';
3
3
  import * as tui from '../../tui';
4
4
  import { projectEnvUpdate } from '@agentuity/server';
5
- import { getAPIBaseURL, APIClient } from '../../api';
6
- import { loadProjectConfig } from '../../config';
7
5
  import {
8
6
  findEnvFile,
9
7
  readEnvFile,
@@ -18,25 +16,15 @@ import { getCommand } from '../../command-prefix';
18
16
  export const importSubcommand = createSubcommand({
19
17
  name: 'import',
20
18
  description: 'Import environment variables from a file to cloud and local .env.production',
21
- requiresAuth: true,
19
+ requires: { auth: true, project: true, apiClient: true },
22
20
  schema: {
23
21
  args: z.object({
24
22
  file: z.string().describe('path to the .env file to import'),
25
23
  }),
26
- options: z.object({
27
- dir: z.string().optional().describe('project directory (default: current directory)'),
28
- }),
29
24
  },
30
25
 
31
26
  async handler(ctx) {
32
- const { args, opts, config } = ctx;
33
- const dir = opts?.dir ?? process.cwd();
34
-
35
- // Load project config to get project ID
36
- const projectConfig = await loadProjectConfig(dir);
37
- if (!projectConfig) {
38
- tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
39
- }
27
+ const { args, apiClient, project, projectDir } = ctx;
40
28
 
41
29
  // Read the import file
42
30
  const importedEnv = await readEnvFile(args.file);
@@ -85,23 +73,20 @@ export const importSubcommand = createSubcommand({
85
73
  }
86
74
  }
87
75
 
88
- const apiUrl = getAPIBaseURL(config);
89
- const client = new APIClient(apiUrl, config);
90
-
91
76
  // Split into env and secrets based on key naming conventions
92
77
  const { env: normalEnv, secrets } = splitEnvAndSecrets(filteredEnv);
93
78
 
94
79
  // Push to cloud
95
80
  await tui.spinner('Importing environment variables to cloud', () => {
96
- return projectEnvUpdate(client, {
97
- id: projectConfig.projectId,
81
+ return projectEnvUpdate(apiClient, {
82
+ id: project.projectId,
98
83
  env: normalEnv,
99
84
  secrets: secrets,
100
85
  });
101
86
  });
102
87
 
103
88
  // Merge with local .env.production file
104
- const localEnvPath = await findEnvFile(dir);
89
+ const localEnvPath = await findEnvFile(projectDir);
105
90
  const localEnv = await readEnvFile(localEnvPath);
106
91
  const mergedEnv = mergeEnvVars(localEnv, filteredEnv);
107
92
 
@@ -2,18 +2,15 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../types';
3
3
  import * as tui from '../../tui';
4
4
  import { projectGet } from '@agentuity/server';
5
- import { getAPIBaseURL, APIClient } from '../../api';
6
- import { loadProjectConfig } from '../../config';
7
5
  import { maskSecret } from '../../env-util';
8
6
 
9
7
  export const listSubcommand = createSubcommand({
10
8
  name: 'list',
11
9
  aliases: ['ls'],
12
10
  description: 'List all environment variables',
13
- requiresAuth: true,
11
+ requires: { auth: true, project: true, apiClient: true },
14
12
  schema: {
15
13
  options: z.object({
16
- dir: z.string().optional().describe('project directory (default: current directory)'),
17
14
  mask: z
18
15
  .boolean()
19
16
  .default(false)
@@ -22,24 +19,14 @@ export const listSubcommand = createSubcommand({
22
19
  },
23
20
 
24
21
  async handler(ctx) {
25
- const { opts, config } = ctx;
26
- const dir = opts?.dir ?? process.cwd();
27
-
28
- // Load project config to get project ID
29
- const projectConfig = await loadProjectConfig(dir);
30
- if (!projectConfig) {
31
- tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
32
- }
33
-
34
- const apiUrl = getAPIBaseURL(config);
35
- const client = new APIClient(apiUrl, config);
22
+ const { opts, apiClient, project } = ctx;
36
23
 
37
24
  // Fetch project with unmasked secrets
38
- const project = await tui.spinner('Fetching environment variables', () => {
39
- return projectGet(client, { id: projectConfig.projectId, mask: false });
25
+ const projectData = await tui.spinner('Fetching environment variables', () => {
26
+ return projectGet(apiClient, { id: project.projectId, mask: false });
40
27
  });
41
28
 
42
- const env = project.env || {};
29
+ const env = projectData.env || {};
43
30
 
44
31
  if (Object.keys(env).length === 0) {
45
32
  tui.info('No environment variables found');
@@ -3,8 +3,6 @@ import { join } from 'node:path';
3
3
  import { createSubcommand } from '../../types';
4
4
  import * as tui from '../../tui';
5
5
  import { projectGet } from '@agentuity/server';
6
- import { getAPIBaseURL, APIClient } from '../../api';
7
- import { loadProjectConfig } from '../../config';
8
6
  import {
9
7
  findEnvFile,
10
8
  findExistingEnvFile,
@@ -16,40 +14,29 @@ import {
16
14
  export const pullSubcommand = createSubcommand({
17
15
  name: 'pull',
18
16
  description: 'Pull environment variables from cloud to local .env.production file',
19
- requiresAuth: true,
17
+ requires: { auth: true, project: true, apiClient: true },
20
18
  schema: {
21
19
  options: z.object({
22
- dir: z.string().optional().describe('project directory (default: current directory)'),
23
20
  force: z.boolean().default(false).describe('overwrite local values with cloud values'),
24
21
  }),
25
22
  },
26
23
 
27
24
  async handler(ctx) {
28
- const { opts, config } = ctx;
29
- const dir = opts?.dir ?? process.cwd();
30
-
31
- // Load project config to get project ID
32
- const projectConfig = await loadProjectConfig(dir);
33
- if (!projectConfig) {
34
- tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
35
- }
36
-
37
- const apiUrl = getAPIBaseURL(config);
38
- const client = new APIClient(apiUrl, config);
25
+ const { opts, apiClient, project, projectDir } = ctx;
39
26
 
40
27
  // Fetch project with unmasked secrets
41
- const project = await tui.spinner('Pulling environment variables from cloud', () => {
42
- return projectGet(client, { id: projectConfig.projectId, mask: false });
28
+ const projectData = await tui.spinner('Pulling environment variables from cloud', () => {
29
+ return projectGet(apiClient, { id: project.projectId, mask: false });
43
30
  });
44
31
 
45
- const cloudEnv = project.env || {};
32
+ const cloudEnv = projectData.env || {};
46
33
 
47
34
  // Read current local env from existing file (.env.production or .env)
48
- const existingEnvPath = await findExistingEnvFile(dir);
35
+ const existingEnvPath = await findExistingEnvFile(projectDir);
49
36
  const localEnv = await readEnvFile(existingEnvPath);
50
37
 
51
38
  // Target file is always .env.production
52
- const targetEnvPath = await findEnvFile(dir);
39
+ const targetEnvPath = await findEnvFile(projectDir);
53
40
 
54
41
  // Merge: cloud values override local if force=true, otherwise keep local
55
42
  let mergedEnv: Record<string, string>;
@@ -67,12 +54,12 @@ export const pullSubcommand = createSubcommand({
67
54
  });
68
55
 
69
56
  // Write AGENTUITY_SDK_KEY to .env if present and missing locally
70
- if (project.api_key) {
71
- const dotEnvPath = join(dir, '.env');
57
+ if (projectData.api_key) {
58
+ const dotEnvPath = join(projectDir, '.env');
72
59
  const dotEnv = await readEnvFile(dotEnvPath);
73
60
 
74
61
  if (!dotEnv.AGENTUITY_SDK_KEY) {
75
- dotEnv.AGENTUITY_SDK_KEY = project.api_key;
62
+ dotEnv.AGENTUITY_SDK_KEY = projectData.api_key;
76
63
  await writeEnvFile(dotEnvPath, dotEnv, {
77
64
  addComment: (key) => {
78
65
  if (key === 'AGENTUITY_SDK_KEY') {
@@ -1,33 +1,18 @@
1
- import { z } from 'zod';
2
1
  import { createSubcommand } from '../../types';
3
2
  import * as tui from '../../tui';
4
3
  import { projectEnvUpdate } from '@agentuity/server';
5
- import { getAPIBaseURL, APIClient } from '../../api';
6
- import { loadProjectConfig } from '../../config';
7
4
  import { findExistingEnvFile, readEnvFile, filterAgentuitySdkKeys } from '../../env-util';
8
5
 
9
6
  export const pushSubcommand = createSubcommand({
10
7
  name: 'push',
11
8
  description: 'Push environment variables from local .env.production file to cloud',
12
- requiresAuth: true,
13
- schema: {
14
- options: z.object({
15
- dir: z.string().optional().describe('project directory (default: current directory)'),
16
- }),
17
- },
9
+ requires: { auth: true, project: true, apiClient: true },
18
10
 
19
11
  async handler(ctx) {
20
- const { opts, config } = ctx;
21
- const dir = opts?.dir ?? process.cwd();
22
-
23
- // Load project config to get project ID
24
- const projectConfig = await loadProjectConfig(dir);
25
- if (!projectConfig) {
26
- tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
27
- }
12
+ const { apiClient, project, projectDir } = ctx;
28
13
 
29
14
  // Read local env file (prefer .env.production, fallback to .env)
30
- const envFilePath = await findExistingEnvFile(dir);
15
+ const envFilePath = await findExistingEnvFile(projectDir);
31
16
  const localEnv = await readEnvFile(envFilePath);
32
17
 
33
18
  // Filter out AGENTUITY_ prefixed keys (don't push SDK keys)
@@ -38,13 +23,10 @@ export const pushSubcommand = createSubcommand({
38
23
  return;
39
24
  }
40
25
 
41
- const apiUrl = getAPIBaseURL(config);
42
- const client = new APIClient(apiUrl, config);
43
-
44
26
  // Push to cloud
45
27
  await tui.spinner('Pushing environment variables to cloud', () => {
46
- return projectEnvUpdate(client, {
47
- id: projectConfig.projectId,
28
+ return projectEnvUpdate(apiClient, {
29
+ id: project.projectId,
48
30
  env: filteredEnv,
49
31
  });
50
32
  });
@@ -2,8 +2,6 @@ import { z } from 'zod';
2
2
  import { createSubcommand } from '../../types';
3
3
  import * as tui from '../../tui';
4
4
  import { projectEnvUpdate } from '@agentuity/server';
5
- import { getAPIBaseURL, APIClient } from '../../api';
6
- import { loadProjectConfig } from '../../config';
7
5
  import {
8
6
  findEnvFile,
9
7
  readEnvFile,
@@ -16,20 +14,16 @@ import { getCommand } from '../../command-prefix';
16
14
  export const setSubcommand = createSubcommand({
17
15
  name: 'set',
18
16
  description: 'Set an environment variable',
19
- requiresAuth: true,
17
+ requires: { auth: true, project: true, apiClient: true },
20
18
  schema: {
21
19
  args: z.object({
22
20
  key: z.string().describe('the environment variable key'),
23
21
  value: z.string().describe('the environment variable value'),
24
22
  }),
25
- options: z.object({
26
- dir: z.string().optional().describe('project directory (default: current directory)'),
27
- }),
28
23
  },
29
24
 
30
25
  async handler(ctx) {
31
- const { args, opts, config } = ctx;
32
- const dir = opts?.dir ?? process.cwd();
26
+ const { args, apiClient, project, projectDir } = ctx;
33
27
 
34
28
  // Validate key doesn't start with AGENTUITY_
35
29
  if (args.key.startsWith('AGENTUITY_')) {
@@ -55,25 +49,16 @@ export const setSubcommand = createSubcommand({
55
49
  }
56
50
  }
57
51
 
58
- // Load project config to get project ID
59
- const projectConfig = await loadProjectConfig(dir);
60
- if (!projectConfig) {
61
- tui.fatal(`No Agentuity project found in ${dir}. Missing agentuity.json`);
62
- }
63
-
64
- const apiUrl = getAPIBaseURL(config);
65
- const client = new APIClient(apiUrl, config);
66
-
67
52
  // Set in cloud
68
53
  await tui.spinner('Setting environment variable in cloud', () => {
69
- return projectEnvUpdate(client, {
70
- id: projectConfig.projectId,
54
+ return projectEnvUpdate(apiClient, {
55
+ id: project.projectId,
71
56
  env: { [args.key]: args.value },
72
57
  });
73
58
  });
74
59
 
75
60
  // Update local .env.production file
76
- const envFilePath = await findEnvFile(dir);
61
+ const envFilePath = await findEnvFile(projectDir);
77
62
  const currentEnv = await readEnvFile(envFilePath);
78
63
  currentEnv[args.key] = args.value;
79
64
 
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
  });
@@ -1,17 +1,17 @@
1
1
  import { z } from 'zod';
2
2
  import { createSubcommand } from '../../types';
3
3
  import * as tui from '../../tui';
4
- import { projectDelete } from '@agentuity/server';
5
- import { getAPIBaseURL, APIClient } from '../../api';
4
+ import { projectDelete, projectList } from '@agentuity/server';
5
+ import enquirer from 'enquirer';
6
6
 
7
7
  export const deleteSubcommand = createSubcommand({
8
8
  name: 'delete',
9
9
  description: 'Delete a project',
10
10
  aliases: ['rm', 'del'],
11
- requiresAuth: true,
11
+ requires: { auth: true, apiClient: true },
12
12
  schema: {
13
13
  args: z.object({
14
- id: z.string().describe('the project id'),
14
+ id: z.string().optional().describe('the project id'),
15
15
  }),
16
16
  options: z.object({
17
17
  confirm: z.boolean().optional().describe('Skip confirmation prompts'),
@@ -19,10 +19,56 @@ export const deleteSubcommand = createSubcommand({
19
19
  },
20
20
 
21
21
  async handler(ctx) {
22
- const { args, opts, config } = ctx;
22
+ const { args, opts, apiClient } = ctx;
23
23
 
24
- const apiUrl = getAPIBaseURL(config);
25
- const client = new APIClient(apiUrl, config);
24
+ let projectIds: string[] = [];
25
+
26
+ if (args.id) {
27
+ // Command line argument provided
28
+ projectIds = [args.id];
29
+ } else {
30
+ // Check TTY before attempting to prompt
31
+ if (!process.stdin.isTTY) {
32
+ tui.fatal('--id is required in non-interactive mode');
33
+ }
34
+
35
+ // Fetch projects and prompt for selection
36
+ const projects = await tui.spinner({
37
+ message: 'Fetching projects',
38
+ clearOnSuccess: true,
39
+ callback: async () => {
40
+ return projectList(apiClient);
41
+ },
42
+ });
43
+
44
+ if (projects.length === 0) {
45
+ tui.info('No projects found to delete');
46
+ return;
47
+ }
48
+
49
+ // Sort projects by name
50
+ projects.sort((a, b) => a.name.localeCompare(b.name));
51
+
52
+ // Build choices for multi-select
53
+ const choices: Array<{ name: string; message: string }> = projects.map((project) => ({
54
+ name: project.id,
55
+ message: `${project.name.padEnd(25)} ${tui.muted(project.id)} (${project.orgName})`,
56
+ }));
57
+
58
+ const response = await enquirer.prompt<{ projects: string[] }>({
59
+ type: 'multiselect',
60
+ name: 'projects',
61
+ message: 'Select project(s) to delete:',
62
+ choices,
63
+ });
64
+
65
+ projectIds = response.projects;
66
+ }
67
+
68
+ if (projectIds.length === 0) {
69
+ tui.info('No projects selected for deletion');
70
+ return;
71
+ }
26
72
 
27
73
  const skipConfirm = opts?.confirm === true;
28
74
 
@@ -30,25 +76,36 @@ export const deleteSubcommand = createSubcommand({
30
76
  tui.fatal('no TTY and --confirm is false');
31
77
  }
32
78
 
79
+ // Confirm deletion
33
80
  if (!skipConfirm) {
34
- const ok = await tui.confirm('Are you sure you want to delete', false);
35
- if (!ok) {
81
+ const projectNames = projectIds.join(', ');
82
+ tui.warning(`You are about to delete: ${tui.bold(projectNames)}`);
83
+
84
+ const confirm = await enquirer.prompt<{ confirm: boolean }>({
85
+ type: 'confirm',
86
+ name: 'confirm',
87
+ message: `Are you sure you want to delete ${projectIds.length > 1 ? 'these projects' : 'this project'}?`,
88
+ initial: false,
89
+ });
90
+
91
+ if (!confirm.confirm) {
92
+ tui.info('Deletion cancelled');
36
93
  return;
37
94
  }
38
95
  }
39
96
 
40
- const deleted = await tui.spinner('Deleting project', async () => {
41
- const val = await projectDelete(client!, args.id);
42
- if (val.length === 1 && val[0] === args.id) {
43
- return true;
44
- }
45
- return false;
97
+ const deleted = await tui.spinner({
98
+ message: `Deleting ${projectIds.length} project(s)`,
99
+ clearOnSuccess: true,
100
+ callback: async () => {
101
+ return projectDelete(apiClient, ...projectIds);
102
+ },
46
103
  });
47
104
 
48
- if (deleted) {
49
- tui.success(`Project ${args.id} deleted`);
105
+ if (deleted.length > 0) {
106
+ tui.success(`Deleted ${deleted.length} project(s): ${deleted.join(', ')}`);
50
107
  } else {
51
- tui.warning(`${args.id} not found`);
108
+ tui.error('Failed to delete projects');
52
109
  }
53
110
  },
54
111
  });
@@ -250,11 +250,11 @@ export async function setupProject(options: SetupOptions): Promise<void> {
250
250
  clearOnSuccess: true,
251
251
  });
252
252
 
253
- // Create initial commit
253
+ // Create initial commit (disable GPG signing to avoid lock issues)
254
254
  await tui.runCommand({
255
255
  command: 'git commit -m "Initial Setup"',
256
256
  cwd: dest,
257
- cmd: ['git', 'commit', '-m', 'Initial Setup'],
257
+ cmd: ['git', '-c', 'commit.gpgsign=false', 'commit', '-m', 'Initial Setup'],
258
258
  clearOnSuccess: true,
259
259
  });
260
260
  }