@ahood/cli 0.8.5 → 0.8.6

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
@@ -244,8 +244,8 @@ Sharing is additive -- it doesn't change `alice/pdf-tools`'s own public/private
244
244
  | Command | What it does |
245
245
  | --- | --- |
246
246
  | `ahood snap create <content> [--tags tag1,tag2] [--json]` | Capture a new private snap, from an argument or piped stdin. |
247
- | `ahood snap list [--json] [--limit <n>]` | List your own snaps, most recent first. |
248
- | `ahood snap search <query> [--json] [--limit <n>]` | Search your own snaps by content. |
247
+ | `ahood snap list [--json] [--limit <n>] [--tags tag1,tag2]` | List your own snaps, most recent first. |
248
+ | `ahood snap search <query> [--json] [--limit <n>] [--tags tag1,tag2]` | Search your own snaps by content. |
249
249
  | `ahood snap show <id> [--json]` | Print a single snap's full content. |
250
250
  | `ahood snap remove <id> [--yes]` | Permanently delete a snap (prompts for confirmation unless --yes is passed). |
251
251
  | `ahood snap share <id> [--json]` | Mint (or return the existing) shareable link for a snap. |
@@ -3,8 +3,8 @@ import { flagValue, parseSearchQuery } from "../flags.js";
3
3
  import { confirm } from "../confirm.js";
4
4
  import { UsageError } from "../usage-error.js";
5
5
  const CREATE_USAGE = "Usage: ahood snap create <content> [--tags tag1,tag2] (or pipe content on stdin)";
6
- const LIST_USAGE = "Usage: ahood snap list [--json] [--limit <n>]";
7
- const SEARCH_USAGE = "Usage: ahood snap search <query> [--json] [--limit <n>]";
6
+ const LIST_USAGE = "Usage: ahood snap list [--json] [--limit <n>] [--tags tag1,tag2]";
7
+ const SEARCH_USAGE = "Usage: ahood snap search <query> [--json] [--limit <n>] [--tags tag1,tag2]";
8
8
  const SHOW_USAGE = "Usage: ahood snap show <id> [--json]";
9
9
  const REMOVE_USAGE = "Usage: ahood snap remove <id> [--yes]";
10
10
  const SHARE_USAGE = "Usage: ahood snap share <id> [--json]";
@@ -113,10 +113,19 @@ export async function createSnap(args) {
113
113
  export async function listSnaps(args) {
114
114
  const jsonOutput = args.includes("--json");
115
115
  const limitStr = flagValue(args, "--limit");
116
+ const tagsStr = flagValue(args, "--tags");
116
117
  validateLimit(limitStr, LIST_USAGE);
117
118
  const qs = new URLSearchParams();
118
119
  if (limitStr !== undefined)
119
120
  qs.set("limit", limitStr);
121
+ // Passed through verbatim rather than split/trimmed the way createSnap's
122
+ // own --tags is: the server owns what a tag filter means (comma-separated,
123
+ // ANDed, case-insensitive, 400 past 8 terms) and deliberately keeps an
124
+ // unstorable term instead of dropping it, since dropping one would silently
125
+ // broaden the result set. Re-parsing here would be a second implementation
126
+ // of that contract, free to drift from it (ahood-cli#118).
127
+ if (tagsStr !== undefined)
128
+ qs.set("tags", tagsStr);
120
129
  const query = qs.toString();
121
130
  const { snaps } = await apiJson(`/api/v1/snaps${query ? `?${query}` : ""}`);
122
131
  // ?? [], not a bare destructure -- a degraded response (snaps: null)
@@ -127,11 +136,19 @@ export async function listSnaps(args) {
127
136
  export async function searchSnaps(args) {
128
137
  const jsonOutput = args.includes("--json");
129
138
  const limitStr = flagValue(args, "--limit");
130
- const query = parseSearchQuery(args, SEARCH_USAGE);
139
+ const tagsStr = flagValue(args, "--tags");
140
+ // --tags declared here so its VALUE isn't swallowed into the joined query
141
+ // string -- `snap search deploy --tags ci` must search for "deploy" filtered
142
+ // to tag "ci", not for "deploy ci" (ahood-cli#118).
143
+ const query = parseSearchQuery(args, SEARCH_USAGE, ["--tags"]);
131
144
  validateLimit(limitStr, SEARCH_USAGE);
132
145
  const qs = new URLSearchParams({ q: query });
133
146
  if (limitStr !== undefined)
134
147
  qs.set("limit", limitStr);
148
+ // Verbatim -- see listSnaps' identical pass-through above (ahood-cli#118).
149
+ // The server ANDs a tag filter with `q`, so this narrows the text results.
150
+ if (tagsStr !== undefined)
151
+ qs.set("tags", tagsStr);
135
152
  const { snaps } = await apiJson(`/api/v1/snaps?${qs}`);
136
153
  // ?? [] -- see listSnaps' identical guard above (ahood-cli#106).
137
154
  printSnaps(jsonOutput, snaps ?? [], "No snaps found.");
package/dist/flags.js CHANGED
@@ -36,8 +36,18 @@ export function flagValue(args, flag) {
36
36
  // --limit (both "--limit N" and "--limit=N" forms) from the positional
37
37
  // args, rejects any other unrecognized "--" flag, and joins what's left
38
38
  // into a single query string.
39
- export function parseSearchQuery(args, usage) {
40
- const queryParts = args.filter((a, i) => a !== "--json" && a !== "--limit" && !a.startsWith("--limit=") && args[i - 1] !== "--limit");
39
+ // `valueFlags` names ADDITIONAL "--flag value" flags this particular command
40
+ // accepts (snap search's --tags, ahood-cli#118), on top of --limit, which
41
+ // every caller takes. Passed per-caller rather than stripping a shared union
42
+ // of every search-ish flag, so `ahood skill search --tags x` still errors on
43
+ // a flag that command doesn't implement instead of silently ignoring it and
44
+ // returning unfiltered results.
45
+ export function parseSearchQuery(args, usage, valueFlags = []) {
46
+ const stripped = ["--limit", ...valueFlags];
47
+ const queryParts = args.filter((a, i) => a !== "--json" &&
48
+ !stripped.includes(a) &&
49
+ !stripped.some((f) => a.startsWith(`${f}=`)) &&
50
+ !stripped.includes(args[i - 1]));
41
51
  const unknownFlag = queryParts.find((a) => a.startsWith("--"));
42
52
  if (unknownFlag)
43
53
  throw new UsageError(`Unknown flag: ${unknownFlag}\n${usage}`);
package/dist/help.js CHANGED
@@ -294,24 +294,29 @@ export const SNAP_COMMANDS_HELP = [
294
294
  ],
295
295
  },
296
296
  {
297
- usage: "ahood snap list [--json] [--limit <n>]",
297
+ usage: "ahood snap list [--json] [--limit <n>] [--tags tag1,tag2]",
298
298
  summary: "List your own snaps, most recent first.",
299
299
  desc: "List your own snaps: id, a truncated content preview, created_at, a (shared) marker if shared, and " +
300
- "any tags in brackets.",
300
+ "any tags in brackets. --tags narrows the list to snaps carrying every tag given (not any of them), " +
301
+ "matched case-insensitively.",
301
302
  flags: [
302
- "--json Emit the raw snap objects instead of formatted lines.",
303
- "--limit <n> Cap the number of results.",
303
+ "--json Emit the raw snap objects instead of formatted lines.",
304
+ "--limit <n> Cap the number of results.",
305
+ "--tags tag1,tag2 Only snaps carrying ALL of these tags. Case-insensitive; at most 8.",
304
306
  ],
307
+ examples: ["ahood snap list --tags deploy", "ahood snap list --tags deploy,bugfix --limit 5"],
305
308
  },
306
309
  {
307
- usage: "ahood snap search <query> [--json] [--limit <n>]",
310
+ usage: "ahood snap search <query> [--json] [--limit <n>] [--tags tag1,tag2]",
308
311
  summary: "Search your own snaps by content.",
309
- desc: "Search your own snaps by content. Same output shape as `ahood snap list`.",
312
+ desc: "Search your own snaps by content. Same output shape as `ahood snap list`. The query matches snap " +
313
+ "CONTENT only and never a tag -- use --tags to filter by tag, which narrows the text results further.",
310
314
  flags: [
311
- "--json Emit the raw snap objects instead of formatted lines.",
312
- "--limit <n> Cap the number of results.",
315
+ "--json Emit the raw snap objects instead of formatted lines.",
316
+ "--limit <n> Cap the number of results.",
317
+ "--tags tag1,tag2 Only snaps carrying ALL of these tags. Case-insensitive; at most 8.",
313
318
  ],
314
- examples: ["ahood snap search flaky-ci"],
319
+ examples: ["ahood snap search flaky-ci", "ahood snap search deploy --tags ci"],
315
320
  },
316
321
  {
317
322
  usage: "ahood snap show <id> [--json]",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahood/cli",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "description": "CLI for ahood, a registry for installing and publishing Claude Code skills.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/AlexKay28/ahood-cli",