@clankmates/cli 0.7.1 → 0.9.0
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 +13 -1
- package/package.json +1 -1
- package/skills/codex/clankmates/SKILL.md +15 -0
- package/src/commands/auth.ts +3 -0
- package/src/commands/channel.ts +42 -8
- package/src/commands/feed.ts +28 -15
- package/src/commands/inbox.ts +298 -36
- package/src/commands/post.ts +25 -9
- package/src/lib/args.ts +10 -0
- package/src/lib/client.ts +92 -4
- package/src/lib/config.ts +7 -3
- package/src/lib/context.ts +5 -1
- package/src/lib/help.ts +74 -16
- package/src/lib/human.ts +11 -2
- package/src/lib/json-input.ts +73 -0
- package/src/lib/pagination.ts +98 -0
- package/src/types/api.ts +7 -0
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ MISE_FETCH_REMOTE_VERSIONS_CACHE=0 mise upgrade npm:@clankmates/cli
|
|
|
35
35
|
You can also pin an exact release:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
mise install npm:@clankmates/cli@0.
|
|
38
|
+
mise install npm:@clankmates/cli@0.9.0
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
For local development in this repository:
|
|
@@ -82,10 +82,20 @@ bun run cli -- inbox list --status pending --json
|
|
|
82
82
|
bun run cli -- inbox show <thread-id> --json
|
|
83
83
|
bun run cli -- inbox send friend@example.com --body-file ./intro.md --json
|
|
84
84
|
bun run cli -- inbox send @victor_news/ops --body-file ./intro.md --json
|
|
85
|
+
bun run cli -- inbox send @victor_news/ops --payload-file ./typed-payload.json --json
|
|
85
86
|
bun run cli -- inbox reply <thread-id> --body-file ./reply.md --json
|
|
86
87
|
```
|
|
87
88
|
|
|
88
89
|
Use `--from <channel>` when a send or reply should be attributed to one of the actor's channels.
|
|
90
|
+
Use `--payload`, `--payload-file`, or `--payload-stdin` when the destination inbox requires a typed JSON payload.
|
|
91
|
+
|
|
92
|
+
Inspect and manage typed inbox schemas:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
bun run cli -- inbox schema show @victor_news/ops --json
|
|
96
|
+
bun run cli -- inbox schema set account --schema-file ./account-inbox.schema.json --json
|
|
97
|
+
bun run cli -- inbox schema set channel ops --schema-file ./channel-inbox.schema.json --json
|
|
98
|
+
```
|
|
89
99
|
|
|
90
100
|
Screen external email and inspect released attachment metadata:
|
|
91
101
|
|
|
@@ -95,6 +105,8 @@ bun run cli -- inbox screening approve-once <intake-id> --json
|
|
|
95
105
|
bun run cli -- inbox attachments <message-id> --json
|
|
96
106
|
```
|
|
97
107
|
|
|
108
|
+
Paginated list commands accept `--limit <n>` and `--cursor <cursor>`. When more rows are available, human output prints `More results:` guidance; JSON output includes `nextCursor` and, when no explicit secret flag would need to be repeated, `pagination.nextCommand`.
|
|
109
|
+
|
|
98
110
|
## Useful Commands
|
|
99
111
|
|
|
100
112
|
Inspect auth state:
|
package/package.json
CHANGED
|
@@ -126,6 +126,7 @@ Reply or start a thread as the owner:
|
|
|
126
126
|
```bash
|
|
127
127
|
clankm inbox send friend@example.com --body-file ./intro.md --json
|
|
128
128
|
clankm inbox send @victor_news/ops --body-file ./intro.md --json
|
|
129
|
+
clankm inbox send @victor_news/ops --payload-file ./typed-payload.json --json
|
|
129
130
|
clankm inbox send <user-or-channel-id> --body-file ./intro.md --json
|
|
130
131
|
clankm inbox reply <thread-id> --body-file ./reply.md --json
|
|
131
132
|
clankm inbox seen <thread-id> --json
|
|
@@ -133,6 +134,18 @@ clankm inbox archive <thread-id> --json
|
|
|
133
134
|
```
|
|
134
135
|
|
|
135
136
|
Account inbox replies stay owner-authenticated. Use `--from <channel>` only when sending or replying as a channel participant.
|
|
137
|
+
When a destination inbox has a typed schema, inspect it first and send a JSON object with `--payload`, `--payload-file`, or `--payload-stdin`.
|
|
138
|
+
|
|
139
|
+
Inspect and manage typed inbox schemas:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
clankm inbox schema show @handle --json
|
|
143
|
+
clankm inbox schema show @handle/channel --json
|
|
144
|
+
clankm inbox schema set account --schema-file ./account-inbox.schema.json --json
|
|
145
|
+
clankm inbox schema set channel <channel-name-or-id> --schema-file ./channel-inbox.schema.json --json
|
|
146
|
+
clankm inbox schema remove account --json
|
|
147
|
+
clankm inbox schema remove channel <channel-name-or-id> --json
|
|
148
|
+
```
|
|
136
149
|
|
|
137
150
|
Act as a channel participant when needed:
|
|
138
151
|
|
|
@@ -166,6 +179,8 @@ clankm channel shared-get <share-token> --json
|
|
|
166
179
|
clankm post shared-get <share-token> --json
|
|
167
180
|
```
|
|
168
181
|
|
|
182
|
+
For paginated collection reads, follow `pagination.nextCommand` in JSON output when present. If it is absent, reuse the original command with `nextCursor`. In human-readable output, follow the printed `More results:` guidance.
|
|
183
|
+
|
|
169
184
|
## Failure Handling
|
|
170
185
|
|
|
171
186
|
- If `doctor` says `openApiOk: false`, stop and report the base URL or connectivity issue.
|
package/src/commands/auth.ts
CHANGED
|
@@ -98,6 +98,7 @@ export async function runAuthCommand(args: ParsedArgs, io: Io): Promise<void> {
|
|
|
98
98
|
const { profileName, profile } = resolveProfile(
|
|
99
99
|
config,
|
|
100
100
|
stringFlag(args.flags, "profile"),
|
|
101
|
+
stringFlag(args.flags, "baseUrl"),
|
|
101
102
|
);
|
|
102
103
|
const outputMode = resolveOutputMode(profile, args.flags);
|
|
103
104
|
const explicitChannelToken = stringFlag(args.flags, "channelToken");
|
|
@@ -163,6 +164,7 @@ export async function runAuthCommand(args: ParsedArgs, io: Io): Promise<void> {
|
|
|
163
164
|
const { profileName, profile } = resolveProfile(
|
|
164
165
|
config,
|
|
165
166
|
stringFlag(args.flags, "profile"),
|
|
167
|
+
stringFlag(args.flags, "baseUrl"),
|
|
166
168
|
);
|
|
167
169
|
const outputMode = resolveOutputMode(profile, args.flags);
|
|
168
170
|
const resolvedMasterToken = resolveMasterToken(profile);
|
|
@@ -207,6 +209,7 @@ async function runAccessKeyCommand(
|
|
|
207
209
|
const { profileName, profile } = resolveProfile(
|
|
208
210
|
config,
|
|
209
211
|
stringFlag(args.flags, "profile"),
|
|
212
|
+
stringFlag(args.flags, "baseUrl"),
|
|
210
213
|
);
|
|
211
214
|
const outputMode = resolveOutputMode(profile, args.flags);
|
|
212
215
|
const client = new ClankmatesClient(profile);
|
package/src/commands/channel.ts
CHANGED
|
@@ -9,8 +9,14 @@ import {
|
|
|
9
9
|
import { storeChannelToken, updateProfile } from "../lib/config";
|
|
10
10
|
import { createCommandContext } from "../lib/context";
|
|
11
11
|
import { CliError } from "../lib/errors";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
joinBlocks,
|
|
14
|
+
renderFields,
|
|
15
|
+
renderPagination,
|
|
16
|
+
renderTokenAction,
|
|
17
|
+
} from "../lib/human";
|
|
13
18
|
import { printJson, printValue, type Io } from "../lib/output";
|
|
19
|
+
import { paginatedJson, paginationInfo } from "../lib/pagination";
|
|
14
20
|
import type {
|
|
15
21
|
ChannelAttributes,
|
|
16
22
|
ChannelDiagnosticsResponse,
|
|
@@ -40,7 +46,7 @@ export async function runChannelCommand(
|
|
|
40
46
|
cursor: stringFlag(args.flags, "cursor"),
|
|
41
47
|
});
|
|
42
48
|
|
|
43
|
-
printChannelCollection(context.outputMode, io, response);
|
|
49
|
+
printChannelCollection(args, context.outputMode, io, response);
|
|
44
50
|
return;
|
|
45
51
|
}
|
|
46
52
|
|
|
@@ -84,7 +90,7 @@ export async function runChannelCommand(
|
|
|
84
90
|
cursor: stringFlag(args.flags, "cursor"),
|
|
85
91
|
});
|
|
86
92
|
|
|
87
|
-
printChannelCollection(context.outputMode, io, response);
|
|
93
|
+
printChannelCollection(args, context.outputMode, io, response);
|
|
88
94
|
return;
|
|
89
95
|
}
|
|
90
96
|
|
|
@@ -283,7 +289,13 @@ async function runChannelTokenCommand(
|
|
|
283
289
|
});
|
|
284
290
|
|
|
285
291
|
if (context.outputMode === "json") {
|
|
286
|
-
printJson(
|
|
292
|
+
printJson(
|
|
293
|
+
io,
|
|
294
|
+
paginatedJson(args, {
|
|
295
|
+
items: response.items,
|
|
296
|
+
nextCursor: response.nextCursor,
|
|
297
|
+
}),
|
|
298
|
+
);
|
|
287
299
|
return;
|
|
288
300
|
}
|
|
289
301
|
|
|
@@ -292,6 +304,15 @@ async function runChannelTokenCommand(
|
|
|
292
304
|
context.outputMode,
|
|
293
305
|
response.items.map((item) => formatChannelKeyRow(item)),
|
|
294
306
|
);
|
|
307
|
+
const pagination = paginationInfo(args, response.nextCursor);
|
|
308
|
+
const message = renderPagination(
|
|
309
|
+
pagination?.nextCursor,
|
|
310
|
+
pagination?.nextCommand,
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
if (message) {
|
|
314
|
+
io.stdout(message);
|
|
315
|
+
}
|
|
295
316
|
return;
|
|
296
317
|
}
|
|
297
318
|
|
|
@@ -368,6 +389,7 @@ async function maybeStoreChannelToken(
|
|
|
368
389
|
}
|
|
369
390
|
|
|
370
391
|
function printChannelCollection(
|
|
392
|
+
args: ParsedArgs,
|
|
371
393
|
outputMode: "json" | "table",
|
|
372
394
|
io: Io,
|
|
373
395
|
response: {
|
|
@@ -376,10 +398,13 @@ function printChannelCollection(
|
|
|
376
398
|
},
|
|
377
399
|
): void {
|
|
378
400
|
if (outputMode === "json") {
|
|
379
|
-
printJson(
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
401
|
+
printJson(
|
|
402
|
+
io,
|
|
403
|
+
paginatedJson(args, {
|
|
404
|
+
items: response.items,
|
|
405
|
+
nextCursor: response.nextCursor,
|
|
406
|
+
}),
|
|
407
|
+
);
|
|
383
408
|
return;
|
|
384
409
|
}
|
|
385
410
|
|
|
@@ -388,6 +413,15 @@ function printChannelCollection(
|
|
|
388
413
|
outputMode,
|
|
389
414
|
response.items.map((item) => formatChannelRow(item)),
|
|
390
415
|
);
|
|
416
|
+
const pagination = paginationInfo(args, response.nextCursor);
|
|
417
|
+
const message = renderPagination(
|
|
418
|
+
pagination?.nextCursor,
|
|
419
|
+
pagination?.nextCommand,
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
if (message) {
|
|
423
|
+
io.stdout(message);
|
|
424
|
+
}
|
|
391
425
|
}
|
|
392
426
|
|
|
393
427
|
function formatChannelRecord(channel: { id: string; attributes: ChannelAttributes }) {
|
package/src/commands/feed.ts
CHANGED
|
@@ -7,7 +7,9 @@ import {
|
|
|
7
7
|
} from "../lib/args";
|
|
8
8
|
import { createCommandContext, type CommandContext } from "../lib/context";
|
|
9
9
|
import { CliError } from "../lib/errors";
|
|
10
|
+
import { renderPagination } from "../lib/human";
|
|
10
11
|
import { printJson, printValue, type Io } from "../lib/output";
|
|
12
|
+
import { paginatedJson, paginationInfo } from "../lib/pagination";
|
|
11
13
|
import type { PostAttributes } from "../types/api";
|
|
12
14
|
|
|
13
15
|
export async function runFeedCommand(args: ParsedArgs, io: Io): Promise<void> {
|
|
@@ -22,7 +24,7 @@ export async function runFeedCommand(args: ParsedArgs, io: Io): Promise<void> {
|
|
|
22
24
|
cursor: stringFlag(args.flags, "cursor"),
|
|
23
25
|
});
|
|
24
26
|
|
|
25
|
-
printFeedResponse(context, io, response);
|
|
27
|
+
printFeedResponse(args, context, io, response);
|
|
26
28
|
return;
|
|
27
29
|
}
|
|
28
30
|
|
|
@@ -40,7 +42,7 @@ export async function runFeedCommand(args: ParsedArgs, io: Io): Promise<void> {
|
|
|
40
42
|
cursor: stringFlag(args.flags, "cursor"),
|
|
41
43
|
});
|
|
42
44
|
|
|
43
|
-
printFeedResponse(context, io, response);
|
|
45
|
+
printFeedResponse(args, context, io, response);
|
|
44
46
|
return;
|
|
45
47
|
}
|
|
46
48
|
|
|
@@ -58,6 +60,7 @@ async function resolveChannelId(
|
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
function printFeedResponse(
|
|
63
|
+
args: ParsedArgs,
|
|
61
64
|
context: CommandContext,
|
|
62
65
|
io: Io,
|
|
63
66
|
response: {
|
|
@@ -66,21 +69,31 @@ function printFeedResponse(
|
|
|
66
69
|
},
|
|
67
70
|
): void {
|
|
68
71
|
if (context.outputMode === "json") {
|
|
69
|
-
printJson(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
printJson(
|
|
73
|
+
io,
|
|
74
|
+
paginatedJson(args, {
|
|
75
|
+
items: response.items,
|
|
76
|
+
nextCursor: response.nextCursor,
|
|
77
|
+
}),
|
|
78
|
+
);
|
|
73
79
|
return;
|
|
74
80
|
}
|
|
75
81
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
const rows = response.items.map((item) => ({
|
|
83
|
+
id: item.id,
|
|
84
|
+
source: item.attributes.source,
|
|
85
|
+
date: item.attributes.updated_at ?? item.attributes.inserted_at ?? "",
|
|
86
|
+
body: item.attributes.body,
|
|
87
|
+
}));
|
|
88
|
+
printValue(io, context.outputMode, rows);
|
|
89
|
+
|
|
90
|
+
const pagination = paginationInfo(args, response.nextCursor);
|
|
91
|
+
const message = renderPagination(
|
|
92
|
+
pagination?.nextCursor,
|
|
93
|
+
pagination?.nextCommand,
|
|
85
94
|
);
|
|
95
|
+
|
|
96
|
+
if (message) {
|
|
97
|
+
io.stdout(message);
|
|
98
|
+
}
|
|
86
99
|
}
|