Every framework ships a CLI. Most of them are scaffold-and-forget: a one-time nest new or next create, then you forget the binary exists and live inside package.json scripts forever. KickJS's kick CLI sits in a different bucket. It is the build tool, the codegen, the diagnostics surface, the package wirer, and — unusually — an interactive REPL with your DI container loaded.
This is not an enumeration of every flag. It is a tour grouped by intent, with the less-obvious commands called out.
Lifecycle — the build tool that happens to ship with the framework
The lifecycle commands are what most teams wire into package.json and forget about, but they are doing more than tsc --watch would.
-
kick new <name>andkick initcreate a new project. Pass.toinitto scaffold into the current directory. -
kick devis a Vite-backed dev server with HMR. It runs typegen on startup, watchessrc/**/*.tsandkick.config.ts, and tears down adapters that implementshutdown()cleanly between reloads. -
kick dev:debugis the same dev server with the Node.js inspector attached, so you can hook a debugger without remembering the--inspectflag pattern. -
kick buildruns the production Vite build and emits a single ESM bundle indist/. -
kick build:assetsrebuilds only the.kickjs-assets.jsonmanifest — useful when only static assets changed. -
kick startruns the compiled production build.
These share state through generated artefacts. kick dev regenerates types as you type; kick build regenerates them before bundling; kick start assumes the build was clean. You don't think about it, which is the point.
Generators — kick g is the codegen surface
The bare form kick g <name> is shorthand for kick g module <name>, because that is what you reach for nine times out of ten. The full set of subcommands covers the whole granularity ladder.
Full-feature generators:
-
module— a complete module folder: controller, service, DTOs, repo, tests, and (critically) registration insrc/modules/index.ts. -
scaffold— full CRUD module driven by a field DSL (more on this in a moment). -
auth-scaffold— a complete auth module: register, login, logout, password hashing, controller, service, DTOs, test stubs. -
plugin— aKickPluginthat bundles DI bindings, modules, adapters, and middleware behind a single registration. -
adapter— anAppAdapterwith lifecycle hooks (start,shutdown).
Single-file scaffolds:
-
service,controller,dto,test— each takes-m <module>to scope it to an existing module folder. -
middleware— Express middleware (also-m-scopable). -
guard— a route guard (auth, roles, anything per-route). -
job— a@Jobqueue processor with@Processhandlers, forkick add queueconsumers. -
resolver— a GraphQL resolver scaffold with the right decorators wired up. Opt-in: only relevant if you're running a GraphQL surface alongside (or instead of) HTTP routes.
Project-level generators:
-
config— emit a freshkick.config.ts. -
agentsandagent-docs— regenerateAGENTS.md,CLAUDE.md, andkickjs-skills.mdfrom the framework's current state.
Cross-cutting flags worth knowing: --list shows what a generator can do without writing anything, --dry-run prints the file plan, --repo (inmemory | drizzle | prisma) picks the persistence flavour, --pattern (rest | ddd | cqrs | minimal) picks the architectural dialect, --minimal / --no-entity / --no-tests / --no-pluralize strip pieces you don't want, and -f / --force overwrites existing files.
kick g module orders --repo drizzle --pattern rest
That registers OrdersModule in src/modules/index.ts for you. The registration step is the one you must not hand-roll: it is alphabetised, import-managed, and aware of removal via kick rm. Hand-edit it and you will eventually leave a dangling import behind.
The unusual ones, paragraph by paragraph
These are the commands that most other frameworks don't have, or only have in some half-built form. They're the reason the CLI is interesting and not just convenient.
kick g scaffold and the field DSL
kick g scaffold takes a list of field specs and emits a full CRUD: Zod input DTO, response DTO, controller (list/get/create/update/archive), use-case files, and tests. The DSL is the trick:
kick g scaffold Post title:string body:text:optional published:boolean:optional
Supported types: string, text, number, int, float, boolean, date, email, url, uuid, json and enum:a,b,c for inline enums. Append :optional and the Zod schema marks it nullable, the TypeScript type widens, and the test fixtures stop passing it. The right tool when you know the shape of an entity and don't want to type it four times across DTO, response, repo, and test.
kick g auth-scaffold
kick g auth-scaffold is g scaffold for the one feature every app re-implements badly: authentication. It emits a controller (/auth/register, /auth/login, /auth/logout), a service with password hashing, the DTOs you actually want, and test stubs. The point isn't that it saves typing; it's that the resulting code is the same shape across every KickJS app, so onboarding onto a new project, you already know where the login handler lives.
kick tinker
kick tinker boots an interactive REPL with the DI container and your services pre-loaded — the Laravel/Rails ergonomic, ported into Node. Drop into a prompt, type await container.resolve(OrdersService).list({ limit: 5 }), and you have data back without writing a script, mocking a request, or curl-ing a route. For exploratory work — "what does this query return for tenant X?" — it beats a debugger.
kick explain
kick explain "<error message>" takes a KickJS error string and returns a description plus a likely fix from the framework's own catalogue. You're not searching GitHub issues; you're asking the binary that produced the error what it meant. A small thing that's disproportionately useful the first month on a new framework.
kick mcp
kick mcp start and kick mcp init expose the framework over the Model Context Protocol — the spec that lets AI assistants treat tools as first-class resources. With kick mcp running, an assistant can introspect your modules, ask the framework for the DI registry, or trigger generators safely. The first framework I've seen ship its own MCP server in the box — a clear opinion that AI tooling is part of the developer surface, not a third-party add-on.
kick g agents
The companion to kick mcp is kick g agents, which regenerates AGENTS.md, CLAUDE.md, and kickjs-skills.md from the framework's current capabilities. The interesting bit is what it implies: the framework treats keeping the AI-tooling docs fresh as part of its own upgrade process. Bump the framework, re-run kick g agents, and your AI tooling is back in sync. The doc isn't a side artefact; it's a build output.
Packages — kick add is not a synonym for pnpm install
kick add auth does what pnpm install @forinda/kickjs-auth does, and wires it. It registers the package's adapters with the bootstrapper, drops imports into src/index.ts where needed, and scaffolds the config block (JWT secret slot, refresh strategy slot) so you have somewhere to put secrets without reading the package README first. The package ships a manifest, the CLI applies the wiring, and prints what it changed.
-
kick list(aliaskick ls) prints every package the CLI knows how to wire — the answer to "is there an official kickjs package for cron?" without leaving the terminal. -
kick remove(aliaskick rm) removes generated code with awareness of the registry files.kick rm module ordersundoes whatkick g module ordersdid, including themodules/index.tsline.
Diagnostics & DX — the bits other CLIs ship as third-party tools
None of these are scripts wrapping npm run.
-
kick infoprints system + framework info: Node version, TS version, KickJS version, package versions, OS. The first thing you paste into a bug report. -
kick checkaudits the project for common issues — missing types, drift betweenkick.config.tsand the generated registry, packages added viapnpmwithout thekick addwiring step. -
kick inspect [url]connects to a running KickJS app and pulls live debug info: registered routes, DI bindings, adapter status.
Cumulatively, you can answer "what's wrong with my app?" without leaving the CLI — novel only if you remember how many frameworks make you write a script, run a curl, or boot an inspector to ask the same questions.
Quality — the CI gate
The quality commands are small in scope but hold the project together over time.
-
kick typegenregenerates.kickjs/types/: route types (soctx.bodymatches your Zod schema), env types (sogetEnv('PORT')is typed), DI registry tokens, module + plugin declarations, asset imports, ContextMeta augmentations.gitignored, treated as a build artefact.kick devruns it on change; CI runs it before typecheck and build. You rarely run it by hand. -
kick testis a passthrough to Vitest with the project's config preloaded. -
kick formatruns Prettier;kick format:checkchecks without writing. -
kick ci:check(aliaskick verify) is the CI gate: typecheck + format check, in the order that fails fastest.
A minimal synthetic kick.config.ts ties it together:
import { defineConfig } from '@forinda/kickjs-cli'
export default defineConfig({
pattern: 'rest',
modules: { dir: 'src/modules', repo: 'drizzle', pluralize: true },
typegen: { schemaValidator: 'zod' },
commands: [
{ name: 'lint', description: 'Lint code', steps: 'eslint src/' },
],
})
pattern picks the controller dialect. modules.dir / modules.repo / modules.pluralize set generator defaults. typegen.schemaValidator: 'zod' tells typegen to crack open Zod schemas for body inference. commands lets you register custom verbs that run as kick lint, with the same logging the built-ins get.
What makes this CLI different
KickJS folds five things — build tool, codegen, package manager wrapper, diagnostics, REPL — into one binary, and ships an MCP server so AI assistants can introspect the app. Most Node frameworks ship one or two of those and rely on you to assemble the rest from package.json scripts and third-party tools. The design decision is worth stealing: a single CLI that stays useful from kick new through to kick tinker on a five-year-old codebase is the one you'll still trust on day 1500.
Top comments (0)