# Intel

> This skill should be used to research a software package OR a developer/CI tool and create or update a structured Basic Memory note with post-write cross-linking. Triggers: 'research package', 'package intel', 'what does [pkg] do', 'add [pkg] to knowledge graph', 'enrich [pkg]', when adding depends_on [[npm-*]] relations, 'research crate/gem/go module/composer/pypi package', 'research a homebrew formula', 'brew intel', 'research a cask', 'research a GitHub Action', 'action intel', 'research a docker image', 'research a VSCode extension', 'vscode intel', 'research a gh CLI extension', 'research a Claude Code plugin', 'research an agent skill', 'tool intel', 'what does [tool] do', 'upgrade haul', or a pasted npm/brew (or crate/go/composer/pypi/gem) outdated/upgrade line. Prefixes: package family — npm:, crate:, go:, composer:, pypi:, gem: (no prefix defaults to npm); tool family — brew:, cask:, action:, docker:, vscode:, gh:, plugin:, skill:.

- Skill: `voxpelli/intel` (Agent Skill, multi-file: 38 files)
- Install (CLI): `npx skillmds@latest add voxpelli/intel`
- Raw SKILL.md: https://api.skillmd.com/api/skills/voxpelli/intel/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: voxpelli (https://skillmd.com/u/voxpelli)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/voxpelli/intel

---


# Intelligence

Research a package **or** a developer/CI tool and synthesize a structured Basic
Memory note, then cross-link existing notes. **One research lifecycle** — detect
→ check → resolve → enrich → synthesize → write → cross-link — routed
per-ecosystem via the table below. The two families (package and tool) share
one BM-note lifecycle end to end; **Step 3 (enrichment) is the only point where
the source roster diverges**. Smaller family-specific bits also exist in
Arguments normalization, Batch mode, Step 1 freshness, Step 4 observation rules,
and Step 6 — but the unifying axis is the shared lifecycle, not the sourcing
mechanics.

Supported ecosystems, by family:

- **package** — npm, Rust crates, Go modules, PHP Composer, Python PyPI, Ruby gems.
- **tool** — Homebrew formulae/casks, GitHub Actions, Docker images, VSCode
  extensions, GitHub CLI extensions, Claude Code plugins, skills.sh agent-skill bundles.

## Arguments

One or more identifiers, each with an optional `<prefix>:` (a single call may mix
families — `npm:fastify brew:ripgrep` — and routes each token by its own prefix).
The prefix alone selects the **family** and the routing row:

| Prefix | Family | BM dir | Note type | Ecosystem ref | Note template |
|--------|--------|--------|-----------|---------------|---------------|
| `npm` | package | `npm/` | `npm_package` | `references/ecosystem-npm.md` | `references/note-template-npm.md` |
| `crate` | package | `crates/` | `crate_package` | `references/ecosystem-crates.md` | `references/note-template-crates.md` |
| `go` | package | `go/` | `go_module` | `references/ecosystem-go.md` | `references/note-template-go.md` |
| `composer` | package | `composer/` | `composer_package` | `references/ecosystem-composer.md` | `references/note-template-composer.md` |
| `pypi` | package | `pypi/` | `pypi_package` | `references/ecosystem-pypi.md` | `references/note-template-pypi.md` |
| `gem` | package | `gems/` | `ruby_gem` | `references/ecosystem-gems.md` | `references/note-template-gems.md` |
| `brew` | tool | `brew/` | `brew_formula` | `references/ecosystem-brew.md` | `references/note-template-brew.md` |
| `cask` | tool | `casks/` | `brew_cask` | `references/ecosystem-cask.md` | `references/note-template-cask.md` |
| `action` | tool | `actions/` | `github_action` | `references/ecosystem-action.md` | `references/note-template-action.md` |
| `docker` | tool | `docker/` | `docker_image` | `references/ecosystem-docker.md` | `references/note-template-docker.md` |
| `vscode` | tool | `vscode/` | `vscode_extension` | `references/ecosystem-vscode.md` | `references/note-template-vscode.md` |
| `gh` | tool | `gh/` | `gh_extension` | `references/ecosystem-gh.md` | `references/note-template-gh.md` |
| `plugin` | tool | `plugins/` | `claude_plugin` | `references/ecosystem-plugin.md` | `references/note-template-plugin.md` |
| `skill` | tool | `plugins/` | `claude_plugin` | `references/ecosystem-skill.md` | `references/note-template-plugin.md` |

Every prefix belongs to exactly one family (the two sets are disjoint), so the
family is unambiguous from the prefix alone.

**Per-prefix identifier normalization.** Package prefixes pass through (scoped
npm `@scope/pkg` stays npm; Go module paths keep their slashes). Tool prefixes
normalize first: `action:` / `docker:` strip a trailing `@version` / `:tag`;
`vscode:` is the dot-separated `publisher.name`; `gh:` / `plugin:` / `skill:`
strip a `github.com/…` URL to `owner/repo`, validate the two-part shape, and
keep an optional `#<name>` suffix.

**Backward compatibility.** No prefix always resolves to **npm** (package
family). A bare *tool* name in a batch is disambiguated inside the tool adapter's
formula-vs-cask auto-routing (see Batch mode), not hoisted here.

## Batch mode: upgrade haul

**Detection hook (before Step 0).** If the input is not a single prefixed
identifier but a **batch** — multiple bare/prefixed names, OR a pasted
upgrade/outdated command line (`npm outdated`, `npm i a@latest b@latest`,
`cargo install-update -l`, `go list -u -m all`, `composer outdated`,
`pip list --outdated`, `bundle outdated`, `brew upgrade`, `brew outdated`) —
treat it as an *upgrade haul* (a batch refresh of already-documented notes
against a version delta) rather than a from-scratch research call. The single
prefixed-identifier path is unchanged.

**Load the shared core.** Read `references/upgrade-haul.md` in full and follow
it — input parsing/de-qualification, highlights-reel synthesis, the two
recording axes, stale-cache arbitration, batch orchestration, and the `--stale`
relationship all live there. Route each operand by its prefix to its family
adapter:

- **package family** — Axis-B narrative target is the note's inline
  `## Release Highlights` section (a one-line convention, no separate adapter
  file). Run the Step-1 existence check as one listing per package directory.
- **tool family** — follow `references/upgrade-haul-adapter-tool.md`
  (bare-name formula-vs-cask auto-routing, the `not-in-api` re-dispatch, the
  `@`-suffix dual-key fetch, inline `[feature]` / `[version]` Axis-B target).

A mixed-family batch routes each operand independently by its own prefix. Batch
detection selects the *orchestration*, not the conclusion that a refresh is due:
if Step 1 finds no existing note for an operand, that operand is fresh research
(there is no recorded version to diff against), regardless of how the input was
shaped.

## Ecosystem Dispatch

### Step 0: Detect ecosystem & family

1. **Explicit prefix** — the part before `:` is the ecosystem. Look it up in the
   Arguments table to set `FAMILY` (`package` | `tool`), the BM directory, note
   type, ecosystem ref, and note template. `FAMILY` is set **once here** and read
   only at Step 3. Strip the prefix for the name (applying the per-prefix
   normalization above).
2. **No prefix (package family only)** — infer from project context:
   `Cargo.toml` → crate, `go.mod` → go, `composer.json` (no `package.json`) →
   composer, `pyproject.toml`/`requirements.txt` (no `package.json`) → pypi,
   `Gemfile` (no `package.json`) → gem, otherwise → npm. State: "No prefix
   detected — treating as `<ecosystem>:<name>` based on project context. Use an
   explicit prefix to override."
3. **Unknown prefix** — error and print the 14-row Arguments table.
4. **Third-party tap (`brew:` only)** — count `/`-segments after `brew:`; the
   zero/one/two-slash dispatch (core formula vs tap formula vs invalid shape)
   lives in `references/ecosystem-brew.md` ("Third-Party Tap Formulae"). BM dir,
   note type, and reference are unchanged; only Step 2's fetch mechanics differ.

**Title convention.** The command uses `:` delimiters, but the BM note title
replaces every `:`, `/`, and `#` with `-` (preserving `@` and `.`) — a purely
literal mapping matching the filename BM generates. Examples: `npm:fastify` →
`npm-fastify`, `npm:@fastify/postgres` → `npm-@fastify-postgres`,
`action:actions/checkout` → `action-actions-checkout`,
`plugin:voxpelli/vp-claude#vp-knowledge` → `plugin-voxpelli-vp-claude-vp-knowledge`.
See CLAUDE.md → "Prefix convention" for the full rule.

### Step 1: Check for existing note

Follow `references/note-lookup-and-freshness.md`: the existence glob, the
freshness-tier matrix (the `<60 days` fast-path differs by family — package runs
Context7 + Socket, tool does not), the append-don't-overwrite rule, and the
audit-context stale-handling branch. Hold the recorded version + `## Relations`
for later steps.

### Step 2: Resolve registry & repository

Read the routing row's `references/ecosystem-<ecosystem>.md` for the
registry/extraction API, required headers, and how to extract `owner/repo` for
the enrichment and changelog steps.

**Forge detection.** Parse the **host** of the resolved repository/homepage URL
and hold it as `repo_forge` (`github`, `codeberg`/any Forgejo, `sourcehut`
`*.sr.ht`, or `unknown`). When `repo_forge != github`, follow
`references/forge-fallback.md` for the DeepWiki-skip rule and the changelog
procedure. `action:` and `gh:` encode a GitHub `owner/repo` by construction — skip
forge detection for them.

When the registry's `repository` and `homepage` fields point at **different**
hosts, the `repository` field wins for `gh`/DeepWiki purposes — a non-GitHub
`homepage` alone does not make it a non-GitHub forge. It usually means a
canonical home with a GitHub mirror (observed: an npm package homed at
`tangled.org` with `repository` on GitHub), which is itself worth a `[gotcha]`
observation: issues and PRs may live on the canonical forge, so a GitHub issue
search understates the project's activity.

If the ecosystem reference documents a download/popularity source, fetch the
count now and hold it as `popularity_count` for Step 4.

### Step 3: Family enrichment — the source-roster branch

This is the point where the two families' **source roster** diverges (other
steps carry smaller family-specific bits). Route by `FAMILY`:

- `FAMILY=package` → load and follow `references/enrichment-package.md`
  (seven sources: DeepWiki, Context7, Tavily, Raindrop, changelog, Readwise,
  Socket depscore).
- `FAMILY=tool` → load and follow `references/enrichment-tool.md` (six sources:
  DeepWiki, Tavily, Raindrop, changelog, Readwise, man-page — plus Homebrew
  analytics and the Open VSX trust signal where applicable).

Five sources are common to both (DeepWiki, Tavily, Raindrop, Readwise,
changelog). **Design invariant:** each family file OWNS its per-ecosystem
skip/run gates as explicit conditionals — DeepWiki skip for brew/cask; man-page
for brew/cask only; Open VSX for vscode only; Context7 for the package family
only; Socket for npm/pypi/cargo/gem only. These gates are NEVER collapsed into a
generic "run these N sources" loop here or in either family file.

### Step 4: Synthesize into note

Read the routing row's `references/note-template-<ecosystem>.md`. Every note uses
three enrichment layers: **frontmatter** (`type`, `tags`, and any `packages`
array), **`## Observations`** with `[category]`-tagged items, and
**`## Relations`** with `[[wiki-links]]`.

Observation conventions:

- **`[version]` (mandatory, every cohort — and EXACTLY ONE per note)** — record
  the documented latest version as a clean leading token, e.g.
  `- [version] 5.8.5`. The same value goes in the header pipe
  (`… | v<version> | …`); keep them consistent. (Which slot `--stale` reads first
  is cohort-dependent — the `[version]` observation for npm, the header pipe
  otherwise — so refresh both.)
  **Never add a second `[version]` line, and never write release prose under the
  `[version]` category.** The extractor takes the first PARSEABLE `[version]`
  line in file order, so a narrative line like
  `- [version] 3.0 dropped Node 18` placed above the canonical token silently
  becomes the recorded version — the note then reads correctly to a human and
  wrong to every consumer. Version narrative belongs in `## Release Highlights`
  (package family) or a `[feature]` observation (tool family). When refreshing,
  UPDATE the existing `[version]` line rather than appending a new one.
- **`[popularity]`** — if a count was obtained, add it with metric window +
  source, e.g. `- [popularity] 2.1M downloads/week (npm, 2026-04)`. Omit for
  PyPI and Go (no reliable count).
- **`[security]`** — Socket depscore (package family) or the Open VSX trust
  signal (vscode); plus any advisory findings.

**No wiki-links in observations.** Never use `[[Target]]` in an observation line —
BM's parser treats `[[` as a relation boundary. Put all wiki-links in
`## Relations` only.

**Verify before capture.** For any note not on Step 1's fast path (missing, 60+
days, or security-sensitive/thin-evidence), follow `references/verify-before-capture.md`
before writing.

### Step 5: Write or update the note

Follow `references/note-write-mechanics.md` for the new-note / relocated-stub /
existing-note decision, the two `edit_note` find_replace templates, the
never-`append`-with-`section=Observations` rule, the large-note anchoring rule, and
the "trust `schema_validate` + the file, not the inline count" rule.

### Step 6: Confirm and summarize

Report a compact summary:

- Family and note location (directory + title).
- Key findings and any `[gotcha]`/`[limitation]` observations recorded.
- Security/analytics concerns — Socket scores (package) or Open VSX/analytics
  (tool), whichever applies.
- Cross-links added (or deferred to follow-up pass for large batches).
- Enrichment-source status — for each Step-3 source, report which of *used /
  attempted-but-failed / intentionally-skipped* applies. Sources must be
  *attempted*, not skipped by assumption; an attempt that fails (auth error,
  server not found) must be surfaced as a failure, never silently omitted or
  relabelled an intentional skip (non-GitHub forge, ecosystem not covered).
- Unresolved contradictions from Step 3–4.

### Step 7: Cross-link existing notes

Follow `references/cross-link-existing-notes.md`: search for notes referencing
this subject, add `relates_to` links where genuine, verify each edge resolved via
the relation index (not `build_context`), and reconcile bare-name stubs.

## References

Every file below is one level deep in `references/` and reachable from the steps
above:

- Lifecycle: `note-lookup-and-freshness.md`, `verify-before-capture.md`,
  `note-write-mechanics.md`, `cross-link-existing-notes.md`.
- Enrichment (Step 3 branch): `enrichment-package.md`, `enrichment-tool.md`.
- Changelog/forge fallbacks: `gh-api-fallback.md`, `forge-fallback.md`.
- Batch: `upgrade-haul.md`, `upgrade-haul-adapter-tool.md`.
- Per-ecosystem recipes + note templates: `ecosystem-<prefix>.md`,
  `note-template-<prefix>.md` (see the Arguments table).

