Skip to content

Commit 702ebce

Browse files
authored
feat(cli): improve help discoverability for subcommands (#1)
Show inherited global flags in nested help output via Commander configuration. Add targeted issues/branch examples including JSON extraction path guidance. Update README command syntax and help-discovery examples.
1 parent 5ae849d commit 702ebce

4 files changed

Lines changed: 69 additions & 8 deletions

File tree

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,18 @@ pnpm verify
3030
## Run CLI
3131

3232
```bash
33-
pnpm --filter @wiseiodev/linear-cli dev -- --help
34-
pnpm --filter @wiseiodev/linear-cli dev -- issues list --json
33+
pnpm --filter @wiseiodev/linear-cli dev --help
34+
pnpm --filter @wiseiodev/linear-cli dev issues list --json
35+
```
36+
37+
## Help Discovery
38+
39+
```bash
40+
linear --help
41+
linear issues --help
42+
linear issues branch --help
43+
linear issues branch ANN-123 --json
44+
# branch name is in .data.branchName
3545
```
3646

3747
## Example Commands
@@ -53,7 +63,7 @@ linear skills install issue-triage
5363

5464
# CRUD
5565
linear issues list --limit 10
56-
linear issues branch ANN-123
66+
linear issues branch ANN-123 --json
5767
linear issues browse
5868
linear issues create --input '{"title":"Investigate bug","teamId":"<team-id>"}'
5969
linear projects list

packages/cli/src/help/root-help.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ Examples:
66
linear auth login --manual
77
linear auth status --json
88
linear auth api-key-set --api-key "$LINEAR_API_KEY"
9+
linear issues --help
10+
linear issues branch --help
911
linear issues list --limit 10
10-
linear issues branch ANN-123
12+
linear issues branch ANN-123 --json
1113
linear issues browse
1214
linear issues create --template "Bug Report" --input '{"teamId":"<team-id>"}'
1315
linear initiatives list
@@ -24,3 +26,19 @@ Docs:
2426
- SDK: https://linear.app/developers/sdk
2527
- OAuth: https://linear.app/developers/oauth-2-0-authentication
2628
`;
29+
30+
export const issuesHelpText = `
31+
Examples:
32+
linear issues --help
33+
linear issues list --limit 10 --json
34+
linear issues create --template "Bug Report" --input '{"teamId":"<team-id>"}' --json
35+
`;
36+
37+
export const issueBranchHelpText = `
38+
Examples:
39+
linear issues branch ANN-123
40+
linear issues branch ANN-123 --json
41+
42+
JSON path:
43+
.data.branchName
44+
`;

packages/cli/src/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import open from "open";
4040
import { runInteractiveOAuthLogin } from "./auth/login.js";
4141
import { registerResourceCommand } from "./commands/resource.js";
4242
import { renderEnvelope } from "./formatters/output.js";
43-
import { rootHelpText } from "./help/root-help.js";
43+
import { issueBranchHelpText, issuesHelpText, rootHelpText } from "./help/root-help.js";
4444
import { getGlobalOptions } from "./runtime/options.js";
4545

4646
function isRecord(value: unknown): value is Record<string, unknown> {
@@ -225,6 +225,7 @@ async function resolveIssueTemplateId(
225225

226226
export function createProgram(authManager = new AuthManager()): Command {
227227
const program = new Command();
228+
program.configureHelp({ showGlobalOptions: true });
228229

229230
program
230231
.name("linear")
@@ -468,11 +469,13 @@ export function createProgram(authManager = new AuthManager()): Command {
468469
issuesCommand?.commands
469470
.find((command) => command.name() === "create")
470471
?.option("--template <id-or-name>", "Apply a template by exact id or exact name");
472+
issuesCommand?.addHelpText("after", issuesHelpText);
471473

472474
issuesCommand
473475
?.command("branch")
474476
.description("Show branch name for an issue id or identifier")
475477
.argument("<id-or-identifier>", "Issue id (UUID) or identifier (e.g. ANN-123)")
478+
.addHelpText("after", issueBranchHelpText)
476479
.action(async (idOrIdentifier, _, cmd) => {
477480
const globals = getGlobalOptions(cmd);
478481

@@ -492,7 +495,6 @@ export function createProgram(authManager = new AuthManager()): Command {
492495
process.exitCode = 1;
493496
}
494497
});
495-
496498
issuesCommand
497499
?.command("browse")
498500
.description("Browse issues in the interactive terminal table")

packages/cli/tests/help.test.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,37 @@
1+
import type { Command } from "commander";
12
import { describe, expect, test } from "vitest";
23
import { createProgram } from "../src/index.js";
34

5+
function captureRenderedHelp(command?: Command): string {
6+
if (!command) {
7+
return "";
8+
}
9+
10+
let output = "";
11+
command.configureOutput({
12+
writeOut: (str: string) => {
13+
output += str;
14+
},
15+
writeErr: (str: string) => {
16+
output += str;
17+
},
18+
});
19+
command.outputHelp();
20+
return output;
21+
}
22+
423
describe("help output", () => {
524
test("contains docs and skills commands", () => {
625
const program = createProgram();
726
const help = program.helpInformation();
8-
const issuesHelp =
9-
program.commands.find((command) => command.name() === "issues")?.helpInformation() ?? "";
27+
const issuesCommand = program.commands.find((command) => command.name() === "issues");
28+
const issuesHelp = issuesCommand?.helpInformation() ?? "";
29+
const issueBranchCommand = issuesCommand?.commands.find(
30+
(command) => command.name() === "branch",
31+
);
32+
const issueBranchHelp = issueBranchCommand?.helpInformation() ?? "";
33+
const renderedIssuesHelp = captureRenderedHelp(issuesCommand);
34+
const renderedIssueBranchHelp = captureRenderedHelp(issueBranchCommand);
1035
const initiativesHelp =
1136
program.commands.find((command) => command.name() === "initiatives")?.helpInformation() ?? "";
1237
const documentsHelp =
@@ -27,6 +52,12 @@ describe("help output", () => {
2752
expect(help).toContain("templates");
2853
expect(issuesHelp).toContain("branch");
2954
expect(issuesHelp).toContain("browse");
55+
expect(renderedIssuesHelp).toContain("Global Options:");
56+
expect(renderedIssuesHelp).toContain("--json");
57+
expect(renderedIssueBranchHelp).toContain("Global Options:");
58+
expect(renderedIssueBranchHelp).toContain("--json");
59+
expect(renderedIssueBranchHelp).toContain(".data.branchName");
60+
expect(issueBranchHelp).toContain("id-or-identifier");
3061
expect(initiativesHelp).toContain("create");
3162
expect(documentsHelp).toContain("list");
3263
expect(templatesHelp).toContain("list");

0 commit comments

Comments
 (0)