@clipboard-health/groundcrew 4.47.3 → 4.47.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.
- package/README.md +1 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +19 -1
- package/dist/commands/completions.d.ts +45 -0
- package/dist/commands/completions.d.ts.map +1 -0
- package/dist/commands/completions.js +524 -0
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -1
- package/docs/commands.md +21 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,6 +111,7 @@ crew open <pr> | --branch <name> [--repo <owner/repo>] # iterate on an existing
|
|
|
111
111
|
crew cleanup [--force] <TASK> # tear down every worktree for a task
|
|
112
112
|
crew cleanup [--force] --all # tear down every idle worktree (no live workspace)
|
|
113
113
|
crew upgrade [<version>] # reinstall crew globally through npm
|
|
114
|
+
crew completions <bash|zsh|fish> # print a shell completion script
|
|
114
115
|
```
|
|
115
116
|
|
|
116
117
|
See [command details](./docs/commands.md) for status output, doctor behavior, and the stop/resume workflow.
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The command names shown in `crew --help` and offered by shell completions:
|
|
3
|
+
* every registered subcommand that is neither hidden nor a deprecated alias.
|
|
4
|
+
*/
|
|
5
|
+
export declare function visibleCommandNames(): readonly string[];
|
|
1
6
|
export declare function run(argv: string[]): Promise<void>;
|
|
2
7
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAuPA;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,MAAM,EAAE,CAIvD;AAiDD,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwCvD"}
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { cleanupWorkspaceCli } from "./commands/cleanupWorkspace.js";
|
|
3
|
+
import { completionsCli } from "./commands/completions.js";
|
|
3
4
|
import { doctor } from "./commands/doctor.js";
|
|
4
5
|
import { initConfigCli } from "./commands/init.js";
|
|
5
6
|
import { interruptWorkspaceCli } from "./commands/interruptWorkspace.js";
|
|
@@ -186,9 +187,26 @@ const SUBCOMMANDS = {
|
|
|
186
187
|
usage: "[<version>]",
|
|
187
188
|
invoke: upgradeCliInvoke,
|
|
188
189
|
},
|
|
190
|
+
completions: {
|
|
191
|
+
summary: "Print a shell completion script for bash, zsh, or fish",
|
|
192
|
+
usage: "<bash|zsh|fish>",
|
|
193
|
+
invoke: completionsCli,
|
|
194
|
+
},
|
|
189
195
|
};
|
|
196
|
+
function isVisibleCommand(command) {
|
|
197
|
+
return command.hidden !== true && command.deprecated !== true;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* The command names shown in `crew --help` and offered by shell completions:
|
|
201
|
+
* every registered subcommand that is neither hidden nor a deprecated alias.
|
|
202
|
+
*/
|
|
203
|
+
export function visibleCommandNames() {
|
|
204
|
+
return Object.entries(SUBCOMMANDS)
|
|
205
|
+
.filter(([, command]) => isVisibleCommand(command))
|
|
206
|
+
.map(([name]) => name);
|
|
207
|
+
}
|
|
190
208
|
function printHelp() {
|
|
191
|
-
const visibleCommands = Object.entries(SUBCOMMANDS).filter(([, command]) => command
|
|
209
|
+
const visibleCommands = Object.entries(SUBCOMMANDS).filter(([, command]) => isVisibleCommand(command));
|
|
192
210
|
const width = Math.max(...visibleCommands.map(([key]) => key.length));
|
|
193
211
|
writeOutput("Usage: crew <command> [...args]\n");
|
|
194
212
|
writeOutput("Options:");
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emits shell completion scripts for the `crew` CLI. The command tree is
|
|
3
|
+
* declared once in `COMPLETION_SPEC` below and rendered into bash, zsh, and
|
|
4
|
+
* fish scripts. Keep the spec in sync with the parsers in this directory; the
|
|
5
|
+
* `completions.test.ts` drift guard asserts the top-level command names match
|
|
6
|
+
* the visible entries in `SUBCOMMANDS` (see `../cli.ts`).
|
|
7
|
+
*/
|
|
8
|
+
/** Describes the value a flag consumes, driving per-shell value completion. */
|
|
9
|
+
type CompletionArg = {
|
|
10
|
+
readonly kind: "enum";
|
|
11
|
+
readonly values: readonly string[];
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: "file";
|
|
14
|
+
} | {
|
|
15
|
+
readonly kind: "dir";
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: "string";
|
|
18
|
+
};
|
|
19
|
+
interface CompletionOption {
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly short?: string;
|
|
22
|
+
readonly summary: string;
|
|
23
|
+
/** Omitted for boolean flags; present when the flag takes a value. */
|
|
24
|
+
readonly arg?: CompletionArg;
|
|
25
|
+
}
|
|
26
|
+
export interface CompletionCommand {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly summary: string;
|
|
29
|
+
readonly options?: readonly CompletionOption[];
|
|
30
|
+
readonly subcommands?: readonly CompletionCommand[];
|
|
31
|
+
/** Static positional values (e.g. `crew completions <shell>`). */
|
|
32
|
+
readonly argValues?: readonly string[];
|
|
33
|
+
}
|
|
34
|
+
export declare const SUPPORTED_SHELLS: readonly ["bash", "zsh", "fish"];
|
|
35
|
+
export type SupportedShell = (typeof SUPPORTED_SHELLS)[number];
|
|
36
|
+
/**
|
|
37
|
+
* The single source of truth for shell completions. Ordering mirrors
|
|
38
|
+
* `crew --help`; hidden and deprecated commands are intentionally excluded.
|
|
39
|
+
*/
|
|
40
|
+
export declare const COMPLETION_SPEC: readonly CompletionCommand[];
|
|
41
|
+
/** Renders the completion script for a supported shell. */
|
|
42
|
+
export declare function generateCompletionScript(shell: SupportedShell): string;
|
|
43
|
+
export declare function completionsCli(argv: string[]): Promise<void>;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=completions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completions.d.ts","sourceRoot":"","sources":["../../src/commands/completions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,+EAA+E;AAC/E,KAAK,aAAa,GACd;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC7D;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;CAAE,GACxB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEhC,UAAU,gBAAgB;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACpD,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,eAAO,MAAM,gBAAgB,YAAI,MAAM,EAAE,KAAK,EAAE,MAAM,CAAU,CAAC;AAEjE,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AA2B/D;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,iBAAiB,EAqJvD,CAAC;AAqXF,2DAA2D;AAC3D,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAEtE;AAQD,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAUlE"}
|
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emits shell completion scripts for the `crew` CLI. The command tree is
|
|
3
|
+
* declared once in `COMPLETION_SPEC` below and rendered into bash, zsh, and
|
|
4
|
+
* fish scripts. Keep the spec in sync with the parsers in this directory; the
|
|
5
|
+
* `completions.test.ts` drift guard asserts the top-level command names match
|
|
6
|
+
* the visible entries in `SUBCOMMANDS` (see `../cli.ts`).
|
|
7
|
+
*/
|
|
8
|
+
import { LOCAL_RUNNER_SETTINGS } from "../lib/config.js";
|
|
9
|
+
import { shellSingleQuote } from "../lib/shell.js";
|
|
10
|
+
import { writeOutput } from "../lib/util.js";
|
|
11
|
+
import { INIT_AGENTS } from "./init.js";
|
|
12
|
+
export const SUPPORTED_SHELLS = ["bash", "zsh", "fish"];
|
|
13
|
+
// `--runner` and `init --agent` values come from the canonical lists their
|
|
14
|
+
// parsers validate against (config.ts, init.ts) so completions never drift.
|
|
15
|
+
// Status has no exported canonical array to import, so it stays a local literal.
|
|
16
|
+
const STATUS_VALUES = ["todo", "in-progress", "in-review", "done", "other"];
|
|
17
|
+
// `init` validates `--agent` against a fixed built-in set; `open`/`task` accept
|
|
18
|
+
// any configured agent name, so their `--agent` is declared free-form (string).
|
|
19
|
+
const INIT_AGENT_OPTION = {
|
|
20
|
+
name: "--agent",
|
|
21
|
+
summary: "Agent name",
|
|
22
|
+
arg: { kind: "enum", values: INIT_AGENTS },
|
|
23
|
+
};
|
|
24
|
+
const REPO_OPTION = {
|
|
25
|
+
name: "--repo",
|
|
26
|
+
summary: "Repository (owner/repo)",
|
|
27
|
+
arg: { kind: "string" },
|
|
28
|
+
};
|
|
29
|
+
const SOURCE_OPTION = {
|
|
30
|
+
name: "--source",
|
|
31
|
+
summary: "Task source name",
|
|
32
|
+
arg: { kind: "string" },
|
|
33
|
+
};
|
|
34
|
+
const JSON_OPTION = { name: "--json", summary: "Print JSON output" };
|
|
35
|
+
const DRY_RUN_OPTION = { name: "--dry-run", summary: "Preview without acting" };
|
|
36
|
+
/**
|
|
37
|
+
* The single source of truth for shell completions. Ordering mirrors
|
|
38
|
+
* `crew --help`; hidden and deprecated commands are intentionally excluded.
|
|
39
|
+
*/
|
|
40
|
+
export const COMPLETION_SPEC = [
|
|
41
|
+
{
|
|
42
|
+
name: "init",
|
|
43
|
+
summary: "Create a crew.config.ts",
|
|
44
|
+
options: [
|
|
45
|
+
{ name: "--global", summary: "Write into the XDG config dir" },
|
|
46
|
+
{ name: "--local", summary: "Write into the current directory" },
|
|
47
|
+
{ name: "--force", summary: "Overwrite an existing config" },
|
|
48
|
+
DRY_RUN_OPTION,
|
|
49
|
+
{ name: "--project-dir", summary: "Workspace project directory", arg: { kind: "dir" } },
|
|
50
|
+
REPO_OPTION,
|
|
51
|
+
{
|
|
52
|
+
name: "--runner",
|
|
53
|
+
summary: "Sandbox runner",
|
|
54
|
+
arg: { kind: "enum", values: LOCAL_RUNNER_SETTINGS },
|
|
55
|
+
},
|
|
56
|
+
INIT_AGENT_OPTION,
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "run",
|
|
61
|
+
summary: "Run the orchestrator over eligible tasks",
|
|
62
|
+
options: [{ name: "--watch", summary: "Poll continuously" }, DRY_RUN_OPTION],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "start",
|
|
66
|
+
summary: "Launch one task immediately",
|
|
67
|
+
options: [DRY_RUN_OPTION],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "doctor",
|
|
71
|
+
summary: "Verify host prerequisites",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: "source",
|
|
75
|
+
summary: "Inspect configured task sources",
|
|
76
|
+
subcommands: [
|
|
77
|
+
{ name: "list", summary: "List configured sources", options: [JSON_OPTION] },
|
|
78
|
+
{ name: "verify", summary: "Verify one or all sources", options: [JSON_OPTION] },
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "task",
|
|
83
|
+
summary: "List, get, create, and complete tasks",
|
|
84
|
+
subcommands: [
|
|
85
|
+
{
|
|
86
|
+
name: "list",
|
|
87
|
+
summary: "List tasks across sources",
|
|
88
|
+
options: [
|
|
89
|
+
SOURCE_OPTION,
|
|
90
|
+
{
|
|
91
|
+
name: "--status",
|
|
92
|
+
summary: "Filter by status",
|
|
93
|
+
arg: { kind: "enum", values: STATUS_VALUES },
|
|
94
|
+
},
|
|
95
|
+
{ name: "--agent", summary: "Filter by agent name", arg: { kind: "string" } },
|
|
96
|
+
REPO_OPTION,
|
|
97
|
+
{ name: "--blocked", summary: "Show only blocked tasks" },
|
|
98
|
+
{ name: "--unblocked", summary: "Show only unblocked tasks" },
|
|
99
|
+
JSON_OPTION,
|
|
100
|
+
{ name: "--limit", summary: "Limit output count", arg: { kind: "string" } },
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "get",
|
|
105
|
+
summary: "Get one task",
|
|
106
|
+
options: [
|
|
107
|
+
SOURCE_OPTION,
|
|
108
|
+
JSON_OPTION,
|
|
109
|
+
{ name: "--prompt", summary: "Print only the task prompt" },
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "create",
|
|
114
|
+
summary: "Create one task",
|
|
115
|
+
options: [
|
|
116
|
+
SOURCE_OPTION,
|
|
117
|
+
{ name: "--agent", summary: "Assign an agent", arg: { kind: "string" } },
|
|
118
|
+
REPO_OPTION,
|
|
119
|
+
{ name: "--team", summary: "Team key", arg: { kind: "string" } },
|
|
120
|
+
{ name: "--id", summary: "Explicit task id", arg: { kind: "string" } },
|
|
121
|
+
{ name: "--priority", summary: "Priority", arg: { kind: "string" } },
|
|
122
|
+
{ name: "--project", summary: "Project (repeatable)", arg: { kind: "string" } },
|
|
123
|
+
{ name: "--context", summary: "Context tag (repeatable)", arg: { kind: "string" } },
|
|
124
|
+
{ name: "--dep", summary: "Dependency (repeatable)", arg: { kind: "string" } },
|
|
125
|
+
{ name: "--due", summary: "Due date", arg: { kind: "string" } },
|
|
126
|
+
{ name: "--rec", summary: "Recurrence", arg: { kind: "string" } },
|
|
127
|
+
{ name: "--prompt-file", summary: "Read prompt from file", arg: { kind: "file" } },
|
|
128
|
+
{ name: "--description", summary: "Task description", arg: { kind: "string" } },
|
|
129
|
+
{ name: "--edit", summary: "Open an editor" },
|
|
130
|
+
JSON_OPTION,
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "done",
|
|
135
|
+
summary: "Mark one task done",
|
|
136
|
+
options: [{ name: "--allow-dirty", summary: "Allow a dirty worktree" }],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "validate",
|
|
140
|
+
summary: "Validate task content",
|
|
141
|
+
options: [JSON_OPTION],
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "status",
|
|
147
|
+
summary: "Print groundcrew state or a task status",
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: "cleanup",
|
|
151
|
+
summary: "Tear down a worktree, or all idle worktrees",
|
|
152
|
+
options: [
|
|
153
|
+
{ name: "--force", summary: "Skip confirmations" },
|
|
154
|
+
{ name: "--all", summary: "Clean up every idle worktree" },
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "stop",
|
|
159
|
+
summary: "Stop a live task workspace",
|
|
160
|
+
options: [{ name: "--reason", summary: "Reason text", arg: { kind: "string" } }],
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: "resume",
|
|
164
|
+
summary: "Reopen an existing task worktree",
|
|
165
|
+
options: [{ name: "--new", summary: "Start a fresh chat session" }],
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "open",
|
|
169
|
+
summary: "Open a PR or branch in a new worktree",
|
|
170
|
+
options: [
|
|
171
|
+
{ name: "--branch", summary: "Branch name", arg: { kind: "string" } },
|
|
172
|
+
REPO_OPTION,
|
|
173
|
+
{ name: "--agent", summary: "Agent name", arg: { kind: "string" } },
|
|
174
|
+
{ name: "--prompt", summary: "Prompt text", arg: { kind: "string" } },
|
|
175
|
+
{ name: "--prompt-file", summary: "Read prompt from file", arg: { kind: "file" } },
|
|
176
|
+
{ name: "--task", summary: "Associate a task id", arg: { kind: "string" } },
|
|
177
|
+
DRY_RUN_OPTION,
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: "upgrade",
|
|
182
|
+
summary: "Install the latest version of crew",
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: "completions",
|
|
186
|
+
summary: "Print a shell completion script",
|
|
187
|
+
argValues: SUPPORTED_SHELLS,
|
|
188
|
+
},
|
|
189
|
+
];
|
|
190
|
+
/** Global flags valid only as the first token. */
|
|
191
|
+
const TOP_LEVEL_GLOBALS = [
|
|
192
|
+
{ name: "--help", short: "-h", summary: "Show help" },
|
|
193
|
+
{ name: "--version", short: "-v", summary: "Print version" },
|
|
194
|
+
{ name: "--verbose", summary: "Show diagnostic output" },
|
|
195
|
+
];
|
|
196
|
+
/** The one global flag every subcommand tolerates (stripped before dispatch). */
|
|
197
|
+
const COMMAND_GLOBAL = "--verbose";
|
|
198
|
+
function optionTokens(options) {
|
|
199
|
+
return (options ?? []).flatMap((option) => option.short === undefined ? [option.name] : [option.name, option.short]);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Collects every value-taking flag across the tree, keyed by flag name, for the
|
|
203
|
+
* shell `prev`-based value cases (bash/zsh) which key on flag name globally.
|
|
204
|
+
* A flag can be declared with different kinds across commands (e.g. `--agent`
|
|
205
|
+
* is an enum under `init` but free-form under `open`/`task`); prefer the enum so
|
|
206
|
+
* value suggestions survive regardless of spec order.
|
|
207
|
+
*/
|
|
208
|
+
function valueArgsByName() {
|
|
209
|
+
const result = new Map();
|
|
210
|
+
function visit(command) {
|
|
211
|
+
for (const option of command.options ?? []) {
|
|
212
|
+
if (option.arg !== undefined) {
|
|
213
|
+
const existing = result.get(option.name);
|
|
214
|
+
if (existing?.kind !== "enum") {
|
|
215
|
+
result.set(option.name, option.arg);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
for (const subcommand of command.subcommands ?? []) {
|
|
220
|
+
visit(subcommand);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
for (const command of COMPLETION_SPEC) {
|
|
224
|
+
visit(command);
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
/** Appends the one global flag (`--verbose`) every subcommand tolerates. */
|
|
229
|
+
function withVerbose(tokens) {
|
|
230
|
+
return [...tokens, COMMAND_GLOBAL].join(" ");
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Walks every value-taking flag once and emits a per-shell `case` line via the
|
|
234
|
+
* given templates. Enum/file/dir flags each get their own line; plain string
|
|
235
|
+
* flags collapse into one fall-through case that offers no completion.
|
|
236
|
+
*/
|
|
237
|
+
function valueCases(render) {
|
|
238
|
+
const lines = [];
|
|
239
|
+
const stringNames = [];
|
|
240
|
+
for (const [name, arg] of valueArgsByName()) {
|
|
241
|
+
if (arg.kind === "enum") {
|
|
242
|
+
lines.push(render.enum(name, arg.values));
|
|
243
|
+
}
|
|
244
|
+
else if (arg.kind === "file") {
|
|
245
|
+
lines.push(render.file(name));
|
|
246
|
+
}
|
|
247
|
+
else if (arg.kind === "dir") {
|
|
248
|
+
lines.push(render.dir(name));
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
stringNames.push(name);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
lines.push(render.string(stringNames));
|
|
255
|
+
return lines.join("\n");
|
|
256
|
+
}
|
|
257
|
+
// -- bash ------------------------------------------------------------------
|
|
258
|
+
function bashValueCases() {
|
|
259
|
+
return valueCases({
|
|
260
|
+
enum: (name, values) => ` ${name}) COMPREPLY=( $(compgen -W "${values.join(" ")}" -- "$cur") ); return ;;`,
|
|
261
|
+
file: (name) => ` ${name}) COMPREPLY=( $(compgen -f -- "$cur") ); return ;;`,
|
|
262
|
+
dir: (name) => ` ${name}) COMPREPLY=( $(compgen -d -- "$cur") ); return ;;`,
|
|
263
|
+
string: (names) => ` ${names.join("|")}) return ;;`,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
function bashCommandCase(command) {
|
|
267
|
+
if (command.subcommands !== undefined) {
|
|
268
|
+
const subNames = command.subcommands.map((sub) => sub.name);
|
|
269
|
+
const subCases = command.subcommands
|
|
270
|
+
.map((sub) => ` ${sub.name}) COMPREPLY=( $(compgen -W "${withVerbose(optionTokens(sub.options))}" -- "$cur") ) ;;`)
|
|
271
|
+
.join("\n");
|
|
272
|
+
return [
|
|
273
|
+
` ${command.name})`,
|
|
274
|
+
` if [ -z "$subcommand" ]; then`,
|
|
275
|
+
` COMPREPLY=( $(compgen -W "${withVerbose(subNames)}" -- "$cur") )`,
|
|
276
|
+
` else`,
|
|
277
|
+
` case "$subcommand" in`,
|
|
278
|
+
subCases,
|
|
279
|
+
` esac`,
|
|
280
|
+
` fi`,
|
|
281
|
+
` ;;`,
|
|
282
|
+
].join("\n");
|
|
283
|
+
}
|
|
284
|
+
if (command.argValues !== undefined) {
|
|
285
|
+
return [
|
|
286
|
+
` ${command.name})`,
|
|
287
|
+
` if [ -z "$subcommand" ]; then`,
|
|
288
|
+
` COMPREPLY=( $(compgen -W "${withVerbose([...command.argValues])}" -- "$cur") )`,
|
|
289
|
+
` fi`,
|
|
290
|
+
` ;;`,
|
|
291
|
+
].join("\n");
|
|
292
|
+
}
|
|
293
|
+
return [
|
|
294
|
+
` ${command.name})`,
|
|
295
|
+
` COMPREPLY=( $(compgen -W "${withVerbose(optionTokens(command.options))}" -- "$cur") )`,
|
|
296
|
+
` ;;`,
|
|
297
|
+
].join("\n");
|
|
298
|
+
}
|
|
299
|
+
function bashScript() {
|
|
300
|
+
const commandNames = COMPLETION_SPEC.map((command) => command.name).join(" ");
|
|
301
|
+
const topGlobals = optionTokens(TOP_LEVEL_GLOBALS).join(" ");
|
|
302
|
+
const commandCases = COMPLETION_SPEC.map(bashCommandCase).join("\n");
|
|
303
|
+
return `# bash completion for crew
|
|
304
|
+
# Install: source <(crew completions bash)
|
|
305
|
+
_crew() {
|
|
306
|
+
local cur prev cmd subcommand i word
|
|
307
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
308
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
309
|
+
|
|
310
|
+
case "$prev" in
|
|
311
|
+
${bashValueCases()}
|
|
312
|
+
esac
|
|
313
|
+
|
|
314
|
+
cmd=""
|
|
315
|
+
subcommand=""
|
|
316
|
+
for (( i=1; i < COMP_CWORD; i++ )); do
|
|
317
|
+
word="\${COMP_WORDS[i]}"
|
|
318
|
+
case "$word" in -*) continue ;; esac
|
|
319
|
+
if [ -z "$cmd" ]; then
|
|
320
|
+
cmd="$word"
|
|
321
|
+
elif [ -z "$subcommand" ]; then
|
|
322
|
+
subcommand="$word"
|
|
323
|
+
fi
|
|
324
|
+
done
|
|
325
|
+
|
|
326
|
+
if [ -z "$cmd" ]; then
|
|
327
|
+
COMPREPLY=( $(compgen -W "${commandNames} ${topGlobals}" -- "$cur") )
|
|
328
|
+
return
|
|
329
|
+
fi
|
|
330
|
+
|
|
331
|
+
case "$cmd" in
|
|
332
|
+
${commandCases}
|
|
333
|
+
*)
|
|
334
|
+
COMPREPLY=( $(compgen -W "${COMMAND_GLOBAL}" -- "$cur") )
|
|
335
|
+
;;
|
|
336
|
+
esac
|
|
337
|
+
}
|
|
338
|
+
complete -F _crew crew
|
|
339
|
+
`;
|
|
340
|
+
}
|
|
341
|
+
// -- zsh -------------------------------------------------------------------
|
|
342
|
+
function zshValueCases() {
|
|
343
|
+
return valueCases({
|
|
344
|
+
enum: (name, values) => ` ${name}) compadd -- ${values.join(" ")}; return ;;`,
|
|
345
|
+
file: (name) => ` ${name}) _files; return ;;`,
|
|
346
|
+
dir: (name) => ` ${name}) _files -/; return ;;`,
|
|
347
|
+
string: (names) => ` ${names.join("|")}) return ;;`,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
function zshDescribeArray(name, entries) {
|
|
351
|
+
const items = entries
|
|
352
|
+
.map((entry) => ` ${shellSingleQuote(`${entry.name}:${entry.summary}`)}`)
|
|
353
|
+
.join("\n");
|
|
354
|
+
return [` local -a ${name}`, ` ${name}=(`, items, ` )`].join("\n");
|
|
355
|
+
}
|
|
356
|
+
function zshCommandCase(command) {
|
|
357
|
+
if (command.subcommands !== undefined) {
|
|
358
|
+
const subCases = command.subcommands
|
|
359
|
+
.map((sub) => ` ${sub.name}) compadd -- ${withVerbose(optionTokens(sub.options))} ;;`)
|
|
360
|
+
.join("\n");
|
|
361
|
+
return [
|
|
362
|
+
` ${command.name})`,
|
|
363
|
+
` if [[ -z $subcommand ]]; then`,
|
|
364
|
+
zshDescribeArray(`${command.name}_subcommands`, command.subcommands)
|
|
365
|
+
.split("\n")
|
|
366
|
+
.map((line) => ` ${line}`)
|
|
367
|
+
.join("\n"),
|
|
368
|
+
` _describe -t subcommands '${command.name} subcommand' ${command.name}_subcommands`,
|
|
369
|
+
` else`,
|
|
370
|
+
` case $subcommand in`,
|
|
371
|
+
subCases,
|
|
372
|
+
` esac`,
|
|
373
|
+
` fi`,
|
|
374
|
+
` ;;`,
|
|
375
|
+
].join("\n");
|
|
376
|
+
}
|
|
377
|
+
if (command.argValues !== undefined) {
|
|
378
|
+
return [
|
|
379
|
+
` ${command.name})`,
|
|
380
|
+
` if [[ -z $subcommand ]]; then compadd -- ${withVerbose([...command.argValues])}; fi`,
|
|
381
|
+
` ;;`,
|
|
382
|
+
].join("\n");
|
|
383
|
+
}
|
|
384
|
+
return [
|
|
385
|
+
` ${command.name})`,
|
|
386
|
+
` compadd -- ${withVerbose(optionTokens(command.options))}`,
|
|
387
|
+
` ;;`,
|
|
388
|
+
].join("\n");
|
|
389
|
+
}
|
|
390
|
+
function zshScript() {
|
|
391
|
+
const topGlobals = optionTokens(TOP_LEVEL_GLOBALS).join(" ");
|
|
392
|
+
const commandCases = COMPLETION_SPEC.map(zshCommandCase).join("\n");
|
|
393
|
+
return `#compdef crew
|
|
394
|
+
# zsh completion for crew
|
|
395
|
+
# Install: crew completions zsh > "\${fpath[1]}/_crew" (or: source <(crew completions zsh))
|
|
396
|
+
_crew() {
|
|
397
|
+
local cur prev cmd subcommand i word
|
|
398
|
+
${zshDescribeArray("commands", COMPLETION_SPEC)}
|
|
399
|
+
cur=$words[CURRENT]
|
|
400
|
+
prev=$words[CURRENT-1]
|
|
401
|
+
|
|
402
|
+
case $prev in
|
|
403
|
+
${zshValueCases()}
|
|
404
|
+
esac
|
|
405
|
+
|
|
406
|
+
cmd=""
|
|
407
|
+
subcommand=""
|
|
408
|
+
for (( i=2; i < CURRENT; i++ )); do
|
|
409
|
+
word=$words[i]
|
|
410
|
+
case $word in -*) continue ;; esac
|
|
411
|
+
if [[ -z $cmd ]]; then
|
|
412
|
+
cmd=$word
|
|
413
|
+
elif [[ -z $subcommand ]]; then
|
|
414
|
+
subcommand=$word
|
|
415
|
+
fi
|
|
416
|
+
done
|
|
417
|
+
|
|
418
|
+
if [[ -z $cmd ]]; then
|
|
419
|
+
_describe -t commands 'crew command' commands
|
|
420
|
+
compadd -- ${topGlobals}
|
|
421
|
+
return
|
|
422
|
+
fi
|
|
423
|
+
|
|
424
|
+
case $cmd in
|
|
425
|
+
${commandCases}
|
|
426
|
+
*)
|
|
427
|
+
compadd -- ${COMMAND_GLOBAL}
|
|
428
|
+
;;
|
|
429
|
+
esac
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
# Support both fpath autoload and sourcing (source <(crew completions zsh)).
|
|
433
|
+
if [ "$funcstack[1]" = "_crew" ]; then
|
|
434
|
+
_crew "$@"
|
|
435
|
+
else
|
|
436
|
+
compdef _crew crew
|
|
437
|
+
fi
|
|
438
|
+
`;
|
|
439
|
+
}
|
|
440
|
+
// -- fish ------------------------------------------------------------------
|
|
441
|
+
function fishDescription(summary) {
|
|
442
|
+
return summary.replaceAll("\\", String.raw `\\`).replaceAll('"', String.raw `\"`);
|
|
443
|
+
}
|
|
444
|
+
function fishArgFlags(arg) {
|
|
445
|
+
if (arg === undefined) {
|
|
446
|
+
return "";
|
|
447
|
+
}
|
|
448
|
+
if (arg.kind === "enum") {
|
|
449
|
+
return ` -x -a "${arg.values.join(" ")}"`;
|
|
450
|
+
}
|
|
451
|
+
if (arg.kind === "file") {
|
|
452
|
+
return " -r -F";
|
|
453
|
+
}
|
|
454
|
+
if (arg.kind === "dir") {
|
|
455
|
+
return ` -x -a "(__fish_complete_directories)"`;
|
|
456
|
+
}
|
|
457
|
+
return " -x";
|
|
458
|
+
}
|
|
459
|
+
function fishOptionLine(condition, option) {
|
|
460
|
+
// Command/subcommand options never carry short forms (only the top-level
|
|
461
|
+
// globals do, and those are emitted separately), so this renders long flags.
|
|
462
|
+
const long = option.name.replace(/^--/, "");
|
|
463
|
+
return `complete -c crew -n '${condition}' -l ${long}${fishArgFlags(option.arg)} -d "${fishDescription(option.summary)}"`;
|
|
464
|
+
}
|
|
465
|
+
function fishOptionLines(condition, options) {
|
|
466
|
+
return (options ?? []).map((option) => fishOptionLine(condition, option));
|
|
467
|
+
}
|
|
468
|
+
function fishCommandLines(command) {
|
|
469
|
+
const lines = [];
|
|
470
|
+
const seenCondition = `__fish_seen_subcommand_from ${command.name}`;
|
|
471
|
+
lines.push(...fishOptionLines(seenCondition, command.options));
|
|
472
|
+
if (command.subcommands !== undefined) {
|
|
473
|
+
const subNames = command.subcommands.map((sub) => sub.name).join(" ");
|
|
474
|
+
const chooseSub = `${seenCondition}; and not __fish_seen_subcommand_from ${subNames}`;
|
|
475
|
+
for (const sub of command.subcommands) {
|
|
476
|
+
lines.push(`complete -c crew -f -n '${chooseSub}' -a ${sub.name} -d "${fishDescription(sub.summary)}"`);
|
|
477
|
+
const subCondition = `${seenCondition}; and __fish_seen_subcommand_from ${sub.name}`;
|
|
478
|
+
lines.push(...fishOptionLines(subCondition, sub.options));
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
if (command.argValues !== undefined) {
|
|
482
|
+
const chooseArg = `${seenCondition}; and not __fish_seen_subcommand_from ${command.argValues.join(" ")}`;
|
|
483
|
+
lines.push(`complete -c crew -f -n '${chooseArg}' -a "${command.argValues.join(" ")}" -d "Shell"`);
|
|
484
|
+
}
|
|
485
|
+
return lines;
|
|
486
|
+
}
|
|
487
|
+
function fishScript() {
|
|
488
|
+
const commandLines = COMPLETION_SPEC.map((command) => `complete -c crew -f -n '__fish_use_subcommand' -a ${command.name} -d "${fishDescription(command.summary)}"`);
|
|
489
|
+
const globalLines = [
|
|
490
|
+
`complete -c crew -l verbose -d "Show diagnostic output"`,
|
|
491
|
+
`complete -c crew -n '__fish_use_subcommand' -l help -s h -d "Show help"`,
|
|
492
|
+
`complete -c crew -n '__fish_use_subcommand' -l version -s v -d "Print version"`,
|
|
493
|
+
];
|
|
494
|
+
const perCommandLines = COMPLETION_SPEC.flatMap(fishCommandLines);
|
|
495
|
+
return `# fish completion for crew
|
|
496
|
+
# Install: crew completions fish > ~/.config/fish/completions/crew.fish
|
|
497
|
+
${commandLines.join("\n")}
|
|
498
|
+
${globalLines.join("\n")}
|
|
499
|
+
${perCommandLines.join("\n")}
|
|
500
|
+
`;
|
|
501
|
+
}
|
|
502
|
+
const GENERATORS = {
|
|
503
|
+
bash: bashScript,
|
|
504
|
+
zsh: zshScript,
|
|
505
|
+
fish: fishScript,
|
|
506
|
+
};
|
|
507
|
+
/** Renders the completion script for a supported shell. */
|
|
508
|
+
export function generateCompletionScript(shell) {
|
|
509
|
+
return GENERATORS[shell]();
|
|
510
|
+
}
|
|
511
|
+
function isSupportedShell(value) {
|
|
512
|
+
return SUPPORTED_SHELLS.includes(value);
|
|
513
|
+
}
|
|
514
|
+
const COMPLETIONS_USAGE = `Usage: crew completions <${SUPPORTED_SHELLS.join("|")}>`;
|
|
515
|
+
export async function completionsCli(argv) {
|
|
516
|
+
const [shell, ...extras] = argv;
|
|
517
|
+
if (shell === undefined || extras.length > 0) {
|
|
518
|
+
throw new Error(COMPLETIONS_USAGE);
|
|
519
|
+
}
|
|
520
|
+
if (!isSupportedShell(shell)) {
|
|
521
|
+
throw new Error(`crew completions: unsupported shell: ${shell}\n${COMPLETIONS_USAGE}`);
|
|
522
|
+
}
|
|
523
|
+
writeOutput(generateCompletionScript(shell));
|
|
524
|
+
}
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* `cp` dance documented in the README.
|
|
6
6
|
*/
|
|
7
7
|
import { type LocalRunnerSetting } from "../lib/config.ts";
|
|
8
|
-
declare const INIT_AGENTS: readonly ["claude", "codex", "cursor"];
|
|
8
|
+
export declare const INIT_AGENTS: readonly ["claude", "codex", "cursor"];
|
|
9
9
|
type InitConfigScope = "global" | "local";
|
|
10
10
|
type InitAgent = (typeof INIT_AGENTS)[number];
|
|
11
11
|
interface InitConfigOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAYlF,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAYlF,eAAO,MAAM,WAAW,YAAI,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAU,CAAC;AAElE,KAAK,eAAe,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC1C,KAAK,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9C,UAAU,iBAAiB;IACzB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,yCAAyC;IACzC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,iEAAiE;IACjE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,qDAAqD;IACrD,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,+EAA+E;IAC/E,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,KAAK,iBAAiB,GAAG,qBAAqB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEpE,UAAU,gBAAgB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CAoB5E;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAWjE"}
|
package/dist/commands/init.js
CHANGED
|
@@ -16,7 +16,7 @@ const DEFAULT_EXAMPLE_PROJECT_DIR = "~/dev/groundcrew";
|
|
|
16
16
|
const INIT_USAGE = "Usage: crew init [--global | --local] [--force] [--dry-run] [--project-dir <dir>] [--repo <owner/repo>]... [--runner <auto|safehouse|sdx|none>] [--agent <claude|codex|cursor>]";
|
|
17
17
|
// Model-variant presets with hyphens (e.g. `cursor-grok`) are enabled via
|
|
18
18
|
// config, not `init`: renderConfig would emit an unquoted, invalid TS key.
|
|
19
|
-
const INIT_AGENTS = ["claude", "codex", "cursor"];
|
|
19
|
+
export const INIT_AGENTS = ["claude", "codex", "cursor"];
|
|
20
20
|
export function initConfig(options = {}) {
|
|
21
21
|
const scope = options.scope ?? "local";
|
|
22
22
|
const cwd = options.cwd ?? process.cwd();
|
package/docs/commands.md
CHANGED
|
@@ -166,3 +166,24 @@ Open checks out the PR's actual head branch (fetching it from the remote when it
|
|
|
166
166
|
When `--prompt`/`--prompt-file` is given, the agent starts with that prompt; otherwise it opens its interactive session with no prompt and hands control to you.
|
|
167
167
|
|
|
168
168
|
`crew cleanup <task>` removes the opened worktree but never deletes the remote PR branch. Fork (cross-repository) PRs and `provision`/sparse-checkout repositories are not supported; for a fork, check the branch out locally and use `--branch`.
|
|
169
|
+
|
|
170
|
+
## Completions
|
|
171
|
+
|
|
172
|
+
`crew completions <bash|zsh|fish>` prints a shell completion script to stdout. The script completes command names, subcommands (for `crew source` and `crew task`), flags, and enumerated flag values (`--runner`, `--status`, `--agent`); `--prompt-file` and `--project-dir` fall back to file and directory completion. Task IDs, source names, and repositories are configuration-specific and are not completed.
|
|
173
|
+
|
|
174
|
+
Load it once per shell session, or install it so your shell loads it automatically.
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# bash — add to ~/.bashrc
|
|
178
|
+
source <(crew completions bash)
|
|
179
|
+
|
|
180
|
+
# zsh — write into a directory on your $fpath (run once), then restart the shell
|
|
181
|
+
crew completions zsh > "${fpath[1]}/_crew"
|
|
182
|
+
# or, to load in the current session, add to ~/.zshrc:
|
|
183
|
+
source <(crew completions zsh)
|
|
184
|
+
|
|
185
|
+
# fish — install once; fish loads it automatically on the next session
|
|
186
|
+
crew completions fish > ~/.config/fish/completions/crew.fish
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The command tree is generated from a single spec in `src/commands/completions.ts`, so completions stay in sync with the CLI as commands and flags change.
|
package/package.json
CHANGED