npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@skedulo/knowledge-hub-agent

v0.1.0

Published

Knowledge Hub agent: corpus reader and linter, guide draft flow, quality gates and Hub publish

Readme

Knowledge Hub agent

@skedulo/knowledge-hub-agent is the knowledge-hub CLI behind the /knowledge-hub-* Claude Code commands (skills/, shipped as the knowledge-hub plugin). It reads the se-knowledge-corpus repo, checks and writes guides, runs the quality gates and publishes guides to the Knowledge Hub tenant. Operators use the commands, not this package directly; see the repo README.

Install

npm install -g @skedulo/knowledge-hub-agent && knowledge-hub setup

The package installs three commands:

  • knowledge-hub, the CLI.
  • knowledge-hub-agent, the same CLI, so npx -y @skedulo/knowledge-hub-agent <command> works.
  • kh, the launcher the skills call. It runs npx -y --package=@skedulo/knowledge-hub-agent@latest knowledge-hub, so the skills always use the newest release. It finds npx in the usual Node locations when PATH lacks it. The plugin ships the same script in its bin/, and Claude Code puts that after your own PATH, so it does not matter which kh runs.

knowledge-hub setup [--no-plugin] signs you in to sked and gh where needed, then sets up Claude Code:

  • Plugin. It runs claude plugin marketplace add Skedulo/se-knowledge-hub#main, then sets extraKnownMarketplaces.se-knowledge-hub.autoUpdate: true in settings.json. Claude's add drops that setting each time it runs, so setup sets it afterwards. Then it runs claude plugin install knowledge-hub@se-knowledge-hub.
    • An entry for se-knowledge-hub with no ref follows dev, and Claude then refuses #main, so setup first writes ref: main into it.
    • It removes the command copies an earlier setup made. It finds them by a .knowledge-hub-setup file in each folder, so a copy you made by hand is reported, never deleted.
  • Copies. Setup uses copies when the claude CLI is missing, when GitHub access fails, or with --no-plugin. It copies the skills into ~/.claude/skills/knowledge-hub-*.
    • Every later run of a newer knowledge-hub (for example through kh) updates those copies. A run from an older version never downgrades them.
    • The update prints one line on stderr only.

Setup then fetches the newest agent into npm's cache and runs preflight --hub. It writes Claude Code's files under $CLAUDE_CONFIG_DIR (default ~/.claude) and nothing else; your logins stay in sked's and gh's own files. Run it again any time.

From the repo:

git clone https://github.com/Skedulo/se-knowledge-hub.git && cd se-knowledge-hub
yarn --cwd packages/agent install --frozen-lockfile
yarn --cwd packages/agent build
node packages/agent/dist/cli.js <command>

To install that build, run npm pack in packages/agent. Its prepack copies the root skills/ and bin/kh into assets/, then builds. The package holds dist/ (without comments), assets/, bin/*.sh, bin/*.py, this README and the corpus contract. Then run npm install -g ./skedulo-knowledge-hub-agent-<version>.tgz. To make kh run that tarball, set KNOWLEDGE_HUB_AGENT_SPEC=<path to the .tgz>.

Release

The plugin's version in .claude-plugin/plugin.json must equal this package's version (a test checks). Installed plugins only update when that string changes.

  1. Bump both versions in a PR to dev.
  2. Merge dev into main with a merge commit, never a squash. The marketplace follows main, so plugin users get the new skills at their next session.
  3. From main, in packages/agent, run npm publish --tag next. Try it with KNOWLEDGE_HUB_AGENT_SPEC=@skedulo/knowledge-hub-agent@next, then run npm dist-tag add @skedulo/knowledge-hub-agent@<version> latest right away.

Between steps 2 and 3, and in sessions opened before an update, new skills can meet the old CLI and old skills the new one. The CLI refuses unknown flags, so a release adds flags and commands and never renames or removes one the previous release's skills use.

Prerequisites

  • macOS for the media and mobile commands. They use Spotlight (mdls), screencapture, Apple Vision and Xcode. lint, gates, draft and the Hub commands are plain Node.
  • Node.js 20 or newer (24 recommended).
  • git, and the GitHub CLI logged in (gh auth login). corpus-sync clones the corpus with gh, and a live publish asks origin for main with git ls-remote.
  • bash, for preflight and corpus-sync.
  • For the Hub commands (publish, unpublish, preview-link, guide-health): the Skedulo CLI (npm install -g @skedulo/cli) logged in to the Hub tenant with sked tenant login web -a knowledge-hub -t knowledge-hub -o. Add -e test when the team is not found in production. A service token in SKEDULO_API_TOKEN and SKEDULO_API_SERVER works instead.
  • Optional, for media:
    • ffmpeg and ffprobe (brew install ffmpeg) for media-info and video frames.
    • The Python at ~/.knowledge-hub/ocr-venv, with Pillow for media-sheet and soft cover bars, and pyobjc for text recognition (mobile --platform mirror, mobile cover). Set it up with python3 -m venv ~/.knowledge-hub/ocr-venv && ~/.knowledge-hub/ocr-venv/bin/pip install pyobjc-framework-Vision pyobjc-framework-Quartz pillow.
  • Optional, for mobile:
    • Android: adb (brew install android-platform-tools).
    • iPhone Simulator: Xcode (xcrun simctl) and idb (brew install facebook/fb/idb-companion && pip3 install fb-idb).
    • A real iPhone: iPhone Mirroring.

knowledge-hub preflight [--hub] checks the tools and the sked login, and prints the fix for each problem.

Commands

knowledge-hub --help | -h | help [<command>]     # usage on stdout, exit 0 (no command at all: exit 2)
knowledge-hub --version | -v
knowledge-hub <command> --help                   # one command's usage, exit 0

knowledge-hub setup [--no-plugin]
knowledge-hub preflight [--hub]
knowledge-hub corpus-sync [main|dev]
knowledge-hub draft pending <corpus>
knowledge-hub draft review <corpus>/customers/<slug> [--base <ref>] [--markdown]
knowledge-hub draft plan <corpus>/customers/<slug>
knowledge-hub draft write <corpus>/customers/<slug> <draft.json>
knowledge-hub draft done <corpus>/customers/<slug> <plan.json> <area>...
knowledge-hub media-info <file> [--frames <dir>]
knowledge-hub media-sheet <spec.json>
knowledge-hub guide-outline <corpus>/customers/<slug>
knowledge-hub mobile labels [--headers <word>]... [--redact-text <text>]...
knowledge-hub mobile tap "<label>"
knowledge-hub mobile shot <out.png> [--focus <label>]... [--redact-text <text>]... [--headers <word>]...
knowledge-hub mobile cover <in.png> <out.png> [--focus <label>]... [--redact-text <text>]... [--headers <word>]...
  # every mobile command: [--platform android|ios|mirror] [--serial <serial>] [--udid <udid>]
knowledge-hub lint <corpus>/customers/<slug> [--allow-dangling]
knowledge-hub gates <corpus>/customers/<slug> [--markdown] [--golden <file.json>]
knowledge-hub publish <corpus>/customers/<slug> [--alias <sked-alias>] [--draft] [--dry-run]
  [--overwrite <guide_id>]... [--skip <guide_id>]... [--kind update|revise|media|publish] [--reason "<why>"]
  [--pr https://github.com/<owner>/<repo>/pull/<n>]
knowledge-hub unpublish <slug> (--guide "<title>"... | --all) --reason "<why>" [--alias <sked-alias>] [--dry-run]
knowledge-hub preview-link <slug> [--alias <sked-alias>] [--days <n>]
knowledge-hub guide-health (<slug> | --all) [--alias <sked-alias>] [--dry-run]

| Command | What it does | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | setup | Installs the /knowledge-hub-* commands in Claude Code (the plugin with auto-update on, or copies) and signs you in to sked and gh; see Install. | | preflight | Checks git, Node.js, gh and its login (with --hub, also sked and the sked login for $SKED_ALIAS, default knowledge-hub). Prints ready or one fix per problem. With the plugin installed, it also warns when its updates are off, it follows a branch other than main, or old copies duplicate it. | | corpus-sync | Clones the corpus or fast-forwards it on main (default) or dev, and prints its path. Refuses a clone with local changes or unpushed commits. | | draft | pending: customers with new material (JSON). review: source checks (--base also checks what a PR changed). plan: what to redraft (save it for done). write: writes one guide from draft.json. done: clears drafted areas. | | media-info | What a screenshot or video says about itself (JSON). --frames saves three stills from a video. | | media-sheet | One contact sheet (PNG) of up to 12 screenshots from { "output", "title", "shots": [{ "image", "title", "note"?, "replaces"? }] }. | | guide-outline | Each guide's sections with their bold UI labels and media (JSON). | | mobile | Reads, taps and screenshots an Android phone, the iPhone Simulator or iPhone Mirroring, with personal data covered. cover covers any screenshot. It never taps a control that changes data. | | lint | Checks sources and guides against the corpus contract, and flags email addresses and phone numbers in guide text. --allow-dangling makes citations of removed sources warnings. | | gates | The quality gates (evidence, coverage, thin content, golden questions) as JSON, or markdown. | | publish | Publishes a customer's guides to the Hub as immutable ProjectGuide versions, live or with --draft. | | unpublish | Takes live guides off the Hub page now, without a PR. Each gets a withdrawn version; nothing is deleted. | | preview-link | Prints { "token", "expiresAt" } for the draft preview link #/<slug>?draft=<token>. Reuses the token until a day before it expires. | | guide-health | Rebuilds the customer's Guide rows and Project counts. It writes only what changed and never deletes. |

draft.json is { guide_id | new: { area, name }, category, title, sources, body_file }.

publish --dry-run marks each guide as one of these:

  • create, update, skip or conflict.
  • withdrawn: taken down and unchanged, so it stays down.
  • returns: taken down, but its text changed, so it comes back. The takedown reason is shown.
  • orphan: live in the Hub but gone from the corpus. A publish leaves orphans live; take them down with unpublish.

Before publishing, a run syncs the media under guides/media on corpus main or dev (as pushed) to the Project's attachments.

After a publish or unpublish writes its status, the run's SyncRun also gets:

  • Kind: from --kind. The default is publish, or update with --draft. update, revise and media need --draft.
  • Reason.
  • Conflicts: the titles left as conflicts.
  • CorpusCommit: the pushed corpus commit.
  • The approval PR from --pr.

The customer's Guide rows and the Project's guide counts and last run are refreshed too. Neither step can fail the run; anything that could not be written is listed under warnings. guide-health is the fix for a "Guide health not refreshed" warning.

Strict flags

The Hub commands stop with exit 2 before they read a login, run git or call the Hub when they get any of these:

  • a flag they don't take, such as --drafts or --dryrun
  • a flag with no value, or whose value starts with --
  • a single-value flag given twice
  • an extra argument

They print one plain line, such as unknown option --drafts, then the usage on stderr. --help or -h prints the usage on stdout and exits 0. Dry runs (publish --dry-run, unpublish --dry-run, guide-health --dry-run) print "dryRun": true in their JSON.

Live-publish guard

A live publish (no --draft, no --dry-run) runs only from the approved main. Before any Hub call, two checks must pass:

  • The corpus clone's HEAD must be the commit that origin has on main. This is checked with git ls-remote origin refs/heads/main, which also works in shallow clones.
  • customers/<slug>/guides must have no uncommitted or untracked changes.

Otherwise it exits 2 with one line, for example:

Live publishing only runs from the approved main branch; the guides folder is on 9f8e7d6, main is a1b2c3d. Run knowledge-hub corpus-sync main and try again.

When git cannot reach origin, it prints could not check the approved main branch: <reason>. knowledge-hub corpus-sync main puts the clone on main. Draft publishes and dry runs work on any branch.

Login

The Hub commands pick their login in this order:

  1. The sked login for --alias <sked-alias>. An explicit alias always wins.
  2. SKEDULO_API_TOKEN + SKEDULO_API_SERVER.
  3. The sked login for $SKED_ALIAS.

There is no default alias, because a default is how someone writes to the wrong tenant. With no login, the command prints this line and exits 2:

No Skedulo login: pass --alias <sked-alias> (e.g. --alias knowledge-hub) or set SKEDULO_API_TOKEN and SKEDULO_API_SERVER.

An expired or missing sked login names the sked tenant login web command to run. The token is read locally and never printed. Only preflight --hub assumes the alias knowledge-hub when SKED_ALIAS is not set.

Each Hub request gives up after 60 s. These failures each print one line:

  • could not reach <host>: <cause> when the Hub cannot be reached.
  • the Hub at <host> did not answer within 60 s on a timeout.
  • the Skedulo login was rejected (HTTP 401); sign in again with sked tenant login web when the login is refused (HTTP 401 or 403). What the Hub said is added in brackets, so a missing permission can be told apart from an old login.

Environment

| Variable | Used by | Meaning | | --------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------- | | SKED_ALIAS | Hub commands, preflight --hub | sked alias to log in with when --alias is not given and no service token is set | | SKED_TEAM | Hub commands, preflight | team named in the login hint (default knowledge-hub) | | SKED_ENV | Hub commands, preflight | environment named in the login hint (-e <env>), e.g. test | | SKED_CONFIG_PATH | Hub commands, preflight --hub | sked's login file (default $XDG_CONFIG_HOME/sked/config.json, else ~/.config/sked/config.json) | | XDG_CONFIG_HOME | Hub commands, preflight --hub | where sked's config lives when SKED_CONFIG_PATH is not set | | SKEDULO_API_TOKEN | Hub commands | service-account token, used with SKEDULO_API_SERVER when no --alias is given | | SKEDULO_API_SERVER | Hub commands | API server for that token, e.g. https://api.skedulo.com | | PUBLISH_TRIGGERED_BY | publish, unpublish | who ran it, kept on the SyncRun (default: the sked login's username, else ci) | | KNOWLEDGE_HUB_CORPUS | corpus-sync | where the corpus clone lives (default ~/.knowledge-hub/corpus) | | KNOWLEDGE_HUB_CORPUS_REPO | corpus-sync | the corpus repo to clone (default Skedulo/se-knowledge-corpus) | | KNOWLEDGE_HUB_OCR_PYTHON | mobile, media-sheet | Python with Pillow and Apple Vision (default ~/.knowledge-hub/ocr-venv/bin/python) | | KNOWLEDGE_HUB_AGENT_SPEC | kh | the package kh runs (default @skedulo/knowledge-hub-agent@latest); @next or a tarball path to try a release | | KNOWLEDGE_HUB_MARKETPLACE | setup | the marketplace to install from (default Skedulo/se-knowledge-hub#main); a branch, for testing | | CLAUDE_CONFIG_DIR | setup, preflight, every run | Claude Code's config folder (default ~/.claude) |

Exit codes

| Code | Meaning | | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | 0 | Done. Also for --help, help and --version. | | 1 | The work failed: a lint or gate problem, the corpus needs attention, a Hub failure, an unknown customer or title, a device or tool not ready (mobile, media-sheet), or an unexpected error (printed as one line). For preflight, a tool every command needs is missing. For corpus-sync, local changes, unpushed commits or no such branch. | | 2 | Bad usage or environment: no command, an unknown command or flag, a missing value, an extra argument, a path outside customers/, a missing file or folder (media-info, guide-outline, publish), no Skedulo login, a live publish that is not on the approved main, or bash not installed. For preflight, only the Skedulo side is missing. | | 3 | publish only: published, but some guides were left because a newer manual edit exists in the Hub (see conflicts). |

Layout

| Path | What it holds | | -------------- | ----------------------------------------------------------------------------------------------------------------- | | src/cli.ts | The knowledge-hub entry point: routing, help, version | | src/corpus/ | Front-matter schemas, corpus reader, dirty marks, lint | | src/draft/ | draft: pending, review, plan, write, done | | src/gates/ | Quality gates: evidence, coverage, thin content, golden questions | | src/media/ | media-info, media-sheet, guide-outline | | src/mobile/ | mobile: Android, iPhone Simulator and iPhone Mirroring capture, personal-data cover | | src/publish/ | publish, unpublish, preview-link, guide-health; GraphQL and Files clients, sked login, live-publish guard | | bin/ | corpus-sync.sh, preflight.sh, and the Python helpers for media and text recognition |

Tests run from the repo root: yarn test, or npx jest packages/agent for this package only.

The corpus format is in docs/corpus-contract.md. How the pieces fit is in docs/current-flow.md.