@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
@@ -130,6 +130,8 @@ export function createAgentInitCommand() {
130
130
  process.exit(1);
131
131
  }
132
132
  }
133
+ // Normalize template to uppercase for case-insensitive matching
134
+ template = template.toUpperCase();
133
135
  // Validate template
134
136
  const validTemplates = [
135
137
  'LLM',
@@ -3,8 +3,8 @@ 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, formatAgentTable } from '../../lib/output.js';
7
6
  import { getOutputMode } from '../../lib/output-mode.js';
7
+ import { createOutputWriter, formatAgentTable } from '../../lib/output.js';
8
8
  const SORT_MAP = {
9
9
  updated: 'updated_at',
10
10
  newest: 'created_at',
@@ -21,11 +21,11 @@ export function createAgentListCommand() {
21
21
  .option('--limit <number>', 'Number of results to return', '20')
22
22
  .option('--offset <number>', 'Offset for pagination', '0')
23
23
  .action(async (options) => {
24
+ const output = createOutputWriter();
24
25
  try {
25
26
  const token = await getAuthToken();
26
27
  if (!token) {
27
- console.error('Not authenticated. Please log in first.');
28
- console.error('Run: guild auth login');
28
+ output.error('Not authenticated. Please log in first.', 'Run: guild auth login');
29
29
  process.exit(1);
30
30
  }
31
31
  const client = new GuildAPIClient();
@@ -44,16 +44,15 @@ export function createAgentListCommand() {
44
44
  }
45
45
  const response = await client.get(`/agents?${params.toString()}`);
46
46
  if (getOutputMode() === 'json') {
47
- console.log(JSON.stringify(response, null, 2));
47
+ output.data(response);
48
48
  }
49
49
  else {
50
50
  formatAgentTable(response.items, response.pagination);
51
51
  }
52
52
  }
53
53
  catch (error) {
54
- const out = createOutputWriter();
55
54
  const formattedError = handleAxiosError(error);
56
- out.error(`Failed to list agents: ${formattedError.details}`);
55
+ output.error(`Failed to list agents: ${formattedError.details}`);
57
56
  process.exit(1);
58
57
  }
59
58
  });
@@ -4,6 +4,7 @@ import { GuildAPIClient } from '../../lib/api-client.js';
4
4
  import { getAgentId } from '../../lib/agent-helpers.js';
5
5
  import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
6
6
  import { pollUntilComplete } from '../../lib/polling.js';
7
+ import { createOutputWriter } from '../../lib/output.js';
7
8
  export function createAgentPublishCommand() {
8
9
  const cmd = new Command('publish');
9
10
  cmd
@@ -11,6 +12,7 @@ export function createAgentPublishCommand() {
11
12
  .argument('[identifier]', 'Agent ID or full name (e.g., owner/agent-name)')
12
13
  .option('--wait', 'Wait for validation to complete before publishing')
13
14
  .action(async (agentIdArg, options) => {
15
+ const output = createOutputWriter();
14
16
  try {
15
17
  const client = new GuildAPIClient();
16
18
  // Resolve agent ID
@@ -23,19 +25,13 @@ export function createAgentPublishCommand() {
23
25
  .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
24
26
  if (draftVersions.length === 0) {
25
27
  const agentName = config?.name || agentId;
26
- console.error(`No draft versions available for agent: ${agentName}`);
27
- console.error('');
28
- console.error('Create a new version:');
29
- console.error(` guild agent save --message "your changes"`);
28
+ output.error(`No draft versions available for agent: ${agentName}`, 'Create a new version:\n guild agent save --message "your changes"');
30
29
  process.exit(1);
31
30
  }
32
31
  const versionToPublish = draftVersions[0];
33
32
  // Check if already published
34
33
  if (versionToPublish.status === 'PUBLISHED') {
35
- console.error(`Version ${versionToPublish.id} is already published`);
36
- console.error('');
37
- console.error('To unpublish:');
38
- console.error(' guild agent unpublish');
34
+ output.error(`Version ${versionToPublish.id} is already published`, 'To unpublish:\n guild agent unpublish');
39
35
  process.exit(1);
40
36
  }
41
37
  // Check validation status before attempting publish
@@ -56,10 +52,7 @@ export function createAgentPublishCommand() {
56
52
  delayMs: 1000,
57
53
  });
58
54
  if (!result.success || !result.response) {
59
- console.error('Validation did not complete in time');
60
- console.error('');
61
- console.error('Check status manually:');
62
- console.error(' guild agent versions');
55
+ output.error('Validation did not complete in time', 'Check status manually:\n guild agent versions');
63
56
  process.exit(1);
64
57
  }
65
58
  currentVersion = result.response;
@@ -68,76 +61,66 @@ export function createAgentPublishCommand() {
68
61
  // by the main validation check
69
62
  }
70
63
  else {
71
- console.error('Cannot publish: validation is still in progress');
72
- console.error('');
73
- console.error(`Validation status: ${validationStatus === 'PENDING' ? 'Waiting to start' : 'Running'}`);
74
- console.error('');
75
- console.error('The version number is extracted from package.json during validation.');
76
- console.error('');
77
- console.error('Options:');
78
- console.error(' • Wait for validation: guild agent publish --wait');
79
- console.error(' • Check status: guild agent versions');
64
+ output.error('Cannot publish: validation is still in progress', `Validation status: ${validationStatus === 'PENDING' ? 'Waiting to start' : 'Running'}\n\nThe version number is extracted from package.json during validation.\n\nOptions:\n • Wait for validation: guild agent publish --wait\n • Check status: guild agent versions`);
80
65
  process.exit(1);
81
66
  }
82
67
  }
83
68
  if (validationStatus === 'FAILED') {
84
- console.error('Cannot publish: validation failed');
85
- console.error('');
86
69
  // Fetch validation steps to show the actual error
70
+ let failureDetails = '';
87
71
  try {
88
72
  const stepsResponse = await client.get(`/versions/${currentVersion.id}/validation/steps`);
89
73
  const failedSteps = stepsResponse.steps.filter((step) => step.status === 'FAILED');
90
74
  if (failedSteps.length > 0) {
91
- for (const step of failedSteps) {
92
- console.error(`Step "${step.name}" failed:`);
75
+ const stepMessages = failedSteps.map((step) => {
76
+ let msg = `Step "${step.name}" failed:`;
93
77
  if (step.content) {
94
- console.error(step.content);
78
+ msg += `\n ${step.content}`;
95
79
  }
96
- console.error('');
97
- }
80
+ return msg;
81
+ });
82
+ failureDetails = stepMessages.join('\n\n');
98
83
  }
99
84
  else {
100
- console.error('No failed steps found. Check validation logs for details.');
101
- console.error('');
85
+ failureDetails =
86
+ 'No failed steps found. Check validation logs for details.';
102
87
  }
103
88
  }
104
89
  catch {
105
90
  // If we can't fetch steps, just show generic message
106
- console.error('Could not fetch validation details.');
107
- console.error('');
91
+ failureDetails = 'Could not fetch validation details.';
108
92
  }
109
- console.error('Fix the issues, then save a new version:');
110
- console.error(' guild agent save --message "Fix validation errors"');
93
+ output.error('Cannot publish: validation failed', `${failureDetails}\n\nFix the issues, then save a new version:\n guild agent save --message "Fix validation errors"`);
111
94
  process.exit(1);
112
95
  }
113
96
  // Note: version_number is only set after validation extracts it from package.json,
114
97
  // and only enforced at publish time (drafts don't require versions)
115
98
  // Publish version
116
99
  await client.post(`/versions/${currentVersion.id}/publish`, {});
117
- console.log(`✓ Published version ${currentVersion.id}`);
118
- console.log(` Agent: ${currentVersion.agent?.name || config?.name || agentId}${config ? '' : ` (${agentId})`}`);
119
- console.log(` Status: DRAFT → PUBLISHED`);
100
+ const details = {
101
+ agent: `${currentVersion.agent?.name || config?.name || agentId}${config ? '' : ` (${agentId})`}`,
102
+ status: 'DRAFT → PUBLISHED',
103
+ };
120
104
  if (currentVersion.version_number) {
121
- console.log(` Version: ${currentVersion.version_number}`);
105
+ details.version = currentVersion.version_number;
122
106
  }
107
+ output.success(`Published version ${currentVersion.id}`, details);
123
108
  }
124
109
  catch (error) {
125
110
  const formattedError = handleAxiosError(error);
126
111
  if (formattedError.code === ErrorCodes.AUTH_REQUIRED) {
127
- console.error('Not authenticated. Run: guild auth login');
112
+ output.error('Not authenticated. Run: guild auth login');
128
113
  process.exit(1);
129
114
  }
130
115
  if (formattedError.code === ErrorCodes.NOT_FOUND) {
131
- console.error('Agent not found');
132
- console.error('');
133
- console.error('Run: guild agent list');
116
+ output.error('Agent not found', 'Run: guild agent list');
134
117
  process.exit(1);
135
118
  }
136
119
  if (formattedError.code === ErrorCodes.CONN_REFUSED) {
137
- console.error('Cannot connect to Guild servers');
120
+ output.error('Cannot connect to Guild servers');
138
121
  process.exit(1);
139
122
  }
140
- console.error(`Failed to publish: ${formattedError.details}`);
123
+ output.error(`Failed to publish: ${formattedError.details}`);
141
124
  process.exit(1);
142
125
  }
143
126
  });
@@ -23,15 +23,7 @@ export function createAgentPullCommand() {
23
23
  .then(() => true)
24
24
  .catch(() => false);
25
25
  if (!guildJsonExists) {
26
- console.error('Error: Not in an agent directory');
27
- console.error('');
28
- console.error('guild.json not found in current directory.');
29
- console.error('');
30
- console.error('Initialize an agent directory:');
31
- console.error(' guild agent init --name my-agent');
32
- console.error('');
33
- console.error('Or clone an existing agent:');
34
- console.error(' guild agent clone <agent-id>');
26
+ output.error('Not in an agent directory', 'guild.json not found in current directory.\n\nInitialize an agent directory:\n guild agent init --name my-agent\n\nOr clone an existing agent:\n guild agent clone <agent-id>');
35
27
  process.exit(1);
36
28
  }
37
29
  // Read guild.json
@@ -40,15 +32,13 @@ export function createAgentPullCommand() {
40
32
  const client = new GuildAPIClient();
41
33
  const agent = await client.get(`/agents/${guildConfig.agent_id}`);
42
34
  if (!agent.git_url) {
43
- console.error('Error: Agent does not have a git repository');
44
- console.error('');
45
- console.error('This agent may not have been initialized with git.');
35
+ output.error('Agent does not have a git repository', 'This agent may not have been initialized with git.');
46
36
  process.exit(1);
47
37
  }
48
38
  // Get authenticated URL
49
39
  const authenticatedUrl = await getAuthenticatedUrl(agent.git_url);
50
40
  if (!authenticatedUrl) {
51
- console.error('Error: Not authenticated. Run: guild auth login');
41
+ output.error('Not authenticated.', 'Run: guild auth login');
52
42
  process.exit(1);
53
43
  }
54
44
  // Get current branch name
@@ -93,17 +83,7 @@ export function createAgentPullCommand() {
93
83
  // Check for rebase conflicts
94
84
  if (errMessage.includes('CONFLICT') ||
95
85
  errMessage.includes('could not apply')) {
96
- console.error('Error: Merge conflict detected');
97
- console.error('');
98
- console.error('Your changes conflict with remote changes.');
99
- console.error('');
100
- console.error('To resolve:');
101
- console.error(' 1. Fix conflicts in the listed files');
102
- console.error(' 2. git add <resolved-files>');
103
- console.error(' 3. git rebase --continue');
104
- console.error('');
105
- console.error('Or abort the rebase:');
106
- console.error(' git rebase --abort');
86
+ output.error('Merge conflict detected', 'Your changes conflict with remote changes.\n\nTo resolve:\n 1. Fix conflicts in the listed files\n 2. git add <resolved-files>\n 3. git rebase --continue\n\nOr abort the rebase:\n git rebase --abort');
107
87
  process.exit(1);
108
88
  }
109
89
  // No upstream branch — nothing to pull
@@ -122,26 +102,19 @@ export function createAgentPullCommand() {
122
102
  }
123
103
  catch (error) {
124
104
  if (error instanceof GitError) {
125
- console.error('Error: Git operation failed');
126
- console.error('');
127
- console.error(formatGitError(error));
105
+ output.error('Git operation failed', formatGitError(error));
128
106
  process.exit(1);
129
107
  }
130
108
  const formattedError = handleAxiosError(error);
131
109
  if (formattedError.code === ErrorCodes.AUTH_REQUIRED) {
132
- console.error('Not authenticated. Please log in first.');
133
- console.error('');
134
- console.error('Run: guild auth login');
110
+ output.error('Not authenticated. Please log in first.', 'Run: guild auth login');
135
111
  process.exit(1);
136
112
  }
137
113
  if (formattedError.code === ErrorCodes.NOT_FOUND) {
138
- console.error('Error: Agent not found');
139
- console.error('');
140
- console.error('The agent may have been deleted.');
141
- console.error('Check your guild.json agent_id.');
114
+ output.error('Agent not found', 'The agent may have been deleted.\nCheck your guild.json agent_id.');
142
115
  process.exit(1);
143
116
  }
144
- console.error(`Failed to pull: ${formattedError.details}`);
117
+ output.error(`Failed to pull: ${formattedError.details}`);
145
118
  process.exit(1);
146
119
  }
147
120
  });
@@ -4,6 +4,7 @@ import { GuildAPIClient } from '../../lib/api-client.js';
4
4
  import { getGuildcoreUrl } from '../../lib/config.js';
5
5
  import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
6
6
  import { getAgentId } from '../../lib/agent-helpers.js';
7
+ import { createOutputWriter } from '../../lib/output.js';
7
8
  export function createAgentRevalidateCommand() {
8
9
  const cmd = new Command('revalidate');
9
10
  cmd
@@ -11,6 +12,7 @@ export function createAgentRevalidateCommand() {
11
12
  .argument('[identifier]', 'Agent ID or full name (e.g., owner/agent-name)')
12
13
  .argument('[version-id]', 'ID of the version to revalidate (uses latest if omitted)')
13
14
  .action(async (agentIdArg, versionIdArg) => {
15
+ const output = createOutputWriter();
14
16
  // Get agent ID from argument or guild.json
15
17
  const { agentId } = await getAgentId(agentIdArg);
16
18
  const baseUrl = getGuildcoreUrl();
@@ -21,38 +23,28 @@ export function createAgentRevalidateCommand() {
21
23
  if (!versionId) {
22
24
  const versions = await client.get(`/agents/${agentId}/versions?limit=1&offset=0`);
23
25
  if (!versions.items || versions.items.length === 0) {
24
- console.error('No versions found for this agent.');
25
- console.error('');
26
- console.error('The agent may still be initializing. Check status:');
27
- console.error(` guild agent get ${agentId}`);
26
+ output.error('No versions found for this agent.', `The agent may still be initializing. Check status:\n guild agent get ${agentId}`);
28
27
  process.exit(1);
29
28
  }
30
29
  versionId = versions.items[0].id;
31
30
  }
32
31
  // Revalidate the version
33
32
  const result = await client.post(`/agents/${agentId}/versions/${versionId}/revalidate`);
34
- console.log(JSON.stringify(result, null, 2));
33
+ output.data(result);
35
34
  }
36
35
  catch (error) {
37
36
  const formattedError = handleAxiosError(error);
38
37
  if (formattedError.code === ErrorCodes.AUTH_REQUIRED) {
39
- console.error('Not authenticated.');
40
- console.error('');
41
- console.error('Please authenticate first:');
42
- console.error(' guild auth login');
38
+ output.error('Not authenticated.', 'Please authenticate first:\n guild auth login');
43
39
  }
44
40
  else if (formattedError.code === ErrorCodes.CONN_REFUSED) {
45
- console.error('Cannot connect to Guild servers');
41
+ output.error('Cannot connect to Guild servers');
46
42
  }
47
43
  else if (formattedError.code === ErrorCodes.NOT_FOUND) {
48
- console.error(`Agent or version not found`);
49
- console.error('');
50
- console.error('Check the agent and version IDs:');
51
- console.error(' guild agent list');
52
- console.error(` guild agent versions ${agentId}`);
44
+ output.error('Agent or version not found', `Check the agent and version IDs:\n guild agent list\n guild agent versions ${agentId}`);
53
45
  }
54
46
  else {
55
- console.error(`Failed to revalidate version: ${formattedError.details}`);
47
+ output.error(`Failed to revalidate version: ${formattedError.details}`);
56
48
  }
57
49
  process.exit(1);
58
50
  }
@@ -2,6 +2,7 @@
2
2
  import { Command } from 'commander';
3
3
  import { GuildAPIClient } from '../../lib/api-client.js';
4
4
  import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
5
+ import { getOutputMode } from '../../lib/output-mode.js';
5
6
  import { createOutputWriter } from '../../lib/output.js';
6
7
  import * as fs from 'fs/promises';
7
8
  import * as path from 'path';
@@ -22,10 +23,7 @@ export function createAgentSaveCommand() {
22
23
  const output = createOutputWriter();
23
24
  // Check for --message
24
25
  if (!options.message) {
25
- console.error('Error: Commit message is required');
26
- console.error('');
27
- console.error('Provide a message describing your changes:');
28
- console.error(' guild agent save --message "Add new feature"');
26
+ output.error('Commit message is required', 'Provide a message describing your changes:\n guild agent save --message "Add new feature"');
29
27
  process.exit(1);
30
28
  }
31
29
  try {
@@ -36,15 +34,7 @@ export function createAgentSaveCommand() {
36
34
  .then(() => true)
37
35
  .catch(() => false);
38
36
  if (!guildJsonExists) {
39
- console.error('Error: Not in an agent directory');
40
- console.error('');
41
- console.error('guild.json not found in current directory.');
42
- console.error('');
43
- console.error('Initialize an agent directory:');
44
- console.error(' guild agent init --name my-agent');
45
- console.error('');
46
- console.error('Or clone an existing agent:');
47
- console.error(' guild agent clone <agent-id>');
37
+ output.error('Not in an agent directory', 'guild.json not found in current directory.\n\nInitialize an agent directory:\n guild agent init --name my-agent\n\nOr clone an existing agent:\n guild agent clone <agent-id>');
48
38
  process.exit(1);
49
39
  }
50
40
  // Read guild.json
@@ -77,9 +67,7 @@ export function createAgentSaveCommand() {
77
67
  }
78
68
  }
79
69
  if (!hasUnpushedCommits) {
80
- console.error('Error: No changes to commit');
81
- console.error('');
82
- console.error('Working tree is clean. Make changes to your code before saving.');
70
+ output.error('No changes to commit', 'Working tree is clean. Make changes to your code before saving.');
83
71
  process.exit(1);
84
72
  }
85
73
  output.progress('✓ Found unpushed commits, resuming push...');
@@ -97,7 +85,7 @@ export function createAgentSaveCommand() {
97
85
  });
98
86
  const authenticatedUrl = await getAuthenticatedUrl(remoteUrl.trim());
99
87
  if (!authenticatedUrl) {
100
- console.error('Error: Not authenticated. Run: guild auth login');
88
+ output.error('Not authenticated.', 'Run: guild auth login');
101
89
  process.exit(1);
102
90
  }
103
91
  // Get current branch name
@@ -120,27 +108,14 @@ export function createAgentSaveCommand() {
120
108
  // Check for rebase conflicts
121
109
  if (errMessage.includes('CONFLICT') ||
122
110
  errMessage.includes('could not apply')) {
123
- console.error('Error: Merge conflict detected');
124
- console.error('');
125
- console.error('Your changes conflict with remote changes.');
126
- console.error('');
127
- console.error('To resolve:');
128
- console.error(' 1. Fix conflicts in the listed files');
129
- console.error(' 2. git add <resolved-files>');
130
- console.error(' 3. git rebase --continue');
131
- console.error(' 4. guild agent save --message "..."');
132
- console.error('');
133
- console.error('Or abort the rebase:');
134
- console.error(' git rebase --abort');
111
+ output.error('Merge conflict detected', 'Your changes conflict with remote changes.\n\nTo resolve:\n 1. Fix conflicts in the listed files\n 2. git add <resolved-files>\n 3. git rebase --continue\n 4. guild agent save --message "..."\n\nOr abort the rebase:\n git rebase --abort');
135
112
  process.exit(1);
136
113
  }
137
114
  // If pull fails, check if it's because there's no upstream
138
115
  if (!errMessage.includes('no tracking information') &&
139
116
  !errMessage.includes("couldn't find remote ref")) {
140
117
  // Real error we don't understand
141
- console.error('Error: Failed to sync with remote');
142
- console.error('');
143
- console.error(errMessage);
118
+ output.error('Failed to sync with remote', errMessage);
144
119
  process.exit(1);
145
120
  }
146
121
  // No upstream branch yet, that's fine - first push will set it
@@ -225,42 +200,34 @@ export function createAgentSaveCommand() {
225
200
  delayMs: 1000,
226
201
  });
227
202
  if (!pollResult.success || !pollResult.response) {
228
- console.error('Validation did not complete in time');
229
- console.error('');
230
- console.error('Check status manually:');
231
- console.error(' guild agent versions');
203
+ output.error('Validation did not complete in time', 'Check status manually:\n guild agent versions');
232
204
  process.exit(1);
233
205
  }
234
206
  version = pollResult.response;
235
207
  // Check validation status
236
208
  if (version.validation_status === 'FAILED') {
237
- console.error('Validation failed');
238
- console.error('');
209
+ let failureDetails = '';
239
210
  // Fetch validation steps to show the actual error
240
211
  try {
241
212
  const stepsResponse = await client.get(`/versions/${version.id}/validation/steps`);
242
213
  const failedSteps = stepsResponse.steps.filter((step) => step.status === 'FAILED');
243
214
  if (failedSteps.length > 0) {
244
- for (const step of failedSteps) {
245
- console.error(`Step "${step.name}" failed:`);
246
- if (step.content) {
247
- console.error(step.content);
248
- }
249
- console.error('');
250
- }
215
+ const stepMessages = failedSteps.map((step) => step.content
216
+ ? `Step "${step.name}" failed: ${step.content}`
217
+ : `Step "${step.name}" failed`);
218
+ failureDetails = stepMessages.join('\n');
251
219
  }
252
220
  else {
253
- console.error('No failed steps found. Check validation logs for details.');
254
- console.error('');
221
+ failureDetails =
222
+ 'No failed steps found. Check validation logs for details.';
255
223
  }
256
224
  }
257
225
  catch {
258
- // If we can't fetch steps, just show generic message
259
- console.error('Could not fetch validation details.');
260
- console.error('');
226
+ failureDetails = 'Could not fetch validation details.';
261
227
  }
262
- console.error('Fix the issues, then save a new version:');
263
- console.error(' guild agent save --message "Fix validation errors"');
228
+ failureDetails +=
229
+ '\n\nFix the issues, then save a new version:\n guild agent save --message "Fix validation errors"';
230
+ output.error('Validation failed', failureDetails);
264
231
  process.exit(1);
265
232
  }
266
233
  }
@@ -288,46 +255,33 @@ export function createAgentSaveCommand() {
288
255
  output.progress('To publish this version:');
289
256
  output.progress(' guild agent save --message "..." --publish');
290
257
  }
291
- // Output JSON to stdout for programmatic use
292
- output.data({ version });
258
+ // Output JSON to stdout only in --json mode.
259
+ // In interactive mode the progress messages above already
260
+ // show version details; dumping raw JSON is noise.
261
+ if (getOutputMode() === 'json') {
262
+ output.data({ version });
263
+ }
293
264
  }
294
265
  catch (error) {
295
266
  if (error instanceof GitError) {
296
- console.error('Error: Git operation failed');
297
- console.error('');
298
- console.error(formatGitError(error));
267
+ output.error('Git operation failed', formatGitError(error));
299
268
  process.exit(1);
300
269
  }
301
270
  // Handle API errors
302
271
  const formattedError = handleAxiosError(error);
303
272
  if (formattedError.code === ErrorCodes.AUTH_REQUIRED) {
304
- console.error('Not authenticated. Please log in first.');
305
- console.error('');
306
- console.error('Run: guild auth login');
273
+ output.error('Not authenticated. Please log in first.', 'Run: guild auth login');
307
274
  process.exit(1);
308
275
  }
309
276
  if (formattedError.code === ErrorCodes.NOT_FOUND) {
310
- console.error(`Error: Agent not found${guildConfig ? ': ' + guildConfig.agent_id : ''}`);
311
- console.error('');
312
- console.error('The agent may have been deleted.');
277
+ output.error(`Agent not found${guildConfig ? ': ' + guildConfig.agent_id : ''}`, 'The agent may have been deleted.');
313
278
  process.exit(1);
314
279
  }
315
280
  if (formattedError.details.includes('does not exist')) {
316
- console.error('Error: Commit not found in repository');
317
- console.error('');
318
- console.error('This might mean:');
319
- console.error(" • The commit wasn't pushed to the remote repository");
320
- console.error(' • The git remote is configured incorrectly');
321
- console.error(" • There's a sync issue with the backend");
322
- console.error('');
323
- console.error('Verify the commit exists:');
324
- console.error(' git log --oneline');
325
- console.error('');
326
- console.error('Verify the remote:');
327
- console.error(' git remote -v');
281
+ output.error('Commit not found in repository', "This might mean:\n • The commit wasn't pushed to the remote repository\n • The git remote is configured incorrectly\n • There's a sync issue with the backend\n\nVerify the commit exists:\n git log --oneline\n\nVerify the remote:\n git remote -v");
328
282
  process.exit(1);
329
283
  }
330
- console.error(`Failed to save agent: ${formattedError.details}`);
284
+ output.error(`Failed to save agent: ${formattedError.details}`);
331
285
  process.exit(1);
332
286
  }
333
287
  });
@@ -3,8 +3,8 @@ 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, formatAgentTable } from '../../lib/output.js';
7
6
  import { getOutputMode } from '../../lib/output-mode.js';
7
+ import { createOutputWriter, formatAgentTable } from '../../lib/output.js';
8
8
  const SORT_MAP = {
9
9
  updated: 'updated_at',
10
10
  newest: 'created_at',
@@ -21,11 +21,11 @@ export function createAgentSearchCommand() {
21
21
  .option('--limit <number>', 'Number of results to return', '20')
22
22
  .option('--offset <number>', 'Offset for pagination', '0')
23
23
  .action(async (query, options) => {
24
+ const output = createOutputWriter();
24
25
  try {
25
26
  const token = await getAuthToken();
26
27
  if (!token) {
27
- console.error('Not authenticated. Please log in first.');
28
- console.error('Run: guild auth login');
28
+ output.error('Not authenticated. Please log in first.', 'Run: guild auth login');
29
29
  process.exit(1);
30
30
  }
31
31
  const client = new GuildAPIClient();
@@ -42,16 +42,15 @@ export function createAgentSearchCommand() {
42
42
  }
43
43
  const response = await client.get(`/agents?${params.toString()}`);
44
44
  if (getOutputMode() === 'json') {
45
- console.log(JSON.stringify(response, null, 2));
45
+ output.data(response);
46
46
  }
47
47
  else {
48
48
  formatAgentTable(response.items, response.pagination);
49
49
  }
50
50
  }
51
51
  catch (error) {
52
- const out = createOutputWriter();
53
52
  const formattedError = handleAxiosError(error);
54
- out.error(`Failed to search agents: ${formattedError.details}`);
53
+ output.error(`Failed to search agents: ${formattedError.details}`);
55
54
  process.exit(1);
56
55
  }
57
56
  });