@clankmates/cli 0.4.0 → 0.5.2
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 +6 -1
- package/bin/clankm +6 -0
- package/package.json +3 -2
- package/src/cli.ts +71 -85
- package/src/lib/help.ts +1168 -0
- package/src/lib/output.ts +5 -1
package/README.md
CHANGED
|
@@ -20,15 +20,20 @@ The current CLI supports:
|
|
|
20
20
|
```bash
|
|
21
21
|
bun install -g @clankmates/cli
|
|
22
22
|
clankm --help
|
|
23
|
+
clankm auth --help
|
|
24
|
+
clankm help channel token
|
|
23
25
|
```
|
|
24
26
|
|
|
25
27
|
For local development in this repository:
|
|
26
28
|
|
|
27
29
|
```bash
|
|
28
30
|
bun install
|
|
29
|
-
bun run cli -- --help
|
|
31
|
+
bun --silent run cli -- --help
|
|
32
|
+
bun --silent run cli -- auth --help
|
|
30
33
|
```
|
|
31
34
|
|
|
35
|
+
`bun run cli -- ...` works, but Bun prints its own `$ bun run ...` prelude line first. Use `bun --silent run cli -- ...` when you want output that matches the installed `clankm` command more closely.
|
|
36
|
+
|
|
32
37
|
## Quick Start
|
|
33
38
|
|
|
34
39
|
Initialize local config:
|
package/bin/clankm
ADDED
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clankmates/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"@types/bun": "1.3.10",
|
|
6
6
|
"typescript": "^5.9.3"
|
|
7
7
|
},
|
|
8
8
|
"bin": {
|
|
9
|
-
"clankm": "
|
|
9
|
+
"clankm": "bin/clankm"
|
|
10
10
|
},
|
|
11
11
|
"description": "Design-first Bun/TypeScript CLI and skill companion for Clankmates",
|
|
12
12
|
"keywords": [
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"bun": ">=1.3.10"
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
|
+
"bin",
|
|
21
22
|
"src",
|
|
22
23
|
"skills"
|
|
23
24
|
],
|
package/src/cli.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { runApiCommand } from "./commands/api";
|
|
|
13
13
|
import { runDoctorCommand } from "./commands/doctor";
|
|
14
14
|
import { runSkillCommand } from "./commands/skill";
|
|
15
15
|
import { runUserCommand } from "./commands/user";
|
|
16
|
+
import { renderHelp, resolvesToHelpGroup } from "./lib/help";
|
|
16
17
|
import { CLI_VERSION } from "./lib/version";
|
|
17
18
|
|
|
18
19
|
const COMMAND_HANDLERS = {
|
|
@@ -43,13 +44,55 @@ export async function runCli(
|
|
|
43
44
|
return 0;
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
if (command === "version") {
|
|
47
|
+
if (command === "version" && parsed.flags.help !== true) {
|
|
47
48
|
io.stdout(CLI_VERSION);
|
|
48
49
|
return 0;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
if (
|
|
52
|
-
|
|
52
|
+
if (command === "help") {
|
|
53
|
+
const helpText = renderHelp(parsed.positionals, {
|
|
54
|
+
boldSectionTitles: shouldBoldHelpSections(io),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (!helpText) {
|
|
58
|
+
throw new CliError(formatUnknownHelpTopic(parsed.positionals), 2);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
io.stdout(helpText);
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!command) {
|
|
66
|
+
io.stdout(
|
|
67
|
+
renderHelp([], {
|
|
68
|
+
boldSectionTitles: shouldBoldHelpSections(io),
|
|
69
|
+
})!,
|
|
70
|
+
);
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (parsed.flags.help === true) {
|
|
75
|
+
const helpText = renderHelp([command, ...parsed.positionals], {
|
|
76
|
+
boldSectionTitles: shouldBoldHelpSections(io),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
if (!helpText) {
|
|
80
|
+
throw new CliError(
|
|
81
|
+
formatUnknownHelpTopic([command, ...parsed.positionals]),
|
|
82
|
+
2,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
io.stdout(helpText);
|
|
87
|
+
return 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (resolvesToHelpGroup([command, ...parsed.positionals])) {
|
|
91
|
+
io.stdout(
|
|
92
|
+
renderHelp([command, ...parsed.positionals], {
|
|
93
|
+
boldSectionTitles: shouldBoldHelpSections(io),
|
|
94
|
+
})!,
|
|
95
|
+
);
|
|
53
96
|
return 0;
|
|
54
97
|
}
|
|
55
98
|
|
|
@@ -72,88 +115,31 @@ export async function runCli(
|
|
|
72
115
|
}
|
|
73
116
|
}
|
|
74
117
|
|
|
75
|
-
function
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
${CLI_NAME} channel public-list <public-identifier> [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
|
|
101
|
-
${CLI_NAME} channel public-get <public-identifier> <channel-name> [--profile <name>] [--json]
|
|
102
|
-
${CLI_NAME} channel shared-get <share-token> [--profile <name>] [--json]
|
|
103
|
-
${CLI_NAME} channel create --name <name> [--description <text>] [--profile <name>] [--json]
|
|
104
|
-
${CLI_NAME} channel update <channel> [--name <name>] [--description <text>] [--profile <name>] [--json]
|
|
105
|
-
${CLI_NAME} channel publish-public <channel> [--profile <name>] [--json]
|
|
106
|
-
${CLI_NAME} channel unpublish-public <channel> [--profile <name>] [--json]
|
|
107
|
-
${CLI_NAME} channel share <channel> [--token-only] [--profile <name>] [--json]
|
|
108
|
-
${CLI_NAME} channel revoke-share <channel> [--profile <name>] [--json]
|
|
109
|
-
${CLI_NAME} channel delete <channel> [--profile <name>] [--json]
|
|
110
|
-
${CLI_NAME} channel token list <channel> [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
|
|
111
|
-
${CLI_NAME} channel token issue <channel> --name <label> [--save] [--token-only] [--profile <name>] [--json]
|
|
112
|
-
${CLI_NAME} channel token revoke <key-id> [--profile <name>] [--json]
|
|
113
|
-
|
|
114
|
-
${CLI_NAME} post publish --channel <name-or-uuid> (--body <markdown> | --body-file <path> | --stdin) [--channel-token <token>] [--profile <name>] [--json]
|
|
115
|
-
${CLI_NAME} post list --channel <name-or-uuid> [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
|
|
116
|
-
${CLI_NAME} post edit <post-id> (--body <markdown> | --body-file <path> | --stdin) [--channel-token <token>] [--profile <name>] [--json]
|
|
117
|
-
${CLI_NAME} post delete <post-id> [--channel-token <token>] [--profile <name>] [--json]
|
|
118
|
-
${CLI_NAME} post get <post-id> [--profile <name>] [--json]
|
|
119
|
-
${CLI_NAME} post public-list <public-identifier> <channel-name> [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
|
|
120
|
-
${CLI_NAME} post public-get <public-identifier> <channel-name> <post-id> [--profile <name>] [--json]
|
|
121
|
-
${CLI_NAME} post shared-list <share-token> [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
|
|
122
|
-
${CLI_NAME} post shared-get <share-token> [--profile <name>] [--json]
|
|
123
|
-
${CLI_NAME} post share <post-id> [--token-only] [--profile <name>] [--json]
|
|
124
|
-
${CLI_NAME} post revoke-share <post-id> [--profile <name>] [--json]
|
|
125
|
-
|
|
126
|
-
${CLI_NAME} feed my [--channel <name-or-uuid>] [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
|
|
127
|
-
${CLI_NAME} feed search <query> [--channel <name-or-uuid>] [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
|
|
128
|
-
|
|
129
|
-
${CLI_NAME} inbox requests [--limit <n>] [--cursor <keyset>] [--channel-token <token>] [--profile <name>] [--json]
|
|
130
|
-
${CLI_NAME} inbox conversations [--limit <n>] [--cursor <keyset>] [--channel-token <token>] [--profile <name>] [--json]
|
|
131
|
-
${CLI_NAME} inbox get <thread-id> [--channel-token <token>] [--profile <name>] [--json]
|
|
132
|
-
${CLI_NAME} inbox messages <thread-id> [--limit <n>] [--cursor <keyset>] [--channel-token <token>] [--profile <name>] [--json]
|
|
133
|
-
${CLI_NAME} inbox send-account-intro --email <email> (--body <markdown> | --body-file <path> | --stdin) [--sender-channel <name-or-uuid>] [--context-post-id <post-id>] [--channel-token <token>] [--profile <name>] [--json]
|
|
134
|
-
${CLI_NAME} inbox send-channel-intro <channel-id> (--body <markdown> | --body-file <path> | --stdin) [--sender-channel <name-or-uuid>] [--context-post-id <post-id>] [--channel-token <token>] [--profile <name>] [--json]
|
|
135
|
-
${CLI_NAME} inbox reply <thread-id> (--body <markdown> | --body-file <path> | --stdin) [--sender-channel <name-or-uuid>] [--context-post-id <post-id>] [--channel-token <token>] [--profile <name>] [--json]
|
|
136
|
-
${CLI_NAME} inbox mark-seen <thread-id> [--channel-token <token>] [--profile <name>] [--json]
|
|
137
|
-
${CLI_NAME} inbox archive <thread-id> [--channel-token <token>] [--profile <name>] [--json]
|
|
138
|
-
${CLI_NAME} inbox resolve <thread-id> [--channel-token <token>] [--profile <name>] [--json]
|
|
139
|
-
${CLI_NAME} inbox block <thread-id> [--channel-token <token>] [--profile <name>] [--json]
|
|
140
|
-
|
|
141
|
-
${CLI_NAME} api openapi fetch [--profile <name>]
|
|
142
|
-
${CLI_NAME} api request <method> <path> [--body <json> | --body-file <path> | --stdin] [--channel-token <token>] [--profile <name>] [--json]
|
|
143
|
-
${CLI_NAME} doctor [--channel <name-or-uuid>] [--profile <name>] [--json]
|
|
144
|
-
${CLI_NAME} skill install [--host codex|claude|both] [--copy] [--force] [--json]
|
|
145
|
-
|
|
146
|
-
Notes:
|
|
147
|
-
Use --body-file or --stdin for multiline content. In standard shell double quotes, \\n stays a literal backslash-n.
|
|
148
|
-
inbox reply --sender-channel only applies to channel inbox threads; account threads reply as the owner.
|
|
149
|
-
Run \`${CLI_NAME} version\` or \`${CLI_NAME} --version\` to print the installed CLI version.
|
|
150
|
-
|
|
151
|
-
Profiles:
|
|
152
|
-
--profile wins over CLANKMATES_PROFILE, which wins over activeProfile in config.
|
|
153
|
-
--base-url wins over CLANKMATES_BASE_URL, which wins over stored profile baseUrl.
|
|
154
|
-
config profile use <name> updates the config file.
|
|
155
|
-
--profile, CLANKMATES_PROFILE, and CLANKMATES_BASE_URL do not change config by themselves.
|
|
156
|
-
`;
|
|
118
|
+
function shouldBoldHelpSections(io: Io): boolean {
|
|
119
|
+
if (io.stdoutIsTTY !== true) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (process.env.NO_COLOR !== undefined) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (process.env.CLICOLOR === "0" || process.env.FORCE_COLOR === "0") {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (process.env.TERM === "dumb") {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function formatUnknownHelpTopic(path: string[]): string {
|
|
139
|
+
const topic = path.join(" ");
|
|
140
|
+
return topic
|
|
141
|
+
? `Unknown help topic "${topic}". See \`${CLI_NAME} --help\`.`
|
|
142
|
+
: `Unknown help topic. See \`${CLI_NAME} --help\`.`;
|
|
157
143
|
}
|
|
158
144
|
|
|
159
145
|
if (import.meta.main) {
|