@runablehq/runkit
v0.1.1
Published
The toolchain behind Runable app templates
Readme
@runablehq/runkit
The toolchain behind Runable app templates. Generated apps depend on this package instead of carrying platform lint config, convention rules, and tool versions in their own tree.
Commands
runkit lint checks structural conventions with konsistent, then lints with oxlint. It stops
after konsistent if conventions fail, so the output stays short.
runkit lint --fix runs oxlint with --fix and skips konsistent, which has no autofix. A
convention error should not block the rewrites oxlint can apply on its own.
What the app still has to provide
The app keeps an .oxlintrc.json at its root:
{
"extends": ["./node_modules/@runablehq/runkit/oxlintrc.json"],
"ignorePatterns": ["dist/**", "dist-electron/**", ".expo/**", "packages/web/public/runable.js"]
}Both keys are required, for different reasons.
extends is what makes the shared config work at all. oxlint resolves overrides.files against
the config that does the extending, so the globs in oxlintrc.json only match when they are
pulled in from the app root. Pointing --config straight at this package instead would resolve
every glob against node_modules, match nothing, and report success while enforcing none of the
overrides.
ignorePatterns does not inherit through extends, so it has to be repeated here. Drop it and
oxlint starts reporting on build output and vendored files.
jsPlugins behaves the opposite way. It resolves against the file that declares it, so
oxlintrc.json points at this package's own lint-rules/ and needs nothing from the app.
Lint rules
lint-rules/ holds the custom oxlint plugin, registered under the template namespace:
asset-imports: web static assets belong inpackages/web/public/, referenced by URL path.protected-files: files under a__path segment are template-managed and must match the hashes in the app's.runable/protected-files.json.
Both resolve paths against process.cwd(), because the rules ship inside node_modules and their
own location says nothing about the app being linted. runkit walks up from the working directory
to the nearest parent holding .runable/ and runs both tools from there, so the two agree on what
the app root is no matter where the command was typed.
The rules are declared by the platform rather than the app: an app has no lint-rules/ of its own
to edit, and no place to register another. This is a default, not a sandbox — an app that rewrites
its .oxlintrc.json or edits the installed package can still opt out. protected-files covers the
app's own __ files; keeping the toolchain itself honest is the image build's job, not this rule's.
To add a rule, create a file in lint-rules/, register it in lint-rules/index.mjs, and enable
it in oxlintrc.json under template/.
Tool versions
oxlint and konsistent are pinned exactly. They decide what every generated app is held to, so
upgrading either is a deliberate change to this package, not something an app can drift into. The
versions here are independent of the ones the Runable monorepo uses on itself.
