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

solid2-agent-kit

v0.18.0

Published

Teach AI coding agents (Cursor, Claude Code) to write correct Solid 2.0 instead of React or Solid 1.x — always-applied rules, an agent skill, and a mechanical pattern gate.

Readme

solid2-agent-kit

Teach AI coding agents to write correct Solid 2.0 — not React, and not Solid 1.x.

LLMs are heavily biased toward React when writing TSX, and their Solid knowledge is mostly Solid 1.x, which is incompatible with Solid 2.0. This kit installs layered guardrails into a project so agents stop destructuring props, reaching for useEffect/createResource, or writing className — and start writing idiomatic Solid 2.0.

Supported agents: Cursor and Claude Code.

What it installs

| Layer | Cursor | Claude Code | Role | |---|---|---|---| | Always-applied hard rules | .cursor/rules/solid-2.mdc (glob-attached to *.tsx/*.jsx) | managed block in CLAUDE.md | 23 hard rules + banned Solid 1.x API table + eslint-plugin-solid lint-heritage table. Injected without the agent having to decide to read anything | | Agent skill | .cursor/skills/solid-2/ | .claude/skills/solid-2/ | Execution-model primer, decision tables, canonical patterns, a “still runs / write the other form” table, review checklist, official-doc URL index | | Shared agent context | managed block in AGENTS.md | same (Claude Code users can reference it from CLAUDE.md) | Core principles and pointers, always in context | | Mechanical gate | solid2-kit check | same | Comment-stripped regex guard over src/**/*.{ts,tsx,jsx} (or explicit [paths...] — files are checked, directories are walked, a missing path fails): fails on props destructuring (including multi-line signatures), { ...props } rest copies, {list().map(...)} in JSX, React imports/hooks/JSX props/React.lazy/useOptimistic/onDoubleClick, Solid 1.x imports/APIs/components/JSX namespaces (valueless use:x included), Solid 1.x createEffect(fn) / createEffect(fn, init) / createMemo(fn, init) signatures, const [x] = createProjection(...) (it returns the store, not a tuple), vite-plugin-solid, old-router <Route>/<A>/<HashRouter>/<FileRoutes>, MetaProvider, Context.Provider, camelCase style keys, key props (except on @solidjs/meta tags), value()! hand-narrowing, hand-rolled loading signals, === undefined readiness branches, SolidStart leftovers (@solidjs/start, h3, createAsync, useSubmission, "use client"), Next.js imports/useRouter/typeof window, history.pushState, render(<App />) (pass a function), isPending(user()) / latest(user()) (pass the accessor), <Dynamic> (use dynamic()), import type { JSX } from "solid-js" (no JSX namespace there — import JSX from @solidjs/web, or use an aliased Element from solid-js), two-phase effects whose apply only writes a local signal (use a writable derivation), core action(async ...) with a plain async function instead of a generator (only yield re-enters the transaction), and setStore(async ...) on a createStore / createOptimisticStore setter (the draft is a synchronous transaction; dev throws [ASYNC_STORE_SETTER]) | | Edit-time hook | postToolUse entry in .cursor/hooks.json | PostToolUse entry in .claude/settings.json (matcher includes Bash) | Runs the mechanical gate automatically on every agent file edit — including edits made through shell commands (sed, heredocs, codemods; source paths mentioned in the command are checked after it ran) — and feeds findings straight back into the conversation (Cursor: additional_context; Claude Code: stderr + exit 2), so enforcement does not depend on the agent remembering to run check. Wired only when the kit is a local devDependency; opt out with --no-hooks | | Turn-end gate | — | Stop entry in .claude/settings.json | Whole-project check + doctor when the agent tries to end its turn: with findings in place the stop is blocked (exit 2) and the findings are fed back, so a turn cannot finish with React/Solid 1.x patterns left behind. Loop-safe via stop_hook_active (one forced continuation, never an infinite loop) | | Pre-execution guard | preToolUse + beforeShellExecution entries in .cursor/hooks.json | PreToolUse entry in .claude/settings.json | Denies actions before they run: edits/deletes of kit-owned guardrail files (an agent blocked by a gate will try to remove the gate), edits that would strip the kit's hook entries or managed blocks, uninspectable shell rewrites of those files, and npm/pnpm/yarn/bun install of banned dependencies (react, vite-plugin-solid, eslint-plugin-solid, SolidStart, ...) — caught proactively instead of post-hoc by doctor | | Project-wiring gate | solid2-kit doctor | same | Config drift the source gate cannot see: React / vite-plugin-solid / eslint-plugin-solid / SolidStart deps in package.json, a Solid 1.x line of solid-js / @solidjs/router / @solidjs/meta / @solidjs/testing-library / @tanstack/solid-router / @tanstack/solid-query (declared, or installed from the latest tag — Solid 2 releases are on next; TanStack Router's and Query's on rc), a Solid 2 prerelease older than the kit's baseline in bin/baseline.mjs (@solidjs/web / @solidjs/signals / @solidjs/diagnostics latest is an older rc than next), jsx ≠ preserve or jsxImportSource ≠ @solidjs/web in tsconfig, Solid 1.x wiring in root config files, and stale installed guidance (kit updated but sync not re-run) | | Review command | .cursor/commands/solid2-review.md | .claude/commands/solid2-review.md | /solid2-review — on-demand deep review: runs both gates, then walks the diff against the skill checklist targeting the semantic failure classes regexes cannot see (post-await reads, effect misuse, unkeyed server rows, boundary placement, context snapshots) |

Managed blocks are delimited with <!-- solid2-agent-kit:*:start/end --> markers; everything outside them is yours. Kit-owned files (solid-2.mdc, the skill directories) are overwritten on sync.

Usage

GitHub is the canonical distribution channel (consumers pin a commit through their lockfile); the package is also published to npm as solid2-agent-kit:

# install guidance for both Cursor and Claude Code (default)
npx github:lightsound/solid2-agent-kit init

# one tool only
npx github:lightsound/solid2-agent-kit init --cursor
npx github:lightsound/solid2-agent-kit init --claude

# run the mechanical pattern gate (default source dir: src; or name files and directories)
npx github:lightsound/solid2-agent-kit check
npx github:lightsound/solid2-agent-kit check --dir app
npx github:lightsound/solid2-agent-kit check src/App.tsx src/routes

# only the files a change touched: a missing path always fails (exit 2), so
# --diff-filter=d keeps deleted files out of the list; -z / -0 keep paths with
# spaces whole, -r skips the run on an empty (or delete-only) diff
git diff --name-only -z --diff-filter=d main | xargs -0 -r npx github:lightsound/solid2-agent-kit check

# check the project wiring (deps, tsconfig, root configs)
npx github:lightsound/solid2-agent-kit doctor

# pull in kit updates later (idempotent; replaces managed blocks, kit-owned
# files, and hook entries)
npx github:lightsound/solid2-agent-kit sync

So that agents (and CI) can run the gate by name, add the kit as a devDependency and wire a script in the consuming project's package.json (with a local install, npx/bunx resolve the project-local bin, so the bare name is safe there):

{
  "devDependencies": { "solid2-agent-kit": "github:lightsound/solid2-agent-kit" },
  "scripts": { "lint:solid": "solid2-agent-kit check" }
}

Update later with bun update solid2-agent-kit (or the npm/pnpm equivalent) followed by npx solid2-agent-kit sync. Outside a project that has the kit installed, prefer the npx github:... form — it always tracks this repo directly.

Edit-time hooks (automatic enforcement)

The rules and skill teach; check verifies — but only if someone runs it. The hook layer closes that gap: init/sync wire solid2-kit hook into both agents' hook systems, so the mechanical gate runs on every file the agent edits and violations come back as feedback the agent must act on, in the same turn it introduced them:

  • Cursor — a postToolUse entry in .cursor/hooks.json; findings are injected into the conversation as additional_context right after the tool result.
  • Claude Code — a PostToolUse entry in .claude/settings.json (matcher Edit|MultiEdit|Write|Bash); findings go to stderr with exit 2, which Claude Code feeds back to the model as a correction prompt.

Agents also edit files through the shell (sed, heredocs, mv, codemod scripts), which never hits the Edit/Write tools — so shell-shaped tool payloads are scanned for source paths mentioned in the command, and those files are checked after the command ran.

Claude Code additionally gets a turn-end gate: a Stop hook re-runs the whole mechanical check (over src/app/lib) plus doctor when the agent tries to finish its turn, and blocks the stop while findings remain. stop_hook_active is honored, so an agent that cannot satisfy the gate is forced to continue exactly once, never looped forever. (Cursor's stop hook cannot feed back to the agent, so there the last line of defense is the always-attached rules plus CI.)

Both agents also get a pre-execution guard (Claude: PreToolUse; Cursor: preToolUse and beforeShellExecution). A blocked agent's classic next move is to decide the gate itself is wrong — edit the rules file, delete the skill, or strip the hook entries. The guard denies, before the tool call runs: writes to kit-owned files (rules .mdc, skill directories, review commands, the kit under node_modules); edits to .cursor/hooks.json / .claude/settings.json / AGENTS.md / CLAUDE.md that would remove the kit's entries or managed blocks (marker-preserving edits pass — agents can still add the user's own hooks and sections); shell rewrites of those files (sed/rm/redirects — uninspectable, so the deny message redirects to the Edit tool); and package-manager installs of dependencies doctor bans (exact token match, so react is denied but react-aria is not). The deny message always tells the agent what to do instead — fix the flagged code, run solid2-kit sync, or stop and ask the user. Pre-execution events never run the content check itself: fixing a currently-bad file is always allowed.

When the kit is installed as a devDependency, init also wires a lint:solid script (solid2-kit check && solid2-kit doctor) into the project's package.json (only if the script does not already exist), so agents and CI can run both gates by name.

The hook command is node node_modules/solid2-agent-kit/bin/solid2-kit.mjs hook <agent>, so it only works when the kit is installed as a devDependency (see above); init skips the wiring and prints a note otherwise. Merging is idempotent — kit entries are refreshed in place on sync, user entries are preserved. Opt out with init --no-hooks. Hooks never break the agent loop: clean edits, read tools, and malformed payloads exit silently, and reports are capped at 40 findings.

Note on gate precision: check (and therefore the hooks) matches against comment-stripped source, so prose like // migrated off createResource never trips the gate, while string checks ("use client") still work.

CI for consuming projects

Run both gates on every PR so nothing an agent (or human) merges can reintroduce React or Solid 1.x patterns:

- uses: actions/setup-node@v7
  with: { node-version: 26 }
- run: npm ci
- run: npx solid2-agent-kit check && npx solid2-agent-kit doctor

Why not eslint-plugin-solid?

eslint-plugin-solid was built for Solid 1.x. Its analyzer predates the Solid 2 model and flags correct Solid 2 idioms — two-phase createEffect(compute, apply), writable derivations (createSignal(fn)), draft store setters — steering agents back toward 1.x patterns. This kit carries over the plugin's still-valid intents (no-destructure, components-return-once, reactivity, prefer-for, prefer-show, no-innerhtml, style-prop, ...) as documented rules plus a regex gate, without the 1.x false positives.

Docs-drift CI

Solid 2.0 is young and its docs move. A weekly GitHub Actions job (.github/workflows/docs-drift.yml) fetches the official docs corpus (llms-full.txt) and verifies that every API the kit recommends still exists: create* primitives are auto-extracted from the kit content, the rest come from an explicit list in scripts/check-docs-drift.mjs. Matching requires code-like contexts (backticked, import/JSX position, or a call), so common-word APIs such as merge or action cannot pass on prose alone. If Solid renames or removes an API, the job fails and the kit content gets fixed before it teaches agents stale names. The same workflow runs tests/check.test.mjs so the mechanical gate's new patterns keep matching.

Note: the canonical docs site https://v2.solidjs.com/ sits behind bot protection, so the kit (and the guidance it installs) points agents at the official markdown mirror https://v2-rebuild--solid-docs-v2.netlify.app (llms.txt index; every page served as markdown with an .md suffix).

Layout

bin/solid2-kit.mjs                 CLI: init / sync / check / doctor / hook
bin/baseline.mjs                   Solid 2 versions the kit is verified against (doctor + check:upstream)
files/shared/rules-body.md         hard rules (rendered into .mdc and CLAUDE.md)
files/shared/agents-section.md     AGENTS.md managed-block content
files/skills/solid-2/              SKILL.md + references/official-docs.md
files/commands/solid2-review.md    /solid2-review command (Cursor + Claude Code)
scripts/check-docs-drift.mjs       weekly docs cross-check
tests/                             check/doctor fixtures + hook and init-merge tests (`npm test`)

Publishing (npm)

Bump version in package.json on main and CI publishes automatically (.github/workflows/publish.yml) — it skips when the version already exists on npm. Auth is npm Trusted Publishing (OIDC), so no NPM_TOKEN secret exists or is needed. One-time setup on npm: package → Settings → Trusted Publisher → GitHub Actions, owner lightsound, repo solid2-agent-kit, workflow publish.yml, environment left empty.

License

MIT