English | 日本語
CLI that watches blogs, official update streams, and release feeds, then hands keyword hits to one of four AI agents (Claude Code / Codex / Gemini / Copilot) to produce Markdown research reports.
Tracking multiple official blogs, docs, and release notes — and summarizing what actually changed — is a good fit for AI agents, but wiring up source management, diffing, template application, and multi-agent delegation by hand every time gets tedious. radar fixes that loop in a CLI and accumulates Markdown reports in your research directory.
- Multi-agent: switch between Claude Code / Codex CLI / Gemini CLI / GitHub Copilot CLI via adapters.
- Multiple feed kinds: RSS / HTML / HTML (JS rendered) / GitHub Releases / npm registry / JSON Feed (1.0 / 1.1) / JSON API (recipe-driven, with
--backfillfor full history) are all driven through the sameSourceabstraction. - Bundled recipes:
radar source recipeslists maintained YAML recipes (e.g. AWS What's New, dev.to) andradar source add <id> --recipe <name>applies one in a single line — no boilerplate. - Digest mode: bundle multiple items hit in a short period — or across feeds on the same topic — into a single cross-cutting report.
- User-owned data:
sources/items/state/research/templates/live in your workspace directory. This package ships only the engine. - Scheduled workflows:
radar workflow generate watch/combinedemits GitHub Actions YAML on demand — combine watch with auto-research under a hard-capped--max-itemsbudget so a runaway feed cannot blow your LLM bill. - Claude Routines:
radar routine generate watch/pipelineemits.claude/routines/*.yamlfor unattended runs on Anthropic's cloud — one self-session Claude (no spawn, no extra API key), output gated to PR /claude/*branches only. - Progress reporting & verbose mode: long-running commands (
research/review/update/watch run --backfill/ html-js fetch /source test) stream phase markers + a spinner + side metrics (stdout/output/page x/N) on stderr. Pass--verboseto also stream the agent CLI's stdout/stderr,--quiet(orRADAR_NO_PROGRESS=1for CI) to silence the reporter. - Single npm package: distributed as
@ozzylabs/feedradarvia OIDC Trusted Publishers.
npm i -g @ozzylabs/feedradarTo use the kind: html-js adapter (SPA / CSR pages rendered after JS runs), install Playwright separately — it is declared as an optional peer dep so users who only need RSS / static HTML do not pay the ~300MB Chromium footprint:
npm i -g playwright
npx playwright install chromiumRun radar doctor to verify Playwright / Chromium are detected before adding an html-js source. CI setup details and a sample workflow are in the user-guide's --kind html-js → CI section (the user-guide is Japanese-only today, so the anchor stays as-is).
While developing locally, clone this repo and run pnpm install && pnpm run build to produce dist/index.js, then invoke node dist/index.js <command>.
Behind a corporate HTTP / HTTPS proxy, just export the standard env vars and
run radar — it auto-detects them and self-configures (no flags / config
edits). For TLS-intercepting proxies (Zscaler / Netskope / etc.) set
NODE_EXTRA_CA_CERTS instead of disabling certificate verification:
export HTTPS_PROXY=http://proxy.corp.example.com:8080
export NODE_EXTRA_CA_CERTS=/path/to/corp-ca.pem # only if TLS is intercepted
radar doctor # verifyNTLM / Kerberos proxies are not supported directly — bridge with cntlm / Px
/ Authoxy. WSL2 → Windows host, npm install proxy config, and the live
radar doctor healthcheck are documented in
docs/user-guide/proxy-setup.md.
# Quickstart (watch anthropics/anthropic-sdk-python GitHub Releases)
radar init
radar source add anthropic-sdk \
--kind github-releases \
--url https://github.com/anthropics/anthropic-sdk-python \
--keywords "feat,fix,release"
radar watch run
radar research <item-id>
# Other subcommands
radar source list # list sources
radar source test <id> # dry-run preview a source (no state/items mutation)
radar research --digest <id1> <id2> ... # bundle multiple items into one digest report
radar dismiss <item-id> ... # move one or more items to dismissed (no LLM)
radar dismiss --batch # bulk-dismiss detected/triaged_unsure items (--status/--filter-tags/--max-items)
radar review <research-id> # cross-review a report with a different agent
radar update <research-id> # refresh an existing report against the latest item (v+1)
radar doctor # check workspace / agent CLI / Playwright / proxy / TLS health
# --no-proxy-check skips the live proxy round-trip (offline-friendly)
radar workflow generate watch # emit a GitHub Actions watch workflow on demand
radar workflow generate combined # watch + auto-research with --max-items hard cap
radar routine generate watch # emit a Claude Routines watch YAML (self-session, no spawn)
radar routine generate pipeline # full watch -> triage -> research -> review self-session routine
radar --help # helpAll 10 subcommands are implemented (init / source / watch / research / dismiss / review / update / doctor / workflow / routine). See docs/user-guide.md for the full spec.
radar ships English (en) and Japanese (ja). The default is en. The i18n scope is user-facing surfaces only — see ADR-0021 for the full design.
The effective locale is resolved per command in this priority order:
--lang flag > RADAR_LANG env var > radar.config.yaml: locale > en (default)
# Initialize a Japanese workspace (report templates + workspace docs land in ja)
radar init --lang ja
# One-off override via env var for a single command
RADAR_LANG=ja radar research <item-id>radar init --lang ja persists the choice to radar.config.yaml so later commands need no flag:
# radar.config.yaml
locale: ja # en | ja — lowest-priority layer; --lang / RADAR_LANG override itWhat follows the locale:
- Generated files — report templates (
templates/default.md/digest.md), workspace docs (FEEDRADAR.md/AGENTS.md/CLAUDE.md), and generatedworkflow/routineYAML (step names / comments) are emitted from the matching per-locale template subtree (en/orja/). - Report body output — the prose (summary / details) produced by
research/review/updatefollows the locale: the adapter is given the locale and an output-language directive. - CLI copy — command help / usage, error messages, result notifications, and progress phase markers are localized.
What does not change with the locale:
- Engine
SKILL.mdand the triage / research prompts stay English — they are the canonical source of truth and are kept as a single English copy; only the output language of the report follows the locale (ADR-0021 D5). - Locale-independent fields (report
# <Title>derived from the source, digest slugs,run:command strings, cron / model ID /network_access) stay identical across locales (ADR-0021 D9).
A workspace initialized before i18n landed keeps its on-disk language; switch by re-running radar init --force --lang ja or hand-editing radar.config.yaml: locale (ADR-0021 D10).
pnpm install # install dependencies
pnpm run build # tsc build (dist/)
pnpm run typecheck # type check
pnpm run test # vitest run
# Invoking the CLI locally (after build)
pnpm radar --help # = node dist/index.js --help (package.json scripts alias)
node dist/index.js --help # equivalentThe local
pnpm radar <cmd>form is thepackage.jsonscripts.radaralias (node dist/index.js) and requires you to have runpnpm run buildfirst to producedist/index.js. The distributedradar <cmd>that end users invoke afternpm i -g @ozzylabs/feedradargoes throughpackage.jsonbin.radar, which points at the publisheddist/, so no build step is needed there. The two share a name but belong to different layers. Note also thatpnpm --prefix <path> radar <cmd>switches CWD to<path>before running scripts, so when you want the scripts alias to run in a different directory (for example a smoke-test scratch workspace) you must callnode <repo-root>/dist/index.js <cmd>directly — usingpnpm --prefixwould causeinitet al. to run against the repo root by accident.
src/
index.ts CLI entry point (#!/usr/bin/env node)
cli/ init / source / watch / research / dismiss / review / update / doctor / workflow / routine
core/
watcher.ts source → adapter → items
filter.ts keyword / excludeKeyword
items.ts items load / save
templates.ts research template loader
state.ts state/<sourceId>.yaml load / save
config.ts radar.config.yaml load / validate
injection-detector.ts prompt injection regex pre-filter
feeds/ rss / html / html-js / github-releases / npm-registry / json-feed / json-api
agents/ 4 CLI adapters (claude-code / codex-cli / gemini-cli / copilot)
schemas/ Zod schemas (Source / Item / State / Research)
skills/ engine SKILL bundle (research / review / update; init copies into .agents/skills/)
claude-skills/ Claude Code slash-command wrappers (init copies into .claude/skills/)
gemini-commands/ Gemini CLI TOML slash-command wrappers (init copies into .gemini/commands/)
templates/ default workspace templates (init copies into templates/)
- docs/architecture.md — system diagrams / module responsibilities / data flow / per-phase scope
- docs/user-guide.md — install / quickstart / command reference
- docs/user-guide/proxy-setup.md — corporate proxy / TLS interception / NTLM bridge / WSL2 setup
- docs/release.md — release procedure (manual initial publish + Trusted Publisher registration + subsequent OIDC automation)
- docs/adr/ — FeedRadar design-decision records (Agent / Source / Output / Schedule / User Data / Filter / Skill Bundling / Status State Machine / Untrusted External Content Handling / html-js Adapter / Digest Research / JSON API & Recipes / Workflow Generate / Progress Reporting / Triage Extension / Host-agent Execution / Claude Routines Generation)
- Language: TypeScript ESM / Node.js 22+ / pnpm
- Commits: Conventional Commits (enforced via
commitlint) - Branching: GitHub Flow (
main+ feature branches, squash-merge only) - Distribution: npm
@ozzylabs/feedradar, OIDC Trusted Publishers (noNPM_TOKEN) - Shared config: distributed from
ozzy-labs/commonsviasync.sh - Shared skills: pulled in from
ozzy-labs/skillsvia the@ozzylabs/skillsRenovate preset
MIT — see LICENSE.