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

@craft-ts/dev-tools

v0.9.3

Published

Development tools for craft-ts: ESLint configs, ESLint rules, and codemods

Readme

@craft-ts/dev-tools

Development tools for CraftTS: ESLint rules, codemods, route automation, and static dependency-graph tooling.

Installation

npm install -D @craft-ts/dev-tools@beta

For coding agents, also install @craft-ts/mcp and follow the coding-agent guide.

Create a project

Create a framework-independent CraftTS application from scratch. Runtime axes, i18n, design-system, typed-CSS, server-function, workspace and reference choices are normalized into one effective configuration:

npx --yes --package @craft-ts/dev-tools@beta craft create my-app
npx --yes --package @craft-ts/dev-tools@beta craft create my-app --effect=v4 --agents=codex,cursor,claude-code
npx --yes --package @craft-ts/dev-tools@beta craft create my-app --effect=none --agents=none
npx --yes --package @craft-ts/dev-tools@beta craft create my-app --effect=none --i18n=none --design-system=none
npx --yes --package @craft-ts/dev-tools@beta craft create my-app --frontend-runtime=effect --backend-runtime=effect --i18n=strict
npx --yes --package @craft-ts/dev-tools@beta craft create my-app --frontend-runtime=plain --backend-runtime=effect
npx --yes --package @craft-ts/dev-tools@beta craft create apps/my-app --workspace=nx --references=craft-ts
npx --yes --package @craft-ts/dev-tools@beta craft create apps/my-app --frontend-runtime=effect --references=all

In a terminal, creation is interactive by default. The first question asks whether the application is frontend-only or full-stack. Full-stack projects then choose a backend runtime, with EffectTS recommended; the frontend runtime is chosen afterwards. The prompts also cover i18n locales, the design system, typed CSS, the workspace, and agent integrations. CraftTS source references are enabled automatically, with EffectTS references added whenever EffectTS is selected. All closed configuration values use keyboard menus: ↑/↓ to move and Enter to confirm; locales and agent integrations additionally use Space for multi-selection. Codex is selected by default. Pass --yes after create to disable all prompts, or pass --agents=codex,cursor / --agents=none for scripted agent selection.

The same defaults apply in non-interactive mode. Use --references=none to opt out, or --references=craft-ts / --references=all to choose explicitly.

New standalone projects are initialized with Git. Projects without references have no initial commit; projects with references receive the minimal initial history required by git subtree. The generated .gitignore covers node_modules/, build outputs, and test reports. If the destination is already inside another Git repository, no nested repository is created.

Canonical options include --frontend-runtime=plain|effect, --backend-runtime=none|promise|effect, --effect-scope=none|frontend|backend|both, --i18n=strict|loose|none, --design-system=basic|none, --workspace=standalone|nx, and --references=none|craft-ts|all. --effect=v4|none, --locales and --default-locale remain compatible aliases. --json includes the complete effective configuration.

With references enabled, .references/manifest.json records the requested ref and resolved SHA. The subtrees are read-only context for coding agents: they are not installed as application dependencies, and generated TypeScript/Vite configuration never points at them. The application uses the published npm packages declared in package.json. Refresh subtrees with npm run update:references (or the generated update:craft-ts/ update:effect-ts scripts).

The starter includes a routed page, a typed API call, flat-config ESLint, unit tests, a graph-wide architecture/ suite, Playwright E2E tests, development logs forwarded to a local JSONL server, .mcp.json for Craft/log/page MCP servers, a browser type-check indicator, and a GitHub Actions workflow with an explicit npm run typecheck gate. codex, cursor, and claude-code install the corresponding project instructions and skills. The legacy cloud-code and gemini values remain accepted as aliases for Gemini CLI output.

Project configuration

Create craft-dev-tools.config.ts when a project needs shared codemod or service-migration options:

import { defineCraftDevToolsConfig } from '@craft-ts/dev-tools';

export default defineCraftDevToolsConfig({
  serviceMigration: {
    overrides: [
      {
        file: 'src/legacy-api.ts',
        symbol: 'LegacyApi',
        name: 'Api',
        providedIn: 'manuallyProvidedAtRoot',
        strategy: 'craftService',
      },
    ],
  },
});

Migration tooling

craft-migrate applies the codemods in dependency order and reports decisions that need human review:

craft-migrate --project tsconfig.app.json --root src --dry-run
craft-migrate --project tsconfig.app.json --root src --write
craft-migrate --project tsconfig.app.json --root src --check --fail-on-manual

The individual stages are available for focused work:

craft-migrate-primitives --project tsconfig.app.json --root src --write
craft-migrate-services --project tsconfig.app.json --root src --write
craft-migrate-streams --project tsconfig.app.json --root src --write
craft-migrate-routes --project tsconfig.app.json --root src --write
craft-migrate-components --project tsconfig.app.json --root src --write
craft-migrate-architecture --project tsconfig.app.json --root src --write

The migration keeps ambiguous code intact and emits a diagnostic instead of guessing business or lifecycle semantics. Use --json <path> for a report.

For standalone markup conversion:

printf '<section><h2>Hello</h2></section>' | craft-migrate-template

Route automation

The craft façade writes ordinary editable TypeScript while keeping route metadata, lazy loading, and dependency proofs aligned:

npx craft route add /users/:userId \
  --component src/users/user-detail.ts#UserDetail
npx craft route add /users/:userId --create-component users/user-detail
npx craft route split \
  --parent src/app.routes.ts#appRoutes \
  --prefix users \
  --target src/users/users.routes.ts

Use --dry-run, --yes, and --json for scripted workflows. The generator adds componentDeps, withRetry, parent-mount assertions, and the file-level route DI proof where applicable.

Static dependency graph

craft-graph analyses one TypeScript program and writes JSON, Mermaid, or HTML artifacts:

craft-graph \
  --project apps/demo/tsconfig.graph.json \
  --out craft-dependency-graph \
  --format both

The graph records services, primitives, route ownership, HTTP endpoints, browser boundaries, and dependency edges. It can be extended with a catalog for backend or other TypeScript sources.

Folder layout proposal

For CraftTS projects with a fresh DependencyGraph v1, craft organize builds a deterministic file projection and writes a read-only folder layout proposal:

craft organize \
  --project apps/demo/tsconfig.graph.json \
  --graph craft-dependency-graph.json \
  --out folder-layout

The command refuses an obsolete or invalid graph and never rebuilds it or moves files. It writes folder-layout-analysis.json, folder-layout-proposal.json, and FOLDER_LAYOUT_REPORT.md.

Files with no route, shell, or importer reachability are marked delete in the proposal and shown in a separate orphaned-files section. This is a proposed deletion in the review output; craft organize does not remove source files.

The layout is feature first. Each route anchors a feature folder on its full path (a collection loaded by a route nests under it; route params are not folders). A file belongs to the features that use it, following CraftTS relations from user to used; imports only decide for files the graph says nothing about. A file then goes to:

  • core/ — main/app.* files, app config, global boundaries, and what the application shell reaches (main.ts itself stays in place);
  • features/<route>/ — the one feature using it, or the deepest one when its users sit on a single route lineage;
  • features/<ancestor>/ — the common ancestor feature of sibling users;
  • shared/ — only what several top-level features use.

Existing directory names are not used as architectural evidence. Use --target-root when the proposed application root should not be inferred from the project tsconfig.

Customize an organizer run

organizeProject is exported from @craft-ts/dev-tools and @craft-ts/dev-tools/folder-layout. Pass weights and thresholds to tune the scoring and feature depth. Add serializable placementRules to override the default placement for files whose Craft graph nodes match the rule:

import { organizeProject } from '@craft-ts/dev-tools/folder-layout';

organizeProject({
  project: 'apps/shop/tsconfig.graph.json',
  graph: 'craft-dependency-graph.json',
  out: 'apps/shop/folder-layout',
  weights: { calls: 4 },
  thresholds: { maxDepth: 2 },
  placementRules: [
    {
      id: 'app-start-services',
      when: { nodeKind: 'service', nodeDetails: { appStart: true } },
      scope: 'core',
      folder: 'core/app-start',
      reason: 'Runs during application bootstrap.',
    },
  ],
});

The same rules can be kept in a JSON file and loaded by the CLI:

{
  "weights": { "calls": 4 },
  "thresholds": { "maxDepth": 2 },
  "placementRules": [
    {
      "id": "app-start-services",
      "when": { "nodeKind": "service", "nodeDetails": { "appStart": true } },
      "scope": "core",
      "folder": "core/app-start",
      "reason": "Runs during application bootstrap."
    }
  ]
}
craft organize \
  --project apps/shop/tsconfig.graph.json \
  --graph craft-dependency-graph.json \
  --config apps/shop/organizer.config.json \
  --out apps/shop/folder-layout

Rules run in array order before the default ownership classification. The first rule matching any Craft node in a file chooses that file's scope and folder; the folder is relative to the organizer's target root. Since proposals move files, a matching rule applies to the whole file. Each rule needs a unique id, a when matcher (nodeKind, nodeDetails, or both), a scope, a relative folder, and a human-readable reason. Explicit rules have confidence 1; destination collisions still require review. The resolved rules are included in the analysis and its config hash. The demo's apps/demo/organizer.config.json uses this to propose app-start services under core/app-start/ without changing defaults for other projects.

Every rule requires a nodeKind; nodeDetails is optional and matches exact values. In TypeScript, nodeKind is a discriminator for nodeDetails. Service metadata is typed, so appStart must be a boolean and misspelled service detail keys are rejected. JSON config receives runtime validation for the built-in service detail keys and value types.

See the folder layout guide for the full configuration reference.

ESLint rules

import craftRules from '@craft-ts/dev-tools/eslint-rules';

export default [
  {
    files: ['**/*.ts'],
    ...craftRules.configs.recommended,
  },
];

The rules cover, among other things:

  • declarative template blocks and granular reactive bindings;
  • state-owned transitions: callers send intent to named state methods instead of calculating a replacement value and writing it through generic mutators;
  • yieldable reads, writes, methods, and resource triggers;
  • transport access through CraftHttpClient;
  • typed route loading, dependency proofs, and exception handling;
  • pure computed values, browser boundaries, and accessibility contracts;
  • the security preset, included in recommended and effect: unchecked DOM URLs, raw HTML, dynamic code, implicit SSR transfer, server functions without limits or explicit per-function error exposure, forwarded headers, and authentication material in browser storage.

The recommended and Effect presets also enable craft-ts/no-external-state-transition. Projects generated by craft create receive it through those presets. Existing projects that spread the preset dynamically receive it after upgrading @craft-ts/dev-tools; projects with a hand-curated rule list must add it themselves. The rule is an error, so existing generic state writes will need to move behind named state commands.

Apply the preset alone — on a library or a tooling folder that does not take recommended — with craftRules.configs.security.

Run eslint --fix after changing generated dependency aliases or route metadata. Keep the generated aliases and proofs in the source file so the compiler and architecture suite can verify them.

Editor and AI workflows

The same ESLint fixes and codemods can be called by editors and coding agents. For a complete workflow, see: