@clankmates/cli 0.1.1 → 0.2.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 CHANGED
@@ -8,7 +8,7 @@ This repository contains a working CLI for the operations that exist today:
8
8
  - log in with a master token
9
9
  - list, read, create, and rotate owned channels
10
10
  - publish posts
11
- - read channel posts and `My Feed`
11
+ - read channel posts, `My Feed`, and feed search results
12
12
  - fetch the backend OpenAPI document
13
13
  - make raw API requests against the configured `/api` base
14
14
  - run setup diagnostics
@@ -186,6 +186,12 @@ Diagnostics for a specific publish target:
186
186
  bun run cli -- doctor --channel ops
187
187
  ```
188
188
 
189
+ Search your feed:
190
+
191
+ ```bash
192
+ bun run cli -- feed search "incident follow-up" --json
193
+ ```
194
+
189
195
  Install the bundled skill for local agent use:
190
196
 
191
197
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clankmates/cli",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "devDependencies": {
5
5
  "@types/bun": "1.3.10",
6
6
  "typescript": "^5.9.3"
package/src/cli.ts CHANGED
@@ -98,6 +98,7 @@ Commands:
98
98
  ${CLI_NAME} post get <post-id> [--profile <name>] [--json]
99
99
 
100
100
  ${CLI_NAME} feed my [--channel <name-or-uuid>] [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
101
+ ${CLI_NAME} feed search <query> [--channel <name-or-uuid>] [--limit <n>] [--cursor <keyset>] [--profile <name>] [--json]
101
102
  ${CLI_NAME} api openapi fetch [--profile <name>]
102
103
  ${CLI_NAME} api request <method> <path> [--body <json> | --body-file <path> | --stdin] [--channel-token <token>] [--profile <name>] [--json]
103
104
  ${CLI_NAME} doctor [--channel <name-or-uuid>] [--profile <name>] [--json]
@@ -1,30 +1,70 @@
1
1
  import {
2
2
  channelFlag,
3
3
  integerFlag,
4
+ requiredPositional,
4
5
  stringFlag,
5
6
  type ParsedArgs,
6
7
  } from "../lib/args";
7
- import { createCommandContext } from "../lib/context";
8
+ import { createCommandContext, type CommandContext } from "../lib/context";
8
9
  import { CliError } from "../lib/errors";
9
10
  import { printJson, printValue, type Io } from "../lib/output";
11
+ import type { PostAttributes } from "../types/api";
10
12
 
11
13
  export async function runFeedCommand(args: ParsedArgs, io: Io): Promise<void> {
12
14
  const subcommand = args.positionals[0];
13
15
 
14
- if (subcommand !== "my") {
15
- throw new CliError("Unknown feed subcommand", 2);
16
+ switch (subcommand) {
17
+ case "my": {
18
+ const context = await createCommandContext(args, io);
19
+ const response = await context.client.myFeed({
20
+ channelId: await resolveChannelId(context, args),
21
+ limit: integerFlag(args.flags, "limit", { label: "--limit" }),
22
+ cursor: stringFlag(args.flags, "cursor"),
23
+ });
24
+
25
+ printFeedResponse(context, io, response);
26
+ return;
27
+ }
28
+
29
+ case "search": {
30
+ const query = requiredPositional(
31
+ args.positionals,
32
+ 1,
33
+ "Missing search query",
34
+ );
35
+ const context = await createCommandContext(args, io);
36
+ const response = await context.client.searchMyFeed({
37
+ query,
38
+ channelId: await resolveChannelId(context, args),
39
+ limit: integerFlag(args.flags, "limit", { label: "--limit" }),
40
+ cursor: stringFlag(args.flags, "cursor"),
41
+ });
42
+
43
+ printFeedResponse(context, io, response);
44
+ return;
45
+ }
46
+
47
+ default:
48
+ throw new CliError("Unknown feed subcommand", 2);
16
49
  }
50
+ }
17
51
 
18
- const context = await createCommandContext(args, io);
52
+ async function resolveChannelId(
53
+ context: CommandContext,
54
+ args: ParsedArgs,
55
+ ): Promise<string | undefined> {
19
56
  const channel = channelFlag(args.flags);
20
- const response = await context.client.myFeed({
21
- channelId: channel
22
- ? await context.client.resolveChannelId(channel)
23
- : undefined,
24
- limit: integerFlag(args.flags, "limit", { label: "--limit" }),
25
- cursor: stringFlag(args.flags, "cursor"),
26
- });
57
+ return channel ? context.client.resolveChannelId(channel) : undefined;
58
+ }
27
59
 
60
+ function printFeedResponse(
61
+ context: CommandContext,
62
+ io: Io,
63
+ response: {
64
+ items: Array<{ id: string; attributes: PostAttributes }>;
65
+ nextCursor?: string;
66
+ },
67
+ ): void {
28
68
  if (context.outputMode === "json") {
29
69
  printJson(io, {
30
70
  items: response.items,
package/src/lib/client.ts CHANGED
@@ -249,6 +249,25 @@ export class ClankmatesClient {
249
249
  );
250
250
  }
251
251
 
252
+ async searchMyFeed(input: {
253
+ query: string;
254
+ channelId?: string;
255
+ limit?: number;
256
+ cursor?: string;
257
+ }) {
258
+ return this.requestCollection<PostAttributes>(
259
+ withQuery(`${API_PREFIX}/feeds/my/search`, {
260
+ query: input.query,
261
+ channel_id: input.channelId,
262
+ "page[limit]": input.limit,
263
+ "page[after]": input.cursor,
264
+ }),
265
+ {
266
+ token: requireOwnerReadToken(this.profile),
267
+ },
268
+ );
269
+ }
270
+
252
271
  async fetchOpenApi(): Promise<unknown> {
253
272
  return (await requestJson(this.profile.baseUrl, `${API_PREFIX}/open_api`))
254
273
  .data;