@guildai/cli 0.5.3 → 0.5.4

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.
@@ -17,49 +17,55 @@
17
17
  import inquirer from 'inquirer';
18
18
  import { loadGlobalConfig } from './guild-config.js';
19
19
  import { debug } from './errors.js';
20
+ /**
21
+ * Look up an owner by ID or name against the current user and their organizations.
22
+ * Returns the resolved owner, or undefined if no match is found.
23
+ */
24
+ export async function lookupOwner(client, val) {
25
+ const me = await client.get('/me');
26
+ if (me.id === val || me.name === val) {
27
+ return { id: me.id, name: me.name, type: 'user' };
28
+ }
29
+ const orgs = await client.fetchAll('/me/organizations');
30
+ const org = orgs.find((o) => o.id === val || o.name === val);
31
+ if (org) {
32
+ return { id: org.id, name: org.name, type: 'organization' };
33
+ }
34
+ return undefined;
35
+ }
20
36
  export async function resolveOwnerId(options) {
21
37
  const { ownerFlag, client, interactive } = options;
22
38
  // Priority 1: --owner flag
23
39
  if (ownerFlag) {
24
40
  debug('Using owner from --owner flag: %s', ownerFlag);
25
- // Try to resolve name from API (user or org)
26
- const me = await client.get('/me');
27
- if (me.id === ownerFlag) {
28
- return { id: me.id, name: me.name, type: 'user' };
29
- }
30
- const orgs = await client.fetchAll('/me/organizations');
31
- const org = orgs.find((o) => o.id === ownerFlag);
32
- if (org) {
33
- return { id: org.id, name: org.name, type: 'organization' };
34
- }
41
+ const match = await lookupOwner(client, ownerFlag);
42
+ if (match)
43
+ return match;
35
44
  // Not found in user or orgs — pass through and let backend validate
36
45
  return { id: ownerFlag, name: ownerFlag, type: 'organization' };
37
46
  }
38
47
  // Priority 2: GUILD_OWNER_ID environment variable
39
48
  if (process.env.GUILD_OWNER_ID) {
40
49
  debug('Using owner from GUILD_OWNER_ID env var: %s', process.env.GUILD_OWNER_ID);
41
- const envOwnerId = process.env.GUILD_OWNER_ID;
42
- const me = await client.get('/me');
43
- if (me.id === envOwnerId) {
44
- return { id: me.id, name: me.name, type: 'user' };
45
- }
46
- const orgs = await client.fetchAll('/me/organizations');
47
- const org = orgs.find((o) => o.id === envOwnerId);
48
- if (org) {
49
- return { id: org.id, name: org.name, type: 'organization' };
50
- }
50
+ const match = await lookupOwner(client, process.env.GUILD_OWNER_ID);
51
+ if (match)
52
+ return match;
51
53
  // Not found in user or orgs — pass through and let backend validate
52
- return { id: envOwnerId, name: envOwnerId, type: 'organization' };
54
+ return {
55
+ id: process.env.GUILD_OWNER_ID,
56
+ name: process.env.GUILD_OWNER_ID,
57
+ type: 'organization',
58
+ };
53
59
  }
54
60
  // Priority 3: default_owner from config
55
61
  const globalConfig = await loadGlobalConfig();
56
62
  if (globalConfig?.default_owner) {
57
63
  debug('Using owner from global config: %s', globalConfig.default_owner);
64
+ const match = await lookupOwner(client, globalConfig.default_owner);
65
+ if (match)
66
+ return match;
58
67
  const name = globalConfig.default_owner_name || globalConfig.default_owner;
59
- // Determine type by checking against current user
60
- const me = await client.get('/me');
61
- const type = me.id === globalConfig.default_owner ? 'user' : 'organization';
62
- return { id: globalConfig.default_owner, name, type };
68
+ return { id: globalConfig.default_owner, name, type: 'organization' };
63
69
  }
64
70
  // Priority 4: Fetch user + orgs
65
71
  const me = await client.get('/me');
package/docs/DESIGN.md CHANGED
@@ -39,52 +39,51 @@ guild env go # Create environment and connect interactively
39
39
 
40
40
  ### Agent Management
41
41
 
42
- Manage agents via guildcore API with git-backed versioning:
43
-
44
- **Basic Operations:**
42
+ Manage agents via the GuildCore API with git-backed versioning:
45
43
 
46
44
  ```bash
47
- guild agent list # List all agents
48
- guild agent list --search "analytics" # Search agents
49
- guild agent create my-agent # Create new agent
50
- guild agent create my-agent --description "..." # Create with description
51
- guild agent get <agent-id> # Get agent details
52
- guild agent update <agent-id> --description "..." # Update description
45
+ guild agent init --name my-agent --template LLM # Initialize a new agent
46
+ guild agent clone owner/agent-name # Clone an existing agent
47
+ guild agent list # List all agents
48
+ guild agent search "analytics" # Search published agents
49
+ guild agent get [identifier] # Get agent details
50
+ guild agent versions [identifier] # List all versions
51
+ guild agent code [identifier] # Fetch latest published code
53
52
  ```
54
53
 
55
54
  **Version Control** (git-backed):
56
55
 
57
56
  ```bash
58
- guild agent save <agent-id> --message "Initial version" --directory ./code
59
- guild agent save <agent-id> --message "v1.0" --publish # Mark as published
60
- guild agent versions <agent-id> # List all versions
61
- guild agent code <agent-id> # Fetch latest published code
62
- guild agent code <agent-id> --draft # Include draft versions
63
- guild agent code <agent-id> --output ./my-agent # Download to directory
57
+ guild agent save --message "Initial version" # Save as draft
58
+ guild agent save --message "v1.0" --wait --publish # Save + validate + publish
59
+ guild agent pull # Pull remote changes
64
60
  ```
65
61
 
66
62
  **How it works:**
67
63
 
68
- - Each agent stores code in a git repository (managed by guildcore)
69
- - `save` creates a new version by committing files to git
64
+ - Each agent stores code in a git repository (managed by GuildCore)
65
+ - `save` commits and pushes code, creating a new version
70
66
  - Versions can be DRAFT or PUBLISHED
71
67
  - `code` fetches the latest version's files
72
68
  - Every version has a git commit SHA for traceability
73
69
 
74
- All agent commands interact with the guildcore backend API. The CLI is a remote client, similar to the web UI.
70
+ All agent commands interact with the GuildCore backend API. The CLI is a remote client, similar to the web UI.
75
71
 
76
72
  ### Chat
77
73
 
78
74
  Interactive chat with streaming:
79
75
 
80
76
  ```bash
81
- guild chat # Interactive chat session
82
- guild chat --debug # Enable debug logging
77
+ guild chat # Interactive chat session
78
+ guild chat "your message" # One-shot message
79
+ guild agent test # Test agent interactively
80
+ guild agent chat "Hello" # Send single message to agent
83
81
  ```
84
82
 
85
- ### Version
83
+ ### Diagnostics
86
84
 
87
85
  ```bash
86
+ guild doctor # Check CLI setup and diagnose issues
88
87
  guild version # Show CLI version info
89
88
  guild --version # Show version number
90
89
  ```
@@ -151,7 +150,7 @@ No YAML files. No terraform. No kubectl. Just simple commands.
151
150
  └────────────────────────┘
152
151
  ```
153
152
 
154
- The CLI is a thin client that communicates with GuildCore API (default: `http://localhost:5001`).
153
+ The CLI is a thin client that communicates with the GuildCore API (default: `https://app.guild.ai/api`).
155
154
 
156
155
  ---
157
156
 
@@ -187,49 +186,16 @@ Environments are Docker containers managed by GuildCore. The CLI provides a simp
187
186
 
188
187
  ---
189
188
 
190
- ## Implementation Status
191
-
192
- **Implemented (v0.1.0):**
193
-
194
- - ✅ OAuth device flow authentication
195
- - ✅ System keyring integration
196
- - ✅ Environment management (create, list, destroy, cleanup, exec, go)
197
- - ✅ Agent management (list, create, get, update)
198
- - ✅ Agent version control (save, versions, code) with git backing
199
- - ✅ Chat with streaming responses
200
- - ✅ JSON output for all commands
201
- - ✅ E2E test coverage
202
- - ✅ TypeScript implementation with Commander.js
203
-
204
- ---
205
-
206
189
  ## Integration with Developer Tools
207
190
 
208
- The CLI is designed to integrate with AI coding assistants like Claude Code, Cursor, and others.
191
+ The CLI integrates with AI coding assistants like Claude Code, Cursor, and others. Run `guild setup` to install Guild skills into your project.
209
192
 
210
193
  **Typical Workflow:**
211
194
 
212
- 1. Create agent: `guild agent create my-agent --description "..."`
195
+ 1. Initialize agent: `guild agent init --name my-agent --template LLM`
213
196
  2. Write agent code locally in your editor
214
- 3. Save as draft version: `guild agent save <agent-id> --message "WIP" --directory ./my-agent`
215
- 4. Test with chat: `guild chat`
197
+ 3. Test interactively: `guild agent test --ephemeral`
198
+ 4. Save as draft: `guild agent save --message "WIP"`
216
199
  5. Iterate on code and save new drafts
217
- 6. Publish stable version: `guild agent save <agent-id> --message "v1.0" --publish`
218
- 7. Pull code later: `guild agent code <agent-id> --output ./downloaded-agent`
219
-
220
- **Version Control Benefits:**
221
-
222
- - Edit code in your favorite editor (VS Code, Vim, etc.)
223
- - AI assistants can help write agent code
224
- - Save drafts for testing without affecting published versions
225
- - Full git history for every change
226
- - Download code to any machine
227
-
228
- The CLI meets developers where they are - use your preferred editor, AI assistant, and workflow.
229
-
230
- ---
231
-
232
- ## Related Documentation
233
-
234
- - [Specifications](../specs/) - Executable specs for all features
235
- - [CLI README](../README.md) - Installation and quick start
200
+ 6. Publish stable version: `guild agent save --message "v1.0" --wait --publish`
201
+ 7. Clone on another machine: `guild agent clone owner/my-agent`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guildai/cli",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Guild.ai CLI - Build, test, and deploy AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -89,12 +89,12 @@
89
89
  "@types/ws": "^8.5.13",
90
90
  "@typescript-eslint/eslint-plugin": "^8.50.0",
91
91
  "@typescript-eslint/parser": "^8.50.0",
92
- "@vitest/coverage-v8": "^2.1.8",
92
+ "@vitest/coverage-v8": "^4.1.2",
93
93
  "eslint": "^9.39.2",
94
94
  "prettier": "^3.7.4",
95
95
  "tsx": "^4.21.0",
96
96
  "typescript": "^5.7.2",
97
- "vitest": "^2.1.8"
97
+ "vitest": "^4.1.2"
98
98
  },
99
99
  "engines": {
100
100
  "node": ">=18.0.0"
@@ -1,44 +0,0 @@
1
- /**
2
- * JSON-serializable value type
3
- */
4
- type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
5
- interface JsonObject {
6
- [key: string]: JsonValue;
7
- }
8
- type JsonArray = JsonValue[];
9
- /**
10
- * Interface for output formatting in the CLI.
11
- * Implementations can provide different output styles (rich terminal, JSON, etc.)
12
- */
13
- export interface OutputFormatter {
14
- /**
15
- * Print an error message
16
- * @param message - The error message
17
- * @param details - Optional detailed error information
18
- */
19
- printError(message: string, details?: string): void;
20
- /**
21
- * Print a success message
22
- * @param message - The success message
23
- * @param data - Optional data to display with the message
24
- */
25
- printSuccess(message: string, data?: JsonObject): void;
26
- }
27
- /**
28
- * JSON output formatter - outputs all messages as JSON
29
- * Useful for scripting and programmatic consumption
30
- */
31
- export declare class JSONOutputFormatter implements OutputFormatter {
32
- printError(message: string, details?: string): void;
33
- printSuccess(message: string, data?: JsonObject): void;
34
- }
35
- /**
36
- * Rich terminal output formatter - uses colors and symbols
37
- * Provides a better user experience in interactive terminals
38
- */
39
- export declare class RichOutputFormatter implements OutputFormatter {
40
- printError(message: string, details?: string): void;
41
- printSuccess(message: string, data?: JsonObject): void;
42
- }
43
- export {};
44
- //# sourceMappingURL=formatters.d.ts.map
@@ -1,51 +0,0 @@
1
- // Copyright (c) 2026 Guild.ai All Rights Reserved
2
- import chalk from 'chalk';
3
- import { brand } from './colors.js';
4
- /**
5
- * JSON output formatter - outputs all messages as JSON
6
- * Useful for scripting and programmatic consumption
7
- */
8
- export class JSONOutputFormatter {
9
- printError(message, details) {
10
- const error = { error: message };
11
- if (details) {
12
- error.details = details;
13
- }
14
- console.log(JSON.stringify(error, null, 2));
15
- }
16
- printSuccess(message, data) {
17
- const result = { success: message };
18
- if (data) {
19
- Object.assign(result, data);
20
- }
21
- console.log(JSON.stringify(result, null, 2));
22
- }
23
- }
24
- /**
25
- * Rich terminal output formatter - uses colors and symbols
26
- * Provides a better user experience in interactive terminals
27
- */
28
- export class RichOutputFormatter {
29
- printError(message, details) {
30
- console.error(chalk.red(message));
31
- if (details) {
32
- console.error(chalk.dim(details));
33
- }
34
- }
35
- printSuccess(message, data) {
36
- console.log(chalk.green('✓'), message);
37
- if (data) {
38
- for (const [key, value] of Object.entries(data)) {
39
- const strValue = value === null
40
- ? 'null'
41
- : value === undefined
42
- ? 'undefined'
43
- : typeof value === 'object'
44
- ? JSON.stringify(value)
45
- : String(value);
46
- console.log(` ${key}: ${brand(strValue)}`);
47
- }
48
- }
49
- }
50
- }
51
- //# sourceMappingURL=formatters.js.map