@guildai/cli 0.5.9 → 0.5.11
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 +28 -1
- package/dist/commands/agent/init.js +24 -3
- package/dist/commands/container/destroy.d.ts +3 -0
- package/dist/commands/container/destroy.js +48 -0
- package/dist/commands/container/events.d.ts +3 -0
- package/dist/commands/container/events.js +44 -0
- package/dist/commands/container/exec.d.ts +3 -0
- package/dist/commands/container/exec.js +64 -0
- package/dist/commands/container/get.d.ts +3 -0
- package/dist/commands/container/get.js +33 -0
- package/dist/commands/container/list.d.ts +3 -0
- package/dist/commands/container/list.js +48 -0
- package/dist/commands/container-image/create.d.ts +3 -0
- package/dist/commands/container-image/create.js +41 -0
- package/dist/commands/container-image/get.d.ts +3 -0
- package/dist/commands/container-image/get.js +33 -0
- package/dist/commands/container-image/list.d.ts +3 -0
- package/dist/commands/container-image/list.js +44 -0
- package/dist/commands/job/get.d.ts +3 -0
- package/dist/commands/job/get.js +44 -0
- package/dist/commands/job/step-get.d.ts +3 -0
- package/dist/commands/job/step-get.js +40 -0
- package/dist/commands/setup.js +11 -4
- package/dist/commands/trigger/create.js +4 -0
- package/dist/commands/trigger/update.js +4 -0
- package/dist/index.js +28 -0
- package/dist/lib/api-types.d.ts +135 -0
- package/dist/lib/generated-types.d.ts +1 -1
- package/dist/lib/generated-types.js +1 -0
- package/dist/lib/output.d.ts +21 -16
- package/dist/lib/output.js +184 -1
- package/dist/lib/session-events.d.ts +1 -0
- package/dist/lib/table.d.ts +22 -0
- package/dist/lib/table.js +60 -0
- package/docs/CLI_WORKFLOW.md +6 -0
- package/docs/DESIGN.md +2 -0
- package/docs/skills/agent-dev.md +6 -0
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -210,8 +210,35 @@ guild version # Show version info
|
|
|
210
210
|
### Coding Assistant Skills
|
|
211
211
|
|
|
212
212
|
```bash
|
|
213
|
-
guild setup # Install
|
|
213
|
+
guild setup # Install skills + configure MCP server
|
|
214
214
|
guild setup --claude-md # Also create a CLAUDE.md template
|
|
215
|
+
guild setup --no-mcp # Install skills only, skip MCP configuration
|
|
216
|
+
guild mcp # Start MCP server (used by Claude Code, etc.)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### MCP Server
|
|
220
|
+
|
|
221
|
+
The CLI includes an [MCP](https://modelcontextprotocol.io/) server that exposes Guild's API to AI coding assistants like Claude Code.
|
|
222
|
+
|
|
223
|
+
**Setup:**
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
guild setup
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
This installs Claude Code skills and adds a `guild` entry to `.mcp.json` in your project. Claude Code (and other MCP-compatible tools) will automatically connect when they detect it.
|
|
230
|
+
|
|
231
|
+
**What it provides:**
|
|
232
|
+
|
|
233
|
+
- 24 tools: workspaces, agents, sessions, triggers, contexts, credentials
|
|
234
|
+
- 2 resources: current workspace info and installed agents
|
|
235
|
+
- All tools use your `guild auth` credentials automatically
|
|
236
|
+
|
|
237
|
+
**Manual start (for debugging):**
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
guild mcp
|
|
241
|
+
guild mcp --debug # Verbose logging to stderr
|
|
215
242
|
```
|
|
216
243
|
|
|
217
244
|
## Configuration
|
|
@@ -34,18 +34,30 @@ function slugify(text) {
|
|
|
34
34
|
.replace(/[^a-z0-9]+/g, '-')
|
|
35
35
|
.replace(/^-+|-+$/g, '');
|
|
36
36
|
}
|
|
37
|
+
const NAME_RULES = 'Lowercase letters, digits, hyphens, and underscores only (1-100 characters)';
|
|
38
|
+
function isValidAgentName(name) {
|
|
39
|
+
return name.length >= 1 && name.length <= 100 && /^[a-z0-9\-_.]+$/.test(name);
|
|
40
|
+
}
|
|
37
41
|
async function promptForName(defaultName) {
|
|
38
42
|
const rl = readline.createInterface({
|
|
39
43
|
input: process.stdin,
|
|
40
44
|
output: process.stdout,
|
|
41
45
|
});
|
|
42
|
-
|
|
46
|
+
const ask = () => new Promise((resolve) => {
|
|
43
47
|
rl.question(`Agent name [${defaultName}]: `, (answer) => {
|
|
44
|
-
rl.close();
|
|
45
48
|
const trimmed = answer.trim();
|
|
46
|
-
|
|
49
|
+
const name = trimmed || defaultName;
|
|
50
|
+
if (!isValidAgentName(name)) {
|
|
51
|
+
console.error(`Invalid name "${name}": ${NAME_RULES}`);
|
|
52
|
+
resolve(ask());
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
rl.close();
|
|
56
|
+
resolve(name);
|
|
57
|
+
}
|
|
47
58
|
});
|
|
48
59
|
});
|
|
60
|
+
return ask();
|
|
49
61
|
}
|
|
50
62
|
async function promptForTemplate() {
|
|
51
63
|
const { template } = await inquirer.prompt([
|
|
@@ -120,6 +132,15 @@ export function createAgentInitCommand() {
|
|
|
120
132
|
process.exit(1);
|
|
121
133
|
}
|
|
122
134
|
}
|
|
135
|
+
// Validate name (catches --name flag and non-interactive paths)
|
|
136
|
+
if (!isValidAgentName(agentName)) {
|
|
137
|
+
console.error(`Error: Invalid agent name "${agentName}"`);
|
|
138
|
+
console.error('');
|
|
139
|
+
console.error(`Agent names must use ${NAME_RULES}`);
|
|
140
|
+
console.error('');
|
|
141
|
+
console.error('Examples: my-agent, my_agent');
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
123
144
|
// Determine template: use --template option, prompt if interactive, or error
|
|
124
145
|
let template = options.template;
|
|
125
146
|
if (!template) {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
|
+
import { getOutputMode } from '../../lib/output-mode.js';
|
|
8
|
+
import { createOutputWriter } from '../../lib/output.js';
|
|
9
|
+
export function createContainerDestroyCommand() {
|
|
10
|
+
const cmd = new Command('destroy');
|
|
11
|
+
cmd
|
|
12
|
+
.description('Destroy a running container')
|
|
13
|
+
.argument('<container-id>', 'Container ID')
|
|
14
|
+
.action(async (containerId) => {
|
|
15
|
+
const output = createOutputWriter();
|
|
16
|
+
try {
|
|
17
|
+
const token = await getAuthToken();
|
|
18
|
+
if (!token) {
|
|
19
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const client = new GuildAPIClient();
|
|
23
|
+
const response = await client.post(`/containers/${containerId}/destroy`, {});
|
|
24
|
+
if (getOutputMode() === 'json') {
|
|
25
|
+
console.log(JSON.stringify(response, null, 2));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
if (response.status === 'SUCCESS') {
|
|
29
|
+
output.success(`Container ${containerId} destroyed`);
|
|
30
|
+
}
|
|
31
|
+
else if (response.status === 'ERROR') {
|
|
32
|
+
output.error(`Failed to destroy container: ${response.error || 'unknown error'}`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
output.progress(`Container destruction ${response.status.toLowerCase()}...`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const formattedError = handleAxiosError(error);
|
|
42
|
+
output.error(`Failed to destroy container: ${formattedError.details}`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return cmd;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=destroy.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
|
+
import { getOutputMode } from '../../lib/output-mode.js';
|
|
8
|
+
import { createOutputWriter, formatContainerEventTable } from '../../lib/output.js';
|
|
9
|
+
export function createContainerEventsCommand() {
|
|
10
|
+
const cmd = new Command('events');
|
|
11
|
+
cmd
|
|
12
|
+
.description('List events for a container')
|
|
13
|
+
.argument('<container-id>', 'Container ID')
|
|
14
|
+
.option('--limit <number>', 'Number of results to return', '20')
|
|
15
|
+
.option('--offset <number>', 'Offset for pagination', '0')
|
|
16
|
+
.action(async (containerId, options) => {
|
|
17
|
+
const output = createOutputWriter();
|
|
18
|
+
try {
|
|
19
|
+
const token = await getAuthToken();
|
|
20
|
+
if (!token) {
|
|
21
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const client = new GuildAPIClient();
|
|
25
|
+
const params = new URLSearchParams();
|
|
26
|
+
params.append('limit', options.limit);
|
|
27
|
+
params.append('offset', options.offset);
|
|
28
|
+
const response = await client.get(`/containers/${containerId}/events?${params.toString()}`);
|
|
29
|
+
if (getOutputMode() === 'json') {
|
|
30
|
+
console.log(JSON.stringify(response, null, 2));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
formatContainerEventTable(response.items, response.pagination);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
const formattedError = handleAxiosError(error);
|
|
38
|
+
output.error(`Failed to list container events: ${formattedError.details}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return cmd;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
6
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
7
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
8
|
+
import { getOutputMode } from '../../lib/output-mode.js';
|
|
9
|
+
import { createOutputWriter } from '../../lib/output.js';
|
|
10
|
+
export function createContainerExecCommand() {
|
|
11
|
+
const cmd = new Command('exec');
|
|
12
|
+
cmd
|
|
13
|
+
.description('Execute a command in a running container')
|
|
14
|
+
.argument('<container-id>', 'Container ID')
|
|
15
|
+
.argument('<command>', 'Command to execute')
|
|
16
|
+
.action(async (containerId, command) => {
|
|
17
|
+
const output = createOutputWriter();
|
|
18
|
+
try {
|
|
19
|
+
const token = await getAuthToken();
|
|
20
|
+
if (!token) {
|
|
21
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const client = new GuildAPIClient();
|
|
25
|
+
const response = await client.post(`/containers/${containerId}/command`, { command });
|
|
26
|
+
if (getOutputMode() === 'json') {
|
|
27
|
+
console.log(JSON.stringify(response, null, 2));
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// Display return code
|
|
31
|
+
if (response.return_code !== null) {
|
|
32
|
+
const codeColor = response.return_code === 0 ? chalk.green : chalk.red;
|
|
33
|
+
console.error(chalk.dim('Return code:'), codeColor(String(response.return_code)));
|
|
34
|
+
}
|
|
35
|
+
// Display stdout
|
|
36
|
+
if (response.stdout) {
|
|
37
|
+
console.log(response.stdout);
|
|
38
|
+
}
|
|
39
|
+
// Display stderr
|
|
40
|
+
if (response.stderr) {
|
|
41
|
+
console.error(chalk.red(response.stderr));
|
|
42
|
+
}
|
|
43
|
+
// Display error from event
|
|
44
|
+
if (response.status === 'ERROR' && response.error) {
|
|
45
|
+
console.error(chalk.red(`Error: ${response.error}`));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Exit with the command's return code if available
|
|
49
|
+
if (response.return_code !== null && response.return_code !== 0) {
|
|
50
|
+
process.exit(response.return_code);
|
|
51
|
+
}
|
|
52
|
+
if (response.status === 'ERROR') {
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const formattedError = handleAxiosError(error);
|
|
58
|
+
output.error(`Failed to execute command: ${formattedError.details}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return cmd;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=exec.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
|
+
import { createOutputWriter } from '../../lib/output.js';
|
|
8
|
+
export function createContainerGetCommand() {
|
|
9
|
+
const cmd = new Command('get');
|
|
10
|
+
cmd
|
|
11
|
+
.description('Get container details')
|
|
12
|
+
.argument('<container-id>', 'Container ID')
|
|
13
|
+
.action(async (containerId) => {
|
|
14
|
+
const output = createOutputWriter();
|
|
15
|
+
try {
|
|
16
|
+
const token = await getAuthToken();
|
|
17
|
+
if (!token) {
|
|
18
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const client = new GuildAPIClient();
|
|
22
|
+
const response = await client.get(`/containers/${containerId}`);
|
|
23
|
+
output.data(response);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const formattedError = handleAxiosError(error);
|
|
27
|
+
output.error(`Failed to get container: ${formattedError.details}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return cmd;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=get.js.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
|
+
import { getOutputMode } from '../../lib/output-mode.js';
|
|
8
|
+
import { createOutputWriter, formatContainerTable } from '../../lib/output.js';
|
|
9
|
+
export function createContainerListCommand() {
|
|
10
|
+
const cmd = new Command('list');
|
|
11
|
+
cmd
|
|
12
|
+
.description('List containers for an account')
|
|
13
|
+
.requiredOption('--account <id-or-name>', 'Account ID or name')
|
|
14
|
+
.option('--status <status>', 'Filter by status: STARTING, RUNNING, ERRORED, DESTROYED')
|
|
15
|
+
.option('--limit <number>', 'Number of results to return', '20')
|
|
16
|
+
.option('--offset <number>', 'Offset for pagination', '0')
|
|
17
|
+
.action(async (options) => {
|
|
18
|
+
const output = createOutputWriter();
|
|
19
|
+
try {
|
|
20
|
+
const token = await getAuthToken();
|
|
21
|
+
if (!token) {
|
|
22
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
const client = new GuildAPIClient();
|
|
26
|
+
const params = new URLSearchParams();
|
|
27
|
+
params.append('limit', options.limit);
|
|
28
|
+
params.append('offset', options.offset);
|
|
29
|
+
if (options.status) {
|
|
30
|
+
params.append('statuses', options.status.toUpperCase());
|
|
31
|
+
}
|
|
32
|
+
const response = await client.get(`/accounts/${options.account}/containers?${params.toString()}`);
|
|
33
|
+
if (getOutputMode() === 'json') {
|
|
34
|
+
console.log(JSON.stringify(response, null, 2));
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
formatContainerTable(response.items, response.pagination);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const formattedError = handleAxiosError(error);
|
|
42
|
+
output.error(`Failed to list containers: ${formattedError.details}`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return cmd;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
|
+
import { createOutputWriter } from '../../lib/output.js';
|
|
8
|
+
export function createContainerImageCreateCommand() {
|
|
9
|
+
const cmd = new Command('create');
|
|
10
|
+
cmd
|
|
11
|
+
.description('Create a container image')
|
|
12
|
+
.requiredOption('--account <id-or-name>', 'Account or organization ID or name')
|
|
13
|
+
.requiredOption('--name <name>', 'Image name (1-100 characters)')
|
|
14
|
+
.requiredOption('--image <image>', 'Container image path (e.g. registry.example.com/org/image)')
|
|
15
|
+
.requiredOption('--tag <tag>', 'Image tag (e.g. latest)')
|
|
16
|
+
.action(async (opts) => {
|
|
17
|
+
const output = createOutputWriter();
|
|
18
|
+
try {
|
|
19
|
+
const token = await getAuthToken();
|
|
20
|
+
if (!token) {
|
|
21
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const client = new GuildAPIClient();
|
|
25
|
+
const response = await client.post('/container-images', {
|
|
26
|
+
name: opts.name,
|
|
27
|
+
image_name: opts.image,
|
|
28
|
+
tag: opts.tag,
|
|
29
|
+
owner_id_or_name: opts.account,
|
|
30
|
+
});
|
|
31
|
+
output.data(response);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
const formattedError = handleAxiosError(error);
|
|
35
|
+
output.error(`Failed to create container image: ${formattedError.details}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
return cmd;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
|
+
import { createOutputWriter } from '../../lib/output.js';
|
|
8
|
+
export function createContainerImageGetCommand() {
|
|
9
|
+
const cmd = new Command('get');
|
|
10
|
+
cmd
|
|
11
|
+
.description('Get container image details')
|
|
12
|
+
.argument('<image-id-or-name>', 'Container image ID or name (owner~name)')
|
|
13
|
+
.action(async (imageIdOrName) => {
|
|
14
|
+
const output = createOutputWriter();
|
|
15
|
+
try {
|
|
16
|
+
const token = await getAuthToken();
|
|
17
|
+
if (!token) {
|
|
18
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
const client = new GuildAPIClient();
|
|
22
|
+
const response = await client.get(`/container-images/${imageIdOrName}`);
|
|
23
|
+
output.data(response);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
const formattedError = handleAxiosError(error);
|
|
27
|
+
output.error(`Failed to get container image: ${formattedError.details}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return cmd;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=get.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
|
+
import { getOutputMode } from '../../lib/output-mode.js';
|
|
8
|
+
import { createOutputWriter, formatContainerImageTable } from '../../lib/output.js';
|
|
9
|
+
export function createContainerImageListCommand() {
|
|
10
|
+
const cmd = new Command('list');
|
|
11
|
+
cmd
|
|
12
|
+
.description('List container images for an account')
|
|
13
|
+
.requiredOption('--account <id-or-name>', 'Account ID or name')
|
|
14
|
+
.option('--limit <number>', 'Number of results to return', '20')
|
|
15
|
+
.option('--offset <number>', 'Offset for pagination', '0')
|
|
16
|
+
.action(async (options) => {
|
|
17
|
+
const output = createOutputWriter();
|
|
18
|
+
try {
|
|
19
|
+
const token = await getAuthToken();
|
|
20
|
+
if (!token) {
|
|
21
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const client = new GuildAPIClient();
|
|
25
|
+
const params = new URLSearchParams();
|
|
26
|
+
params.append('limit', options.limit);
|
|
27
|
+
params.append('offset', options.offset);
|
|
28
|
+
const response = await client.get(`/accounts/${options.account}/container-images?${params.toString()}`);
|
|
29
|
+
if (getOutputMode() === 'json') {
|
|
30
|
+
console.log(JSON.stringify(response, null, 2));
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
formatContainerImageTable(response.items, response.pagination);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
const formattedError = handleAxiosError(error);
|
|
38
|
+
output.error(`Failed to list container images: ${formattedError.details}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return cmd;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
|
+
import { getOutputMode } from '../../lib/output-mode.js';
|
|
8
|
+
import { createOutputWriter, formatJobStepTable } from '../../lib/output.js';
|
|
9
|
+
export function createJobGetCommand() {
|
|
10
|
+
const cmd = new Command('get');
|
|
11
|
+
cmd
|
|
12
|
+
.description('Get job details and steps')
|
|
13
|
+
.argument('<job-id>', 'Job ID')
|
|
14
|
+
.action(async (jobId) => {
|
|
15
|
+
const output = createOutputWriter();
|
|
16
|
+
try {
|
|
17
|
+
const token = await getAuthToken();
|
|
18
|
+
if (!token) {
|
|
19
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const client = new GuildAPIClient();
|
|
23
|
+
const [job, stepsResponse] = await Promise.all([
|
|
24
|
+
client.get(`/jobs/${jobId}`),
|
|
25
|
+
client.get(`/jobs/${jobId}/steps`),
|
|
26
|
+
]);
|
|
27
|
+
if (getOutputMode() === 'json') {
|
|
28
|
+
console.log(JSON.stringify({ ...job, steps: stepsResponse.steps }, null, 2));
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
output.data(job);
|
|
32
|
+
console.log();
|
|
33
|
+
formatJobStepTable(stepsResponse.steps);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
const formattedError = handleAxiosError(error);
|
|
38
|
+
output.error(`Failed to get job: ${formattedError.details}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return cmd;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=get.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
|
+
import { createOutputWriter } from '../../lib/output.js';
|
|
8
|
+
export function createJobStepGetCommand() {
|
|
9
|
+
const cmd = new Command('step-get');
|
|
10
|
+
cmd
|
|
11
|
+
.description('Get details of a step in a job')
|
|
12
|
+
.argument('<job-id>', 'Job ID')
|
|
13
|
+
.argument('<step-name>', 'Step name')
|
|
14
|
+
.action(async (jobId, stepName) => {
|
|
15
|
+
const output = createOutputWriter();
|
|
16
|
+
try {
|
|
17
|
+
const token = await getAuthToken();
|
|
18
|
+
if (!token) {
|
|
19
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
const client = new GuildAPIClient();
|
|
23
|
+
const stepsResponse = await client.get(`/jobs/${jobId}/steps`);
|
|
24
|
+
const step = stepsResponse.steps.find((s) => s.name === stepName);
|
|
25
|
+
if (!step) {
|
|
26
|
+
const available = stepsResponse.steps.map((s) => s.name).join(', ');
|
|
27
|
+
output.error(`Step "${stepName}" not found. Available steps: ${available || 'none'}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
output.data(step);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
const formattedError = handleAxiosError(error);
|
|
34
|
+
output.error(`Failed to get job step: ${formattedError.details}`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return cmd;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=step-get.js.map
|
package/dist/commands/setup.js
CHANGED
|
@@ -60,8 +60,8 @@ async function setupMcp(options) {
|
|
|
60
60
|
const content = await fs.readFile(mcpPath, 'utf-8');
|
|
61
61
|
existing = JSON.parse(content);
|
|
62
62
|
if (existing.mcpServers && 'guild' in existing.mcpServers && !options.force) {
|
|
63
|
-
output.progress('Guild
|
|
64
|
-
return;
|
|
63
|
+
output.progress('.mcp.json already has Guild server (use --force to overwrite)');
|
|
64
|
+
return 'skipped';
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
const updated = {
|
|
@@ -78,6 +78,7 @@ async function setupMcp(options) {
|
|
|
78
78
|
else {
|
|
79
79
|
output.success('Created .mcp.json with Guild MCP server');
|
|
80
80
|
}
|
|
81
|
+
return 'created';
|
|
81
82
|
}
|
|
82
83
|
async function setup(options) {
|
|
83
84
|
const output = createOutputWriter();
|
|
@@ -116,7 +117,13 @@ async function setup(options) {
|
|
|
116
117
|
}
|
|
117
118
|
// Handle --mcp flag
|
|
118
119
|
if (options.mcp) {
|
|
119
|
-
await setupMcp({ force: options.force });
|
|
120
|
+
const result = await setupMcp({ force: options.force });
|
|
121
|
+
if (result === 'created') {
|
|
122
|
+
filesCreated++;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
filesSkipped++;
|
|
126
|
+
}
|
|
120
127
|
}
|
|
121
128
|
// Handle CLAUDE.md template
|
|
122
129
|
if (options.claudeMd) {
|
|
@@ -155,7 +162,7 @@ export function createSetupCommand() {
|
|
|
155
162
|
.description('Set up Guild CLI skills for coding assistants (Claude Code, etc.)')
|
|
156
163
|
.option('--force', 'Overwrite existing skill files', false)
|
|
157
164
|
.option('--claude-md', 'Also create a CLAUDE.md template in the project root', false)
|
|
158
|
-
.option('--mcp', '
|
|
165
|
+
.option('--no-mcp', 'Skip MCP server configuration')
|
|
159
166
|
.action(async (options) => {
|
|
160
167
|
await setup(options);
|
|
161
168
|
});
|
|
@@ -24,6 +24,7 @@ export function createTriggerCreateCommand() {
|
|
|
24
24
|
.option('--time <time>', 'Time of day in HH:MM format')
|
|
25
25
|
.option('--days-of-week <days>', 'Days of week (comma-separated: MONDAY,TUESDAY,...)')
|
|
26
26
|
.option('--days-of-month <days>', 'Days of month (comma-separated: 1,15,-1)')
|
|
27
|
+
.option('--minutes-of-hour <minutes>', 'Minutes of hour, comma-separated (0-59)')
|
|
27
28
|
.option('--input <json>', 'Agent input as JSON object')
|
|
28
29
|
.action(async (options) => {
|
|
29
30
|
const output = createOutputWriter();
|
|
@@ -130,6 +131,9 @@ export function createTriggerCreateCommand() {
|
|
|
130
131
|
if (options.daysOfMonth) {
|
|
131
132
|
body.days_of_month = options.daysOfMonth;
|
|
132
133
|
}
|
|
134
|
+
if (options.minutesOfHour) {
|
|
135
|
+
body.minutes_of_hour = options.minutesOfHour;
|
|
136
|
+
}
|
|
133
137
|
}
|
|
134
138
|
const response = await client.post(`/workspaces/${workspaceId}/triggers`, body);
|
|
135
139
|
output.data(response);
|