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

@neonwatty/limner

v0.1.32

Published

Agent-guided visual fidelity workbench for turning images into HTML references and comparing references to real apps.

Readme

Limner

Limner is an agent-guided visual fidelity workbench. It helps a coding agent turn an input image into an approved HTML mockup, then compare that approved mockup against a real implementation.

Limner is model-agnostic. It does not call a vision model and it does not make final pass/fail judgments. It prepares artifacts and schemas for agent-authored UX comparison scores, diffs, and next-iteration guidance.

The older visual spec workflow is archived in docs/archive/visual-spec-workflow.md; active loops use DB-native agent comparison responses.

Install

Use the published CLI:

npm install -g @neonwatty/limner
limner --help
npx @neonwatty/limner --help

Install from source for development:

npm install
npm run build

Run from source during development:

npm run dev -- --help
npm --silent run dev -- ledger list --active --format json

Use npm --silent run dev -- ... for agent-ingestible JSON so npm does not prepend lifecycle output.

Before PRs, run npm run check; it covers ESLint, TypeScript, Vitest, build, Knip, and the tracked-file line-count guard.

Polish Demo Fixture

Use the Swissifier fixture to load a synthetic local trajectory with score progression, screenshots, and mixed proof states. The launcher tour maps viewer controls to CLI commands and agent workflows; it is demo data, not proof against a real application. See docs/polish-demo-fixtures.md for details.

npm run dev -- polish view --port 53456
npm --silent run dev -- polish demo seed --fixture swissifier --reset --format json
npm run dev -- polish view --trajectory <trajectory-id> --port 53456
npm --silent run dev -- polish demo remove --fixture swissifier --yes --format json

Codex Polish Plugin

Fetch the Codex plugin source from GitHub at plugins/limner-polish/; it is intentionally not bundled in the npm package. It provides limner-image-mockup-loop, limner-mockup-implementation-loop, and limner-image-implementation-loop. The plugin does not replace Limner's CLI or ledger. Its skills and scripts help agents run the canonical loop, preserve LIMNER_LEDGER_HOME, keep comparison work subagent-friendly, and pass Ralph Loop iteration count N through limner loop start --max-iterations <N>.

Generate an agent-ingestible command envelope with:

node plugins/limner-polish/scripts/loop-command-envelope.mjs --mode image-mockup --target replay-boundaries --name replay-boundaries-polish --iterations 5
node plugins/limner-polish/scripts/loop-command-envelope.mjs --mode mockup-implementation --target replay-boundaries --iterations 5 --url http://localhost:3152/replay-boundaries

Use node plugins/limner-polish/scripts/response-skeleton.mjs --mode <mode> for a schema-shaped starter response and node plugins/limner-polish/scripts/validate-plugin-surface.mjs for a fast plugin surface check.

Install or refresh the plugin globally for Codex with limner plugin install from the published CLI, or npm run plugin:install from a source checkout.

Basic Workflow

limner init ./ideal.png --target replay-boundaries
limner preview --target replay-boundaries
limner preview status
limner capture reference --target replay-boundaries
limner loop start --mode image-mockup --target replay-boundaries --name replay-boundaries-polish --max-iterations 5
limner loop compare --trajectory traj_... --format json
limner loop response submit --trajectory traj_... --from-run run_... --file ./response.json --format json
limner loop task --trajectory traj_... --executor subagent --format json
limner loop action start --trajectory traj_... --from-run run_... --kind polish --executor subagent --summary "Resize dashboard preview" --format json
limner loop action complete --trajectory traj_... --action act_... --executor subagent --summary "Adjusted preview sizing" --files "src/app/page.tsx"
limner loop status --trajectory traj_...
limner compare image-reference --target replay-boundaries
limner compare reference-implementation --target replay-boundaries --url http://localhost:3152/internal/optimization-lab/wedding-envelope#replay-boundaries --storage-state ./e2e/.auth/user.json
limner report --target replay-boundaries
limner ledger export traj_... --format markdown
limner runs list

Preview note: limner preview --target <target> is the static reference server with /__limner status; limner variants view --concept <concept> is the graphical variants workbench with lineage nodes and selected next bases.

Asset Provenance

limner assets add ./ideal.png --source-label imagegen_original --concept replay-boundaries --format json
limner assets reconcile ./candidate.png --format json
limner assets contact-sheet --run-dir ./.limner/runs/<run-id> --format json

Use source labels imagegen_original, downloaded_copy, derived_edit, html_frame, or reference_screenshot. Loop runs auto-register known visual inputs by default; add --require-registered-assets to limner loop start or limner loop compare for strict workflows. Use assets reconcile before trusting ad hoc images, and use assets contact-sheet to write .limner/runs/<run-id>/assets/contact-sheet.png with asset ID, source label, dimensions, and status. Agent final answers should not claim visual proof from stale artifacts or unregistered image sources.

Availability Diagnostics

Use limner doctor --target <target> --mode <mode> --url <implementation-url> --json, limner target list --json, and limner target status --target <target> --json before claiming proof is blocked. Agents must report cli, target, reference, implementation, auth, and comparison separately. Say "Limner unavailable" only when command -v limner or limner --version fails; otherwise report the exact LIMNER_* blocking reason code.

Workspace Shape

limner-workspace/
  limner.config.ts
  targets/
    replay-boundaries/
      source/ideal.png
      contract/regions.json
      contract/tokens.json
      contract/acceptance.md
      reference/index.html
      reference/styles.css
      AGENT_GUIDE.md
  .limner/runs/

Modes

Loop Ledger

Use limner loop for Ralph Loop-style polishing. Loop work is tracked in a global local-only SQLite ledger at ~/.limner/ledger.sqlite; no telemetry is sent.

limner loop start --mode image-mockup --target replay-boundaries --name replay-boundaries-polish --max-iterations 5
limner loop compare --trajectory traj_... --format json
limner loop task --trajectory traj_... --executor subagent --format json
limner loop action start --trajectory traj_... --from-run run_... --kind polish --executor subagent --summary "Resize dashboard preview" --format json
limner loop action complete --trajectory traj_... --action act_... --executor subagent --summary "Adjusted preview sizing" --files "src/app/page.tsx" --format json
limner loop action skip --trajectory traj_... --from-run run_... --summary "Comparison smoke only; no edit intended" --format json
limner loop response submit --trajectory traj_... --from-run run_... --file ./response.json --format json
limner loop status --trajectory traj_... --feedback "Prompt should mention button contrast."
limner loop next --trajectory traj_...
limner loop close --trajectory traj_...

Loop modes:

  • image-mockup: source image to editable HTML mockup.
  • mockup-implementation: approved mockup to real implementation.
  • image-implementation: source image directly to real implementation. Every meaningful loop interaction writes a ledger event. Agent responses are submitted into local SQLite with the full JSON body, response hash, validation status, and freshness (missing, fresh, stale, or invalid). When a response validates, Limner rewrites the same run report at .limner/runs/<run-id>/reports/comparison.md with the validated score, top fix, and comparison artifacts. Written artifacts that exist on disk are copied into local immutable snapshots under ~/.limner/snapshots and exposed as snapshotPath in ledger exports. agentFeedback is an optional 255-character field for short process-improvement notes; longer comments belong in notes or project artifacts.

Current comparison artifacts are Limner-owned run state under .limner/runs/<run-id>/. Use the run ID printed by loop compare, or returned by loop compare --format json, to submit responses and inspect the matching screenshots, report, prompt, schema, and examples. Loop run manifests use the loop mode as the primary mode (image-mockup, mockup-implementation, or image-implementation) and keep the legacy comparison command name in comparisonMode when they differ. Legacy targets/<target>/captures/** and targets/<target>/reports/** paths may appear in old ledgers, but new compare runs write current artifacts under the run directory.

When reference and implementation data intentionally differ, add --comparison-note "<fixture caveat>" to loop start or loop compare; Limner includes it in agent prompts and preserves it in task rerun commands. Use --state-policy fixture-expected when populated fixture data is expected, --state-policy current-rendered when the agent should assess whatever the app currently renders, or --state-policy empty-ok when empty/sparse data is acceptable. For hydrated apps, add --wait-for-selector, --wait-for-text, and optional --wait-timeout-ms so implementation screenshots wait for the intended app-ready state. Capture commands hide known local dev overlays by default before screenshots and write *.capture.json beside screenshots with final URL, readiness milestones, hidden selectors, visible text inventory, and region evidence hints. Pass --show-capture-overlays only when those overlays are intentionally part of the comparison. Region contracts require id, label, and referenceSelector; add appSelector when comparing against an implementation. Example: { "id": "event-list", "label": "Event List", "referenceSelector": "[data-limner-region='event-list']", "appSelector": "[data-testid='event-list']", "checks": ["bounds", "visible", "text"] }. Contracted regions are reported as captured, absent, hidden, zero-size, or offscreen in reports and agent prompts.

Action Logging

After loop compare creates a comparison prompt, have the agent submit structured JSON with limner loop response submit --trajectory traj_... --from-run run_... --file ./response.json --format json. Each generated prompt pack includes agent-response.minimal.json as a schema-valid starter for simple diffs. Once the response validates, use limner loop task --trajectory traj_... --executor subagent to print the next edit brief. The intended loop is:

loop compare -> loop response submit -> loop task --executor subagent -> loop action start -> edit -> loop action complete -> loop compare

The task brief names likely files, selectors, prioritized diffs, next steps, action logging commands, and the compare command to rerun. JSON task output includes taskFreshness, ledgerContext, and a commandEnvelope with LIMNER_LEDGER_HOME-prefixed commands that another agent can run without guessing which local ledger is active. When newer compare runs are unresolved, loop task blocks by default with status: "stale" and no action commands. Submit the newer response first, or intentionally use older guidance with limner loop task --trajectory traj_... --executor subagent --allow-stale --format json. Record loop action start before edits and loop action complete after edits; --from-run must reference an existing run for that trajectory, complete must reference an existing started action, and --summary must stay under 255 characters. Completed, failed, or skipped actions cannot be completed again. Use loop action skip for comparison-only smoke runs where no edit is intended. Limner records executor intent and action claims; it cannot prove an external orchestrator actually used a subagent. --executor codex is accepted as an alias for the generic agent executor. Use --format json when another tool needs machine-readable handoff data.

Use limner ledger to query and export trajectories:

limner ledger list --active
limner ledger list --active --format json
limner ledger current --target homepage-desktop --mode image-mockup --format json
limner ledger status --trajectory traj_...
limner ledger status --trajectory traj_... --format json
limner ledger show traj_...
limner ledger next --trajectory traj_...
limner ledger next --trajectory traj_... --format json
limner ledger export traj_... --format json
limner ledger export traj_... --format markdown
limner ledger delete trajectory --trajectory traj_... --dry-run --format json
limner ledger delete trajectory --trajectory traj_... --yes --backup ./limner-backup.json
limner ledger delete run --trajectory traj_... --run 2026-... --dry-run
limner ledger delete response --response resp_... --dry-run
limner workspace clean-artifacts --target homepage-desktop --legacy --dry-run
limner workspace clean-artifacts --target homepage-desktop --legacy --yes

Ledger JSON outputs include ledgerContext with the resolved local ledger home, SQLite database path, snapshots directory, and the exact LIMNER_LEDGER_HOME value to reuse in another session.

Ledger deletes are dry-run by default. Pass --yes to actually delete matching local SQLite rows. Use --backup <path> with trajectory deletion to write the trajectory export before hard deletion.

Workspace artifact cleanup is also dry-run by default. --legacy removes only target-scoped captures/ and reports/ roots; current run artifacts under .limner/runs/<run-id>/ are preserved.

Agents can discover the current CLI surface with:

limner --help
limner loop --help
limner loop task --help
limner ledger --help
limner runs list --format json
limner runs show <run-id> --format json
limner workspace --help

Image To Reference

Use this while recreating the ideal image as a standalone HTML/CSS mockup. This mode uses the ideal-to-mockup agent comparison profile.

limner compare image-reference --target replay-boundaries

Outputs:

  • .limner/runs/<run-id>/captures/reference.png
  • .limner/runs/<run-id>/captures/side-by-side.png
  • .limner/runs/<run-id>/agent-comparison/agent-prompt.codex.md
  • .limner/runs/<run-id>/agent-comparison/agent-response.schema.json
  • .limner/runs/<run-id>/reports/comparison.md

In a loop trajectory, submit the agent's structured response with limner loop response submit --trajectory <trajectory-id> --from-run <run-id> --file ./response.json. Limner validates and emits:

  • .limner/runs/<run-id>/captures/image-comparison.json
  • .limner/runs/<run-id>/captures/comparison-summary.json
  • .limner/runs/<run-id>/reports/comparison.md refreshed with the validated result

Agents should inspect the ideal image and reference screenshot separately. The side-by-side image is comparison context, not the source image to parse.

Reference To Implementation

Use this after the HTML mockup is approved and the real implementation needs to match it. This mode uses the mockup-to-implementation agent comparison profile.

limner compare reference-implementation --target replay-boundaries --url http://localhost:3152/... --storage-state ./e2e/.auth/user.json

Outputs:

  • .limner/runs/<run-id>/captures/reference.png
  • .limner/runs/<run-id>/captures/implementation.png
  • .limner/runs/<run-id>/captures/side-by-side.png
  • .limner/runs/<run-id>/captures/dom-metrics.json
  • .limner/runs/<run-id>/agent-comparison/agent-prompt.codex.md
  • .limner/runs/<run-id>/agent-comparison/agent-response.schema.json
  • .limner/runs/<run-id>/reports/comparison.md

In a loop trajectory, submit the agent's structured response with limner loop response submit --trajectory <trajectory-id> --from-run <run-id> --file ./response.json. Limner validates and emits:

  • .limner/runs/<run-id>/captures/image-comparison.json
  • .limner/runs/<run-id>/captures/structure-comparison.json
  • .limner/runs/<run-id>/captures/comparison-summary.json
  • .limner/runs/<run-id>/reports/comparison.md refreshed with the validated result

Capture commands default to viewport-only screenshots. Add --full-page when the full scrollable page is the comparison target.

limner init writes .limner-scaffold.json in each target with template and content hashes for generated scaffold files. If every tracked scaffold file still matches its template, the state is reported as an untouched template scaffold.

Local Logs

Limner writes local structured logs only. There is no remote telemetry.

.limner/runs/<run-id>/
  manifest.json
  events.jsonl
  agent-notes.md
  captures/
  reports/comparison.md
  agent-comparison/