@guildai/cli 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/commands/agent/chat.js +10 -7
  2. package/dist/commands/agent/clone.js +2 -0
  3. package/dist/commands/agent/fork.js +2 -0
  4. package/dist/commands/agent/init.js +57 -44
  5. package/dist/commands/agent/list.js +2 -2
  6. package/dist/commands/agent/logs.d.ts +3 -0
  7. package/dist/commands/agent/logs.js +62 -0
  8. package/dist/commands/agent/owners.js +3 -3
  9. package/dist/commands/agent/pull.js +8 -12
  10. package/dist/commands/agent/save.js +2 -3
  11. package/dist/commands/agent/search.js +2 -2
  12. package/dist/commands/agent/test.js +9 -6
  13. package/dist/commands/agent/update.js +9 -1
  14. package/dist/commands/agent/versions.js +2 -2
  15. package/dist/commands/agent/workspaces.js +2 -2
  16. package/dist/commands/auth/login.js +1 -3
  17. package/dist/commands/chat.js +99 -28
  18. package/dist/commands/config/get.js +4 -4
  19. package/dist/commands/config/list.js +2 -3
  20. package/dist/commands/config/path.js +2 -3
  21. package/dist/commands/config/set.js +12 -12
  22. package/dist/commands/credentials/endpoint-list.js +2 -2
  23. package/dist/commands/credentials/list.js +2 -2
  24. package/dist/commands/credentials/policy-list.js +2 -2
  25. package/dist/commands/doctor.js +5 -5
  26. package/dist/commands/integration/connect.js +2 -2
  27. package/dist/commands/integration/create.js +2 -2
  28. package/dist/commands/integration/get.js +2 -2
  29. package/dist/commands/integration/list.js +2 -2
  30. package/dist/commands/integration/operation/create.js +4 -4
  31. package/dist/commands/integration/operation/list.js +2 -2
  32. package/dist/commands/integration/update.js +2 -2
  33. package/dist/commands/integration/version/build.js +2 -2
  34. package/dist/commands/integration/version/create.js +2 -2
  35. package/dist/commands/integration/version/get.js +2 -2
  36. package/dist/commands/integration/version/list.js +2 -2
  37. package/dist/commands/integration/version/publish.js +2 -2
  38. package/dist/commands/integration/version/test.js +2 -2
  39. package/dist/commands/job/get.js +2 -2
  40. package/dist/commands/session/list.js +2 -2
  41. package/dist/commands/session/tasks.js +2 -2
  42. package/dist/commands/setup.d.ts +16 -0
  43. package/dist/commands/setup.js +76 -46
  44. package/dist/commands/trigger/list.js +2 -2
  45. package/dist/commands/workspace/agent/list.js +2 -2
  46. package/dist/commands/workspace/context/list.js +2 -2
  47. package/dist/commands/workspace/list.js +2 -2
  48. package/dist/index.js +15 -4
  49. package/dist/lib/auth.d.ts +1 -1
  50. package/dist/lib/auth.js +2 -2
  51. package/dist/lib/output-mode.d.ts +9 -2
  52. package/dist/lib/output-mode.js +23 -2
  53. package/dist/lib/output.d.ts +7 -1
  54. package/dist/lib/output.js +32 -1
  55. package/dist/lib/session-events.d.ts +13 -2
  56. package/dist/lib/session-events.js +15 -1
  57. package/dist/lib/session-polling.js +9 -3
  58. package/dist/lib/session-resume.d.ts +15 -1
  59. package/dist/lib/session-resume.js +149 -16
  60. package/dist/lib/splash.js +3 -2
  61. package/dist/lib/stdin.d.ts +5 -1
  62. package/dist/lib/stdin.js +8 -1
  63. package/dist/lib/version-helpers.js +24 -8
  64. package/package.json +1 -1
@@ -5,7 +5,7 @@ import chalk from 'chalk';
5
5
  import { GuildAPIClient } from '../../../lib/api-client.js';
6
6
  import { getAuthToken } from '../../../lib/auth.js';
7
7
  import { handleAxiosError } from '../../../lib/errors.js';
8
- import { getOutputMode } from '../../../lib/output-mode.js';
8
+ import { isMachineReadable } from '../../../lib/output-mode.js';
9
9
  import { createOutputWriter } from '../../../lib/output.js';
10
10
  import { resolveVersionId } from '../../../lib/integration-helpers.js';
11
11
  import { Table } from '../../../lib/table.js';
@@ -32,7 +32,7 @@ export function createIntegrationOperationListCommand() {
32
32
  params.append('limit', options.limit);
33
33
  params.append('offset', options.offset);
34
34
  const response = await client.get(`/integration_versions/${versionId}/endpoints?${params.toString()}`);
35
- if (getOutputMode() === 'json') {
35
+ if (isMachineReadable()) {
36
36
  output.data(response);
37
37
  }
38
38
  else {
@@ -5,7 +5,7 @@ import chalk from 'chalk';
5
5
  import { GuildAPIClient } from '../../lib/api-client.js';
6
6
  import { getAuthToken } from '../../lib/auth.js';
7
7
  import { handleAxiosError } from '../../lib/errors.js';
8
- import { getOutputMode } from '../../lib/output-mode.js';
8
+ import { isMachineReadable } from '../../lib/output-mode.js';
9
9
  import { createOutputWriter } from '../../lib/output.js';
10
10
  function formatUpdatedIntegration(integration) {
11
11
  console.log(chalk.green('Integration updated successfully'));
@@ -121,7 +121,7 @@ export function createIntegrationUpdateCommand() {
121
121
  process.exit(1);
122
122
  }
123
123
  const response = await client.patch(`/integrations/${identifier}`, body);
124
- if (getOutputMode() === 'json') {
124
+ if (isMachineReadable()) {
125
125
  output.data(response);
126
126
  }
127
127
  else {
@@ -5,7 +5,7 @@ import chalk from 'chalk';
5
5
  import { GuildAPIClient } from '../../../lib/api-client.js';
6
6
  import { getAuthToken } from '../../../lib/auth.js';
7
7
  import { handleAxiosError } from '../../../lib/errors.js';
8
- import { getOutputMode } from '../../../lib/output-mode.js';
8
+ import { isMachineReadable } from '../../../lib/output-mode.js';
9
9
  import { createOutputWriter } from '../../../lib/output.js';
10
10
  import { createSpinner } from '../../../lib/progress.js';
11
11
  import { resolveLatestDraftId } from '../../../lib/integration-helpers.js';
@@ -36,7 +36,7 @@ export function createIntegrationVersionBuildCommand() {
36
36
  const buildResponse = await client.post(`/integration_versions/${versionId}/build`, {
37
37
  version_number: options.versionNumber,
38
38
  });
39
- if (getOutputMode() === 'json') {
39
+ if (isMachineReadable()) {
40
40
  output.data(buildResponse);
41
41
  return;
42
42
  }
@@ -5,7 +5,7 @@ import chalk from 'chalk';
5
5
  import { GuildAPIClient } from '../../../lib/api-client.js';
6
6
  import { getAuthToken } from '../../../lib/auth.js';
7
7
  import { handleAxiosError } from '../../../lib/errors.js';
8
- import { getOutputMode } from '../../../lib/output-mode.js';
8
+ import { isMachineReadable } from '../../../lib/output-mode.js';
9
9
  import { createOutputWriter } from '../../../lib/output.js';
10
10
  export function createIntegrationVersionCreateCommand() {
11
11
  const cmd = new Command('create');
@@ -22,7 +22,7 @@ export function createIntegrationVersionCreateCommand() {
22
22
  }
23
23
  const client = new GuildAPIClient();
24
24
  const response = await client.post(`/integrations/${identifier}/versions`, {});
25
- if (getOutputMode() === 'json') {
25
+ if (isMachineReadable()) {
26
26
  output.data(response);
27
27
  }
28
28
  else {
@@ -5,7 +5,7 @@ import chalk from 'chalk';
5
5
  import { GuildAPIClient } from '../../../lib/api-client.js';
6
6
  import { getAuthToken } from '../../../lib/auth.js';
7
7
  import { handleAxiosError } from '../../../lib/errors.js';
8
- import { getOutputMode } from '../../../lib/output-mode.js';
8
+ import { isMachineReadable } from '../../../lib/output-mode.js';
9
9
  import { createOutputWriter } from '../../../lib/output.js';
10
10
  import { resolveVersionId } from '../../../lib/integration-helpers.js';
11
11
  function formatDate(dateStr) {
@@ -46,7 +46,7 @@ export function createIntegrationVersionGetCommand() {
46
46
  const client = new GuildAPIClient();
47
47
  const versionId = await resolveVersionId(client, identifier, options.versionNumber);
48
48
  const response = await client.get(`/integration_versions/${versionId}`);
49
- if (getOutputMode() === 'json') {
49
+ if (isMachineReadable()) {
50
50
  output.data(response);
51
51
  }
52
52
  else {
@@ -4,7 +4,7 @@ import { Command } from 'commander';
4
4
  import { GuildAPIClient } from '../../../lib/api-client.js';
5
5
  import { getAuthToken } from '../../../lib/auth.js';
6
6
  import { handleAxiosError } from '../../../lib/errors.js';
7
- import { getOutputMode } from '../../../lib/output-mode.js';
7
+ import { isMachineReadable } from '../../../lib/output-mode.js';
8
8
  import { createOutputWriter, formatIntegrationVersionTable, } from '../../../lib/output.js';
9
9
  import { DEFAULT_PAGE_LIMIT } from '../../../lib/api-types.js';
10
10
  export function createIntegrationVersionListCommand() {
@@ -27,7 +27,7 @@ export function createIntegrationVersionListCommand() {
27
27
  params.append('limit', options.limit);
28
28
  params.append('offset', options.offset);
29
29
  const response = await client.get(`/integrations/${identifier}/versions?${params.toString()}`);
30
- if (getOutputMode() === 'json') {
30
+ if (isMachineReadable()) {
31
31
  output.data(response);
32
32
  }
33
33
  else {
@@ -5,7 +5,7 @@ import chalk from 'chalk';
5
5
  import { GuildAPIClient } from '../../../lib/api-client.js';
6
6
  import { getAuthToken } from '../../../lib/auth.js';
7
7
  import { handleAxiosError } from '../../../lib/errors.js';
8
- import { getOutputMode } from '../../../lib/output-mode.js';
8
+ import { isMachineReadable } from '../../../lib/output-mode.js';
9
9
  import { createOutputWriter } from '../../../lib/output.js';
10
10
  import { createSpinner } from '../../../lib/progress.js';
11
11
  import { resolveVersionId } from '../../../lib/integration-helpers.js';
@@ -38,7 +38,7 @@ export function createIntegrationVersionPublishCommand() {
38
38
  const currentVersion = await client.get(`/integration_versions/${versionId}`);
39
39
  const versionDisplay = currentVersion.version_number || versionId;
40
40
  const publishResponse = await client.post(`/integration_versions/${versionId}/publish`, {});
41
- if (getOutputMode() === 'json') {
41
+ if (isMachineReadable()) {
42
42
  output.data(publishResponse);
43
43
  return;
44
44
  }
@@ -5,7 +5,7 @@ import chalk from 'chalk';
5
5
  import { GuildAPIClient } from '../../../lib/api-client.js';
6
6
  import { getAuthToken } from '../../../lib/auth.js';
7
7
  import { handleAxiosError } from '../../../lib/errors.js';
8
- import { getOutputMode } from '../../../lib/output-mode.js';
8
+ import { isMachineReadable } from '../../../lib/output-mode.js';
9
9
  import { createOutputWriter } from '../../../lib/output.js';
10
10
  import { resolveVersionId } from '../../../lib/integration-helpers.js';
11
11
  function parseJsonFlag(value, flagName) {
@@ -60,7 +60,7 @@ export function createIntegrationVersionTestCommand() {
60
60
  body.credential_id = creds.items[0].id;
61
61
  }
62
62
  const response = await client.post(`/integration_versions/${versionId}/test`, body);
63
- if (getOutputMode() === 'json') {
63
+ if (isMachineReadable()) {
64
64
  output.data(response);
65
65
  }
66
66
  else {
@@ -4,7 +4,7 @@ import { Command } from 'commander';
4
4
  import { GuildAPIClient } from '../../lib/api-client.js';
5
5
  import { getAuthToken } from '../../lib/auth.js';
6
6
  import { handleAxiosError } from '../../lib/errors.js';
7
- import { getOutputMode } from '../../lib/output-mode.js';
7
+ import { isMachineReadable } from '../../lib/output-mode.js';
8
8
  import { createOutputWriter, formatJobStepTable } from '../../lib/output.js';
9
9
  export function createJobGetCommand() {
10
10
  const cmd = new Command('get');
@@ -24,7 +24,7 @@ export function createJobGetCommand() {
24
24
  client.get(`/jobs/${jobId}`),
25
25
  client.get(`/jobs/${jobId}/steps`),
26
26
  ]);
27
- if (getOutputMode() === 'json') {
27
+ if (isMachineReadable()) {
28
28
  console.log(JSON.stringify({ ...job, steps: stepsResponse.steps }, null, 2));
29
29
  }
30
30
  else {
@@ -5,7 +5,7 @@ import { GuildAPIClient } from '../../lib/api-client.js';
5
5
  import { getAuthToken } from '../../lib/auth.js';
6
6
  import { getWorkspaceId } from '../../lib/guild-config.js';
7
7
  import { handleAxiosError } from '../../lib/errors.js';
8
- import { getOutputMode } from '../../lib/output-mode.js';
8
+ import { isMachineReadable } from '../../lib/output-mode.js';
9
9
  import { createOutputWriter, formatSessionTable } from '../../lib/output.js';
10
10
  import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
11
11
  export function createSessionListCommand() {
@@ -41,7 +41,7 @@ export function createSessionListCommand() {
41
41
  params.append('types', options.type.toLowerCase());
42
42
  }
43
43
  const response = await client.get(`/workspaces/${workspaceId}/sessions?${params.toString()}`);
44
- if (getOutputMode() === 'json') {
44
+ if (isMachineReadable()) {
45
45
  console.log(JSON.stringify(response, null, 2));
46
46
  }
47
47
  else {
@@ -4,7 +4,7 @@ import { Command } from 'commander';
4
4
  import { GuildAPIClient } from '../../lib/api-client.js';
5
5
  import { getAuthToken } from '../../lib/auth.js';
6
6
  import { handleAxiosError } from '../../lib/errors.js';
7
- import { getOutputMode } from '../../lib/output-mode.js';
7
+ import { isMachineReadable } from '../../lib/output-mode.js';
8
8
  import { createOutputWriter, formatTaskTable } from '../../lib/output.js';
9
9
  import { DEFAULT_PAGE_LIMIT_LARGE } from '../../lib/api-types.js';
10
10
  export function createSessionTasksCommand() {
@@ -27,7 +27,7 @@ export function createSessionTasksCommand() {
27
27
  params.append('limit', options.limit);
28
28
  params.append('offset', options.offset);
29
29
  const response = await client.get(`/sessions/${sessionId}/tasks?${params.toString()}`);
30
- if (getOutputMode() === 'json') {
30
+ if (isMachineReadable()) {
31
31
  console.log(JSON.stringify(response, null, 2));
32
32
  }
33
33
  else {
@@ -1,3 +1,19 @@
1
1
  import { Command } from 'commander';
2
+ /**
3
+ * Run setup in a target directory. Exported so init/clone can call it.
4
+ * When called with `quiet: true`, suppresses progress output (used as a
5
+ * post-init/clone step where the caller handles its own progress UI).
6
+ */
7
+ export declare function runSetup(targetDir: string, options?: {
8
+ force?: boolean;
9
+ claudeMd?: boolean;
10
+ codex?: boolean;
11
+ agentsMd?: boolean;
12
+ mcp?: boolean;
13
+ quiet?: boolean;
14
+ }): Promise<{
15
+ filesCreated: number;
16
+ filesSkipped: number;
17
+ }>;
2
18
  export declare function createSetupCommand(): Command;
3
19
  //# sourceMappingURL=setup.d.ts.map
@@ -79,9 +79,9 @@ const MCP_SERVER_CONFIG = {
79
79
  command: 'guild',
80
80
  args: ['mcp'],
81
81
  };
82
- async function setupMcp(options) {
82
+ async function setupMcp(targetDir, options) {
83
83
  const output = createOutputWriter();
84
- const mcpPath = path.join(process.cwd(), '.mcp.json');
84
+ const mcpPath = path.join(targetDir, '.mcp.json');
85
85
  let existing = {};
86
86
  const exists = await fileExists(mcpPath);
87
87
  if (exists) {
@@ -108,55 +108,74 @@ async function setupMcp(options) {
108
108
  }
109
109
  return 'created';
110
110
  }
111
- async function setup(options) {
111
+ /**
112
+ * Run setup in a target directory. Exported so init/clone can call it.
113
+ * When called with `quiet: true`, suppresses progress output (used as a
114
+ * post-init/clone step where the caller handles its own progress UI).
115
+ */
116
+ export async function runSetup(targetDir, options = {}) {
112
117
  const output = createOutputWriter();
113
- if (options.agentsMd && !options.codex) {
118
+ const force = options.force ?? false;
119
+ const claudeMd = options.claudeMd ?? false;
120
+ const codex = options.codex ?? false;
121
+ const agentsMd = options.agentsMd ?? false;
122
+ const mcp = options.mcp ?? true;
123
+ const quiet = options.quiet ?? false;
124
+ if (agentsMd && !codex) {
114
125
  output.error('--agents-md requires --codex', 'Create Codex setup files with:\n guild setup --codex --agents-md');
115
126
  process.exit(1);
116
127
  }
117
- if (options.claudeMd && options.codex) {
128
+ if (claudeMd && codex) {
118
129
  output.error('--claude-md cannot be used with --codex', 'Create Claude setup with:\n guild setup --claude-md\n\nCreate Codex setup with:\n guild setup --codex --agents-md');
119
130
  process.exit(1);
120
131
  }
121
- const skillFiles = options.codex ? CODEX_SKILL_FILES : CLAUDE_SKILL_FILES;
132
+ const skillFiles = codex ? CODEX_SKILL_FILES : CLAUDE_SKILL_FILES;
122
133
  // Verify source docs exist
123
134
  for (const file of skillFiles) {
124
135
  if (!(await fileExists(file.src))) {
125
- output.error('Could not find Guild CLI docs. Reinstall the CLI: npm install -g @guildai/cli');
126
- process.exit(1);
136
+ if (!quiet) {
137
+ output.error('Could not find Guild CLI docs. Reinstall the CLI: npm install -g @guildai/cli');
138
+ }
139
+ return { filesCreated: 0, filesSkipped: 0 };
127
140
  }
128
141
  }
129
- output.progress('Setting up Guild CLI skills...');
130
- output.progress('');
142
+ if (!quiet) {
143
+ output.progress('Setting up Guild CLI skills...');
144
+ output.progress('');
145
+ }
131
146
  let filesCreated = 0;
132
147
  let filesSkipped = 0;
133
148
  let codexProjectFilesChanged = false;
134
149
  // Copy skill files
135
150
  for (const file of skillFiles) {
136
- const destPath = path.join(process.cwd(), file.dest);
151
+ const destPath = path.join(targetDir, file.dest);
137
152
  const exists = await fileExists(destPath);
138
- if (exists && !options.force) {
139
- output.progress(`${file.label} already exists (use --force to overwrite)`);
153
+ if (exists && !force) {
154
+ if (!quiet) {
155
+ output.progress(`${file.label} already exists (use --force to overwrite)`);
156
+ }
140
157
  filesSkipped++;
141
158
  }
142
159
  else {
143
160
  await fs.mkdir(path.dirname(destPath), { recursive: true });
144
161
  await fs.copyFile(file.src, destPath);
145
- if (exists) {
146
- output.success(`Updated ${file.label}`);
147
- }
148
- else {
149
- output.success(`Created ${file.label}`);
162
+ if (!quiet) {
163
+ if (exists) {
164
+ output.success(`Updated ${file.label}`);
165
+ }
166
+ else {
167
+ output.success(`Created ${file.label}`);
168
+ }
150
169
  }
151
170
  filesCreated++;
152
- if (options.codex) {
171
+ if (codex) {
153
172
  codexProjectFilesChanged = true;
154
173
  }
155
174
  }
156
175
  }
157
- // Handle --mcp flag
158
- if (options.mcp) {
159
- const result = await setupMcp({ force: options.force });
176
+ // Handle MCP config
177
+ if (mcp) {
178
+ const result = await setupMcp(targetDir, { force });
160
179
  if (result === 'created') {
161
180
  filesCreated++;
162
181
  }
@@ -165,53 +184,64 @@ async function setup(options) {
165
184
  }
166
185
  }
167
186
  // Handle CLAUDE.md template
168
- if (options.claudeMd) {
169
- const claudeMdPath = path.join(process.cwd(), 'CLAUDE.md');
187
+ if (claudeMd) {
188
+ const claudeMdPath = path.join(targetDir, 'CLAUDE.md');
170
189
  const exists = await fileExists(claudeMdPath);
171
190
  if (exists) {
172
- output.progress('CLAUDE.md already exists (not overwriting)');
191
+ if (!quiet) {
192
+ output.progress('CLAUDE.md already exists (not overwriting)');
193
+ }
173
194
  filesSkipped++;
174
195
  }
175
196
  else {
176
197
  await fs.writeFile(claudeMdPath, CLAUDE_MD_TEMPLATE, 'utf-8');
177
- output.success('Created CLAUDE.md');
198
+ if (!quiet) {
199
+ output.success('Created CLAUDE.md');
200
+ }
178
201
  filesCreated++;
179
202
  }
180
203
  }
181
204
  // Handle AGENTS.md template for Codex setup
182
- if (options.agentsMd) {
183
- const agentsMdPath = path.join(process.cwd(), 'AGENTS.md');
205
+ if (agentsMd) {
206
+ const agentsMdPath = path.join(targetDir, 'AGENTS.md');
184
207
  const exists = await fileExists(agentsMdPath);
185
208
  if (exists) {
186
- output.progress('AGENTS.md already exists (not overwriting)');
209
+ if (!quiet) {
210
+ output.progress('AGENTS.md already exists (not overwriting)');
211
+ }
187
212
  filesSkipped++;
188
213
  }
189
214
  else {
190
215
  await fs.writeFile(agentsMdPath, AGENTS_MD_TEMPLATE, 'utf-8');
191
- output.success('Created AGENTS.md');
216
+ if (!quiet) {
217
+ output.success('Created AGENTS.md');
218
+ }
192
219
  filesCreated++;
193
220
  codexProjectFilesChanged = true;
194
221
  }
195
222
  }
196
- // Summary
197
- output.progress('');
198
- if (filesCreated > 0 && filesSkipped === 0) {
199
- if (options.force) {
200
- output.success('Guild CLI skills updated.');
223
+ // Summary (only in standalone mode)
224
+ if (!quiet) {
225
+ output.progress('');
226
+ if (filesCreated > 0 && filesSkipped === 0) {
227
+ if (force) {
228
+ output.success('Guild CLI skills updated.');
229
+ }
230
+ else {
231
+ output.success('Guild CLI skills installed. Your coding assistant can now drive agent development.');
232
+ }
233
+ }
234
+ else if (filesCreated === 0) {
235
+ output.progress('No files were modified. Use --force to overwrite existing files.');
201
236
  }
202
237
  else {
203
- output.success('Guild CLI skills installed. Your coding assistant can now drive agent development.');
238
+ output.success('Guild CLI skills installed.');
239
+ }
240
+ if (codexProjectFilesChanged) {
241
+ output.progress('Restart Codex to pick up the new project instructions.');
204
242
  }
205
243
  }
206
- else if (filesCreated === 0) {
207
- output.progress('No files were modified. Use --force to overwrite existing files.');
208
- }
209
- else {
210
- output.success('Guild CLI skills installed.');
211
- }
212
- if (codexProjectFilesChanged) {
213
- output.progress('Restart Codex to pick up the new project instructions.');
214
- }
244
+ return { filesCreated, filesSkipped };
215
245
  }
216
246
  export function createSetupCommand() {
217
247
  const cmd = new Command('setup');
@@ -223,7 +253,7 @@ export function createSetupCommand() {
223
253
  .option('--agents-md', 'With --codex, also create an AGENTS.md template in the project root', false)
224
254
  .option('--no-mcp', 'Skip MCP server configuration')
225
255
  .action(async (options) => {
226
- await setup(options);
256
+ await runSetup(process.cwd(), options);
227
257
  });
228
258
  return cmd;
229
259
  }
@@ -5,7 +5,7 @@ import { GuildAPIClient } from '../../lib/api-client.js';
5
5
  import { getAuthToken } from '../../lib/auth.js';
6
6
  import { getWorkspaceId } from '../../lib/guild-config.js';
7
7
  import { handleAxiosError } from '../../lib/errors.js';
8
- import { getOutputMode } from '../../lib/output-mode.js';
8
+ import { isMachineReadable } from '../../lib/output-mode.js';
9
9
  import { createOutputWriter, formatTriggerTable } from '../../lib/output.js';
10
10
  import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
11
11
  export function createTriggerListCommand() {
@@ -39,7 +39,7 @@ export function createTriggerListCommand() {
39
39
  params.append('limit', options.limit);
40
40
  params.append('offset', options.offset);
41
41
  const response = await client.get(`/workspaces/${workspaceId}/triggers?${params.toString()}`);
42
- if (getOutputMode() === 'json') {
42
+ if (isMachineReadable()) {
43
43
  console.log(JSON.stringify(response, null, 2));
44
44
  }
45
45
  else {
@@ -6,7 +6,7 @@ import { getAuthToken } from '../../../lib/auth.js';
6
6
  import { getWorkspaceId } from '../../../lib/guild-config.js';
7
7
  import { handleAxiosError, ErrorCodes } from '../../../lib/errors.js';
8
8
  import { createOutputWriter, formatWorkspaceAgentTable } from '../../../lib/output.js';
9
- import { getOutputMode } from '../../../lib/output-mode.js';
9
+ import { isMachineReadable } from '../../../lib/output-mode.js';
10
10
  import { resolveWorkspaceId } from '../../../lib/workspace-helpers.js';
11
11
  import { DEFAULT_PAGE_LIMIT } from '../../../lib/api-types.js';
12
12
  export function createWorkspaceAgentListCommand() {
@@ -52,7 +52,7 @@ export function createWorkspaceAgentListCommand() {
52
52
  params.append('limit', options.limit);
53
53
  params.append('offset', options.offset);
54
54
  const response = await client.get(`/workspaces/${workspaceId}/workspace_agents?${params.toString()}`);
55
- if (getOutputMode() === 'json') {
55
+ if (isMachineReadable()) {
56
56
  output.data(response);
57
57
  }
58
58
  else {
@@ -3,7 +3,7 @@
3
3
  import { Command } from 'commander';
4
4
  import { GuildAPIClient } from '../../../lib/api-client.js';
5
5
  import { handleAxiosError, ErrorCodes } from '../../../lib/errors.js';
6
- import { getOutputMode } from '../../../lib/output-mode.js';
6
+ import { isMachineReadable } from '../../../lib/output-mode.js';
7
7
  import { createOutputWriter, formatContextTable } from '../../../lib/output.js';
8
8
  import { DEFAULT_PAGE_LIMIT } from '../../../lib/api-types.js';
9
9
  export function createWorkspaceContextListCommand() {
@@ -21,7 +21,7 @@ export function createWorkspaceContextListCommand() {
21
21
  params.append('limit', options.limit);
22
22
  params.append('offset', options.offset);
23
23
  const response = await client.get(`/workspaces/${workspaceId}/contexts?${params.toString()}`);
24
- if (getOutputMode() === 'json') {
24
+ if (isMachineReadable()) {
25
25
  output.data(response);
26
26
  }
27
27
  else {
@@ -3,7 +3,7 @@
3
3
  import { Command } from 'commander';
4
4
  import { GuildAPIClient } from '../../lib/api-client.js';
5
5
  import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
6
- import { getOutputMode } from '../../lib/output-mode.js';
6
+ import { isMachineReadable } from '../../lib/output-mode.js';
7
7
  import { createOutputWriter, formatWorkspaceTable } from '../../lib/output.js';
8
8
  import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
9
9
  export function createWorkspaceListCommand() {
@@ -44,7 +44,7 @@ export function createWorkspaceListCommand() {
44
44
  params.append('offset', options.offset);
45
45
  response = await client.get(`/me/workspaces?${params.toString()}`);
46
46
  }
47
- if (getOutputMode() === 'json') {
47
+ if (isMachineReadable()) {
48
48
  console.log(JSON.stringify(response, null, 2));
49
49
  }
50
50
  else {
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ import { createAgentForkCommand } from './commands/agent/fork.js';
24
24
  import { createAgentPublishCommand } from './commands/agent/publish.js';
25
25
  import { createAgentUnpublishCommand } from './commands/agent/unpublish.js';
26
26
  import { createAgentRevalidateCommand } from './commands/agent/revalidate.js';
27
+ import { createAgentLogsCommand } from './commands/agent/logs.js';
27
28
  import { createAgentSearchCommand } from './commands/agent/search.js';
28
29
  import { createAgentOwnersCommand } from './commands/agent/owners.js';
29
30
  import { createAgentWorkspacesCommand } from './commands/agent/workspaces.js';
@@ -111,8 +112,11 @@ program
111
112
  .description('Guild.ai CLI - Build, test, and deploy AI agents')
112
113
  .version(packageJson.version)
113
114
  .option('--debug', 'Enable debug mode with verbose logging')
114
- .option('--json', 'Output pure JSON format (non-interactive)')
115
+ .option('--mode <format>', 'Output format: interactive (default), json, or jsonl')
116
+ // Backward compat: --json is a hidden alias for --mode json
117
+ .addOption(new Option('--json').default(false).hideHelp())
115
118
  .option('--quiet, -q', 'Suppress progress and log messages')
119
+ .option('--non-interactive', 'Disable interactive prompts (for CI, scripts, and coding agents)')
116
120
  // Dev shortcuts — hidden from help, use env vars GUILD_USE_SHARED / GUILD_USE_LOCAL instead
117
121
  .addOption(new Option('--shared').default(false).hideHelp())
118
122
  .addOption(new Option('--local').default(false).hideHelp())
@@ -135,11 +139,13 @@ program
135
139
  .argument('[prompt...]', 'Optional initial prompt (multiple words)')
136
140
  .option('--agent <identifier>', 'Agent ID or full name, e.g., foo~bar (default: assistant)')
137
141
  .option('--once', 'One-shot mode: send message, wait for response, exit (non-interactive)')
138
- .option('--mode <format>', 'Machine-readable output format: json or jsonl')
139
142
  .option('--workspace <identifier>', 'Workspace ID or full name (e.g., owner/workspace-name)')
140
143
  .option('--no-splash', 'Skip the splash screen animation')
141
144
  .option('--resume <session-id>', 'Resume an existing session')
142
145
  .option('--events <types>', 'Event types to show (default: user). Shorthands: none, user, system, all, or comma-separated type names (e.g. agent_console,llm_start)')
146
+ // Accept --mode here so `guild chat --mode json` doesn't error.
147
+ // The actual value is read from process.argv by getOutputMode().
148
+ .addOption(new Option('--mode <format>').hideHelp())
143
149
  .addHelpText('after', '\nTo chat with a local agent under development: guild agent chat')
144
150
  .action(async (promptArgs, options) => {
145
151
  const { handleChatAction } = await import('./commands/chat.js');
@@ -170,12 +176,14 @@ agentCmd
170
176
  .argument('[prompt...]', 'Optional initial prompt for the agent')
171
177
  .option('--path <dir>', 'Path to agent directory (defaults to current directory)')
172
178
  .option('--workspace <identifier>', 'Workspace ID or full name (e.g., owner~workspace-name)')
173
- .option('--mode <format>', 'Input mode: json (one-shot) or jsonl (line-by-line)')
174
179
  .option('--agent-version <id>', 'Chat with a specific version (UUID or version number)')
175
180
  .option('--no-splash', 'Skip the splash screen animation')
176
181
  .option('--resume <session-id>', 'Resume an existing session')
177
182
  .option('--open', 'Open session in web dashboard')
178
183
  .option('--no-cache', 'Skip ephemeral build cache (force a fresh build)')
184
+ // Accept --mode here so `guild agent chat --mode json` doesn't error.
185
+ // The actual value is read from process.argv by getOutputMode().
186
+ .addOption(new Option('--mode <format>').hideHelp())
179
187
  .addHelpText('after', '\nTo chat with a published agent by name: guild chat --agent owner~agent-name')
180
188
  .action(async (promptArgs, options) => {
181
189
  const { handleAgentChatAction } = await import('./commands/agent/chat.js');
@@ -190,13 +198,15 @@ agentCmd
190
198
  .command('test')
191
199
  .description('Test agent in interactive REPL session')
192
200
  .option('--workspace <identifier>', 'Workspace ID or full name (e.g., owner/workspace-name)')
193
- .option('--mode <format>', 'Input mode: json (one-shot) or jsonl (line-by-line)')
194
201
  .option('--agent-version <id>', 'Test a specific version (UUID or version number)')
195
202
  .option('--resume <session-id>', 'Resume an existing test session')
196
203
  .option('--open', 'Open session in web dashboard')
197
204
  .option('--events <types>', 'Event types to stream (default: all). Shorthands: none, user, system, all, or comma-separated type names')
198
205
  .option('--bundle <file>', 'Path to a pre-built gzip+base64 bundle file')
199
206
  .option('--no-cache', 'Skip ephemeral build cache (force a fresh build)')
207
+ // Accept --mode here so `guild agent test --mode json` doesn't error.
208
+ // The actual value is read from process.argv by getOutputMode().
209
+ .addOption(new Option('--mode <format>').hideHelp())
200
210
  .action(async (options) => {
201
211
  const { handleAgentTestAction } = await import('./commands/agent/test.js');
202
212
  await handleAgentTestAction(options);
@@ -204,6 +214,7 @@ agentCmd
204
214
  agentCmd.addCommand(createAgentPublishCommand());
205
215
  agentCmd.addCommand(createAgentUnpublishCommand());
206
216
  agentCmd.addCommand(createAgentRevalidateCommand());
217
+ agentCmd.addCommand(createAgentLogsCommand());
207
218
  agentCmd.addCommand(createAgentSearchCommand());
208
219
  agentCmd.addCommand(createAgentOwnersCommand());
209
220
  agentCmd.addCommand(createAgentWorkspacesCommand());
@@ -46,7 +46,7 @@ export declare function pollForToken(authUrl: string, code: string, interval: nu
46
46
  * @param returnLabel - Optional friendly label for return button (e.g., "VSCode")
47
47
  * @returns true if successful, false otherwise
48
48
  */
49
- export declare function login(returnUrl?: string, returnLabel?: string, nonInteractive?: boolean): Promise<boolean>;
49
+ export declare function login(returnUrl?: string, returnLabel?: string): Promise<boolean>;
50
50
  /**
51
51
  * Perform logout
52
52
  */
package/dist/lib/auth.js CHANGED
@@ -191,12 +191,12 @@ export async function pollForToken(authUrl, code, interval) {
191
191
  * @param returnLabel - Optional friendly label for return button (e.g., "VSCode")
192
192
  * @returns true if successful, false otherwise
193
193
  */
194
- export async function login(returnUrl, returnLabel, nonInteractive) {
194
+ export async function login(returnUrl, returnLabel) {
195
195
  const authUrl = getGuildcoreUrl();
196
196
  try {
197
197
  console.log(chalk.bold('\nGuild.ai Authentication'));
198
198
  const deviceCode = await startDeviceFlow(authUrl, returnUrl, returnLabel);
199
- const skipBrowser = nonInteractive || !isInteractive();
199
+ const skipBrowser = !isInteractive();
200
200
  if (skipBrowser) {
201
201
  console.log(`\nVerification code: ${deviceCode.user_code}`);
202
202
  console.log(`Open to authenticate: ${deviceCode.verification_uri_complete}\n`);
@@ -1,11 +1,18 @@
1
- export type OutputMode = 'interactive' | 'json';
1
+ export type OutputMode = 'interactive' | 'json' | 'jsonl';
2
2
  /**
3
3
  * Detect output mode from CLI flags or config
4
4
  *
5
- * Checks --json flag and config. CLI flag overrides config.
5
+ * Priority: --mode <value> > --json (backward compat) > config
6
6
  * Does NOT auto-detect pipes (user must request JSON explicitly).
7
7
  */
8
8
  export declare function getOutputMode(): OutputMode;
9
+ /**
10
+ * Check if the current output mode is machine-readable (json or jsonl).
11
+ *
12
+ * Use this in list/get commands instead of `getOutputMode() === 'json'`
13
+ * so that both --mode json and --mode jsonl trigger non-interactive output.
14
+ */
15
+ export declare function isMachineReadable(): boolean;
9
16
  /**
10
17
  * Check if quiet mode is enabled (CLI flag or config)
11
18
  *