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

@caryhu/codemine-forge

v1.0.0

Published

Browser-side runtime layer for Codemine demos.

Readme

Codemine Forge

Codemine Forge is the browser-side runtime layer for Codemine demos.

It is not a full Node.js emulator and it is not a backend runner. Its job is to make browser-hosted projects feel like a small StackBlitz-style environment by owning the virtual workspace, simulated terminal commands, dependency resolution, browser bundling, and preview runtime.

Scope

Forge owns these capabilities:

  • Virtual file system for project files, snapshots, package cache, and build cache.
  • Fake terminal with a controlled command registry.
  • Browser bundling through esbuild-wasm.
  • TS, JSX, TSX, CSS, JSON, and static asset bundling.
  • package.json dependency parsing.
  • Import map generation or bundle alias generation.
  • Simulated forge start (install → build → dev) experience, with the individual forge run install, forge run build, and forge run dev commands still available.
  • Vite-like dev server compatibility for preview workflows.

Forge does not own:

  • User accounts, billing, permissions, or product navigation.
  • Server-side execution, containers, SSH, or unrestricted shell access.
  • Full npm CLI compatibility.
  • Native Node modules, node-gyp, install scripts, or arbitrary process spawning.
  • Generated frontend output in the main Codemine repository.

Runtime Shape

Codemine host app
  Editor / file tree / demo page
        |
        v
Codemine Forge
  Virtual FS
  Fake terminal
  Package resolver
  Build worker
  Dev server facade
        |
        v
Preview iframe
  Runs compiled browser modules

Forge should expose a small API to the host application. The host application can render its own editor, file tree, tabs, and buttons, while Forge provides the runtime behavior behind those controls.

Document Map

Demo

Start the interactive demo with Vite:

pnpm run demo

The demo defaults to http://127.0.0.1:4175/ and accepts PORT and SAMPLE environment variables.

AI-assisted debugging

The demo relays its browser-side state (samples, dev sessions, build summaries, diagnostics, and console output) to the Vite dev server. A terminal agent can read it — and, through a whitelisted control channel, drive it — without touching the page:

pnpm run debug:forge state
pnpm run debug:forge console --level error --limit 50
pnpm run debug:forge events --type sample:error
pnpm run debug:forge run "forge start"

An MCP client can use the bundled stdio server instead:

pnpm run debug:mcp

See Demo Debug Bridge for the full endpoint, control-channel, MCP tool, and window.__forgeDebug surface. The project .pi/mcp.json, the codemode setup, and concurrent catalog audits are described in Pi Agent Workflows.

Bounded AI repair loop

The repair loop composes the behavior runner with an external coding agent. It requires an already running demo, writes each iteration's report and repair-context.json under .tmp/forge-repair-loop/, and stops after a bounded number of iterations or when a failure needs human review. The agent command is run from the repository root with FORGE_REPAIR_CONTEXT pointing at the JSON context file.

# Validate the selection without connecting to a demo
pnpm run debug:repair-loop -- --dry-run --sample pure-framework/react-tsx

# The command may be a wrapper around OpenHands, SWE-agent, or another coding agent
$env:FORGE_REPAIR_AGENT_COMMAND = 'node scripts/my-coding-agent.mjs'
pnpm run debug:repair-loop -- `
  --base-url http://127.0.0.1:4175 `
  --sample pure-framework/react-tsx `
  --scenario counter.increment-twice `
  --max-iterations 3

Omit --scenario and choose autonomous exploration in the Demo panel, or use the CLI directly:

pnpm run debug:repair-loop -- `
  --base-url http://127.0.0.1:4175 `
  --mode explore `
  --sample pure-framework/react-tsx

Exploration reads the rendered preview, identifies common controls, performs a small bounded set of real browser actions, and records before/after text, screenshots, a video of the run, console errors, and action results. Only visible, enabled controls are offered; editable text fields are filled, while non-editable inputs (Wijmo/InputMan combo boxes, pickers) are clicked to open their list, and each interaction is capped at 5s. When a modal is open only its own controls are offered (a covered background control cannot be clicked), and if an unknown overlay still blocks an action, Escape is pressed and the action is retried once before it is recorded as failed. Canvas-rendered surfaces are not skipped either: a SpreadJS workbook's cells are exposed as targets through the public GC.Spread.Sheets API (click the cell, type, Enter), and a bare canvas falls back to a center click. The video is written as exploration-video.webm next to exploration-report.json (both fields: video relative to evidenceDir, videoPath absolute); set FORGE_EXPLORE_VIDEO=0 to skip the encoding cost. It is a discovery signal and can produce a repair hypothesis; a stable scenario is still the stronger regression contract for a feature that has been confirmed.

The loop does not start or restart the demo, does not approve arbitrary shell commands, and treats infrastructure and unsupported-probe failures as needs-human-review instead of asking the agent to guess.

Jev AI judge and exploration policy (optional)

The autonomous explorer can call a self-hosted Jev decisions model for two advisory capabilities:

  • A - judge. After each sample it asks Jev to classify the run (healthy / real_defect / env_noise / harness_flake / render_incomplete), score severity, and pick the next step. The verdict is written to exploration-report.json as ai. The repair loop uses it only to narrow the automated scope: environment/tool problems or an explicit needs_human decision are never handed to a coding agent.
  • B - action policy. With FORGE_JEV_ACTION=1 Jev plans the preview interactions instead of the explorer clicking the first N controls in DOM order. Because Jev answers a set of named questions per request, one call returns an ordered group of action_1 … action_n choices; the explorer executes that group, re-lists the controls, and plans the next group until the step budget runs out. When a goal, description or source is available the model first picks which behavior to verify, so the plan is targeted at the sample's intent rather than at whatever control is first. Supply that grounding with --goal, --description-file, --docs-dir (a README / description checkout such as the onboarding Sites archive, resolved per sample by keyword) or --docs-map (a curated { sampleId: docPath } JSON, which wins over the keyword lookup and is the reliable option when the archive's folder taxonomy has drifted). FORGE_JEV_PLAN_ACTIONS caps the actions per call (default 4). If the model call fails, the remaining controls are still exercised deterministically, so a model outage cannot silently reduce coverage. The own actions are executed in the explorer's isolated browser (that is where screenshots and console evidence come from) and mirrored onto the connected demo tab through the debug bridge, so the person watching the demo sees each AI action happen in the real UI. Set FORGE_EXPLORE_MIRROR=0 to keep exploration headless-only.

Both are off by default and only read the key from the environment; a key is never written to disk, embedded in an artifact, or printed in an error.

Every call is streamed as a jev:* event (jev:judge:started, jev:judge:finished, jev:goal:decided, jev:plan:decided, jev:action:failed, …). The repair monitor at /repair.html draws the batch as a flow chart: one lane per sample with a node per stage (排队 → 探索 → AI 动作 → AI 判定 → 结果). Hovering a lane opens a status card with the verdict, reason code and recent event timeline, so the model's decisions are visible instead of being buried in exploration-report.json. Samples resumed from a previous run are skipped, so their card replays that run's AI verdict and the controls the AI touched last time. A run that passes the automated checks but that Jev still classifies as a real_defect (or an incomplete render) is shown as AI 标记 instead of passed, and is re-run next batch so a defect the checks missed cannot hide behind a green result. A run whose documented goal action could not be performed at all (for example a control that is not visible) is shown as 动作失败 and re-run too: an incomplete verification of a claimed behavior is not a pass, matching the repo's "untested does not count as success" rule. An exploratory click that is not bound to a documented action and could not be executed is recorded on the report but does not flag the run, because the AI verdict already decides whether the unexercised extra interaction hides a defect. When a batch resumes from progress.json, those samples are marked amber as soon as the previous verdicts load, so they stand out from the already-passed gray lanes instead of waiting for the sequential run to reach them. The header shows how many samples Jev judged and the verdict breakdown. The raw JSON event log stays available behind the footer toggle.

Exploration report page

Each sample gets its own self-contained index.html beside its exploration-report.json (samples/<id>/index.html), regenerated whenever the sample runs or is resumed. It is grounded in the sample's own forge.goal.json: a Sample 目标 panel shows the description, the documented behaviors and their expectations, the source documentation and the frameworks, and each executed step is tagged with the goal it served, its position in the AI's plan and (when the control matches a documented action) the outcome that action was meant to prove. When the exploration recorded its own decisions (goal choice and action plan groups), an AI 决策轨迹 list replays them above the steps. The Jev verdict with severity / next step sits beside the recorded exploration-video.webm, and the page links to that sample's exploration-report.json, before.png and after.png. The debug bridge serves the audit tree at /__forge/repair/report/..., so clicking a lane in the monitor opens the page; the file also opens directly from disk with no server.

$env:FORGE_JEV = '1'            # enable the judge (A)
$env:FORGE_JEV_ACTION = '1'     # also let Jev pick actions (B)
$env:JEV_BASE_URL = 'http://10.32.0.160:8080/v1/systemone'
$env:JEV_MODEL = 'jev-1.13.0'
$env:JEV_API_KEY = '<key>'
$env:JEV_MAX_RETRIES = '5'      # optional; retries per request (default 5)
$env:JEV_RETRY_DELAY_MS = '3000' # optional; delay between retries (default 3000)

Or put the same keys in a gitignored .env (repository root or demo/); the demo's Vite config loads it for the server process, FORGE_JEV=1 included:

FORGE_JEV=1
FORGE_JEV_ACTION=1
JEV_BASE_URL=http://10.32.0.160:8080/v1/systemone
JEV_MODEL=jev-1.13.0
JEV_API_KEY=...
JEV_MAX_RETRIES=5
JEV_RETRY_DELAY_MS=3000

A real environment variable always wins over .env, and the repo-root .env wins over demo/.env. The demo prints [demo] Jev judge enabled/disabled at startup, and the repair monitor's first line is a [jev] {"type":"jev:config"…} record.

Jev is not an OpenAI chat model: it answers typed questions (noul, choice, score) about an arbitrary JSON state. The client lives in scripts/agent/jev-client.mjs and the Forge question sets in scripts/agent/jev-questions.mjs. Transport errors, request timeouts and retryable HTTP statuses (408/425/429/5xx) are retried 5 times with a 3s gap before the request is reported as failed (JEV_MAX_RETRIES, JEV_RETRY_DELAY_MS).

Per-demo goal files (forge.goal.json)

A demo is the directory that holds its per-framework samples (angular/, react/, vue/, purejs/) and one shared README. That directory carries a single forge.goal.json describing what the demo is meant to demonstrate (intent), what to check (goals[].expect), and how (goals[].actions) plus provenance (docs, source, frameworks[]). The explorer auto-loads it when no explicit --goal / --description-file / --docs-dir grounding is given, looking in the framework sample directory first and then one level up at the demo directory, so the AI plans targeted actions instead of walking the DOM.

Generation is one-time and then incremental:

# 1. scaffold: intent + goals; syncs each demo's README/des.md into the demo dir
pnpm run goals:generate -- \
  --docs-dir "wijmo=D:/Products/Wijmo/source-code/wijmo/monorepo_migration/wijmo-sample;D:/Archive/Onboarding Related/Onboarding Site/Sites"
# once a demo is synced, --docs-dir is optional (the synced bundle is the grounding)
pnpm run goals:generate -- --only <sampleId>

# 2. enrich: an AI agent fills goals[].actions from the README + sample source
pnpm run goals:generate -- --docs-dir <archive> --agent pi --limit 20
# or a custom agent (FORGE_GOAL_CONTEXT in, FORGE_GOAL_OUTPUT out):
pnpm run goals:generate -- --docs-dir <archive> --agent-command "node scripts/my-goal-agent.mjs"

scripts/agent/generate-sample-goals.mjs walks the hands-on catalog, groups the framework samples by demo, grounds each demo in its sources and the matching README/description, and writes one scaffold (reviewed: false). The matched documentation is synced into the demo directory in its original bundle form — readme.md plus the description.md / des.md beside it, whichever the sample uses (one set per demo, shared by every framework) — so the docs live with the samples and the goal does not depend on an absolute archive path. Provenance keeps the original location in docs.sourcePath.

Grounding is then read from the synced bundle rather than from the archive, so --docs-dir is only needed to bootstrap or refresh a demo's docs; once a demo has been synced, later runs (and --only runs) need no archive at all and produce the same docsText and fingerprint either way. Passing --docs-dir re-syncs the bundle, rewriting a file only when its content differs; --force is separate and forces the goal itself to be rewritten even when the fingerprint is unchanged.

The archive match itself is exact-first: a demo id's <category>/<leaf> tail is looked up as a path suffix under the product's site, and only when that fails does the keyword scoring run. The scorer cannot resolve stopword leaves (overview, basic, style) at all, so the path pass is what grounds them. A flat id (activereports-js/parameters) has no category to disambiguate with, so its unique leaf is trusted when every candidate carries the same text, and locale-qualified docs (readme{ja}.md) are indexed with the plain file preferred.

--docs-dir takes a ;-separated list of roots. An entry may be labeled <product>=<dir> to restrict that root to one product — Wijmo's documentation lives in its own single-product sample repository (D:/Products/Wijmo/source-code/wijmo/monorepo_migration/wijmo-sample), whose feature-samples/samples/<category>/<leaf> tree the exact-path pass resolves directly, while the keyword fallback would happily let a Wijmo page answer an InputMan sample. Unlabeled roots are still scoped per product site, and a product's canonical site may itself be a nested path: SpreadJS is served from js-sheets-demo/public/en/tutorial/source/demos/en/feature-samples/samples/features, which mirrors the catalog ids but sits under a public/ directory that the indexer skips when walking into a root.

The actions are written by an AI agent, not by regex heuristics: for each demo the generator writes a context (README + every framework's source + the draft goals) and invokes the agent, which returns the goal with goals[].actions filled and reviewed: true. --agent pi uses the bundled scripts/agent/goal-agent-pi.mjs adapter (pi in non-interactive mode), which is locked to --tools read,write: enrichment only needs to read the context and write the goal, and dropping bash makes an OS-level find / structurally impossible. The adapter also runs with cwd set to the demo directory, hands the agent absolute input paths, writes a per-demo agent.log and session directory, and loads scripts/pi-extensions/guard-workspace-search.ts, which blocks any search that points outside the working directory. Each nested agent runs inside a Windows Job Object so a timeout tears down the whole process tree instead of leaking it. Action shape:

{ "kind": "click", "target": { "hint": "JSON", "selector": "#toJSON" }, "expect": "a download.ssjson snapshot is downloaded" }

Two goals are run-level checks, not behaviors: every draft writes a render goal and a standing console goal ("check": "console-clean"). A check goal never carries actions — it is filtered out of the action policy's candidate list so the AI cannot answer it with clicks — and the explorer evaluates it deterministically from the runtime records (scripts/agent/console-check.mjs): only internal records count (preview transport faults and external CDNs are environment noise), an unexplained uncaught exception fails with runtime_error, and an unexplained internal console.error / failed request fails with console_error (repairable by the repair loop). Known benign noise is declared per demo, using the same shape as the behavior runner's diagnostic policy:

"diagnosticPolicy": {
  "allowedNoise": [
    { "source": "console", "textContains": "NG0304", "reason": "Angular linker probe (upstream)" }
  ]
}

ensureConsoleGoal re-asserts the check after every agent run, so a goal file cannot lose its console check or turn it into planned actions.

Each goal stores a fingerprint of the demo's framework sources, its README and the draft version, so a re-run skips unchanged demos and only rewrites the ones whose sources moved; a stale per-framework goal left by an earlier layout is removed. When an agent is configured, a demo that has no actions yet (or whose sources changed) is re-enriched, while a reviewed: true goal with actions is left alone unless --force-agent is passed. The file is the durable product of the AI's judgment, not a per-run artifact.

Because the fingerprint also covers the draft version, a draft-logic upgrade invalidates every goal at once. When that happens, run the generator without --agent first: the merge is purely local (it appends the new standing goals and refreshes provenance) and rewrites the fingerprint, so a later --agent pi run only enriches demos that still lack actions instead of re-querying the model for all of them.

Syncing the sample repositories

The regenerated goal files and the synced documentation live in the codemine-forge-demo-* submodules, so they are committed there first and the superproject then points at the result. scripts/repo/ owns that order:

pnpm run repo:status    # branch, upstream, ahead/behind and pending changes per repo
pnpm run repo:sync      # commit + push the submodules, then the pointer commit + push
pnpm run repo:sync -- --dry-run          # report only, change nothing
pnpm run repo:sync -- --only codemine-forge-demo-spread-js

A submodule commit is pushed before the superproject pointer commit, so a pointer never references a commit nobody else can fetch. A submodule that carries a path outside the generated set (forge.goal.json, readme.md, description.md, des.md) is refused unless --allow-any is passed, and working-tree changes outside the submodule paths are left uncommitted for the operator to handle.

Forge sample catalog

The demo ships no bundled samples: every sample is loaded from external static directories, by default the codemine-forge-demo-* git submodules under samples/. This keeps the initial browser bundle small: only catalog.json is loaded at startup, and the selected sample's files are fetched when it is opened.

When FORGE_SAMPLES_DIR is unset, pnpm run demo resolves the roots in this order: an in-repo samples/ directory (check the product repositories out there, for example as git submodules), C:/Users/cary/Desktop/forge-demos, and the historical single-root C:/Users/cary/Desktop/sample-migration/forge-samples. Point it somewhere else with an explicit value, or set it to an empty string to start without the external catalog:

$env:FORGE_SAMPLES_DIR = 'D:\path\to\forge-demos'
pnpm run demo

Two layouts are supported (see demo/sample-roots.mjs):

  • Product repositories (the recommended layout): one git repository per product, named codemine-forge-demo-<product> and holding <category>/<sample>/<framework>/. A directory that contains them is expanded automatically, and each repository is mounted at /forge-samples/<product>. A repository name may be mapped to a different product id (for example codemine-forge-demo-wijmo-js -> wijmo).
  • A monolithic root: one directory holding <product>/... directly, optionally with its own catalog.json (the historical forge-samples migration output). The root is mounted at the /forge-samples URL root.

FORGE_SAMPLES_DIR accepts a ;/,-separated list, so several roots can be served together. The Vite host serves the roots at /forge-samples and synthesizes /forge-samples/catalog.json when a root does not ship one: it reads any catalog.json beside the samples and otherwise scans the root for package.json + vite.config.* sample directories. In production, publish the same sample directories beside the demo assets, or set VITE_FORGE_SAMPLE_CATALOG_URL to the deployed catalog URL. Forge receives only the selected sample files through the existing virtual file system; no migration logic runs in Forge.

Sample submodules

The product repositories are vendored as git submodules under samples/, so a fresh checkout resolves them before any machine-local path:

git submodule update --init --recursive
pnpm run demo

pnpm run demo serves samples/codemine-forge-demo-<product> at /forge-samples/<product> and needs no FORGE_SAMPLES_DIR. Update the samples with git submodule update --remote samples/... and commit the new gitlinks. The machine-local defaults (~/Desktop/forge-demos, then the historical single-root forge-samples) remain as fallbacks for an external checkout.

Publishing

Before publishing, run the complete release gate:

pnpm run validate

This includes type checking, automated tests, the static browser demo smoke, and npm package-content verification. See Release Validation for focused commands and the Playwright browser prerequisite.

Publish prerelease builds to npm with:

pnpm run publish:npm

The script updates the package version, validates the package, checks that the target version is not already published, runs a package dry run, and publishes with the alpha dist-tag by default. In auto mode, it keeps the current version when it has not been published yet and bumps to the next available prerelease version when it has. If npm login is required, it starts the npm web login flow in the browser and waits for authentication to complete.

Useful options:

pnpm run publish:npm -- --dry-run
pnpm run publish:npm -- --bump prerelease
pnpm run publish:npm -- --tag next
pnpm run publish:npm -- --login-only
pnpm run publish:npm -- --otp 123456
pnpm run publish:npm -- --version 0.0.2-alpha.0

--dry-run still validates and packs the selected target version, but restores package.json before exiting so a rehearsal does not leave a version bump in the working tree.

Design Principles

  • Prefer browser-native execution over hidden backend work.
  • Keep commands deterministic and explicitly supported.
  • Treat forge start and forge run commands as product affordances, not a real shell.
  • Make unsupported Node behavior fail early with clear diagnostics.
  • Cache aggressively, but keep cache invalidation visible and debuggable.
  • Keep the preview iframe isolated from Codemine application privileges.

First Milestone

The first useful milestone is a browser-only runner that can:

  • Load a template workspace from memory.
  • Persist edits in IndexedDB.
  • Parse package.json.
  • Resolve public browser-compatible dependencies.
  • Bundle a React or Vue entry with esbuild-wasm.
  • Simulate forge start (install → build → dev) and the individual forge run commands.
  • Render the result in an iframe.
  • Rebuild and refresh the iframe after file changes.

Preview URL resources

The preview API supports resourceMode: 'inline' | 'url'. URL mode serves session-scoped HTML, JavaScript, classic assets and source maps through serve(), while inline mode preserves srcdoc compatibility. Hosts may set previewBaseUrl for a mounted application path. The demo keeps inline mode as its compatibility default; the Service Worker transport is available for explicit URL-mode hosts.