@guildai/cli 0.9.0 → 0.9.1

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 (41) hide show
  1. package/dist/commands/agent/chat.d.ts +1 -0
  2. package/dist/commands/agent/chat.js +24 -1
  3. package/dist/commands/agent/init.js +1 -1
  4. package/dist/commands/agent/test.d.ts +1 -0
  5. package/dist/commands/agent/test.js +92 -34
  6. package/dist/commands/chat.d.ts +1 -0
  7. package/dist/commands/chat.js +178 -46
  8. package/dist/commands/integration/connect.js +1 -1
  9. package/dist/commands/integration/create.js +36 -36
  10. package/dist/commands/integration/operation/create.js +2 -1
  11. package/dist/commands/integration/operation/list.js +23 -15
  12. package/dist/commands/mcp.js +1 -1
  13. package/dist/commands/session/events.js +16 -7
  14. package/dist/commands/session/send.js +1 -1
  15. package/dist/commands/workspace/agent/add.js +16 -3
  16. package/dist/commands/workspace/agent/list.js +14 -1
  17. package/dist/commands/workspace/agent/remove.js +14 -1
  18. package/dist/commands/workspace/clear.d.ts +3 -0
  19. package/dist/commands/workspace/clear.js +45 -0
  20. package/dist/commands/workspace/select.js +3 -1
  21. package/dist/index.js +53 -6
  22. package/dist/lib/api-types.d.ts +1 -0
  23. package/dist/lib/generated-types.d.ts +1 -1
  24. package/dist/lib/generated-types.js +1 -0
  25. package/dist/lib/guild-config.d.ts +13 -0
  26. package/dist/lib/guild-config.js +19 -0
  27. package/dist/lib/npmrc.js +6 -2
  28. package/dist/lib/session-events.d.ts +32 -16
  29. package/dist/lib/session-events.js +22 -0
  30. package/dist/lib/session-polling.d.ts +4 -3
  31. package/dist/lib/session-polling.js +75 -17
  32. package/dist/lib/session-resume.js +4 -1
  33. package/dist/lib/stdin.d.ts +4 -0
  34. package/dist/lib/stdin.js +23 -0
  35. package/dist/lib/validate-input-schema.d.ts +19 -0
  36. package/dist/lib/validate-input-schema.js +208 -0
  37. package/dist/lib/workspace-helpers.d.ts +20 -0
  38. package/dist/lib/workspace-helpers.js +49 -0
  39. package/dist/mcp/tools.js +8 -52
  40. package/docs/skills/agent-dev.md +191 -128
  41. package/package.json +2 -1
@@ -2,7 +2,6 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import { Command } from 'commander';
4
4
  import chalk from 'chalk';
5
- import inquirer from 'inquirer';
6
5
  import { GuildAPIClient } from '../../lib/api-client.js';
7
6
  import { getAuthToken } from '../../lib/auth.js';
8
7
  import { handleAxiosError } from '../../lib/errors.js';
@@ -66,47 +65,44 @@ export function createIntegrationCreateCommand() {
66
65
  });
67
66
  // Resolve description
68
67
  let description = options.description;
69
- if (!description) {
70
- if (interactive) {
71
- const answer = await inquirer.prompt([
72
- { type: 'input', name: 'description', message: 'Description:' },
73
- ]);
74
- description = answer.description;
75
- }
68
+ if (!description && interactive) {
69
+ const { default: inquirer } = await import('inquirer');
70
+ const answer = await inquirer.prompt([
71
+ { type: 'input', name: 'description', message: 'Description:' },
72
+ ]);
73
+ description = answer.description;
76
74
  }
77
75
  // Resolve base URL
78
76
  let baseUrl = options.baseUrl;
79
- if (!baseUrl) {
80
- if (interactive) {
81
- const answer = await inquirer.prompt([
82
- { type: 'input', name: 'baseUrl', message: 'Base URL:' },
83
- ]);
84
- baseUrl = answer.baseUrl;
85
- }
77
+ if (!baseUrl && interactive) {
78
+ const { default: inquirer } = await import('inquirer');
79
+ const answer = await inquirer.prompt([
80
+ { type: 'input', name: 'baseUrl', message: 'Base URL:' },
81
+ ]);
82
+ baseUrl = answer.baseUrl;
86
83
  }
87
84
  // Resolve auth scheme
88
85
  let authScheme = options.authScheme;
89
- if (!authScheme) {
90
- if (interactive) {
91
- const answer = await inquirer.prompt([
92
- {
93
- type: 'list',
94
- name: 'authScheme',
95
- message: 'Select authentication scheme:',
96
- choices: [
97
- {
98
- name: 'API Key - Static token sent in request headers',
99
- value: 'api-key',
100
- },
101
- {
102
- name: 'OAuth 2.0 - User grants access via authorization flow',
103
- value: 'oauth',
104
- },
105
- ],
106
- },
107
- ]);
108
- authScheme = answer.authScheme;
109
- }
86
+ if (!authScheme && interactive) {
87
+ const { default: inquirer } = await import('inquirer');
88
+ const answer = await inquirer.prompt([
89
+ {
90
+ type: 'list',
91
+ name: 'authScheme',
92
+ message: 'Select authentication scheme:',
93
+ choices: [
94
+ {
95
+ name: 'API Key - Static token sent in request headers',
96
+ value: 'api-key',
97
+ },
98
+ {
99
+ name: 'OAuth 2.0 - User grants access via authorization flow',
100
+ value: 'oauth',
101
+ },
102
+ ],
103
+ },
104
+ ]);
105
+ authScheme = answer.authScheme;
110
106
  }
111
107
  // Validate required fields in non-interactive mode
112
108
  const missing = [];
@@ -126,6 +122,7 @@ export function createIntegrationCreateCommand() {
126
122
  if (normalizedScheme === 'api-key') {
127
123
  let headerTemplate = options.headerTemplate || 'X-API-Key: {token}';
128
124
  if (interactive && !options.headerTemplate) {
125
+ const { default: inquirer } = await import('inquirer');
129
126
  const answer = await inquirer.prompt([
130
127
  {
131
128
  type: 'input',
@@ -151,6 +148,7 @@ export function createIntegrationCreateCommand() {
151
148
  let clientId = options.clientId;
152
149
  let clientSecret = options.clientSecret;
153
150
  if (interactive) {
151
+ const { default: inquirer } = await import('inquirer');
154
152
  if (!installUrl) {
155
153
  const a = await inquirer.prompt([
156
154
  { type: 'input', name: 'val', message: 'Install URL:' },
@@ -205,6 +203,7 @@ export function createIntegrationCreateCommand() {
205
203
  authConfig.scopes = options.scopes.split(',').map((s) => s.trim());
206
204
  }
207
205
  else if (interactive) {
206
+ const { default: inquirer } = await import('inquirer');
208
207
  const answer = await inquirer.prompt([
209
208
  {
210
209
  type: 'input',
@@ -237,6 +236,7 @@ export function createIntegrationCreateCommand() {
237
236
  }
238
237
  }
239
238
  else if (interactive) {
239
+ const { default: inquirer } = await import('inquirer');
240
240
  const answer = await inquirer.prompt([
241
241
  {
242
242
  type: 'confirm',
@@ -2,7 +2,6 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import { Command } from 'commander';
4
4
  import chalk from 'chalk';
5
- import inquirer from 'inquirer';
6
5
  import { readFileSync, existsSync } from 'fs';
7
6
  import { GuildAPIClient } from '../../../lib/api-client.js';
8
7
  import { getAuthToken } from '../../../lib/auth.js';
@@ -59,6 +58,7 @@ export function createIntegrationOperationCreateCommand() {
59
58
  let method = options.method;
60
59
  let operationPath = options.path;
61
60
  if (isInteractive()) {
61
+ const { default: inquirer } = await import('inquirer');
62
62
  if (!operation) {
63
63
  const a = await inquirer.prompt([
64
64
  {
@@ -110,6 +110,7 @@ export function createIntegrationOperationCreateCommand() {
110
110
  };
111
111
  let summary = options.summary;
112
112
  if (!summary && isInteractive()) {
113
+ const { default: inquirer } = await import('inquirer');
113
114
  const a = await inquirer.prompt([
114
115
  { type: 'input', name: 'val', message: 'Summary (optional):' },
115
116
  ]);
@@ -41,24 +41,32 @@ export function createIntegrationOperationListCommand() {
41
41
  }
42
42
  console.log(chalk.bold('Operations'));
43
43
  console.log();
44
+ const isMcp = response.items.some((ep) => !ep.method);
44
45
  const table = new Table({
45
- columns: [
46
- { name: 'operation', title: 'OPERATION', alignment: 'left' },
47
- {
48
- name: 'method',
49
- title: 'METHOD',
50
- alignment: 'left',
51
- color: 'cyan',
52
- },
53
- { name: 'path', title: 'PATH', alignment: 'left' },
54
- ],
46
+ columns: isMcp
47
+ ? [
48
+ { name: 'operation', title: 'OPERATION', alignment: 'left' },
49
+ { name: 'description', title: 'DESCRIPTION', alignment: 'left' },
50
+ ]
51
+ : [
52
+ { name: 'operation', title: 'OPERATION', alignment: 'left' },
53
+ {
54
+ name: 'method',
55
+ title: 'METHOD',
56
+ alignment: 'left',
57
+ color: 'cyan',
58
+ },
59
+ { name: 'path', title: 'PATH', alignment: 'left' },
60
+ ],
55
61
  });
56
62
  response.items.forEach((ep) => {
57
- table.addRow({
58
- operation: ep.operation,
59
- method: ep.method,
60
- path: ep.path,
61
- });
63
+ table.addRow(isMcp
64
+ ? { operation: ep.operation, description: ep.description ?? '' }
65
+ : {
66
+ operation: ep.operation,
67
+ method: ep.method ?? '',
68
+ path: ep.path ?? '',
69
+ });
62
70
  });
63
71
  table.printTable();
64
72
  const showing = Math.min(response.pagination.limit, response.items.length);
@@ -1,7 +1,6 @@
1
1
  // Copyright 2026 Guild.ai
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import { Command } from 'commander';
4
- import { startMcpServer } from '../mcp/server.js';
5
4
  export function createMcpCommand() {
6
5
  const cmd = new Command('mcp');
7
6
  cmd
@@ -24,6 +23,7 @@ Configuration:
24
23
  Or run: guild setup --mcp
25
24
  `)
26
25
  .action(async (options) => {
26
+ const { startMcpServer } = await import('../mcp/server.js');
27
27
  await startMcpServer({
28
28
  workspace: options.workspace,
29
29
  debug: options.debug,
@@ -3,7 +3,7 @@
3
3
  import { Command } from 'commander';
4
4
  import { GuildAPIClient } from '../../lib/api-client.js';
5
5
  import { getAuthToken } from '../../lib/auth.js';
6
- import { parseEventFilter } from '../../lib/event-filter.js';
6
+ import { parseEventFilter, DEFAULT_EVENT_TYPES, USER_EVENT_TYPES, SYSTEM_EVENT_TYPES, } from '../../lib/event-filter.js';
7
7
  import { handleAxiosError } from '../../lib/errors.js';
8
8
  import { createOutputWriter } from '../../lib/output.js';
9
9
  export function createSessionEventsCommand() {
@@ -11,9 +11,18 @@ export function createSessionEventsCommand() {
11
11
  cmd
12
12
  .description('List events in a session')
13
13
  .argument('<session-id>', 'Session ID')
14
- .option('--events <types>', 'Event types to show. Shorthands: none, user, system, all, or comma-separated type names')
14
+ .option('--events <types>', 'Event types to show (default: user). Shorthands: none, user, system, all, or comma-separated type names')
15
15
  .option('--limit <number>', 'Number of results to return', '100')
16
16
  .option('--offset <number>', 'Offset for pagination', '0')
17
+ .addHelpText('after', [
18
+ '',
19
+ 'Available event types:',
20
+ ' User events (shown by default):',
21
+ ` ${USER_EVENT_TYPES.join(', ')}`,
22
+ '',
23
+ ' System / debug events:',
24
+ ` ${SYSTEM_EVENT_TYPES.join(', ')}`,
25
+ ].join('\n'))
17
26
  .action(async (sessionId, options) => {
18
27
  const output = createOutputWriter();
19
28
  try {
@@ -26,11 +35,11 @@ export function createSessionEventsCommand() {
26
35
  const params = new URLSearchParams();
27
36
  params.append('limit', options.limit);
28
37
  params.append('offset', options.offset);
29
- if (options.events) {
30
- const filter = parseEventFilter(options.events);
31
- if (filter.size > 0) {
32
- params.append('types', [...filter].join(','));
33
- }
38
+ const rawFilter = options.events
39
+ ? parseEventFilter(options.events)
40
+ : DEFAULT_EVENT_TYPES;
41
+ if (rawFilter.size > 0) {
42
+ params.append('types', [...rawFilter].join(','));
34
43
  }
35
44
  const response = await client.get(`/sessions/${sessionId}/events?${params.toString()}`);
36
45
  output.data(response);
@@ -8,7 +8,7 @@ import { createOutputWriter } from '../../lib/output.js';
8
8
  export function createSessionSendCommand() {
9
9
  const cmd = new Command('send');
10
10
  cmd
11
- .description('Send a message or event to a session')
11
+ .description('Send a user message to a session')
12
12
  .argument('<session-id>', 'Session ID')
13
13
  .option('--message <text>', 'Text message content')
14
14
  .option('--json <json>', 'JSON content object (sets mode to json)')
@@ -6,13 +6,14 @@ 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 } from '../../../lib/output.js';
9
+ import { resolveWorkspaceId } from '../../../lib/workspace-helpers.js';
9
10
  export function createWorkspaceAgentAddCommand() {
10
11
  const cmd = new Command('add');
11
12
  cmd
12
13
  .description('Add an agent to a workspace')
13
14
  .argument('<agent>', 'Agent identifier (e.g., owner~agent-name or UUID)')
14
- .option('--workspace <id>', 'Target workspace ID or name')
15
- .option('--no-autoupdate', 'Disable automatic updates for this agent')
15
+ .option('--workspace <id>', 'Workspace ID or name')
16
+ .option('--no-autoupdate', 'Disable automatic updates for this agent (default: autoupdate enabled)')
16
17
  .action(async (agentIdentifier, options) => {
17
18
  const output = createOutputWriter();
18
19
  try {
@@ -24,7 +25,19 @@ export function createWorkspaceAgentAddCommand() {
24
25
  const client = new GuildAPIClient();
25
26
  // Resolve workspace
26
27
  let workspaceId = options.workspace;
27
- if (!workspaceId) {
28
+ if (workspaceId) {
29
+ try {
30
+ workspaceId = await resolveWorkspaceId(client, workspaceId);
31
+ }
32
+ catch (err) {
33
+ if (err instanceof Error && err.message.startsWith('Workspace "')) {
34
+ output.error('Workspace not found');
35
+ process.exit(1);
36
+ }
37
+ throw err; // let the outer catch handle network/auth errors via handleAxiosError
38
+ }
39
+ }
40
+ else {
28
41
  const resolved = await getWorkspaceId();
29
42
  if (!resolved) {
30
43
  output.error('No workspace specified.', 'Either use --workspace flag:\n guild workspace agent add <agent> --workspace <workspace-id>\n\nOr select a default workspace:\n guild workspace select');
@@ -7,6 +7,7 @@ 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
9
  import { getOutputMode } from '../../../lib/output-mode.js';
10
+ import { resolveWorkspaceId } from '../../../lib/workspace-helpers.js';
10
11
  export function createWorkspaceAgentListCommand() {
11
12
  const cmd = new Command('list');
12
13
  cmd
@@ -25,7 +26,19 @@ export function createWorkspaceAgentListCommand() {
25
26
  const client = new GuildAPIClient();
26
27
  // Resolve workspace
27
28
  let workspaceId = options.workspace;
28
- if (!workspaceId) {
29
+ if (workspaceId) {
30
+ try {
31
+ workspaceId = await resolveWorkspaceId(client, workspaceId);
32
+ }
33
+ catch (err) {
34
+ if (err instanceof Error && err.message.startsWith('Workspace "')) {
35
+ output.error('Workspace not found');
36
+ process.exit(1);
37
+ }
38
+ throw err; // let the outer catch handle network/auth errors via handleAxiosError
39
+ }
40
+ }
41
+ else {
29
42
  const resolved = await getWorkspaceId();
30
43
  if (!resolved) {
31
44
  output.error('No workspace specified.', 'Either use --workspace flag:\n guild workspace agent list --workspace <workspace-id>\n\nOr select a default workspace:\n guild workspace select');
@@ -6,6 +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 } from '../../../lib/output.js';
9
+ import { resolveWorkspaceId } from '../../../lib/workspace-helpers.js';
9
10
  export function createWorkspaceAgentRemoveCommand() {
10
11
  const cmd = new Command('remove');
11
12
  cmd
@@ -23,7 +24,19 @@ export function createWorkspaceAgentRemoveCommand() {
23
24
  const client = new GuildAPIClient();
24
25
  // Resolve workspace
25
26
  let workspaceId = options.workspace;
26
- if (!workspaceId) {
27
+ if (workspaceId) {
28
+ try {
29
+ workspaceId = await resolveWorkspaceId(client, workspaceId);
30
+ }
31
+ catch (err) {
32
+ if (err instanceof Error && err.message.startsWith('Workspace "')) {
33
+ output.error('Workspace not found');
34
+ process.exit(1);
35
+ }
36
+ throw err; // let the outer catch handle network/auth errors via handleAxiosError
37
+ }
38
+ }
39
+ else {
27
40
  const resolved = await getWorkspaceId();
28
41
  if (!resolved) {
29
42
  output.error('No workspace specified.', 'Either use --workspace flag:\n guild workspace agent remove <agent> --workspace <workspace-id>\n\nOr select a default workspace:\n guild workspace select');
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createWorkspaceClearCommand(): Command;
3
+ //# sourceMappingURL=clear.d.ts.map
@@ -0,0 +1,45 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import * as fs from 'fs/promises';
5
+ import { createOutputWriter } from '../../lib/output.js';
6
+ import { isAgentDirectory, loadLocalConfig, getLocalConfigPath, loadGlobalConfig, getGlobalConfigDir, getGlobalConfigPath, } from '../../lib/guild-config.js';
7
+ export function createWorkspaceClearCommand() {
8
+ const cmd = new Command('clear');
9
+ cmd.description('Clear the default workspace setting').action(async () => {
10
+ const output = createOutputWriter();
11
+ try {
12
+ if (await isAgentDirectory()) {
13
+ // In agent directory: remove workspace_id from guild.json
14
+ const localConfig = await loadLocalConfig();
15
+ if (!localConfig || !('workspace_id' in localConfig)) {
16
+ output.progress('No default workspace was set.');
17
+ return;
18
+ }
19
+ const { workspace_id: _removed, ...updated } = localConfig;
20
+ await fs.writeFile(getLocalConfigPath(), JSON.stringify(updated, null, 2) + '\n');
21
+ output.success('Cleared workspace setting for this agent');
22
+ return;
23
+ }
24
+ // Not in agent directory: remove default_workspace from global config
25
+ const globalConfig = await loadGlobalConfig();
26
+ if (!globalConfig ||
27
+ (!('default_workspace' in globalConfig) &&
28
+ !('default_workspace_name' in globalConfig))) {
29
+ output.progress('No default workspace was set.');
30
+ return;
31
+ }
32
+ const { default_workspace: _ws, default_workspace_name: _wsName, ...rest } = globalConfig;
33
+ await fs.mkdir(getGlobalConfigDir(), { recursive: true });
34
+ await fs.writeFile(getGlobalConfigPath(), JSON.stringify(rest, null, 2) + '\n');
35
+ output.success('Default workspace cleared');
36
+ }
37
+ catch (error) {
38
+ const message = error instanceof Error ? error.message : String(error);
39
+ output.error(`Failed to clear workspace: ${message}`);
40
+ process.exit(1);
41
+ }
42
+ });
43
+ return cmd;
44
+ }
45
+ //# sourceMappingURL=clear.js.map
@@ -2,7 +2,6 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import { Command } from 'commander';
4
4
  import * as fs from 'fs/promises';
5
- import search from '@inquirer/search';
6
5
  import { GuildAPIClient } from '../../lib/api-client.js';
7
6
  import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
8
7
  import { createOutputWriter } from '../../lib/output.js';
@@ -83,6 +82,7 @@ export function createWorkspaceSelectCommand() {
83
82
  }
84
83
  else {
85
84
  output.success(`Default workspace set to: ${formatWorkspaceDisplay(workspace)}`);
85
+ output.progress('To clear the default, run: guild workspace clear');
86
86
  }
87
87
  return;
88
88
  }
@@ -110,6 +110,7 @@ export function createWorkspaceSelectCommand() {
110
110
  const current = await getWorkspaceId();
111
111
  const currentId = current?.workspaceId;
112
112
  // Interactive searchable selection
113
+ const { default: search } = await import('@inquirer/search');
113
114
  const selectedId = await search({
114
115
  message: 'Select a workspace (type to filter)',
115
116
  pageSize: 15,
@@ -138,6 +139,7 @@ export function createWorkspaceSelectCommand() {
138
139
  }
139
140
  else {
140
141
  output.success(`Default workspace set to: ${formatWorkspaceDisplay(selectedWorkspace)}`);
142
+ output.progress('To clear the default, run: guild workspace clear');
141
143
  }
142
144
  }
143
145
  catch (error) {
package/dist/index.js CHANGED
@@ -17,12 +17,10 @@ import { createAgentVersionsCommand } from './commands/agent/versions.js';
17
17
  import { createAgentSaveCommand } from './commands/agent/save.js';
18
18
  import { createAgentPullCommand } from './commands/agent/pull.js';
19
19
  import { createAgentCodeCommand } from './commands/agent/code.js';
20
- import { createAgentChatCommand } from './commands/agent/chat.js';
21
20
  import { createAgentInitCommand } from './commands/agent/init.js';
22
21
  import { createAgentGrepCommand } from './commands/agent/grep.js';
23
22
  import { createAgentCloneCommand } from './commands/agent/clone.js';
24
23
  import { createAgentForkCommand } from './commands/agent/fork.js';
25
- import { createAgentTestCommand } from './commands/agent/test.js';
26
24
  import { createAgentPublishCommand } from './commands/agent/publish.js';
27
25
  import { createAgentUnpublishCommand } from './commands/agent/unpublish.js';
28
26
  import { createAgentRevalidateCommand } from './commands/agent/revalidate.js';
@@ -33,12 +31,12 @@ import { createAgentTagsListCommand } from './commands/agent/tags/list.js';
33
31
  import { createAgentTagsAddCommand } from './commands/agent/tags/add.js';
34
32
  import { createAgentTagsRemoveCommand } from './commands/agent/tags/remove.js';
35
33
  import { createAgentTagsSetCommand } from './commands/agent/tags/set.js';
36
- import { createChatCommand } from './commands/chat.js';
37
34
  import { createWorkspaceListCommand } from './commands/workspace/list.js';
38
35
  import { createWorkspaceCreateCommand } from './commands/workspace/create.js';
39
36
  import { createWorkspaceGetCommand } from './commands/workspace/get.js';
40
37
  import { createWorkspaceSelectCommand } from './commands/workspace/select.js';
41
38
  import { createWorkspaceCurrentCommand } from './commands/workspace/current.js';
39
+ import { createWorkspaceClearCommand } from './commands/workspace/clear.js';
42
40
  import { createWorkspaceAgentAddCommand } from './commands/workspace/agent/add.js';
43
41
  import { createWorkspaceAgentListCommand } from './commands/workspace/agent/list.js';
44
42
  import { createWorkspaceAgentRemoveCommand } from './commands/workspace/agent/remove.js';
@@ -130,7 +128,23 @@ program
130
128
  });
131
129
  // Register commands
132
130
  program.addCommand(createVersionCommand());
133
- program.addCommand(createChatCommand());
131
+ // chat — lazy-loaded to avoid importing React, Ink, marked at startup
132
+ program
133
+ .command('chat')
134
+ .description('Chat with an agent (default: Guild assistant)')
135
+ .argument('[prompt...]', 'Optional initial prompt (multiple words)')
136
+ .option('--agent <identifier>', 'Agent ID or full name, e.g., foo~bar (default: assistant)')
137
+ .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
+ .option('--workspace <identifier>', 'Workspace ID or full name (e.g., owner/workspace-name)')
140
+ .option('--no-splash', 'Skip the splash screen animation')
141
+ .option('--resume <session-id>', 'Resume an existing session')
142
+ .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)')
143
+ .addHelpText('after', '\nTo chat with a local agent under development: guild agent chat')
144
+ .action(async (promptArgs, options) => {
145
+ const { handleChatAction } = await import('./commands/chat.js');
146
+ await handleChatAction(promptArgs, options);
147
+ });
134
148
  program.addCommand(createMcpCommand());
135
149
  program.addCommand(createDoctorCommand());
136
150
  program.addCommand(createSetupCommand());
@@ -149,12 +163,44 @@ agentCmd.addCommand(createAgentVersionsCommand());
149
163
  agentCmd.addCommand(createAgentSaveCommand());
150
164
  agentCmd.addCommand(createAgentPullCommand());
151
165
  agentCmd.addCommand(createAgentCodeCommand());
152
- agentCmd.addCommand(createAgentChatCommand());
166
+ // agent chat — lazy-loaded to avoid importing React, Ink, open at startup
167
+ agentCmd
168
+ .command('chat')
169
+ .description('Chat with the agent in current directory')
170
+ .argument('[prompt...]', 'Optional initial prompt for the agent')
171
+ .option('--path <dir>', 'Path to agent directory (defaults to current directory)')
172
+ .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
+ .option('--agent-version <id>', 'Chat with a specific version (UUID or version number)')
175
+ .option('--no-splash', 'Skip the splash screen animation')
176
+ .option('--resume <session-id>', 'Resume an existing session')
177
+ .option('--open', 'Open session in web dashboard')
178
+ .option('--no-cache', 'Skip ephemeral build cache (force a fresh build)')
179
+ .addHelpText('after', '\nTo chat with a published agent by name: guild chat --agent owner~agent-name')
180
+ .action(async (promptArgs, options) => {
181
+ const { handleAgentChatAction } = await import('./commands/agent/chat.js');
182
+ await handleAgentChatAction(promptArgs, options);
183
+ });
153
184
  agentCmd.addCommand(createAgentInitCommand());
154
185
  agentCmd.addCommand(createAgentGrepCommand());
155
186
  agentCmd.addCommand(createAgentCloneCommand());
156
187
  agentCmd.addCommand(createAgentForkCommand());
157
- agentCmd.addCommand(createAgentTestCommand());
188
+ // agent test — lazy-loaded to avoid importing React, Ink, open at startup
189
+ agentCmd
190
+ .command('test')
191
+ .description('Test agent in interactive REPL session')
192
+ .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
+ .option('--agent-version <id>', 'Test a specific version (UUID or version number)')
195
+ .option('--resume <session-id>', 'Resume an existing test session')
196
+ .option('--open', 'Open session in web dashboard')
197
+ .option('--events <types>', 'Event types to stream (default: all). Shorthands: none, user, system, all, or comma-separated type names')
198
+ .option('--bundle <file>', 'Path to a pre-built gzip+base64 bundle file')
199
+ .option('--no-cache', 'Skip ephemeral build cache (force a fresh build)')
200
+ .action(async (options) => {
201
+ const { handleAgentTestAction } = await import('./commands/agent/test.js');
202
+ await handleAgentTestAction(options);
203
+ });
158
204
  agentCmd.addCommand(createAgentPublishCommand());
159
205
  agentCmd.addCommand(createAgentUnpublishCommand());
160
206
  agentCmd.addCommand(createAgentRevalidateCommand());
@@ -199,6 +245,7 @@ workspaceCmd.addCommand(createWorkspaceCreateCommand());
199
245
  workspaceCmd.addCommand(createWorkspaceGetCommand());
200
246
  workspaceCmd.addCommand(createWorkspaceSelectCommand());
201
247
  workspaceCmd.addCommand(createWorkspaceCurrentCommand());
248
+ workspaceCmd.addCommand(createWorkspaceClearCommand());
202
249
  // Workspace agent subcommand group
203
250
  const workspaceAgentCmd = workspaceCmd
204
251
  .command('agent')
@@ -71,6 +71,7 @@ export interface WorkspaceAgent {
71
71
  id: string;
72
72
  name: string;
73
73
  };
74
+ is_default_chat_agent: boolean;
74
75
  should_autoupdate: boolean;
75
76
  }
76
77
  /**
@@ -2,6 +2,6 @@ export declare const WEBHOOK_SERVICES: readonly ["AZURE_DEVOPS", "BITBUCKET", "C
2
2
  export type WebhookService = (typeof WEBHOOK_SERVICES)[number];
3
3
  export declare const TIME_TRIGGER_FREQUENCIES: readonly ["HOURLY", "DAILY", "WEEKLY", "MONTHLY", "CRON"];
4
4
  export type TimeTriggerFrequency = (typeof TIME_TRIGGER_FREQUENCIES)[number];
5
- export declare const EVENT_TYPES: readonly ["user_message", "agent_console", "runtime_start", "runtime_running", "runtime_waiting", "runtime_error", "runtime_done", "credentials_request", "agent_install_request", "agent_notification_message", "agent_notification_progress", "agent_notification_error", "system_error", "trigger_message", "interrupted", "llm_start", "llm_done"];
5
+ export declare const EVENT_TYPES: readonly ["user_message", "agent_console", "runtime_start", "runtime_running", "runtime_waiting", "runtime_error", "runtime_done", "credentials_request", "agent_install_request", "agent_notification_message", "agent_notification_progress", "agent_notification_error", "system_error", "system_message", "trigger_message", "interrupted", "llm_start", "llm_done"];
6
6
  export type EventType = (typeof EVENT_TYPES)[number];
7
7
  //# sourceMappingURL=generated-types.d.ts.map
@@ -47,6 +47,7 @@ export const EVENT_TYPES = [
47
47
  'agent_notification_progress',
48
48
  'agent_notification_error',
49
49
  'system_error',
50
+ 'system_message',
50
51
  'trigger_message',
51
52
  'interrupted',
52
53
  'llm_start',
@@ -83,4 +83,17 @@ export declare function getWorkspaceId(cwd?: string): Promise<{
83
83
  * Check if we're in an agent directory (has guild.json)
84
84
  */
85
85
  export declare function isAgentDirectory(cwd?: string): Promise<boolean>;
86
+ /**
87
+ * Get a human-readable label for the workspace source.
88
+ * Returns undefined for 'env' (treated as explicit, like --workspace flag; no label needed).
89
+ *
90
+ * @param source - The source of workspace resolution
91
+ * @returns Human-readable label, or undefined for env source
92
+ *
93
+ * @example
94
+ * getWorkspaceSourceLabel('local') // → 'guild.json'
95
+ * getWorkspaceSourceLabel('global') // → 'global config'
96
+ * getWorkspaceSourceLabel('env') // → undefined
97
+ */
98
+ export declare function getWorkspaceSourceLabel(source: 'env' | 'local' | 'global'): string | undefined;
86
99
  //# sourceMappingURL=guild-config.d.ts.map
@@ -156,4 +156,23 @@ export async function getWorkspaceId(cwd = process.cwd()) {
156
156
  export async function isAgentDirectory(cwd = process.cwd()) {
157
157
  return fileExists(getLocalConfigPath(cwd));
158
158
  }
159
+ /**
160
+ * Get a human-readable label for the workspace source.
161
+ * Returns undefined for 'env' (treated as explicit, like --workspace flag; no label needed).
162
+ *
163
+ * @param source - The source of workspace resolution
164
+ * @returns Human-readable label, or undefined for env source
165
+ *
166
+ * @example
167
+ * getWorkspaceSourceLabel('local') // → 'guild.json'
168
+ * getWorkspaceSourceLabel('global') // → 'global config'
169
+ * getWorkspaceSourceLabel('env') // → undefined
170
+ */
171
+ export function getWorkspaceSourceLabel(source) {
172
+ if (source === 'local')
173
+ return 'guild.json';
174
+ if (source === 'global')
175
+ return 'global config';
176
+ return undefined; // 'env' is explicit (GUILD_WORKSPACE_ID), no magic label needed
177
+ }
159
178
  //# sourceMappingURL=guild-config.js.map