@profoundlogic/coderflow-cli 0.2.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.
package/lib/help.js ADDED
@@ -0,0 +1,444 @@
1
+ /**
2
+ * Help text and usage information
3
+ */
4
+
5
+ const commandHelp = {
6
+ apply: `
7
+ Usage: coder apply [task-id] [options]
8
+
9
+ Apply patches from a completed task to your local repositories.
10
+ Changes are staged (git add) but not committed.
11
+
12
+ Arguments:
13
+ task-id Task ID to apply (optional - interactive selection if omitted)
14
+
15
+ Options:
16
+ --include=<pattern> Only apply files matching glob pattern
17
+
18
+ Examples:
19
+ coder apply # Interactive selection from completed tasks
20
+ coder apply 1759542727986-3uoyf48lr # Apply specific task
21
+ coder apply --include="*.js" # Only apply JavaScript files
22
+ `,
23
+
24
+ discard: `
25
+ Usage: coder discard [options]
26
+
27
+ Discard all uncommitted changes from repositories (unstage, restore, clean).
28
+ Use this to undo changes applied with 'coder apply'.
29
+
30
+ Options:
31
+ --env=<environment> Environment to discard changes from (uses default if omitted)
32
+ --yes Skip confirmation prompt
33
+
34
+ Examples:
35
+ coder discard # Discard changes in default environment
36
+ coder discard --env=hello # Discard changes in specific environment
37
+ coder discard --yes # Skip confirmation
38
+ `,
39
+
40
+ attach: `
41
+ Usage: coder attach [container-id] [options]
42
+
43
+ Connect to a running container.
44
+
45
+ Arguments:
46
+ container-id Container ID to attach to (optional - uses last container if omitted)
47
+
48
+ Options:
49
+ --agent=<agent> Agent to use (claude, codex)
50
+ --shell Start bash shell instead of agent
51
+
52
+ Examples:
53
+ coder attach # Reconnect to last container
54
+ coder attach 188b8e72d656 # Connect to specific container
55
+ coder attach --shell # Connect with bash shell
56
+ coder attach --agent=codex # Connect with specific agent
57
+ `,
58
+
59
+ login: `
60
+ Usage: coder login [options]
61
+
62
+ Authenticate with the CoderFlow server.
63
+
64
+ Options:
65
+ --sso Use Single Sign-On (OIDC) authentication
66
+
67
+ Without --sso, prompts for username and password.
68
+ With --sso, opens browser for OIDC device flow authentication.
69
+
70
+ Examples:
71
+ coder login # Username/password login
72
+ coder login --sso # SSO/OIDC login
73
+ `,
74
+
75
+ config: `
76
+ Usage: coder config <command> [key] [value]
77
+
78
+ Manage CLI configuration settings.
79
+
80
+ Commands:
81
+ show Show all configuration
82
+ get <key> Get a configuration value
83
+ set <key> <value> Set a configuration value
84
+ remove <key> Remove a configuration value
85
+
86
+ Keys:
87
+ serverUrl Server URL
88
+ apiKey API key (use 'coder login' instead)
89
+ defaultEnvironment Default environment for commands
90
+
91
+ Examples:
92
+ coder config show
93
+ coder config set serverUrl http://localhost:3000
94
+ coder config get serverUrl
95
+ coder config remove defaultEnvironment
96
+ `,
97
+
98
+ profile: `
99
+ Usage: coder profile <command> [options]
100
+
101
+ Manage CLI configuration profiles for multiple servers/environments.
102
+
103
+ Commands:
104
+ list List all profiles
105
+ show [name] Show profile details (active if no name)
106
+ create <name> Create a new profile
107
+ switch <name> Switch to a different profile
108
+ delete <name> Delete a profile
109
+ copy <source> <dest> Copy a profile
110
+ set <key> <value> Set a value in the active profile
111
+ get <key> Get a value from the active profile
112
+ current Show the current active profile name
113
+ migrate <name> Create profile from legacy config
114
+
115
+ Examples:
116
+ coder profile list
117
+ coder profile create prod
118
+ coder profile switch prod
119
+ coder profile set serverUrl https://prod.example.com
120
+ coder --profile=prod list # Use profile for single command
121
+ `,
122
+
123
+ run: `
124
+ Usage: coder run [task-type] [options]
125
+
126
+ Create and run a task. Usually done in the Web UI, but available here
127
+ for scripting or when browser access isn't available.
128
+
129
+ Arguments:
130
+ task-type Task template name (optional - interactive if omitted)
131
+
132
+ Options:
133
+ --env=<environment> Environment to run in
134
+ --<param>=<value> Template parameters (varies by template)
135
+
136
+ Examples:
137
+ coder run # Interactive task creation
138
+ coder run add-function --function_name=multiply # Run with template
139
+ coder run fix-test --env=hello --verbose=true # Specify environment
140
+ `,
141
+
142
+ status: `
143
+ Usage: coder status <task-id>
144
+
145
+ Check the status of a task.
146
+
147
+ Arguments:
148
+ task-id Task ID to check (required)
149
+
150
+ Examples:
151
+ coder status 1759542727986-3uoyf48lr
152
+ `,
153
+
154
+ results: `
155
+ Usage: coder results <task-id>
156
+
157
+ Get the results of a completed task.
158
+
159
+ Arguments:
160
+ task-id Task ID to get results for (required)
161
+
162
+ Examples:
163
+ coder results 1759542727986-3uoyf48lr
164
+ `,
165
+
166
+ logs: `
167
+ Usage: coder logs <task-id> [options]
168
+
169
+ Show logs from a task.
170
+
171
+ Arguments:
172
+ task-id Task ID to show logs for (required)
173
+
174
+ Options:
175
+ --tail=<N> Show last N lines only
176
+
177
+ Examples:
178
+ coder logs 1759542727986-3uoyf48lr
179
+ coder logs 1759542727986-3uoyf48lr --tail=100
180
+ `,
181
+
182
+ list: `
183
+ Usage: coder list [options]
184
+
185
+ List tasks with optional filters.
186
+
187
+ Options:
188
+ --status=<status> Filter by status (pending, running, completed, failed)
189
+ --environment=<name> Filter by environment
190
+
191
+ Examples:
192
+ coder list
193
+ coder list --status=completed
194
+ coder list --environment=hello --status=running
195
+ `,
196
+
197
+ reject: `
198
+ Usage: coder reject <task-id> [options]
199
+
200
+ Reject task results.
201
+
202
+ Arguments:
203
+ task-id Task ID to reject (required)
204
+
205
+ Options:
206
+ --cleanup Also delete task artifacts
207
+
208
+ Examples:
209
+ coder reject 1759542727986-3uoyf48lr
210
+ coder reject 1759542727986-3uoyf48lr --cleanup
211
+ `,
212
+
213
+ start: `
214
+ Usage: coder start <environment> [options]
215
+
216
+ Start an interactive session with an AI agent.
217
+ Usually done in the Web UI, but available here for CLI workflows.
218
+
219
+ Arguments:
220
+ environment Environment to start session in (required)
221
+
222
+ Options:
223
+ --agent=<agent> Agent to use (claude, codex)
224
+ --no-attach Start container but don't auto-connect
225
+ --branch <repo>=<branch> Override branch for specific repository
226
+ --env=<KEY>=<value> Pass custom environment variables
227
+
228
+ Examples:
229
+ coder start hello
230
+ coder start hello --agent=codex
231
+ coder start hello --no-attach
232
+ coder start hello --branch profoundjs=feature-xyz
233
+ `,
234
+
235
+ shell: `
236
+ Usage: coder shell <environment> [options]
237
+
238
+ Start an interactive bash shell session in an environment.
239
+ Usually done in the Web UI, but available here for CLI workflows.
240
+
241
+ Arguments:
242
+ environment Environment to start shell in (required)
243
+
244
+ Options:
245
+ --no-attach Start container but don't auto-connect
246
+ --branch <repo>=<branch> Override branch for specific repository
247
+ --env=<KEY>=<value> Pass custom environment variables
248
+
249
+ Examples:
250
+ coder shell hello
251
+ coder shell hello --branch profoundjs=feature-xyz
252
+ `,
253
+
254
+ test: `
255
+ Usage: coder test <test-name> [options]
256
+
257
+ Run tests in an ephemeral container with your local repository state.
258
+
259
+ Arguments:
260
+ test-name Name of the test to run (from environment's tests.json)
261
+
262
+ Options:
263
+ --env=<environment> Environment to run test in (uses default if omitted)
264
+ --cmd="<command>" Run custom command instead of named test
265
+ --list List available tests for the environment
266
+ --no-local-state Don't capture local repo state
267
+
268
+ Examples:
269
+ coder test mytest --env=hello # Run named test
270
+ coder test --list --env=hello # List available tests
271
+ coder test --cmd="npm test" # Run custom command
272
+ coder test mytest --no-local-state # Run without local changes
273
+ `,
274
+
275
+ containers: `
276
+ Usage: coder containers [command] [options]
277
+
278
+ List or clean containers.
279
+
280
+ Commands:
281
+ (none) List all containers
282
+ clean Clean up containers
283
+
284
+ Options (for clean):
285
+ --stopped Clean stopped containers
286
+ --older-than=<time> Clean containers older than time (e.g., 7d, 24h)
287
+ --dry-run Show what would be cleaned without doing it
288
+ --yes Skip confirmation
289
+
290
+ Examples:
291
+ coder containers
292
+ coder containers clean --stopped --yes
293
+ coder containers clean --older-than=7d --dry-run
294
+ `
295
+ };
296
+
297
+ /**
298
+ * Show help for a specific command
299
+ */
300
+ export function showCommandHelp(command) {
301
+ const help = commandHelp[command];
302
+ if (help) {
303
+ console.log(help);
304
+ return true;
305
+ }
306
+ return false;
307
+ }
308
+
309
+ export function showHelp() {
310
+ console.log(`
311
+ CoderFlow CLI
312
+
313
+ Usage: coder <command> [options]
314
+
315
+ Commands:
316
+ coder apply [task-id] Apply patches from completed task to local repos
317
+ coder discard [--env=<environment>] [--yes] Discard applied changes from repos
318
+ coder attach [container-id] [options] Connect to a running container
319
+
320
+ Setup:
321
+ coder login [--sso] Authenticate with server
322
+ coder config <set|get|remove|show> [key] [value] Manage CLI configuration
323
+ coder profile <command> [options] Manage connection profiles
324
+
325
+ Global Options:
326
+ --profile=<name> Use a specific profile for this command
327
+
328
+ Examples:
329
+ coder apply # Interactively select a completed task to apply
330
+ coder apply 1759542727986-3uoyf48lr # Apply patches from specific task
331
+ coder discard # Undo applied changes in default environment
332
+ coder discard --env=hello # Undo changes in specific environment
333
+ coder attach # Connect to last container
334
+ coder attach --shell # Connect and start bash shell
335
+
336
+ Task creation and management is best done in the Web UI.
337
+ For CLI alternatives to Web UI features: coder --help-all
338
+
339
+ Run 'coder <command> --help' for detailed command usage.
340
+ `);
341
+ }
342
+
343
+ export function showExtendedHelp() {
344
+ console.log(`
345
+ CoderFlow CLI - All Commands
346
+
347
+ ================================================================================
348
+ CORE COMMANDS
349
+ ================================================================================
350
+
351
+ These are the primary CLI commands for working with your local repositories.
352
+
353
+ Applying Changes:
354
+ coder apply [task-id] Apply patches from completed task to local repos
355
+ coder discard [--env=<environment>] [--yes] Discard applied changes from repos
356
+
357
+ Connecting to Containers:
358
+ coder attach [container-id] [--agent=<agent>] [--shell] Connect to a running container
359
+
360
+ Setup & Configuration:
361
+ coder login [--sso] Authenticate with server
362
+ coder config <set|get|remove|show> [key] [value] Manage CLI configuration
363
+ coder profile <command> [options] Manage connection profiles
364
+
365
+ ================================================================================
366
+ CLI ALTERNATIVES TO WEB UI
367
+ ================================================================================
368
+
369
+ These commands provide command-line access to features typically managed
370
+ through the Web UI. Use these when you prefer command-line workflows or
371
+ don't have browser access.
372
+
373
+ Task Management:
374
+ coder run <task-type> [--env=<env>] [--param=val] Create and run a task with template
375
+ coder run Create and run a task interactively
376
+ coder status <task-id> Check status of a task
377
+ coder results <task-id> Get results of a completed task
378
+ coder logs <task-id> [--tail=N] Show task logs
379
+ coder list [--status=...] [--environment=...] List tasks with optional filters
380
+ coder reject <task-id> [--cleanup] Reject task results
381
+
382
+ Interactive Sessions:
383
+ coder start <environment> [options] Start interactive session with AI agent
384
+ coder shell <environment> [options] Start interactive session with bash shell
385
+
386
+ Testing & Containers:
387
+ coder test <test-name> [--env=<environment>] Run tests in environment
388
+ coder containers [clean] [options] List or clean containers
389
+
390
+ ================================================================================
391
+ PROFILE COMMANDS
392
+ ================================================================================
393
+
394
+ coder profile list List all profiles (shows active profile)
395
+ coder profile show [name] Show profile details (active if no name)
396
+ coder profile create <name> Create a new profile
397
+ coder profile switch <name> Switch to a different profile
398
+ coder profile delete <name> Delete a profile
399
+ coder profile copy <source> <dest> Copy an existing profile
400
+ coder profile set <key> <value> Set a value in the active profile
401
+ coder profile get <key> Get a value from the active profile
402
+ coder profile current Show the current active profile name
403
+ coder profile migrate <name> Create profile from legacy config
404
+
405
+ ================================================================================
406
+ ENVIRONMENT VARIABLES
407
+ ================================================================================
408
+
409
+ CODER_SERVER_URL Server URL (default: http://localhost:3000)
410
+ CODER_API_KEY API key for authentication (use 'coder login' to generate)
411
+ CODER_PROFILE Override active profile (takes precedence over config)
412
+
413
+ ================================================================================
414
+ EXAMPLES
415
+ ================================================================================
416
+
417
+ Core Workflow:
418
+ coder apply # Interactively select a completed task
419
+ coder apply 1759542727986-3uoyf48lr # Apply patches from specific task
420
+ coder discard # Undo all changes in default environment
421
+ coder discard --env=hello --yes # Undo changes, skip confirmation
422
+ coder attach # Connect to last container
423
+ coder attach 188b8e72d656 --shell # Connect to specific container with shell
424
+
425
+ Setup:
426
+ coder login # Authenticate with username/password
427
+ coder login --sso # Authenticate with SSO/OIDC
428
+ coder config set serverUrl http://localhost:3000 # Set server URL
429
+ coder profile create prod # Create a new profile
430
+ coder profile switch prod # Switch to prod profile
431
+
432
+ Task Management (Web UI alternative):
433
+ coder run add-function --function_name=multiply # Run task with template
434
+ coder run add-function --env=hello --verbose=true # Run in specific environment
435
+ coder status 1759542727986-3uoyf48lr # Check task status
436
+ coder results 1759542727986-3uoyf48lr # Get task results
437
+ coder list --status=completed # List completed tasks
438
+
439
+ Interactive Sessions (Web UI alternative):
440
+ coder start hello # Start AI agent in environment
441
+ coder start hello --agent=codex # Start with specific agent
442
+ coder shell hello # Start bash shell in environment
443
+ `);
444
+ }
@@ -0,0 +1,180 @@
1
+ /**
2
+ * HTTP client for Coder Server API
3
+ */
4
+
5
+ import { getServerUrl, getApiKey } from './config.js';
6
+
7
+ /**
8
+ * Format a helpful error message based on error type
9
+ */
10
+ function formatErrorMessage(error, url, response, serverUrl) {
11
+ // Connection errors
12
+ if (error.code === 'ECONNREFUSED' || error.cause?.code === 'ECONNREFUSED') {
13
+ console.error(`\nError: Cannot connect to Coder server at ${serverUrl}`);
14
+ console.error('\nPossible solutions:');
15
+ console.error(' 1. Start the server:');
16
+ console.error(' cd packages/server && CODER_SETUP_PATH=/path/to/coder-setup npm start');
17
+ console.error(' 2. Check if server is running on a different port');
18
+ console.error(' 3. Set CODER_SERVER_URL environment variable if using non-default port');
19
+ return true;
20
+ }
21
+
22
+ if (error.code === 'ENOTFOUND' || error.cause?.code === 'ENOTFOUND') {
23
+ console.error(`\nError: Cannot resolve hostname: ${serverUrl}`);
24
+ console.error('\nCheck CODER_SERVER_URL environment variable');
25
+ return true;
26
+ }
27
+
28
+ // HTTP errors with response
29
+ if (response) {
30
+ const status = response.status;
31
+ const message = error.message;
32
+
33
+ // Special case: 404 on local-state-summary is expected (file not created yet)
34
+ // Don't treat as fatal error, allow retry logic to handle it
35
+ if (status === 404 && url.includes('/local-state-summary')) {
36
+ return false; // Not fatal, caller can retry
37
+ }
38
+
39
+ console.error(`\nError: ${message}`);
40
+
41
+ // Provide actionable guidance based on status code
42
+ if (status === 401) {
43
+ console.error('\nAuthentication required.');
44
+ console.error('Possible solutions:');
45
+ console.error(' 1. Log in: coder login');
46
+ console.error(' 2. Set API key: export CODER_API_KEY=your-key');
47
+ console.error(' 3. Your session may have expired - log in again');
48
+ } else if (status === 403) {
49
+ console.error('\nPermission denied.');
50
+ console.error('You do not have permission to access this resource.');
51
+ console.error('Contact an administrator if you believe this is an error.');
52
+ } else if (status === 404) {
53
+ if (url.includes('/tasks/')) {
54
+ console.error('\nThe requested task was not found.');
55
+ console.error('Possible solutions:');
56
+ console.error(' 1. Check the task ID is correct');
57
+ console.error(' 2. Use "coder list" to see all tasks');
58
+ console.error(' 3. Server may have been restarted (task state is not persistent)');
59
+ } else if (url.includes('/containers/')) {
60
+ console.error('\nThe requested container was not found.');
61
+ console.error('Possible solutions:');
62
+ console.error(' 1. Check the container ID is correct');
63
+ console.error(' 2. Use "coder containers" to list all containers');
64
+ } else if (url.includes('/environments/')) {
65
+ console.error('\nThe requested environment was not found.');
66
+ console.error('Possible solutions:');
67
+ console.error(' 1. Check environment name spelling');
68
+ console.error(' 2. Use "coder run --env=<name>" with a valid environment');
69
+ console.error(' 3. Check environments/ directory in your coder-setup');
70
+ }
71
+ } else if (status === 400) {
72
+ console.error('\nBad request - check your command arguments');
73
+ } else if (status === 413) {
74
+ console.error('\nRequest too large.');
75
+ console.error('\nThe data you are trying to send is too large for the server to process.');
76
+ console.error('This typically occurs when capturing local state with large diffs.');
77
+ console.error('\nPossible solutions:');
78
+ console.error(' 1. Commit or stash large changes before capturing local state');
79
+ console.error(' 2. Reduce the number of modified files');
80
+ console.error(' 3. Contact an administrator to increase server payload limits');
81
+ } else if (status === 500) {
82
+ console.error('\nServer error occurred.');
83
+
84
+ // Show detailed error message if available
85
+ if (error.detailedError && error.detailedError !== message) {
86
+ console.error(`\nServer Error Details:`);
87
+ console.error(` ${error.detailedError}`);
88
+ }
89
+
90
+ console.error('\nPossible solutions:');
91
+ console.error(' 1. Check server logs for details');
92
+ console.error(' 2. Verify Docker is running: docker ps');
93
+ console.error(' 3. Check CODER_SETUP_PATH is set correctly');
94
+ console.error(' 4. Verify coder-setup configuration files are valid');
95
+ }
96
+
97
+ return true;
98
+ }
99
+
100
+ return false;
101
+ }
102
+
103
+ /**
104
+ * Make HTTP request to Coder Server
105
+ */
106
+ export async function request(path, options = {}) {
107
+ const serverUrl = await getServerUrl();
108
+ const url = `${serverUrl}${path}`;
109
+
110
+ try {
111
+ const { parse = 'json', ...fetchOptions } = options;
112
+
113
+ // Get API key and add to headers if available
114
+ const apiKey = await getApiKey();
115
+ const headers = {
116
+ 'Content-Type': 'application/json',
117
+ ...fetchOptions.headers
118
+ };
119
+
120
+ if (apiKey) {
121
+ headers['Authorization'] = `Bearer ${apiKey}`;
122
+ }
123
+
124
+ const response = await fetch(url, {
125
+ ...fetchOptions,
126
+ headers
127
+ });
128
+
129
+ let data;
130
+
131
+ if (parse === 'text') {
132
+ data = await response.text();
133
+ } else {
134
+ const contentType = response.headers.get('content-type') || '';
135
+ if (contentType.includes('application/json')) {
136
+ data = await response.json();
137
+ } else {
138
+ data = await response.text();
139
+ }
140
+ }
141
+
142
+ if (!response.ok) {
143
+ let message;
144
+ let detailedError = null;
145
+
146
+ if (typeof data === 'string') {
147
+ message = data.trim() || `HTTP ${response.status}`;
148
+ // Try to parse error details from string response
149
+ detailedError = data.trim();
150
+ } else {
151
+ message = data?.error || data?.message || `HTTP ${response.status}`;
152
+ // Capture additional error details if available
153
+ if (data?.error && data?.message) {
154
+ detailedError = `${data.error}: ${data.message}`;
155
+ } else if (data?.message) {
156
+ detailedError = data.message;
157
+ } else if (data?.error) {
158
+ detailedError = data.error;
159
+ }
160
+ }
161
+
162
+ const error = new Error(message);
163
+ error.detailedError = detailedError;
164
+ error.statusCode = response.status;
165
+
166
+ if (formatErrorMessage(error, url, response, serverUrl)) {
167
+ process.exit(1);
168
+ }
169
+ throw error;
170
+ }
171
+
172
+ return data;
173
+ } catch (error) {
174
+ // Handle network/connection errors
175
+ if (formatErrorMessage(error, url, null, serverUrl)) {
176
+ process.exit(1);
177
+ }
178
+ throw error;
179
+ }
180
+ }