implement
Adders

Adders

Config you can add while scaffolding, or any time after, with the add command.

An addon changes the app the templates write — Tailwind swaps the stylesheet, icons change what the counter renders — so it only means something while the app is being created. An adder is self contained: config files of its own, dependencies, and scripts. Nothing about it depends on being there from the start, which is what lets it be added to an app that already exists.

npm create implement-app@latest my-app -- --oxlint   # while scaffolding
npx create-implement-app add oxlint                  # any time after

Both write the same thing.

AdderWhat it adds
oxlintoxlint and oxfmt, with the @implementjs/eslint rules

oxlint

The adder writes an oxlint.config.ts and an oxfmt.config.ts, adds oxlint, oxfmt, and @implementjs/eslint as dev dependencies, and gives the app four scripts:

ScriptWhat it does
lintLint the app
lint:fixLint it, fixing what can be fixed
formatFormat every file
format:checkCheck the formatting, for CI

The lint config turns on oxlint's own correctness rules and runs the framework's rules alongside them, through oxlint's ESLint-compatible plugin API — a dropped unsubscribe, a signal tested for truth, a .get().map() that renders a list once and never again:

// my-app/oxlint.config.ts
import { defineConfig } from "oxlint";

export default defineConfig({
	plugins: ["eslint", "typescript", "unicorn", "oxc", "import"],
	jsPlugins: ["@implementjs/eslint"],
	categories: {
		correctness: "error",
		suspicious: "warn",
	},
	rules: {
		"implementjs/no-hanging-unsubscribe": "error",
		// …
	},
});

oxfmt is set to tabs at 100 columns, which is what the templates write — down to where a long class list wraps and which arrays stay on one line, so a new app's first format has nothing to rewrite and format:check passes on an app nobody has edited yet.

Both configs stay out of dist/ and, for the kit template, out of the generated .implement/.

The rules the linter turns on are part of what the templates target: unicorn/no-array-sort fixes an array.sort(...) to Array#toSorted(), which is ES2023, so both templates emit a tsconfig.json on "target": "ES2023" and lib it. On anything lower lint asks for a method check says does not exist.

Adding one later

add applies an adder to the app in the current directory. Name the adders to apply, or leave them off and it asks:

npx create-implement-app add oxlint
npx create-implement-app add oxlint --cwd ./my-app --install

It leaves alone anything the app already has — a config file that has been edited since, a script under a name the adder wanted, a dependency the app already depends on. Each of those is reported at the end, and --overwrite replaces them instead of keeping them. Running the same adder twice changes nothing the second time.

FlagWhat it does
[adders...]The adders to add. Leave it off to be asked.
--cwd <path>The app to add to, instead of the current directory.
--installInstall the dependencies the adder added.
--overwriteReplace config files and scripts the app already has.
--package-managernpm, pnpm, yarn, bun, or deno. Detected from the app otherwise.
--link <path>Point the implement packages the adder needs at a local clone of the implement repo.
--workspaceDepend on the implement packages with workspace:*, for an app inside this monorepo.
-y, --yesSkip the prompt — with nothing named, that's an error rather than a guess.

The package.json is rewritten in place, keeping its own indentation and everything the adder had no opinion about.