@ozzylabs/feedradar 0.1.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.
Files changed (168) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +104 -0
  3. package/dist/agents/_boundary.d.ts +44 -0
  4. package/dist/agents/_boundary.d.ts.map +1 -0
  5. package/dist/agents/_boundary.js +59 -0
  6. package/dist/agents/_boundary.js.map +1 -0
  7. package/dist/agents/claude-code.d.ts +32 -0
  8. package/dist/agents/claude-code.d.ts.map +1 -0
  9. package/dist/agents/claude-code.js +256 -0
  10. package/dist/agents/claude-code.js.map +1 -0
  11. package/dist/agents/codex-cli.d.ts +31 -0
  12. package/dist/agents/codex-cli.d.ts.map +1 -0
  13. package/dist/agents/codex-cli.js +303 -0
  14. package/dist/agents/codex-cli.js.map +1 -0
  15. package/dist/agents/copilot.d.ts +29 -0
  16. package/dist/agents/copilot.d.ts.map +1 -0
  17. package/dist/agents/copilot.js +282 -0
  18. package/dist/agents/copilot.js.map +1 -0
  19. package/dist/agents/gemini-cli.d.ts +30 -0
  20. package/dist/agents/gemini-cli.d.ts.map +1 -0
  21. package/dist/agents/gemini-cli.js +316 -0
  22. package/dist/agents/gemini-cli.js.map +1 -0
  23. package/dist/agents/index.d.ts +12 -0
  24. package/dist/agents/index.d.ts.map +1 -0
  25. package/dist/agents/index.js +33 -0
  26. package/dist/agents/index.js.map +1 -0
  27. package/dist/agents/types.d.ts +103 -0
  28. package/dist/agents/types.d.ts.map +1 -0
  29. package/dist/agents/types.js +2 -0
  30. package/dist/agents/types.js.map +1 -0
  31. package/dist/claude-skills/dismiss/SKILL.md +41 -0
  32. package/dist/claude-skills/research/SKILL.md +45 -0
  33. package/dist/claude-skills/review/SKILL.md +45 -0
  34. package/dist/claude-skills/update/SKILL.md +49 -0
  35. package/dist/cli/dismiss.d.ts +28 -0
  36. package/dist/cli/dismiss.d.ts.map +1 -0
  37. package/dist/cli/dismiss.js +122 -0
  38. package/dist/cli/dismiss.js.map +1 -0
  39. package/dist/cli/index.d.ts +7 -0
  40. package/dist/cli/index.d.ts.map +1 -0
  41. package/dist/cli/index.js +64 -0
  42. package/dist/cli/index.js.map +1 -0
  43. package/dist/cli/init.d.ts +148 -0
  44. package/dist/cli/init.d.ts.map +1 -0
  45. package/dist/cli/init.js +578 -0
  46. package/dist/cli/init.js.map +1 -0
  47. package/dist/cli/research.d.ts +30 -0
  48. package/dist/cli/research.d.ts.map +1 -0
  49. package/dist/cli/research.js +313 -0
  50. package/dist/cli/research.js.map +1 -0
  51. package/dist/cli/review.d.ts +34 -0
  52. package/dist/cli/review.d.ts.map +1 -0
  53. package/dist/cli/review.js +418 -0
  54. package/dist/cli/review.js.map +1 -0
  55. package/dist/cli/source.d.ts +57 -0
  56. package/dist/cli/source.d.ts.map +1 -0
  57. package/dist/cli/source.js +511 -0
  58. package/dist/cli/source.js.map +1 -0
  59. package/dist/cli/update.d.ts +43 -0
  60. package/dist/cli/update.d.ts.map +1 -0
  61. package/dist/cli/update.js +429 -0
  62. package/dist/cli/update.js.map +1 -0
  63. package/dist/cli/watch.d.ts +22 -0
  64. package/dist/cli/watch.d.ts.map +1 -0
  65. package/dist/cli/watch.js +101 -0
  66. package/dist/cli/watch.js.map +1 -0
  67. package/dist/core/config.d.ts +60 -0
  68. package/dist/core/config.d.ts.map +1 -0
  69. package/dist/core/config.js +101 -0
  70. package/dist/core/config.js.map +1 -0
  71. package/dist/core/feeds/derive-id.d.ts +43 -0
  72. package/dist/core/feeds/derive-id.d.ts.map +1 -0
  73. package/dist/core/feeds/derive-id.js +66 -0
  74. package/dist/core/feeds/derive-id.js.map +1 -0
  75. package/dist/core/feeds/github-api.d.ts +69 -0
  76. package/dist/core/feeds/github-api.d.ts.map +1 -0
  77. package/dist/core/feeds/github-api.js +161 -0
  78. package/dist/core/feeds/github-api.js.map +1 -0
  79. package/dist/core/feeds/github-releases.d.ts +3 -0
  80. package/dist/core/feeds/github-releases.d.ts.map +1 -0
  81. package/dist/core/feeds/github-releases.js +85 -0
  82. package/dist/core/feeds/github-releases.js.map +1 -0
  83. package/dist/core/feeds/html.d.ts +10 -0
  84. package/dist/core/feeds/html.d.ts.map +1 -0
  85. package/dist/core/feeds/html.js +263 -0
  86. package/dist/core/feeds/html.js.map +1 -0
  87. package/dist/core/feeds/index.d.ts +5 -0
  88. package/dist/core/feeds/index.d.ts.map +1 -0
  89. package/dist/core/feeds/index.js +18 -0
  90. package/dist/core/feeds/index.js.map +1 -0
  91. package/dist/core/feeds/npm-registry.d.ts +36 -0
  92. package/dist/core/feeds/npm-registry.d.ts.map +1 -0
  93. package/dist/core/feeds/npm-registry.js +200 -0
  94. package/dist/core/feeds/npm-registry.js.map +1 -0
  95. package/dist/core/feeds/rss.d.ts +12 -0
  96. package/dist/core/feeds/rss.d.ts.map +1 -0
  97. package/dist/core/feeds/rss.js +222 -0
  98. package/dist/core/feeds/rss.js.map +1 -0
  99. package/dist/core/feeds/types.d.ts +45 -0
  100. package/dist/core/feeds/types.d.ts.map +1 -0
  101. package/dist/core/feeds/types.js +2 -0
  102. package/dist/core/feeds/types.js.map +1 -0
  103. package/dist/core/filter.d.ts +25 -0
  104. package/dist/core/filter.d.ts.map +1 -0
  105. package/dist/core/filter.js +123 -0
  106. package/dist/core/filter.js.map +1 -0
  107. package/dist/core/injection-detector.d.ts +57 -0
  108. package/dist/core/injection-detector.d.ts.map +1 -0
  109. package/dist/core/injection-detector.js +109 -0
  110. package/dist/core/injection-detector.js.map +1 -0
  111. package/dist/core/items.d.ts +20 -0
  112. package/dist/core/items.d.ts.map +1 -0
  113. package/dist/core/items.js +105 -0
  114. package/dist/core/items.js.map +1 -0
  115. package/dist/core/state.d.ts +12 -0
  116. package/dist/core/state.d.ts.map +1 -0
  117. package/dist/core/state.js +42 -0
  118. package/dist/core/state.js.map +1 -0
  119. package/dist/core/templates.d.ts +21 -0
  120. package/dist/core/templates.d.ts.map +1 -0
  121. package/dist/core/templates.js +52 -0
  122. package/dist/core/templates.js.map +1 -0
  123. package/dist/core/watcher.d.ts +72 -0
  124. package/dist/core/watcher.d.ts.map +1 -0
  125. package/dist/core/watcher.js +240 -0
  126. package/dist/core/watcher.js.map +1 -0
  127. package/dist/gemini-commands/dismiss.toml +2 -0
  128. package/dist/gemini-commands/research.toml +2 -0
  129. package/dist/gemini-commands/review.toml +2 -0
  130. package/dist/gemini-commands/update.toml +2 -0
  131. package/dist/index.d.ts +3 -0
  132. package/dist/index.d.ts.map +1 -0
  133. package/dist/index.js +8 -0
  134. package/dist/index.js.map +1 -0
  135. package/dist/schemas/config.d.ts +39 -0
  136. package/dist/schemas/config.d.ts.map +1 -0
  137. package/dist/schemas/config.js +23 -0
  138. package/dist/schemas/config.js.map +1 -0
  139. package/dist/schemas/index.d.ts +6 -0
  140. package/dist/schemas/index.d.ts.map +1 -0
  141. package/dist/schemas/index.js +6 -0
  142. package/dist/schemas/index.js.map +1 -0
  143. package/dist/schemas/item.d.ts +38 -0
  144. package/dist/schemas/item.d.ts.map +1 -0
  145. package/dist/schemas/item.js +34 -0
  146. package/dist/schemas/item.js.map +1 -0
  147. package/dist/schemas/research.d.ts +82 -0
  148. package/dist/schemas/research.d.ts.map +1 -0
  149. package/dist/schemas/research.js +45 -0
  150. package/dist/schemas/research.js.map +1 -0
  151. package/dist/schemas/source.d.ts +139 -0
  152. package/dist/schemas/source.d.ts.map +1 -0
  153. package/dist/schemas/source.js +127 -0
  154. package/dist/schemas/source.js.map +1 -0
  155. package/dist/schemas/state.d.ts +19 -0
  156. package/dist/schemas/state.d.ts.map +1 -0
  157. package/dist/schemas/state.js +12 -0
  158. package/dist/schemas/state.js.map +1 -0
  159. package/dist/skills/research/SKILL.md +156 -0
  160. package/dist/skills/review/SKILL.md +173 -0
  161. package/dist/skills/update/SKILL.md +200 -0
  162. package/dist/templates/agents/AGENTS.md +161 -0
  163. package/dist/templates/claude/CLAUDE.md +5 -0
  164. package/dist/templates/default.md +16 -0
  165. package/dist/templates/feedradar.md +165 -0
  166. package/dist/templates/routines/watch-daily.md +42 -0
  167. package/dist/templates/workflows/watch.yaml +70 -0
  168. package/package.json +73 -0
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: review
3
+ description: Cross-review an existing research report with a different agent via the FeedRadar CLI.
4
+ argument-hint: <research-id> [--agent claude-code|codex-cli|gemini-cli|copilot] [--template <id>]
5
+ ---
6
+
7
+ # review
8
+
9
+ Append a review block to an existing `research/<id>.md` and stamp the
10
+ frontmatter `reviewedAt` / `reviewedBy` fields.
11
+
12
+ This skill is a thin wrapper: it delegates to the `radar` CLI, which
13
+ handles research file resolution, template loading, adapter dispatch, schema
14
+ validation, and the `researched → reviewed` status transition. The canonical
15
+ review procedure (rubric, where the review block lands, frontmatter stamp
16
+ format) lives in `.agents/skills/review/SKILL.md` (the SSoT) and is invoked
17
+ by the agent adapter that the CLI spawns. Do not duplicate that procedure
18
+ here.
19
+
20
+ ## Steps
21
+
22
+ 1. Resolve `$ARGUMENTS`. If empty or `--help`, run:
23
+
24
+ ```bash
25
+ radar review --help
26
+ ```
27
+
28
+ and report the usage. Otherwise pass `$ARGUMENTS` through verbatim.
29
+ 2. Execute:
30
+
31
+ ```bash
32
+ radar review $ARGUMENTS
33
+ ```
34
+
35
+ 3. Report the result: the CLI prints the research path it updated and the
36
+ item status transition (`status -> reviewed`).
37
+
38
+ ## Notes
39
+
40
+ - For meaningful cross-checking, pick `--agent` different from the one that
41
+ wrote the original v1 (ADR-0001 § クロスエージェント運用). Example: if v1
42
+ was authored by `claude-code`, run review with `--agent codex-cli` or
43
+ `--agent gemini-cli`.
44
+ - If the CLI exits non-zero, surface the error and exit code; do not retry
45
+ with a different agent without user direction.
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: update
3
+ description: Regenerate an existing research report as v+1 via the FeedRadar CLI (rewrite-and-supersede).
4
+ argument-hint: <research-id> [--agent claude-code|codex-cli|gemini-cli|copilot] [--template <id>]
5
+ ---
6
+
7
+ # update
8
+
9
+ Generate a new `<base>_v<N+1>.md` from the supplied predecessor research,
10
+ writing `supersedes: <prev-id>` into the new frontmatter and leaving the
11
+ predecessor file untouched (immutable history, ADR-0003).
12
+
13
+ This skill is a thin wrapper: it delegates to the `radar` CLI, which
14
+ handles predecessor parsing, version increment, supersedes wiring, adapter
15
+ dispatch, schema validation, and the **items.yaml status invariance** rule
16
+ (ADR-0008: update never changes the source item's `status`, regardless of
17
+ how many v+N files it generates). The canonical update procedure
18
+ (rewrite-and-supersede strategy, materiality judgement, what fields v+1
19
+ resets) lives in `.agents/skills/update/SKILL.md` (the SSoT) and is invoked
20
+ by the agent adapter that the CLI spawns. Do not duplicate that procedure
21
+ here.
22
+
23
+ ## Steps
24
+
25
+ 1. Resolve `$ARGUMENTS`. If empty or `--help`, run:
26
+
27
+ ```bash
28
+ radar update --help
29
+ ```
30
+
31
+ and report the usage. Otherwise pass `$ARGUMENTS` through verbatim.
32
+ 2. Execute:
33
+
34
+ ```bash
35
+ radar update $ARGUMENTS
36
+ ```
37
+
38
+ 3. Report the v+1 file path the CLI produced (printed as `update: wrote
39
+ <path>` and `update: supersedes <prev-id> (items.yaml status unchanged
40
+ per ADR-0008)`).
41
+
42
+ ## Notes
43
+
44
+ - v+1 always resets `reviewedAt` / `reviewedBy` to `null` because a review
45
+ only applies to the version it was written against (ADR-0003). To
46
+ re-review the new version, run `/review <new-id>` afterwards.
47
+ - If the CLI exits non-zero (e.g. the supplied predecessor's frontmatter
48
+ doesn't match the schema), surface the error and exit code; do not edit
49
+ the predecessor file to fix it — that violates immutable history.
@@ -0,0 +1,28 @@
1
+ import type { Command } from "./index.js";
2
+ /** Sinks for the dismiss command's user-facing output. Tests inject capturing sinks. */
3
+ export interface DismissIO {
4
+ log?: (message: string) => void;
5
+ error?: (message: string) => void;
6
+ }
7
+ export interface DismissCommandOptions {
8
+ cwd?: string;
9
+ io?: DismissIO;
10
+ }
11
+ /**
12
+ * Implementation of `radar dismiss <item-id>`.
13
+ *
14
+ * Triggers the `detected → dismissed` state transition (ADR-0008). The command
15
+ * is intentionally agent-free: it only mutates `items/<sourceId>/<item-id>.yaml`
16
+ * so users can prune noise from `watch run` output without spending agent
17
+ * tokens.
18
+ *
19
+ * Flow:
20
+ * 1. Parse + validate args.
21
+ * 2. Locate `items/<sourceId>/<item-id>.yaml`.
22
+ * 3. Reject if the item is not in `detected` (terminal/researched states
23
+ * cannot be dismissed; there is no `undismiss`).
24
+ * 4. Write back with `status: dismissed`.
25
+ */
26
+ export declare function runDismiss(args: string[], options?: DismissCommandOptions): Promise<number>;
27
+ export declare const dismissCommand: Command;
28
+ //# sourceMappingURL=dismiss.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dismiss.d.ts","sourceRoot":"","sources":["../../src/cli/dismiss.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,wFAAwF;AACxF,MAAM,WAAW,SAAS;IACxB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,SAAS,CAAC;CAChB;AA8DD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,CAAC,CAgDjB;AAED,eAAO,MAAM,cAAc,EAAE,OAI5B,CAAC"}
@@ -0,0 +1,122 @@
1
+ import { access } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { loadItems, saveItems } from "../core/items.js";
4
+ function parseArgs(args) {
5
+ const out = {};
6
+ for (let i = 0; i < args.length; i++) {
7
+ const a = args[i];
8
+ if (a === "-h" || a === "--help") {
9
+ out.help = true;
10
+ continue;
11
+ }
12
+ if (a?.startsWith("--")) {
13
+ throw new Error(`unknown option: ${a}`);
14
+ }
15
+ if (!out.itemId) {
16
+ out.itemId = a;
17
+ continue;
18
+ }
19
+ throw new Error(`unexpected positional argument: ${a}`);
20
+ }
21
+ return out;
22
+ }
23
+ function printHelp(log) {
24
+ log("Usage: radar dismiss <item-id>");
25
+ log("");
26
+ log("Arguments:");
27
+ log(" <item-id> Item id (matches items/<sourceId>/<item-id>.yaml)");
28
+ log("");
29
+ log("Transitions the item's status from `detected` to `dismissed` (ADR-0008).");
30
+ log("Items already in `researched`, `reviewed`, or `dismissed` cannot be dismissed.");
31
+ }
32
+ async function pathExists(p) {
33
+ try {
34
+ await access(p);
35
+ return true;
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ /**
42
+ * Locate `items/<sourceId>/<item-id>.yaml` across all source directories.
43
+ *
44
+ * Mirrors the lookup strategy used by `research`: `loadItems` walks every
45
+ * source subdir and we match by id, so the caller only needs `<item-id>`
46
+ * (sourceId is inferred from the loaded item).
47
+ */
48
+ async function findItem(cwd, itemId) {
49
+ const itemsDir = join(cwd, "items");
50
+ if (!(await pathExists(itemsDir)))
51
+ return null;
52
+ const items = await loadItems(itemsDir);
53
+ const match = items.find((i) => i.id === itemId);
54
+ if (!match)
55
+ return null;
56
+ return { item: match };
57
+ }
58
+ /**
59
+ * Implementation of `radar dismiss <item-id>`.
60
+ *
61
+ * Triggers the `detected → dismissed` state transition (ADR-0008). The command
62
+ * is intentionally agent-free: it only mutates `items/<sourceId>/<item-id>.yaml`
63
+ * so users can prune noise from `watch run` output without spending agent
64
+ * tokens.
65
+ *
66
+ * Flow:
67
+ * 1. Parse + validate args.
68
+ * 2. Locate `items/<sourceId>/<item-id>.yaml`.
69
+ * 3. Reject if the item is not in `detected` (terminal/researched states
70
+ * cannot be dismissed; there is no `undismiss`).
71
+ * 4. Write back with `status: dismissed`.
72
+ */
73
+ export async function runDismiss(args, options = {}) {
74
+ const cwd = options.cwd ?? process.cwd();
75
+ const log = options.io?.log ?? ((m) => console.log(m));
76
+ const error = options.io?.error ?? ((m) => console.error(m));
77
+ let parsed;
78
+ try {
79
+ parsed = parseArgs(args);
80
+ }
81
+ catch (e) {
82
+ error(`dismiss: ${e instanceof Error ? e.message : String(e)}`);
83
+ return 2;
84
+ }
85
+ if (parsed.help) {
86
+ printHelp(log);
87
+ return 0;
88
+ }
89
+ if (!parsed.itemId) {
90
+ error("dismiss: missing <item-id>");
91
+ printHelp(error);
92
+ return 2;
93
+ }
94
+ const found = await findItem(cwd, parsed.itemId);
95
+ if (!found) {
96
+ error(`dismiss: item '${parsed.itemId}' not found under items/`);
97
+ return 1;
98
+ }
99
+ const { item } = found;
100
+ if (item.status !== "detected") {
101
+ error(`dismiss: item '${item.id}' is in status '${item.status}', expected 'detected' (dismiss is only valid from the detected state; ADR-0008)`);
102
+ return 1;
103
+ }
104
+ const updated = { ...item, status: "dismissed" };
105
+ try {
106
+ // saveItems writes by sourceId+id, so it overwrites the existing file in
107
+ // place. The status transition is the entire effect of the command.
108
+ await saveItems(join(cwd, "items"), [updated]);
109
+ }
110
+ catch (e) {
111
+ error(`dismiss: failed to update item status: ${e instanceof Error ? e.message : String(e)}`);
112
+ return 1;
113
+ }
114
+ log(`dismiss: items/${item.sourceId}/${item.id}.yaml status -> dismissed`);
115
+ return 0;
116
+ }
117
+ export const dismissCommand = {
118
+ name: "dismiss",
119
+ summary: "Mark a detected item as dismissed (no research/review)",
120
+ run: (args) => runDismiss(args),
121
+ };
122
+ //# sourceMappingURL=dismiss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dismiss.js","sourceRoot":"","sources":["../../src/cli/dismiss.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface Command {
2
+ name: string;
3
+ summary: string;
4
+ run: (args: string[]) => Promise<number>;
5
+ }
6
+ export declare function run(argv: string[]): Promise<void>;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1C;AAqCD,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBvD"}
@@ -0,0 +1,64 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { dismissCommand } from "./dismiss.js";
5
+ import { initCommand } from "./init.js";
6
+ import { researchCommand } from "./research.js";
7
+ import { reviewCommand } from "./review.js";
8
+ import { sourceCommand } from "./source.js";
9
+ import { updateCommand } from "./update.js";
10
+ import { watchCommand } from "./watch.js";
11
+ const commands = [
12
+ initCommand,
13
+ sourceCommand,
14
+ watchCommand,
15
+ researchCommand,
16
+ dismissCommand,
17
+ reviewCommand,
18
+ updateCommand,
19
+ ];
20
+ // Read the installed package's version at runtime so `radar --version`
21
+ // tracks release-please bumps without a parallel source edit. The bin
22
+ // ships as dist/cli/index.js with package.json two levels up; the path
23
+ // is identical in both npm-installed and local-built layouts because
24
+ // tsc preserves src/ → dist/ structure.
25
+ const PKG_PATH = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "package.json");
26
+ const VERSION = JSON.parse(readFileSync(PKG_PATH, "utf8")).version;
27
+ function printHelp() {
28
+ console.log("FeedRadar — Multi-agent CLI for blog/release feed research");
29
+ console.log("");
30
+ console.log("Usage: radar <command> [options]");
31
+ console.log("");
32
+ console.log("Commands:");
33
+ for (const c of commands) {
34
+ console.log(` ${c.name.padEnd(10)} ${c.summary}`);
35
+ }
36
+ console.log("");
37
+ console.log("Options:");
38
+ console.log(" -h, --help Show this help");
39
+ console.log(" -v, --version Show version");
40
+ console.log("");
41
+ console.log("Status: alpha — Phase 1-5 complete, Phase 6 (npm publish 0.1.0) pending.");
42
+ }
43
+ export async function run(argv) {
44
+ const [first, ...rest] = argv;
45
+ if (!first || first === "-h" || first === "--help" || first === "help") {
46
+ printHelp();
47
+ return;
48
+ }
49
+ if (first === "-v" || first === "--version" || first === "version") {
50
+ console.log(VERSION);
51
+ return;
52
+ }
53
+ const command = commands.find((c) => c.name === first);
54
+ if (!command) {
55
+ console.error(`radar: unknown command '${first}'`);
56
+ console.error("Run 'radar --help' for available commands.");
57
+ process.exit(2);
58
+ }
59
+ const code = await command.run(rest);
60
+ if (code !== 0) {
61
+ process.exit(code);
62
+ }
63
+ }
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,148 @@
1
+ import type { Command } from "./index.js";
2
+ interface InitOptions {
3
+ cwd: string;
4
+ force: boolean;
5
+ /** Override the source location of bundled engine skills (used by tests). */
6
+ skillsRoot?: string;
7
+ /** Override the source location of bundled init templates (used by tests). */
8
+ templatesRoot?: string;
9
+ /** Override the source location of bundled Claude discovery skills (used by tests). */
10
+ claudeSkillsRoot?: string;
11
+ /** Override the source location of bundled Gemini CLI command TOMLs (used by tests). */
12
+ geminiCommandsRoot?: string;
13
+ /**
14
+ * Skip writing Claude Code slash-command wrappers to
15
+ * `<cwd>/.claude/skills/`. Useful for workspaces that already manage that
16
+ * directory via the `@ozzylabs/skills` Renovate preset and don't want
17
+ * FeedRadar's discovery skills to land alongside the preset ones.
18
+ *
19
+ * The engine SKILLs at `<cwd>/.agents/skills/` (which the agent adapter
20
+ * reads when the CLI spawns the agent) are always written regardless of
21
+ * this flag; they are the SSoT.
22
+ */
23
+ noClaudeSkills?: boolean;
24
+ /**
25
+ * Skip writing Gemini CLI slash-command TOMLs to
26
+ * `<cwd>/.gemini/commands/`. Useful for workspaces that already manage
27
+ * that directory via another mechanism, or that don't use Gemini CLI.
28
+ *
29
+ * The engine SKILLs at `<cwd>/.agents/skills/` are always written
30
+ * regardless of this flag; they are the SSoT. Codex CLI / Gemini CLI
31
+ * interactive sessions also fall back to the engine SKILLs via the
32
+ * "Invocation modes" dual-mode procedure when no slash command is
33
+ * configured.
34
+ */
35
+ noGeminiCommands?: boolean;
36
+ /**
37
+ * Skip writing `<cwd>/AGENTS.md`. By default `init` copies the bundled
38
+ * AGENTS.md template into the workspace so that agent CLIs which auto-read
39
+ * an agent-agnostic instructions file (Codex / Gemini / Copilot) get
40
+ * workspace context (available commands, typical workflow, docs pointers)
41
+ * the moment a user opens an interactive session.
42
+ *
43
+ * Useful for workspaces that already manage their own AGENTS.md (e.g. a
44
+ * monorepo with project-wide instructions) and don't want FeedRadar's
45
+ * boilerplate to land at the root.
46
+ *
47
+ * See ADR-0007 (revised 2026-05-17 b) for the four-layer init bundle
48
+ * (engine SKILL / claude discovery / AGENTS.md / schedule scaffolds).
49
+ */
50
+ noAgentsMd?: boolean;
51
+ /**
52
+ * Skip writing `<cwd>/CLAUDE.md`. By default `init` writes a minimal
53
+ * `CLAUDE.md` at the workspace root that re-exports `AGENTS.md` via the
54
+ * `@AGENTS.md` import directive. Without `CLAUDE.md`, Claude Code does
55
+ * not auto-read `AGENTS.md`, so the industry-standard pattern of "single
56
+ * source of truth in AGENTS.md, imported by CLAUDE.md" breaks.
57
+ *
58
+ * Useful for workspaces that already manage their own `CLAUDE.md` (and
59
+ * load `AGENTS.md` via a different mechanism) or that don't use Claude
60
+ * Code at all.
61
+ *
62
+ * Note: when `noAgentsMd` is true, the bundled `CLAUDE.md` template's
63
+ * `@AGENTS.md` import would dangle, so `init` auto-skips `CLAUDE.md` in
64
+ * that case and emits a warning explaining why.
65
+ */
66
+ noClaudeMd?: boolean;
67
+ /**
68
+ * Skip writing `<cwd>/templates/default.md`. By default `init` emits a
69
+ * starter Markdown template body that mirrors the engine `research`
70
+ * SKILL's fallback structure (要約 / 詳細 / 出典). The file is the
71
+ * first editable artifact the user can tweak to customize report
72
+ * shape; the research engine SKILL falls back to its own built-in
73
+ * structure when `templateBody` is empty, so skipping does not break
74
+ * runtime behavior — it only removes the editable starter.
75
+ *
76
+ * Useful for workspaces that manage `templates/` via another mechanism
77
+ * or that already have a populated `templates/default.md`.
78
+ */
79
+ noTemplates?: boolean;
80
+ /**
81
+ * Skip writing `<cwd>/FEEDRADAR.md` (human-facing workspace guide).
82
+ * By default `init` emits this file at the workspace root to teach the
83
+ * user how to drive the workspace via natural-language requests to AI
84
+ * agents (primary) or CLI direct invocation (secondary). Useful for
85
+ * workspaces that already have their own user-facing documentation, or
86
+ * that manage this file via another mechanism.
87
+ */
88
+ noFeedradarMd?: boolean;
89
+ /**
90
+ * Emit the Claude Routines schedule template
91
+ * (`claude/routines/watch-daily.md`).
92
+ */
93
+ withRoutines?: boolean;
94
+ /**
95
+ * Emit the GitHub Actions schedule template (`.github/workflows/watch.yaml`).
96
+ */
97
+ withActions?: boolean;
98
+ /** Sink for warnings; defaults to console.warn. */
99
+ warn?: (message: string) => void;
100
+ /** Sink for info messages; defaults to console.log. */
101
+ info?: (message: string) => void;
102
+ }
103
+ interface InitResult {
104
+ createdDirs: string[];
105
+ copiedFiles: string[];
106
+ skippedFiles: string[];
107
+ }
108
+ /**
109
+ * Initialize the current directory as a FeedRadar workspace.
110
+ *
111
+ * Creates the canonical workspace directories and copies bundled SKILL.md
112
+ * files into `.agents/skills/<name>/SKILL.md`. Existing files are protected
113
+ * unless `force` is true.
114
+ *
115
+ * Claude Code discoverability (ADR-0007, revised 2026-05-17 via #75): in
116
+ * addition to the engine SKILLs at `.agents/skills/`, `init` also writes
117
+ * thin slash-command wrappers to `.claude/skills/` so that Claude Code,
118
+ * when opened interactively in the workspace, surfaces `/research` /
119
+ * `/review` / `/update` / `/dismiss`. The wrappers delegate to the
120
+ * `radar` CLI rather than duplicating the engine procedure (the
121
+ * engine SKILL at `.agents/skills/<name>/SKILL.md` remains the SSoT).
122
+ * Existing files are protected, so workspaces that already manage
123
+ * `.claude/skills/` via the `@ozzylabs/skills` Renovate preset won't be
124
+ * surprised; alternatively use `--no-claude-skills` to skip the discovery
125
+ * layer entirely.
126
+ *
127
+ * Multi-agent context (ADR-0007, revised 2026-05-17 b via #77): `init`
128
+ * also writes an agent-agnostic `AGENTS.md` at the workspace root. Codex
129
+ * CLI, Gemini CLI, and GitHub Copilot CLI auto-read this file when opened
130
+ * interactively in the workspace, giving those agents context about
131
+ * available commands, typical workflow, and docs pointers without any
132
+ * extra setup. Opt out via `--no-agents-md` (workspaces that already have
133
+ * their own AGENTS.md).
134
+ *
135
+ * Gemini CLI slash commands (ADR-0007, revised 2026-05-17 c via #78):
136
+ * `init` writes Gemini CLI's native slash command TOMLs at
137
+ * `<cwd>/.gemini/commands/{research,review,update,dismiss}.toml`. These
138
+ * thin wrappers shell out to the `radar` CLI through Gemini's
139
+ * `{{args}}` interpolation, surfacing `/research` etc. inside Gemini CLI
140
+ * interactive sessions. Opt out via `--no-gemini-commands` (engine SKILLs
141
+ * remain in place via the dual-mode "Invocation modes" fallback). This
142
+ * closes the slash-command UX gap for Gemini CLI (Codex CLI is covered by
143
+ * the engine SKILL dual-mode procedure itself).
144
+ */
145
+ export declare function initWorkspace(options: InitOptions): Promise<InitResult>;
146
+ export declare const initCommand: Command;
147
+ export {};
148
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AA0F1C,UAAU,WAAW;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,OAAO,CAAC;IACf,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uFAAuF;IACvF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wFAAwF;IACxF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;OAWG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,mDAAmD;IACnD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,uDAAuD;IACvD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAoJD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAuN7E;AAoGD,eAAO,MAAM,WAAW,EAAE,OAkGzB,CAAC"}