@guildai/cli 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/commands/agent/chat.js +17 -42
- package/dist/commands/agent/test.js +24 -51
- package/dist/commands/chat.d.ts +2 -1
- package/dist/commands/chat.js +161 -73
- package/dist/commands/session/interrupt.d.ts +3 -0
- package/dist/commands/session/interrupt.js +33 -0
- package/dist/commands/setup.js +70 -11
- package/dist/index.js +2 -0
- package/dist/lib/event-filter.d.ts +50 -0
- package/dist/lib/event-filter.js +91 -0
- package/dist/lib/generated-types.d.ts +2 -0
- package/dist/lib/generated-types.js +20 -0
- package/dist/lib/session-events.d.ts +26 -1
- package/docs/CLI_WORKFLOW.md +7 -1
- package/docs/DESIGN.md +1 -1
- package/docs/skills/codex-agent-dev.md +155 -0
- package/docs/skills/integrations.md +338 -0
- package/package.json +1 -1
package/dist/commands/setup.js
CHANGED
|
@@ -11,7 +11,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
11
11
|
const __dirname = path.dirname(__filename);
|
|
12
12
|
const packageRoot = path.resolve(__dirname, '..', '..');
|
|
13
13
|
const docsDir = path.join(packageRoot, 'docs');
|
|
14
|
-
const
|
|
14
|
+
const CLAUDE_SKILL_FILES = [
|
|
15
15
|
{
|
|
16
16
|
src: path.join(docsDir, 'skills', 'agent-dev.md'),
|
|
17
17
|
dest: path.join('.claude', 'skills', 'agent-dev', 'skill.md'),
|
|
@@ -22,6 +22,18 @@ const SKILL_FILES = [
|
|
|
22
22
|
dest: path.join('.claude', 'skills', 'guild-cli-workflow', 'skill.md'),
|
|
23
23
|
label: '.claude/skills/guild-cli-workflow/skill.md',
|
|
24
24
|
},
|
|
25
|
+
{
|
|
26
|
+
src: path.join(docsDir, 'skills', 'integrations.md'),
|
|
27
|
+
dest: path.join('.claude', 'skills', 'integrations', 'skill.md'),
|
|
28
|
+
label: '.claude/skills/integrations/skill.md',
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
const CODEX_SKILL_FILES = [
|
|
32
|
+
{
|
|
33
|
+
src: path.join(docsDir, 'skills', 'codex-agent-dev.md'),
|
|
34
|
+
dest: path.join('.agents', 'skills', 'guild-agent-dev', 'SKILL.md'),
|
|
35
|
+
label: '.agents/skills/guild-agent-dev/SKILL.md',
|
|
36
|
+
},
|
|
25
37
|
];
|
|
26
38
|
const CLAUDE_MD_TEMPLATE = `# CLAUDE.md
|
|
27
39
|
|
|
@@ -38,6 +50,22 @@ guild agent save --message "Initial version" --wait --publish
|
|
|
38
50
|
|
|
39
51
|
See \`.claude/skills/agent-dev/skill.md\` for SDK reference, patterns, and anti-hallucination guide.
|
|
40
52
|
`;
|
|
53
|
+
const AGENTS_MD_TEMPLATE = `# AGENTS.md
|
|
54
|
+
|
|
55
|
+
## Guild Agent Development
|
|
56
|
+
|
|
57
|
+
This project uses Guild for agent development. Codex instructions are installed in \`.agents/skills/guild-agent-dev/SKILL.md\`.
|
|
58
|
+
|
|
59
|
+
### Quick Start
|
|
60
|
+
|
|
61
|
+
\`\`\`bash
|
|
62
|
+
guild agent init --name my-agent --template LLM
|
|
63
|
+
guild agent test --ephemeral
|
|
64
|
+
guild agent save -A --message "Initial version"
|
|
65
|
+
\`\`\`
|
|
66
|
+
|
|
67
|
+
Use \`guild doctor\` to check authentication, server connectivity, workspace selection, and git setup.
|
|
68
|
+
`;
|
|
41
69
|
async function fileExists(filePath) {
|
|
42
70
|
try {
|
|
43
71
|
await fs.access(filePath);
|
|
@@ -82,21 +110,29 @@ async function setupMcp(options) {
|
|
|
82
110
|
}
|
|
83
111
|
async function setup(options) {
|
|
84
112
|
const output = createOutputWriter();
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
113
|
+
if (options.agentsMd && !options.codex) {
|
|
114
|
+
output.error('--agents-md requires --codex', 'Create Codex setup files with:\n guild setup --codex --agents-md');
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
if (options.claudeMd && options.codex) {
|
|
118
|
+
output.error('--claude-md cannot be used with --codex', 'Create Claude setup with:\n guild setup --claude-md\n\nCreate Codex setup with:\n guild setup --codex --agents-md');
|
|
89
119
|
process.exit(1);
|
|
90
120
|
}
|
|
121
|
+
const skillFiles = options.codex ? CODEX_SKILL_FILES : CLAUDE_SKILL_FILES;
|
|
122
|
+
// Verify source docs exist
|
|
123
|
+
for (const file of skillFiles) {
|
|
124
|
+
if (!(await fileExists(file.src))) {
|
|
125
|
+
output.error('Could not find Guild CLI docs. Reinstall the CLI: npm install -g @guildai/cli');
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
91
129
|
output.progress('Setting up Guild CLI skills...');
|
|
92
130
|
output.progress('');
|
|
93
|
-
// Ensure .claude/skills/ directory exists
|
|
94
|
-
const skillsDir = path.join(process.cwd(), '.claude', 'skills');
|
|
95
|
-
await fs.mkdir(skillsDir, { recursive: true });
|
|
96
131
|
let filesCreated = 0;
|
|
97
132
|
let filesSkipped = 0;
|
|
133
|
+
let codexProjectFilesChanged = false;
|
|
98
134
|
// Copy skill files
|
|
99
|
-
for (const file of
|
|
135
|
+
for (const file of skillFiles) {
|
|
100
136
|
const destPath = path.join(process.cwd(), file.dest);
|
|
101
137
|
const exists = await fileExists(destPath);
|
|
102
138
|
if (exists && !options.force) {
|
|
@@ -113,6 +149,9 @@ async function setup(options) {
|
|
|
113
149
|
output.success(`Created ${file.label}`);
|
|
114
150
|
}
|
|
115
151
|
filesCreated++;
|
|
152
|
+
if (options.codex) {
|
|
153
|
+
codexProjectFilesChanged = true;
|
|
154
|
+
}
|
|
116
155
|
}
|
|
117
156
|
}
|
|
118
157
|
// Handle --mcp flag
|
|
@@ -139,6 +178,21 @@ async function setup(options) {
|
|
|
139
178
|
filesCreated++;
|
|
140
179
|
}
|
|
141
180
|
}
|
|
181
|
+
// Handle AGENTS.md template for Codex setup
|
|
182
|
+
if (options.agentsMd) {
|
|
183
|
+
const agentsMdPath = path.join(process.cwd(), 'AGENTS.md');
|
|
184
|
+
const exists = await fileExists(agentsMdPath);
|
|
185
|
+
if (exists) {
|
|
186
|
+
output.progress('AGENTS.md already exists (not overwriting)');
|
|
187
|
+
filesSkipped++;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
await fs.writeFile(agentsMdPath, AGENTS_MD_TEMPLATE, 'utf-8');
|
|
191
|
+
output.success('Created AGENTS.md');
|
|
192
|
+
filesCreated++;
|
|
193
|
+
codexProjectFilesChanged = true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
142
196
|
// Summary
|
|
143
197
|
output.progress('');
|
|
144
198
|
if (filesCreated > 0 && filesSkipped === 0) {
|
|
@@ -155,13 +209,18 @@ async function setup(options) {
|
|
|
155
209
|
else {
|
|
156
210
|
output.success('Guild CLI skills installed.');
|
|
157
211
|
}
|
|
212
|
+
if (codexProjectFilesChanged) {
|
|
213
|
+
output.progress('Restart Codex to pick up the new project instructions.');
|
|
214
|
+
}
|
|
158
215
|
}
|
|
159
216
|
export function createSetupCommand() {
|
|
160
217
|
const cmd = new Command('setup');
|
|
161
218
|
cmd
|
|
162
|
-
.description('Set up Guild CLI skills for coding assistants (Claude Code, etc.)')
|
|
163
|
-
.option('--force', 'Overwrite existing skill files', false)
|
|
219
|
+
.description('Set up Guild CLI skills for coding assistants (Claude Code, Codex, etc.)')
|
|
220
|
+
.option('--force', 'Overwrite existing skill files and Guild MCP config', false)
|
|
221
|
+
.option('--codex', 'Install Codex skill files instead of Claude Code skills', false)
|
|
164
222
|
.option('--claude-md', 'Also create a CLAUDE.md template in the project root', false)
|
|
223
|
+
.option('--agents-md', 'With --codex, also create an AGENTS.md template in the project root', false)
|
|
165
224
|
.option('--no-mcp', 'Skip MCP server configuration')
|
|
166
225
|
.action(async (options) => {
|
|
167
226
|
await setup(options);
|
package/dist/index.js
CHANGED
|
@@ -59,6 +59,7 @@ import { createSessionEventsCommand } from './commands/session/events.js';
|
|
|
59
59
|
import { createSessionTasksCommand } from './commands/session/tasks.js';
|
|
60
60
|
import { createSessionCreateCommand } from './commands/session/create.js';
|
|
61
61
|
import { createSessionSendCommand } from './commands/session/send.js';
|
|
62
|
+
import { createSessionInterruptCommand } from './commands/session/interrupt.js';
|
|
62
63
|
import { createJobGetCommand } from './commands/job/get.js';
|
|
63
64
|
import { createJobStepGetCommand } from './commands/job/step-get.js';
|
|
64
65
|
import { createConfigListCommand } from './commands/config/list.js';
|
|
@@ -276,6 +277,7 @@ sessionCmd.addCommand(createSessionEventsCommand());
|
|
|
276
277
|
sessionCmd.addCommand(createSessionTasksCommand());
|
|
277
278
|
sessionCmd.addCommand(createSessionCreateCommand());
|
|
278
279
|
sessionCmd.addCommand(createSessionSendCommand());
|
|
280
|
+
sessionCmd.addCommand(createSessionInterruptCommand());
|
|
279
281
|
// Job command group
|
|
280
282
|
const jobCmd = program.command('job').description('Job management');
|
|
281
283
|
jobCmd.addCommand(createJobGetCommand());
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event type filtering for the CLI `--events` flag.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the web UI's "Filter by type" modal, which groups event types into
|
|
5
|
+
* two categories: user-facing events (on by default) and system/debug events
|
|
6
|
+
* (off by default).
|
|
7
|
+
*
|
|
8
|
+
* The canonical event type list is generated from the backend EventType enum
|
|
9
|
+
* (see generated-types.ts). The user/system grouping is a UI concern defined
|
|
10
|
+
* here and in www/src/components/EventTypeFilters/types.ts.
|
|
11
|
+
*/
|
|
12
|
+
import type { EventType } from './generated-types.js';
|
|
13
|
+
/**
|
|
14
|
+
* User-facing event types — shown by default (mirrors web UI defaults).
|
|
15
|
+
*/
|
|
16
|
+
export declare const USER_EVENT_TYPES: readonly EventType[];
|
|
17
|
+
/**
|
|
18
|
+
* System / debug event types — hidden by default (mirrors web UI defaults).
|
|
19
|
+
*/
|
|
20
|
+
export declare const SYSTEM_EVENT_TYPES: readonly EventType[];
|
|
21
|
+
/**
|
|
22
|
+
* Default active filter: all user-facing types, no system types.
|
|
23
|
+
*/
|
|
24
|
+
export declare const DEFAULT_EVENT_TYPES: Set<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Parse the value of the `--events` flag into a Set of event type names.
|
|
27
|
+
*
|
|
28
|
+
* Whatever you pass replaces the defaults entirely:
|
|
29
|
+
* - `none` → empty set (no event types shown)
|
|
30
|
+
* - `user` → all USER_EVENT_TYPES (same as default)
|
|
31
|
+
* - `system` → only SYSTEM_EVENT_TYPES
|
|
32
|
+
* - `all` → both USER_EVENT_TYPES + SYSTEM_EVENT_TYPES
|
|
33
|
+
*
|
|
34
|
+
* Comma-separated for fine-grained control:
|
|
35
|
+
* - `agent_console,llm_start` → only those two types
|
|
36
|
+
* - `user,system` → same as `all`
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseEventFilter(raw: string): Set<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Check whether an event should be shown given the active filter.
|
|
41
|
+
*
|
|
42
|
+
* Returns `true` when the event type is in the filter set.
|
|
43
|
+
*
|
|
44
|
+
* Note: certain event types (e.g. `agent_notification_progress`,
|
|
45
|
+
* `agent_notification_message`) drive core UI state (spinner, chat history)
|
|
46
|
+
* and are always processed regardless of the filter; only their *display* is
|
|
47
|
+
* gated here for new/optional event types.
|
|
48
|
+
*/
|
|
49
|
+
export declare function shouldShowEvent(type: string, filter: Set<string>): boolean;
|
|
50
|
+
//# sourceMappingURL=event-filter.d.ts.map
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* User-facing event types — shown by default (mirrors web UI defaults).
|
|
5
|
+
*/
|
|
6
|
+
export const USER_EVENT_TYPES = [
|
|
7
|
+
'user_message',
|
|
8
|
+
'agent_notification_message',
|
|
9
|
+
'agent_notification_progress',
|
|
10
|
+
'agent_notification_error',
|
|
11
|
+
'credentials_request',
|
|
12
|
+
'agent_install_request',
|
|
13
|
+
'trigger_message',
|
|
14
|
+
'system_error',
|
|
15
|
+
];
|
|
16
|
+
/**
|
|
17
|
+
* System / debug event types — hidden by default (mirrors web UI defaults).
|
|
18
|
+
*/
|
|
19
|
+
export const SYSTEM_EVENT_TYPES = [
|
|
20
|
+
'agent_console',
|
|
21
|
+
'runtime_start',
|
|
22
|
+
'runtime_running',
|
|
23
|
+
'runtime_waiting',
|
|
24
|
+
'runtime_error',
|
|
25
|
+
'runtime_done',
|
|
26
|
+
'llm_start',
|
|
27
|
+
'llm_done',
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Default active filter: all user-facing types, no system types.
|
|
31
|
+
*/
|
|
32
|
+
export const DEFAULT_EVENT_TYPES = new Set(USER_EVENT_TYPES);
|
|
33
|
+
/**
|
|
34
|
+
* Parse the value of the `--events` flag into a Set of event type names.
|
|
35
|
+
*
|
|
36
|
+
* Whatever you pass replaces the defaults entirely:
|
|
37
|
+
* - `none` → empty set (no event types shown)
|
|
38
|
+
* - `user` → all USER_EVENT_TYPES (same as default)
|
|
39
|
+
* - `system` → only SYSTEM_EVENT_TYPES
|
|
40
|
+
* - `all` → both USER_EVENT_TYPES + SYSTEM_EVENT_TYPES
|
|
41
|
+
*
|
|
42
|
+
* Comma-separated for fine-grained control:
|
|
43
|
+
* - `agent_console,llm_start` → only those two types
|
|
44
|
+
* - `user,system` → same as `all`
|
|
45
|
+
*/
|
|
46
|
+
export function parseEventFilter(raw) {
|
|
47
|
+
const tokens = raw
|
|
48
|
+
.split(',')
|
|
49
|
+
.map((t) => t.trim())
|
|
50
|
+
.filter(Boolean);
|
|
51
|
+
// `none` returns an empty set — no event types shown
|
|
52
|
+
if (tokens.length === 1 && tokens[0] === 'none') {
|
|
53
|
+
return new Set();
|
|
54
|
+
}
|
|
55
|
+
const result = new Set();
|
|
56
|
+
for (const token of tokens) {
|
|
57
|
+
switch (token) {
|
|
58
|
+
case 'all':
|
|
59
|
+
for (const t of USER_EVENT_TYPES)
|
|
60
|
+
result.add(t);
|
|
61
|
+
for (const t of SYSTEM_EVENT_TYPES)
|
|
62
|
+
result.add(t);
|
|
63
|
+
break;
|
|
64
|
+
case 'user':
|
|
65
|
+
for (const t of USER_EVENT_TYPES)
|
|
66
|
+
result.add(t);
|
|
67
|
+
break;
|
|
68
|
+
case 'system':
|
|
69
|
+
for (const t of SYSTEM_EVENT_TYPES)
|
|
70
|
+
result.add(t);
|
|
71
|
+
break;
|
|
72
|
+
default:
|
|
73
|
+
result.add(token);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check whether an event should be shown given the active filter.
|
|
80
|
+
*
|
|
81
|
+
* Returns `true` when the event type is in the filter set.
|
|
82
|
+
*
|
|
83
|
+
* Note: certain event types (e.g. `agent_notification_progress`,
|
|
84
|
+
* `agent_notification_message`) drive core UI state (spinner, chat history)
|
|
85
|
+
* and are always processed regardless of the filter; only their *display* is
|
|
86
|
+
* gated here for new/optional event types.
|
|
87
|
+
*/
|
|
88
|
+
export function shouldShowEvent(type, filter) {
|
|
89
|
+
return filter.has(type);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=event-filter.js.map
|
|
@@ -2,4 +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"];
|
|
6
|
+
export type EventType = (typeof EVENT_TYPES)[number];
|
|
5
7
|
//# sourceMappingURL=generated-types.d.ts.map
|
|
@@ -32,4 +32,24 @@ export const TIME_TRIGGER_FREQUENCIES = [
|
|
|
32
32
|
'MONTHLY',
|
|
33
33
|
'CRON',
|
|
34
34
|
];
|
|
35
|
+
// Source: python/guildcore/routes/serializers.py -> EventType
|
|
36
|
+
export const EVENT_TYPES = [
|
|
37
|
+
'user_message',
|
|
38
|
+
'agent_console',
|
|
39
|
+
'runtime_start',
|
|
40
|
+
'runtime_running',
|
|
41
|
+
'runtime_waiting',
|
|
42
|
+
'runtime_error',
|
|
43
|
+
'runtime_done',
|
|
44
|
+
'credentials_request',
|
|
45
|
+
'agent_install_request',
|
|
46
|
+
'agent_notification_message',
|
|
47
|
+
'agent_notification_progress',
|
|
48
|
+
'agent_notification_error',
|
|
49
|
+
'system_error',
|
|
50
|
+
'trigger_message',
|
|
51
|
+
'interrupted',
|
|
52
|
+
'llm_start',
|
|
53
|
+
'llm_done',
|
|
54
|
+
];
|
|
35
55
|
//# sourceMappingURL=generated-types.js.map
|
|
@@ -117,6 +117,31 @@ export interface AgentConsoleEvent extends BaseEvent {
|
|
|
117
117
|
level: 'debug' | 'info' | 'warn' | 'error';
|
|
118
118
|
content: string;
|
|
119
119
|
}
|
|
120
|
+
export interface TriggerMessageEvent extends BaseEvent {
|
|
121
|
+
type: 'trigger_message';
|
|
122
|
+
content: {
|
|
123
|
+
type: 'text';
|
|
124
|
+
data: string;
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export interface SystemErrorEvent extends BaseEvent {
|
|
128
|
+
type: 'system_error';
|
|
129
|
+
content: {
|
|
130
|
+
type: 'text';
|
|
131
|
+
data: string;
|
|
132
|
+
};
|
|
133
|
+
details?: Record<string, unknown>;
|
|
134
|
+
}
|
|
135
|
+
export interface LlmStartEvent extends BaseEvent {
|
|
136
|
+
type: 'llm_start';
|
|
137
|
+
provider: string;
|
|
138
|
+
payload: Record<string, unknown>;
|
|
139
|
+
}
|
|
140
|
+
export interface LlmDoneEvent extends BaseEvent {
|
|
141
|
+
type: 'llm_done';
|
|
142
|
+
status_code: number;
|
|
143
|
+
body: string;
|
|
144
|
+
}
|
|
120
145
|
/** Agent info as returned in install request */
|
|
121
146
|
export interface RequestedAgent {
|
|
122
147
|
id: string;
|
|
@@ -149,7 +174,7 @@ export interface InterruptedEvent extends BaseEvent {
|
|
|
149
174
|
interrupted_at: string;
|
|
150
175
|
interrupted_by_id: string;
|
|
151
176
|
}
|
|
152
|
-
export type SessionEvent = UserMessageEvent | RuntimeStartEvent | RuntimeRunningEvent | RuntimeWaitingEvent | RuntimeErrorEvent | RuntimeDoneEvent | AgentNotificationMessageEvent | AgentNotificationProgressEvent | AgentNotificationErrorEvent | AgentConsoleEvent | AgentInstallRequestEvent | CredentialsRequestEvent | InterruptedEvent;
|
|
177
|
+
export type SessionEvent = UserMessageEvent | RuntimeStartEvent | RuntimeRunningEvent | RuntimeWaitingEvent | RuntimeErrorEvent | RuntimeDoneEvent | AgentNotificationMessageEvent | AgentNotificationProgressEvent | AgentNotificationErrorEvent | AgentConsoleEvent | TriggerMessageEvent | SystemErrorEvent | LlmStartEvent | LlmDoneEvent | AgentInstallRequestEvent | CredentialsRequestEvent | InterruptedEvent;
|
|
153
178
|
export interface Session {
|
|
154
179
|
id: string;
|
|
155
180
|
workspace_id?: string;
|
package/docs/CLI_WORKFLOW.md
CHANGED
|
@@ -57,11 +57,17 @@ guild agent save --message "Description" --wait --publish
|
|
|
57
57
|
### Project Setup
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
|
-
# Install Guild CLI skills for coding assistants (Claude Code, etc.)
|
|
60
|
+
# Install Guild CLI skills for coding assistants (Claude Code, Codex, etc.)
|
|
61
61
|
guild setup
|
|
62
62
|
|
|
63
63
|
# Also create a CLAUDE.md template
|
|
64
64
|
guild setup --claude-md
|
|
65
|
+
|
|
66
|
+
# Install Codex skill files
|
|
67
|
+
guild setup --codex
|
|
68
|
+
|
|
69
|
+
# Also create an AGENTS.md template for Codex
|
|
70
|
+
guild setup --codex --agents-md
|
|
65
71
|
```
|
|
66
72
|
|
|
67
73
|
### Creating Agents
|
package/docs/DESIGN.md
CHANGED
|
@@ -188,7 +188,7 @@ Environments are Docker containers managed by GuildCore. The CLI provides a simp
|
|
|
188
188
|
|
|
189
189
|
## Integration with Developer Tools
|
|
190
190
|
|
|
191
|
-
The CLI integrates with AI coding assistants like Claude Code, Cursor, and others. Run `guild setup` to install
|
|
191
|
+
The CLI integrates with AI coding assistants like Claude Code, Cursor, and others. Run `guild setup` to install Claude Code skills into your project, or `guild setup --codex` to install Codex skills.
|
|
192
192
|
|
|
193
193
|
The CLI also exposes a [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server via `guild mcp`. This gives coding assistants direct access to Guild's API — searching agents, managing workspaces, reading contexts, and starting sessions — without leaving the editor. `guild setup` configures it by default; use `--no-mcp` to skip.
|
|
194
194
|
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: guild-agent-dev
|
|
3
|
+
description: Use when working on Guild agents with Codex: creating agents, editing agent code, testing with the Guild CLI, saving versions, publishing, debugging sessions, or answering questions about Guild agent development.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Guild Agent Development
|
|
7
|
+
|
|
8
|
+
Use the Guild CLI for local agent development. Prefer commands that are scriptable and safe for a coding agent to run.
|
|
9
|
+
|
|
10
|
+
## First Checks
|
|
11
|
+
|
|
12
|
+
Before changing an agent, establish the local context:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
guild --version
|
|
16
|
+
guild auth status
|
|
17
|
+
guild workspace current
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
If authentication or workspace selection is missing, tell the user the exact command to run:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
guild auth login
|
|
24
|
+
guild workspace select
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Core Rules
|
|
28
|
+
|
|
29
|
+
- Use `guild agent init`, `guild agent clone`, `guild agent pull`, `guild agent test`, `guild agent chat`, and `guild agent save` for agent lifecycle work.
|
|
30
|
+
- Do not edit `guild.json`; it is managed by the CLI.
|
|
31
|
+
- Prefer `guild agent save -A --message "..."` instead of raw `git add`, `git commit`, or `git push`.
|
|
32
|
+
- Do not use `git push` directly for agent repositories; use `guild agent save`.
|
|
33
|
+
- Keep edits scoped to the agent files requested by the user.
|
|
34
|
+
- Surface command output that matters, especially validation errors, session links, workspace IDs, and next commands.
|
|
35
|
+
|
|
36
|
+
## Common Workflows
|
|
37
|
+
|
|
38
|
+
Create a new agent:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
mkdir my-agent && cd my-agent
|
|
42
|
+
guild agent init --name my-agent --template LLM
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Clone an existing agent:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
guild agent clone owner/agent-name
|
|
49
|
+
cd agent-name
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Sync before editing when collaborating:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
guild agent pull
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Test unsaved local changes:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
guild agent test --ephemeral
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
For non-interactive Codex test loops, prefer JSON input:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
printf '{"type":"text","text":"hello"}\n' | guild agent test --ephemeral --mode json
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Send a single message to the agent in the current directory:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
guild agent chat --ephemeral "Hello"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Save a draft version:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
guild agent save -A --message "Describe the change"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Save, validate, and publish:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
guild agent save -A --message "Ready" --wait --publish
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Debugging
|
|
89
|
+
|
|
90
|
+
If a test fails or stalls:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
guild doctor
|
|
94
|
+
guild agent versions
|
|
95
|
+
guild session events <session-id>
|
|
96
|
+
guild session tasks <session-id>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Use `--debug` when command output is too sparse:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
guild --debug agent test --ephemeral
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Agent Code Patterns
|
|
106
|
+
|
|
107
|
+
LLM agents use a prompt and tools:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { llmAgent, guildTools } from '@guildai/agents-sdk';
|
|
111
|
+
|
|
112
|
+
export default llmAgent({
|
|
113
|
+
description: 'Helps users with Guild workspaces',
|
|
114
|
+
tools: { ...guildTools },
|
|
115
|
+
systemPrompt: `You are a helpful Guild workspace assistant.`,
|
|
116
|
+
mode: 'multi-turn',
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Code-first agents call tools through `task.tools`:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
'use agent';
|
|
124
|
+
|
|
125
|
+
import { agent, guildTools, type Task } from '@guildai/agents-sdk';
|
|
126
|
+
import { z } from 'zod';
|
|
127
|
+
|
|
128
|
+
const tools = { ...guildTools };
|
|
129
|
+
type Tools = typeof tools;
|
|
130
|
+
|
|
131
|
+
const inputSchema = z.object({
|
|
132
|
+
type: z.literal('text'),
|
|
133
|
+
text: z.string(),
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const outputSchema = z.object({
|
|
137
|
+
type: z.literal('text'),
|
|
138
|
+
text: z.string(),
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
async function run(input: z.infer<typeof inputSchema>, task: Task<Tools>) {
|
|
142
|
+
await task.tools.guild_debug_log({ message: input.text });
|
|
143
|
+
return { type: 'text' as const, text: input.text };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export default agent({
|
|
147
|
+
description: 'Echoes user text',
|
|
148
|
+
inputSchema,
|
|
149
|
+
outputSchema,
|
|
150
|
+
tools,
|
|
151
|
+
run,
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
All tool calls go through `task.tools.<toolName>(args)`.
|