@guildai/cli 0.3.16 → 0.3.18

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 (69) hide show
  1. package/dist/commands/agent/clone.js +22 -67
  2. package/dist/commands/agent/code.js +12 -32
  3. package/dist/commands/agent/create.js +14 -30
  4. package/dist/commands/agent/fork.js +27 -73
  5. package/dist/commands/agent/get.js +5 -4
  6. package/dist/commands/agent/grep.js +7 -9
  7. package/dist/commands/agent/init.js +2 -0
  8. package/dist/commands/agent/list.js +5 -6
  9. package/dist/commands/agent/publish.js +27 -44
  10. package/dist/commands/agent/pull.js +8 -35
  11. package/dist/commands/agent/revalidate.js +8 -16
  12. package/dist/commands/agent/save.js +30 -76
  13. package/dist/commands/agent/search.js +5 -6
  14. package/dist/commands/agent/tags/add.js +14 -24
  15. package/dist/commands/agent/tags/list.js +12 -23
  16. package/dist/commands/agent/tags/remove.js +16 -27
  17. package/dist/commands/agent/tags/set.js +14 -19
  18. package/dist/commands/agent/unpublish.js +12 -17
  19. package/dist/commands/agent/update.js +12 -29
  20. package/dist/commands/agent/versions.js +13 -11
  21. package/dist/commands/agent/workspaces.d.ts +3 -0
  22. package/dist/commands/agent/workspaces.js +51 -0
  23. package/dist/commands/auth/login.js +4 -2
  24. package/dist/commands/auth/logout.js +3 -1
  25. package/dist/commands/auth/status.js +4 -3
  26. package/dist/commands/auth/token.js +3 -2
  27. package/dist/commands/config/get.js +7 -9
  28. package/dist/commands/config/list.js +13 -11
  29. package/dist/commands/config/path.js +6 -4
  30. package/dist/commands/config/set.js +17 -22
  31. package/dist/commands/doctor.js +9 -7
  32. package/dist/commands/session/create.js +7 -5
  33. package/dist/commands/session/events.js +5 -3
  34. package/dist/commands/session/get.js +5 -3
  35. package/dist/commands/session/list.js +5 -4
  36. package/dist/commands/session/send.js +7 -5
  37. package/dist/commands/session/tasks.js +5 -3
  38. package/dist/commands/setup.js +15 -14
  39. package/dist/commands/trigger/activate.js +7 -6
  40. package/dist/commands/trigger/create.js +16 -15
  41. package/dist/commands/trigger/deactivate.js +7 -6
  42. package/dist/commands/trigger/get.js +5 -4
  43. package/dist/commands/trigger/list.js +5 -5
  44. package/dist/commands/trigger/sessions.js +7 -6
  45. package/dist/commands/trigger/update.js +11 -10
  46. package/dist/commands/version.js +7 -5
  47. package/dist/commands/workspace/agent/add.js +16 -22
  48. package/dist/commands/workspace/agent/list.js +12 -32
  49. package/dist/commands/workspace/agent/remove.js +9 -15
  50. package/dist/commands/workspace/context/edit.js +13 -27
  51. package/dist/commands/workspace/context/get.js +8 -14
  52. package/dist/commands/workspace/context/list.js +12 -37
  53. package/dist/commands/workspace/context/publish.js +7 -11
  54. package/dist/commands/workspace/create.js +7 -11
  55. package/dist/commands/workspace/current.js +19 -31
  56. package/dist/commands/workspace/get.js +7 -11
  57. package/dist/commands/workspace/list.js +5 -8
  58. package/dist/commands/workspace/select.js +17 -22
  59. package/dist/index.js +2 -0
  60. package/dist/lib/agent-helpers.js +2 -2
  61. package/dist/lib/generated-types.d.ts +1 -1
  62. package/dist/lib/generated-types.js +1 -0
  63. package/dist/lib/npmrc.js +9 -1
  64. package/dist/lib/output.d.ts +18 -4
  65. package/dist/lib/output.js +112 -19
  66. package/docs/getting-started.md +1 -1
  67. package/docs/output-format.md +1 -1
  68. package/docs/skills/agent-dev.md +18 -17
  69. package/package.json +1 -1
@@ -1,13 +1,14 @@
1
1
  // Copyright (c) 2026 Guild.ai All Rights Reserved
2
2
  import { Command } from 'commander';
3
- import chalk from 'chalk';
4
3
  import { getAuthToken } from '../../lib/auth.js';
4
+ import { createOutputWriter } from '../../lib/output.js';
5
5
  export function createAuthTokenCommand() {
6
6
  const cmd = new Command('token');
7
7
  cmd.description('Print auth token to stdout (for scripting)').action(async () => {
8
+ const output = createOutputWriter();
8
9
  const token = await getAuthToken();
9
10
  if (!token) {
10
- console.error(chalk.red('Not authenticated. Run: guild auth login'));
11
+ output.error('Not authenticated. Run: guild auth login');
11
12
  process.exit(1);
12
13
  }
13
14
  console.log(token);
@@ -2,6 +2,7 @@
2
2
  import { Command } from 'commander';
3
3
  import { loadConfig, } from '../../lib/guild-config.js';
4
4
  import { getOutputMode } from '../../lib/output-mode.js';
5
+ import { createOutputWriter } from '../../lib/output.js';
5
6
  /**
6
7
  * All valid config keys across global and local configs.
7
8
  * Note: default_workspace_name is internal (auto-resolved from API).
@@ -21,14 +22,11 @@ export function createConfigGetCommand() {
21
22
  .description('Get a configuration value')
22
23
  .argument('<key>', `Config key (${ALL_VALID_KEYS.join(', ')})`)
23
24
  .action(async (key) => {
25
+ const output = createOutputWriter();
24
26
  const config = await loadConfig();
25
27
  const mode = getOutputMode();
26
28
  if (!ALL_VALID_KEYS.includes(key)) {
27
- console.error(`Unknown config key: ${key}`);
28
- console.error('');
29
- console.error('Valid keys:');
30
- console.error(` Global: ${VALID_GLOBAL_KEYS.join(', ')}`);
31
- console.error(` Local: ${VALID_LOCAL_KEYS.join(', ')}`);
29
+ output.error(`Unknown config key: ${key}\n\nValid keys:\n Global: ${VALID_GLOBAL_KEYS.join(', ')}\n Local: ${VALID_LOCAL_KEYS.join(', ')}`);
32
30
  process.exit(1);
33
31
  }
34
32
  // Look up in global first, then local
@@ -46,18 +44,18 @@ export function createConfigGetCommand() {
46
44
  }
47
45
  if (value === undefined) {
48
46
  if (mode === 'json') {
49
- console.log(JSON.stringify({ key, value: null, source: null }));
47
+ output.data({ key, value: null, source: null });
50
48
  }
51
49
  else {
52
- console.error(`Key not found: ${key}`);
50
+ output.error(`Key not found: ${key}`);
53
51
  }
54
52
  process.exit(1);
55
53
  }
56
54
  if (mode === 'json') {
57
- console.log(JSON.stringify({ key, value, source }, null, 2));
55
+ output.data({ key, value, source });
58
56
  }
59
57
  else {
60
- console.log(value);
58
+ output.data(value);
61
59
  }
62
60
  });
63
61
  return cmd;
@@ -3,39 +3,41 @@ import { Command } from 'commander';
3
3
  import chalk from 'chalk';
4
4
  import { loadConfig } from '../../lib/guild-config.js';
5
5
  import { getOutputMode } from '../../lib/output-mode.js';
6
+ import { createOutputWriter } from '../../lib/output.js';
6
7
  export function createConfigListCommand() {
7
8
  const cmd = new Command('list');
8
9
  cmd.description('Show all configuration values').action(async () => {
10
+ const output = createOutputWriter();
9
11
  const config = await loadConfig();
10
12
  const mode = getOutputMode();
11
13
  if (mode === 'json') {
12
- console.log(JSON.stringify({
14
+ output.data({
13
15
  global: config.global || null,
14
16
  local: config.local || null,
15
- }, null, 2));
17
+ });
16
18
  return;
17
19
  }
18
20
  const hasGlobal = config.global && Object.keys(config.global).length > 0;
19
21
  const hasLocal = config.local && Object.keys(config.local).length > 0;
20
22
  if (!hasGlobal && !hasLocal) {
21
- console.log('No configuration found.');
22
- console.log('');
23
- console.log('Set a default workspace:');
24
- console.log(chalk.dim(' guild workspace select'));
23
+ output.progress('No configuration found.');
24
+ output.progress('');
25
+ output.progress('Set a default workspace:');
26
+ output.progress(chalk.dim(' guild workspace select'));
25
27
  return;
26
28
  }
27
29
  if (hasGlobal) {
28
- console.log(chalk.bold('Global config') + chalk.dim(' (~/.guild/config.json):'));
30
+ output.progress(chalk.bold('Global config') + chalk.dim(' (~/.guild/config.json):'));
29
31
  for (const [key, value] of Object.entries(config.global)) {
30
- console.log(` ${key}: ${chalk.cyan(String(value))}`);
32
+ output.progress(` ${key}: ${chalk.cyan(String(value))}`);
31
33
  }
32
34
  }
33
35
  if (hasLocal) {
34
36
  if (hasGlobal)
35
- console.log('');
36
- console.log(chalk.bold('Local config') + chalk.dim(' (guild.json):'));
37
+ output.progress('');
38
+ output.progress(chalk.bold('Local config') + chalk.dim(' (guild.json):'));
37
39
  for (const [key, value] of Object.entries(config.local)) {
38
- console.log(` ${key}: ${chalk.cyan(String(value))}`);
40
+ output.progress(` ${key}: ${chalk.cyan(String(value))}`);
39
41
  }
40
42
  }
41
43
  });
@@ -4,6 +4,7 @@ import chalk from 'chalk';
4
4
  import * as fs from 'fs/promises';
5
5
  import { getGlobalConfigPath, getLocalConfigPath } from '../../lib/guild-config.js';
6
6
  import { getOutputMode } from '../../lib/output-mode.js';
7
+ import { createOutputWriter } from '../../lib/output.js';
7
8
  async function fileExists(filePath) {
8
9
  return fs
9
10
  .access(filePath)
@@ -13,22 +14,23 @@ async function fileExists(filePath) {
13
14
  export function createConfigPathCommand() {
14
15
  const cmd = new Command('path');
15
16
  cmd.description('Show configuration file paths').action(async () => {
17
+ const output = createOutputWriter();
16
18
  const globalPath = getGlobalConfigPath();
17
19
  const localPath = getLocalConfigPath();
18
20
  const mode = getOutputMode();
19
21
  const globalExists = await fileExists(globalPath);
20
22
  const localExists = await fileExists(localPath);
21
23
  if (mode === 'json') {
22
- console.log(JSON.stringify({
24
+ output.data({
23
25
  global: { path: globalPath, exists: globalExists },
24
26
  local: { path: localPath, exists: localExists },
25
- }, null, 2));
27
+ });
26
28
  return;
27
29
  }
28
30
  const globalStatus = globalExists ? chalk.green('exists') : chalk.dim('not found');
29
31
  const localStatus = localExists ? chalk.green('exists') : chalk.dim('not found');
30
- console.log(`Global: ${globalPath} (${globalStatus})`);
31
- console.log(`Local: ${localPath} (${localStatus})`);
32
+ output.progress(`Global: ${globalPath} (${globalStatus})`);
33
+ output.progress(`Local: ${localPath} (${localStatus})`);
32
34
  });
33
35
  return cmd;
34
36
  }
@@ -3,6 +3,7 @@ import { Command } from 'commander';
3
3
  import chalk from 'chalk';
4
4
  import { saveGlobalConfig } from '../../lib/guild-config.js';
5
5
  import { getOutputMode } from '../../lib/output-mode.js';
6
+ import { createOutputWriter } from '../../lib/output.js';
6
7
  import { GuildAPIClient } from '../../lib/api-client.js';
7
8
  import { debug } from '../../lib/errors.js';
8
9
  /**
@@ -19,15 +20,13 @@ const VALID_GLOBAL_KEYS = [
19
20
  const BOOLEAN_KEYS = new Set(['debug', 'json', 'quiet']);
20
21
  const TRUTHY = new Set(['true', 'yes', 'on', '1']);
21
22
  const FALSY = new Set(['false', 'no', 'off', '0']);
22
- function parseBoolean(value, key) {
23
+ function parseBoolean(value, key, output) {
23
24
  const lower = value.toLowerCase();
24
25
  if (TRUTHY.has(lower))
25
26
  return true;
26
27
  if (FALSY.has(lower))
27
28
  return false;
28
- console.error(`Invalid boolean value for "${key}": "${value}"`);
29
- console.error('');
30
- console.error('Accepted values: true/false, yes/no, on/off, 1/0');
29
+ output.error(`Invalid boolean value for "${key}": "${value}"\n\nAccepted values: true/false, yes/no, on/off, 1/0`);
31
30
  process.exit(1);
32
31
  }
33
32
  /**
@@ -66,12 +65,12 @@ async function resolveOwnerName(ownerId) {
66
65
  return undefined;
67
66
  }
68
67
  }
69
- function printResult(key, value, mode) {
68
+ function printResult(key, value, mode, output) {
70
69
  if (mode === 'json') {
71
- console.log(JSON.stringify({ key, value }, null, 2));
70
+ output.data({ key, value });
72
71
  }
73
72
  else {
74
- console.log(`Set ${chalk.bold(key)} = ${chalk.cyan(String(value))}`);
73
+ output.success(`Set ${chalk.bold(key)} = ${chalk.cyan(String(value))}`);
75
74
  }
76
75
  }
77
76
  export function createConfigSetCommand() {
@@ -81,21 +80,17 @@ export function createConfigSetCommand() {
81
80
  .argument('<key>', `Config key (${VALID_GLOBAL_KEYS.join(', ')})`)
82
81
  .argument('<value>', 'Value to set')
83
82
  .action(async (key, value) => {
83
+ const output = createOutputWriter();
84
84
  const mode = getOutputMode();
85
85
  if (!VALID_GLOBAL_KEYS.includes(key)) {
86
- console.error(`Unknown config key: ${key}`);
87
- console.error('');
88
- console.error('Valid keys:');
89
- for (const k of VALID_GLOBAL_KEYS) {
90
- console.error(` ${k}`);
91
- }
86
+ output.error(`Unknown config key: ${key}\n\nValid keys:\n${VALID_GLOBAL_KEYS.map((k) => ` ${k}`).join('\n')}`);
92
87
  process.exit(1);
93
88
  }
94
89
  const typedKey = key;
95
90
  if (BOOLEAN_KEYS.has(typedKey)) {
96
- const boolValue = parseBoolean(value, key);
91
+ const boolValue = parseBoolean(value, key, output);
97
92
  await saveGlobalConfig({ [typedKey]: boolValue });
98
- printResult(key, boolValue, mode);
93
+ printResult(key, boolValue, mode, output);
99
94
  return;
100
95
  }
101
96
  if (typedKey === 'default_workspace') {
@@ -104,15 +99,15 @@ export function createConfigSetCommand() {
104
99
  default_workspace: value,
105
100
  default_workspace_name: name,
106
101
  });
107
- printResult(key, value, mode);
102
+ printResult(key, value, mode, output);
108
103
  if (name) {
109
104
  if (mode !== 'json') {
110
- console.log(chalk.dim(` Workspace name: ${name}`));
105
+ output.progress(` Workspace name: ${name}`);
111
106
  }
112
107
  }
113
108
  else {
114
109
  if (mode !== 'json') {
115
- console.error(chalk.dim(' Could not resolve workspace name (not authenticated?)'));
110
+ output.error('Could not resolve workspace name (not authenticated?)');
116
111
  }
117
112
  }
118
113
  return;
@@ -123,21 +118,21 @@ export function createConfigSetCommand() {
123
118
  default_owner: value,
124
119
  default_owner_name: name,
125
120
  });
126
- printResult(key, value, mode);
121
+ printResult(key, value, mode, output);
127
122
  if (name) {
128
123
  if (mode !== 'json') {
129
- console.log(chalk.dim(` Owner name: ${name}`));
124
+ output.progress(` Owner name: ${name}`);
130
125
  }
131
126
  }
132
127
  else {
133
128
  if (mode !== 'json') {
134
- console.error(chalk.dim(' Could not resolve owner name (not authenticated?)'));
129
+ output.error('Could not resolve owner name (not authenticated?)');
135
130
  }
136
131
  }
137
132
  return;
138
133
  }
139
134
  await saveGlobalConfig({ [typedKey]: value });
140
- printResult(key, value, mode);
135
+ printResult(key, value, mode, output);
141
136
  });
142
137
  return cmd;
143
138
  }
@@ -6,6 +6,7 @@ import { getAuthToken } from '../lib/auth.js';
6
6
  import { getGuildcoreUrl } from '../lib/config.js';
7
7
  import { loadGlobalConfig, isAgentDirectory, getGlobalConfigPath, loadLocalConfig, } from '../lib/guild-config.js';
8
8
  import { getOutputMode } from '../lib/output-mode.js';
9
+ import { createOutputWriter } from '../lib/output.js';
9
10
  async function checkAuth() {
10
11
  const token = await getAuthToken();
11
12
  if (token) {
@@ -175,10 +176,11 @@ async function checkGit() {
175
176
  export function createDoctorCommand() {
176
177
  const cmd = new Command('doctor');
177
178
  cmd.description('Check CLI setup and diagnose issues').action(async () => {
179
+ const output = createOutputWriter();
178
180
  const mode = getOutputMode();
179
181
  const checks = [];
180
182
  if (mode !== 'json') {
181
- console.log('\nChecking Guild CLI setup...\n');
183
+ output.progress('\nChecking Guild CLI setup...\n');
182
184
  }
183
185
  const runners = [
184
186
  checkAuth,
@@ -199,10 +201,10 @@ export function createDoctorCommand() {
199
201
  ? chalk.red('✗')
200
202
  : chalk.dim('-');
201
203
  const nameCol = result.name.padEnd(20);
202
- console.log(` ${icon} ${chalk.bold(nameCol)} ${result.message}`);
204
+ output.progress(` ${icon} ${chalk.bold(nameCol)} ${result.message}`);
203
205
  if (result.suggestion) {
204
- console.log(` ${chalk.dim(result.suggestion)}`);
205
- console.log('');
206
+ output.progress(` ${chalk.dim(result.suggestion)}`);
207
+ output.progress('');
206
208
  }
207
209
  }
208
210
  }
@@ -210,10 +212,10 @@ export function createDoctorCommand() {
210
212
  const failed = checks.filter((c) => c.status === 'fail').length;
211
213
  const skipped = checks.filter((c) => c.status === 'skip').length;
212
214
  if (mode === 'json') {
213
- console.log(JSON.stringify({ checks, passed, failed, skipped }, null, 2));
215
+ output.data({ checks, passed, failed, skipped });
214
216
  }
215
217
  else {
216
- console.log('');
218
+ output.progress('');
217
219
  const parts = [];
218
220
  if (passed > 0)
219
221
  parts.push(chalk.green(`${passed} passed`));
@@ -221,7 +223,7 @@ export function createDoctorCommand() {
221
223
  parts.push(chalk.red(`${failed} failed`));
222
224
  if (skipped > 0)
223
225
  parts.push(chalk.dim(`${skipped} skipped`));
224
- console.log(parts.join(', '));
226
+ output.progress(parts.join(', '));
225
227
  }
226
228
  process.exit(failed > 0 ? 1 : 0);
227
229
  });
@@ -4,6 +4,7 @@ import { GuildAPIClient } from '../../lib/api-client.js';
4
4
  import { getAuthToken } from '../../lib/auth.js';
5
5
  import { getWorkspaceId } from '../../lib/guild-config.js';
6
6
  import { handleAxiosError } from '../../lib/errors.js';
7
+ import { createOutputWriter } from '../../lib/output.js';
7
8
  export function createSessionCreateCommand() {
8
9
  const cmd = new Command('create');
9
10
  cmd
@@ -13,21 +14,22 @@ export function createSessionCreateCommand() {
13
14
  .option('--prompt <text>', 'Initial prompt (required for chat sessions)')
14
15
  .option('--agent <identifier>', 'Agent identifier, e.g., owner/agent-name')
15
16
  .action(async (options) => {
17
+ const output = createOutputWriter();
16
18
  try {
17
19
  const token = await getAuthToken();
18
20
  if (!token) {
19
- console.error('Not authenticated. Run: guild auth login');
21
+ output.error('Not authenticated. Run: guild auth login');
20
22
  process.exit(1);
21
23
  }
22
24
  if (options.type === 'chat' && !options.prompt) {
23
- console.error('Error: --prompt is required for chat sessions');
25
+ output.error('--prompt is required for chat sessions');
24
26
  process.exit(1);
25
27
  }
26
28
  let workspaceId = options.workspace;
27
29
  if (!workspaceId) {
28
30
  const resolved = await getWorkspaceId();
29
31
  if (!resolved) {
30
- console.error('No workspace specified. Run: guild workspace select');
32
+ output.error('No workspace specified. Run: guild workspace select');
31
33
  process.exit(1);
32
34
  }
33
35
  workspaceId = resolved.workspaceId;
@@ -43,11 +45,11 @@ export function createSessionCreateCommand() {
43
45
  body.agent_id = options.agent;
44
46
  }
45
47
  const response = await client.post(`/workspaces/${workspaceId}/sessions`, body);
46
- console.log(JSON.stringify(response, null, 2));
48
+ output.data(response);
47
49
  }
48
50
  catch (error) {
49
51
  const formattedError = handleAxiosError(error);
50
- console.error(`Failed to create session: ${formattedError.details}`);
52
+ output.error(`Failed to create session: ${formattedError.details}`);
51
53
  process.exit(1);
52
54
  }
53
55
  });
@@ -3,6 +3,7 @@ import { Command } from 'commander';
3
3
  import { GuildAPIClient } from '../../lib/api-client.js';
4
4
  import { getAuthToken } from '../../lib/auth.js';
5
5
  import { handleAxiosError } from '../../lib/errors.js';
6
+ import { createOutputWriter } from '../../lib/output.js';
6
7
  export function createSessionEventsCommand() {
7
8
  const cmd = new Command('events');
8
9
  cmd
@@ -12,10 +13,11 @@ export function createSessionEventsCommand() {
12
13
  .option('--limit <number>', 'Number of results to return', '100')
13
14
  .option('--offset <number>', 'Offset for pagination', '0')
14
15
  .action(async (sessionId, options) => {
16
+ const output = createOutputWriter();
15
17
  try {
16
18
  const token = await getAuthToken();
17
19
  if (!token) {
18
- console.error('Not authenticated. Run: guild auth login');
20
+ output.error('Not authenticated. Run: guild auth login');
19
21
  process.exit(1);
20
22
  }
21
23
  const client = new GuildAPIClient();
@@ -26,11 +28,11 @@ export function createSessionEventsCommand() {
26
28
  params.append('types', options.types);
27
29
  }
28
30
  const response = await client.get(`/sessions/${sessionId}/events?${params.toString()}`);
29
- console.log(JSON.stringify(response, null, 2));
31
+ output.data(response);
30
32
  }
31
33
  catch (error) {
32
34
  const formattedError = handleAxiosError(error);
33
- console.error(`Failed to get session events: ${formattedError.details}`);
35
+ output.error(`Failed to get session events: ${formattedError.details}`);
34
36
  process.exit(1);
35
37
  }
36
38
  });
@@ -3,25 +3,27 @@ import { Command } from 'commander';
3
3
  import { GuildAPIClient } from '../../lib/api-client.js';
4
4
  import { getAuthToken } from '../../lib/auth.js';
5
5
  import { handleAxiosError } from '../../lib/errors.js';
6
+ import { createOutputWriter } from '../../lib/output.js';
6
7
  export function createSessionGetCommand() {
7
8
  const cmd = new Command('get');
8
9
  cmd
9
10
  .description('Get session details')
10
11
  .argument('<session-id>', 'Session ID')
11
12
  .action(async (sessionId) => {
13
+ const output = createOutputWriter();
12
14
  try {
13
15
  const token = await getAuthToken();
14
16
  if (!token) {
15
- console.error('Not authenticated. Run: guild auth login');
17
+ output.error('Not authenticated. Run: guild auth login');
16
18
  process.exit(1);
17
19
  }
18
20
  const client = new GuildAPIClient();
19
21
  const response = await client.get(`/sessions/${sessionId}`);
20
- console.log(JSON.stringify(response, null, 2));
22
+ output.data(response);
21
23
  }
22
24
  catch (error) {
23
25
  const formattedError = handleAxiosError(error);
24
- console.error(`Failed to get session: ${formattedError.details}`);
26
+ output.error(`Failed to get session: ${formattedError.details}`);
25
27
  process.exit(1);
26
28
  }
27
29
  });
@@ -5,7 +5,7 @@ import { getAuthToken } from '../../lib/auth.js';
5
5
  import { getWorkspaceId } from '../../lib/guild-config.js';
6
6
  import { handleAxiosError } from '../../lib/errors.js';
7
7
  import { getOutputMode } from '../../lib/output-mode.js';
8
- import { formatSessionTable } from '../../lib/output.js';
8
+ import { createOutputWriter, formatSessionTable } from '../../lib/output.js';
9
9
  export function createSessionListCommand() {
10
10
  const cmd = new Command('list');
11
11
  cmd
@@ -15,17 +15,18 @@ export function createSessionListCommand() {
15
15
  .option('--limit <number>', 'Number of results to return', '20')
16
16
  .option('--offset <number>', 'Offset for pagination', '0')
17
17
  .action(async (options) => {
18
+ const output = createOutputWriter();
18
19
  try {
19
20
  const token = await getAuthToken();
20
21
  if (!token) {
21
- console.error('Not authenticated. Run: guild auth login');
22
+ output.error('Not authenticated. Run: guild auth login');
22
23
  process.exit(1);
23
24
  }
24
25
  let workspaceId = options.workspace;
25
26
  if (!workspaceId) {
26
27
  const resolved = await getWorkspaceId();
27
28
  if (!resolved) {
28
- console.error('No workspace specified. Run: guild workspace select');
29
+ output.error('No workspace specified. Run: guild workspace select');
29
30
  process.exit(1);
30
31
  }
31
32
  workspaceId = resolved.workspaceId;
@@ -47,7 +48,7 @@ export function createSessionListCommand() {
47
48
  }
48
49
  catch (error) {
49
50
  const formattedError = handleAxiosError(error);
50
- console.error(`Failed to list sessions: ${formattedError.details}`);
51
+ output.error(`Failed to list sessions: ${formattedError.details}`);
51
52
  process.exit(1);
52
53
  }
53
54
  });
@@ -3,6 +3,7 @@ import { Command } from 'commander';
3
3
  import { GuildAPIClient } from '../../lib/api-client.js';
4
4
  import { getAuthToken } from '../../lib/auth.js';
5
5
  import { handleAxiosError } from '../../lib/errors.js';
6
+ import { createOutputWriter } from '../../lib/output.js';
6
7
  export function createSessionSendCommand() {
7
8
  const cmd = new Command('send');
8
9
  cmd
@@ -11,14 +12,15 @@ export function createSessionSendCommand() {
11
12
  .option('--message <text>', 'Text message content')
12
13
  .option('--json <json>', 'JSON content object (sets mode to json)')
13
14
  .action(async (sessionId, options) => {
15
+ const output = createOutputWriter();
14
16
  try {
15
17
  const token = await getAuthToken();
16
18
  if (!token) {
17
- console.error('Not authenticated. Run: guild auth login');
19
+ output.error('Not authenticated. Run: guild auth login');
18
20
  process.exit(1);
19
21
  }
20
22
  if (!options.message && !options.json) {
21
- console.error('Error: Either --message or --json is required');
23
+ output.error('Either --message or --json is required');
22
24
  process.exit(1);
23
25
  }
24
26
  const client = new GuildAPIClient();
@@ -29,7 +31,7 @@ export function createSessionSendCommand() {
29
31
  parsed = JSON.parse(options.json);
30
32
  }
31
33
  catch {
32
- console.error('Error: --json value must be valid JSON');
34
+ output.error('--json value must be valid JSON');
33
35
  process.exit(1);
34
36
  }
35
37
  body = { content: parsed, mode: 'json' };
@@ -38,11 +40,11 @@ export function createSessionSendCommand() {
38
40
  body = { content: options.message, mode: 'text' };
39
41
  }
40
42
  const response = await client.post(`/sessions/${sessionId}/events`, body);
41
- console.log(JSON.stringify(response, null, 2));
43
+ output.data(response);
42
44
  }
43
45
  catch (error) {
44
46
  const formattedError = handleAxiosError(error);
45
- console.error(`Failed to send message: ${formattedError.details}`);
47
+ output.error(`Failed to send message: ${formattedError.details}`);
46
48
  process.exit(1);
47
49
  }
48
50
  });
@@ -3,6 +3,7 @@ import { Command } from 'commander';
3
3
  import { GuildAPIClient } from '../../lib/api-client.js';
4
4
  import { getAuthToken } from '../../lib/auth.js';
5
5
  import { handleAxiosError } from '../../lib/errors.js';
6
+ import { createOutputWriter } from '../../lib/output.js';
6
7
  export function createSessionTasksCommand() {
7
8
  const cmd = new Command('tasks');
8
9
  cmd
@@ -11,10 +12,11 @@ export function createSessionTasksCommand() {
11
12
  .option('--limit <number>', 'Number of results to return', '100')
12
13
  .option('--offset <number>', 'Offset for pagination', '0')
13
14
  .action(async (sessionId, options) => {
15
+ const output = createOutputWriter();
14
16
  try {
15
17
  const token = await getAuthToken();
16
18
  if (!token) {
17
- console.error('Not authenticated. Run: guild auth login');
19
+ output.error('Not authenticated. Run: guild auth login');
18
20
  process.exit(1);
19
21
  }
20
22
  const client = new GuildAPIClient();
@@ -22,11 +24,11 @@ export function createSessionTasksCommand() {
22
24
  params.append('limit', options.limit);
23
25
  params.append('offset', options.offset);
24
26
  const response = await client.get(`/sessions/${sessionId}/tasks?${params.toString()}`);
25
- console.log(JSON.stringify(response, null, 2));
27
+ output.data(response);
26
28
  }
27
29
  catch (error) {
28
30
  const formattedError = handleAxiosError(error);
29
- console.error(`Failed to get session tasks: ${formattedError.details}`);
31
+ output.error(`Failed to get session tasks: ${formattedError.details}`);
30
32
  process.exit(1);
31
33
  }
32
34
  });
@@ -3,7 +3,7 @@ import { Command } from 'commander';
3
3
  import { fileURLToPath } from 'url';
4
4
  import path from 'path';
5
5
  import fs from 'fs/promises';
6
- import { format } from '../lib/progress.js';
6
+ import { createOutputWriter } from '../lib/output.js';
7
7
  // Resolve the CLI package root from the compiled JS location
8
8
  // dist/commands/setup.js -> dist/ -> cli/
9
9
  const __filename = fileURLToPath(import.meta.url);
@@ -47,14 +47,15 @@ async function fileExists(filePath) {
47
47
  }
48
48
  }
49
49
  async function setup(options) {
50
+ const output = createOutputWriter();
50
51
  // Verify source docs exist
51
52
  const docsExist = await fileExists(path.join(docsDir, 'skills', 'agent-dev.md'));
52
53
  if (!docsExist) {
53
- format.error('Could not find Guild CLI docs. Reinstall the CLI: npm install -g @guildai/cli');
54
+ output.error('Could not find Guild CLI docs. Reinstall the CLI: npm install -g @guildai/cli');
54
55
  process.exit(1);
55
56
  }
56
- format.info('Setting up Guild CLI skills...');
57
- console.error('');
57
+ output.progress('Setting up Guild CLI skills...');
58
+ output.progress('');
58
59
  // Ensure .claude/skills/ directory exists
59
60
  const skillsDir = path.join(process.cwd(), '.claude', 'skills');
60
61
  await fs.mkdir(skillsDir, { recursive: true });
@@ -65,17 +66,17 @@ async function setup(options) {
65
66
  const destPath = path.join(process.cwd(), file.dest);
66
67
  const exists = await fileExists(destPath);
67
68
  if (exists && !options.force) {
68
- format.warn(`${file.label} already exists (use --force to overwrite)`);
69
+ output.progress(`${file.label} already exists (use --force to overwrite)`);
69
70
  filesSkipped++;
70
71
  }
71
72
  else {
72
73
  await fs.mkdir(path.dirname(destPath), { recursive: true });
73
74
  await fs.copyFile(file.src, destPath);
74
75
  if (exists) {
75
- format.success(`Updated ${file.label}`);
76
+ output.success(`Updated ${file.label}`);
76
77
  }
77
78
  else {
78
- format.success(`Created ${file.label}`);
79
+ output.success(`Created ${file.label}`);
79
80
  }
80
81
  filesCreated++;
81
82
  }
@@ -85,30 +86,30 @@ async function setup(options) {
85
86
  const claudeMdPath = path.join(process.cwd(), 'CLAUDE.md');
86
87
  const exists = await fileExists(claudeMdPath);
87
88
  if (exists) {
88
- format.warn('CLAUDE.md already exists (not overwriting)');
89
+ output.progress('CLAUDE.md already exists (not overwriting)');
89
90
  filesSkipped++;
90
91
  }
91
92
  else {
92
93
  await fs.writeFile(claudeMdPath, CLAUDE_MD_TEMPLATE, 'utf-8');
93
- format.success('Created CLAUDE.md');
94
+ output.success('Created CLAUDE.md');
94
95
  filesCreated++;
95
96
  }
96
97
  }
97
98
  // Summary
98
- console.error('');
99
+ output.progress('');
99
100
  if (filesCreated > 0 && filesSkipped === 0) {
100
101
  if (options.force) {
101
- format.success('Guild CLI skills updated.');
102
+ output.success('Guild CLI skills updated.');
102
103
  }
103
104
  else {
104
- format.success('Guild CLI skills installed. Your coding assistant can now drive agent development.');
105
+ output.success('Guild CLI skills installed. Your coding assistant can now drive agent development.');
105
106
  }
106
107
  }
107
108
  else if (filesCreated === 0) {
108
- format.warn('No files were modified. Use --force to overwrite existing files.');
109
+ output.progress('No files were modified. Use --force to overwrite existing files.');
109
110
  }
110
111
  else {
111
- format.success('Guild CLI skills installed.');
112
+ output.success('Guild CLI skills installed.');
112
113
  }
113
114
  }
114
115
  export function createSetupCommand() {