- name
- kickjs-cli-plugin
- description
- Use when adding a kick <name> command, a kick g <name> generator, or a typegen emitter to this project or a package it ships.
<!-- Generated by `kick g agents` for settings-api. Edits are overwritten on the next refresh; keep customisation in a SKILL.local.md alongside. -->
A CLI plugin contributes commands, generators and typegen emitters to the
`kick` CLI. Every built-in command ships as one, so the contract is the same
one the framework uses.
**Steps**:
1. Write the plugin. All four contribution kinds are optional:
```ts
// kick-tool.ts
import { defineCliPlugin } from '@forinda/kickjs-cli'
export const toolPlugin = (options: { watch?: boolean } = {}) =>
defineCliPlugin({
// Stable id, unique across plugins — it names the plugin in conflict errors.
name: 'my-tool',
// Declarative: same shape as kick.config.ts `commands`.
commands: [{ name: 'db:migrate', description: 'Apply migrations', steps: 'node ./scripts/migrate.js' }],
// Programmatic: full commander API, when you need options or subcommands.
register(program, ctx) {
program
.command('my-tool')
.description('Do the thing')
.option('--watch', 'Watch mode')
.action(async () => {
ctx.log(`running in ${ctx.projectRoot}`)
// ctx.config is the loaded kick.config.ts
})
},
})
```
2. Register it in `kick.config.ts`:
```ts
import { toolPlugin } from './kick-tool'
export default defineConfig({ plugins: [toolPlugin()] })
```
3. Check it is loaded, per contribution kind: `kick --help` lists a command,
`kick g --list` lists a generator, `kick typegen` runs an emitter. A
plugin that fails to load takes the whole CLI down with a conflict error,
so silence here means the config never referenced it.
**Which kind to use**: `commands` for a shell one-liner, `register` for
options / subcommands / async work, `generators` (`defineGenerator`) for
`kick g <name>` scaffolders, `typegens` for a file under `.kickjs/types/`.
**Red flags**:
- Confusing this with a runtime plugin: `defineCliPlugin` (from
`@forinda/kickjs-cli`) extends the CLI; `definePlugin` (from
`@forinda/kickjs`) hooks the running app. They share nothing.
- Claiming a command name a built-in owns (`build:netlify`, `typegen`,
`generate`) — duplicate declarative names are a startup conflict, and
`register` has no conflict detection at all, so it silently loses. Namespace
your own (`my-tool:build`).
- Doing real work inside `register` — it runs at CLI startup for every
command, so it must only register. Put the work in the action.
- Importing heavy dependencies at module scope. `await import()` them inside
the action, so an unrelated `kick dev` does not pay for them.
عرض على GitHub