npm
Source
Description
A CLI scaffolding tool for creating new WolfStar HTTP Framework bot projects.Usage
- Project name — an npm-compatible name for your bot
- Package manager — npm, yarn, pnpm, or bun
- Language — TypeScript or JavaScript
- Build tool — tsdown, Vite, Vite + Nitro, TypeScript 6, or the TypeScript 7 release candidate (Vite and Vite + Nitro are experimental)
- Linter and formatter — Oxlint / ESLint and Oxfmt / Prettier
- Port — the port the HTTP server will listen on (default:
3000) - Optional features (multiselect) —
- i18n — add
@wolfstar/plugin-i18next - Subcommands — add an example command that uses subcommands
- Testing — set up Vitest with
@wolfstar/http-framework-test-utils - Gateway — receive gateway events next to the HTTP interactions with
@wolfstar/plugin-gateway - Cache — cache gateway entities with
@wolfstar/plugin-cache, in memory or in Redis (asked as a follow-up) - Sharder — spread gateway shards across cluster workers with
@wolfstar/plugin-sharder - Dev tunnel — open a
cloudflaredquick tunnel instars devso Discord reaches the bot on your machine (see Dev tunnel) - Environment schema — describe the environment in a validated, typed varlock
.env.schema(see varlock)
- i18n — add
- Auto-install — install dependencies immediately after scaffolding
Options
Non-interactive / AI agent mode
When the CLI detects an AI agent is running it (via@vercel/detect-agent), it automatically enters non-interactive mode, equivalent to passing --no-interactive. A project name argument is required in this mode:
Generated project structure
src/locales/en-US/commands/ping.jsonandsrc/@types/i18next.d.tsare only generated when i18n is enabled.src/@types/i18next.d.tsis produced by@wolfstar/i18next-type-generator; the CLI runs it automatically at the end of scaffolding, and it can be re-run any time locale files change (seegenerate:i18nbelow).src/commands/math.tsis only generated when Subcommands is enabled.src/lib/cache.tsis only generated with Cache,src/shard.tswith Sharder, andcompose.yamlwith Redis.tests/ping.test.ts,vitest.config.ts, andvitest.setup.tsare only generated when Testing is enabled.AGENTS.mdandllms.txtare always generated. They only describe the features the project was created with. See AI agent files.- With a linter, the generated
.oxlintrc.jsonoreslint.config.mjsenables the rules of@wolfstar/eslint-plugin-http-framework. See Framework lint rules. - In TypeScript projects built with tsdown or Vite,
src/lib/setup/all.tsdoesn’t load the environment itself.starsloads.env(theenvoption instars.config.ts) before any module of the bot runs. Projects built withtsc, Vite + Nitro, or JavaScript still callsetup()from@wolfstar/env-utilities.
TypeScript configuration
TypeScript projects built with tsdown, Vite, or Vite + Nitro are generated forfuture.compatibilityVersion 6. Their
root tsconfig.json is solution-style. It only references the two configs that stars prepare writes to .stars/:
.stars/tsconfig.app.json covers the bot sources, and .stars/tsconfig.node.json covers the config files and scripts
Node runs. See Generated TypeScript configuration.
The postinstall script runs stars prepare, so both files exist after you install dependencies.
These projects also get a typecheck script that runs stars typecheck:
tsc on the root tsconfig.json checks nothing, because it only references .stars/. The generated
README.md and AGENTS.md list the typecheck script. Projects built with tsc6 or tsc7 keep their composite
tsconfig.json and src/tsconfig.json, without a typecheck script.
When you run the CLI again on an existing project, it replaces the root tsconfig.json only when the file is one
the generator wrote: the solution-style file, or the older one that extends ./.stars/tsconfig.json. The CLI
compares the files as JSON, so formatting changes don’t count as edits. It keeps a hand-edited tsconfig.json and
prints a warning. If that file extends ./.stars/tsconfig.json, make it reference the two generated configs instead.
AI agent files
Every project gets two files for AI coding agents:AGENTS.mdlists the project’s commands, its layout, and the framework rules that are easy to get wrong.llms.txtlinks the upstream documentation, grouped by topic.
AGENTS.md or llms.txt, the CLI keeps your version and prints a warning. To get the generated version, delete the file and run the CLI again.
Framework lint rules
When you pick a linter, the CLI adds@wolfstar/eslint-plugin-http-framework to devDependencies and enables its rules. They catch mistakes TypeScript can’t, such as decorator order, raw Discord fetches, and dynamic translation keys.
With ESLint, eslint.config.mjs registers the plugin with its recommended rules:
eslint.config.mjs
.oxlintrc.json loads the plugin through jsPlugins and sets each wolfstar/* rule to error:
.oxlintrc.json
Dev tunnel
Discord sends interactions to a public URL, so a bot running on your machine needs a tunnel while you develop.--tunnel (or the Dev tunnel feature in the prompt) writes dev: { tunnel: true } to stars.config.ts. stars dev then opens a cloudflared quick tunnel at startup.
stars.config.ts
t in stars dev to open a tunnel on demand. See Type checking, tunnel and logs for the other dev.tunnel options.
varlock
--env varlock (or the Environment schema feature in the prompt) sets the project up with varlock, which validates the environment and types it:
.env.schemadeclaresDISCORD_TOKEN,DISCORD_PUBLIC_KEY,DISCORD_CLIENT_ID, the HTTP port,HTTP_POST_PATH, and what the other features need (REDIS_URL,SHARDER_CLUSTERS). The values stay in.env.varlockis added as a dependency.@wolfstar/env-utilitiesloads the schema by itself, because it picks varlock when it finds a.env.schemaand an installedvarlock.src/lib/types/augments.tsderivesEnvfromsrc/@types/env.d.tswithEnvFromVarlockfrom@wolfstar/env-utilities/varlock, instead of declaring each variable by hand. The scaffold ships a stand-insrc/@types/env.d.tsso the project type-checks right away. The schema’s@generateTsTypesdirective makes varlock replace it, with the same shape, whenever it loads the schema (npm run dev, ornpx varlock load).- For
tsdownandviteprojects,stars.config.tsalso getsenv: { loader: 'varlock' }, sostars devandstars doctorread the variables the way the bot does.tsc, JavaScript, and Nitro projects load the environment themselves, so they get the schema and the dependency but noenventry.
src/lib/types/augments.ts
--ignore, without the flag:
- With a
.env.schema(insrc/, the project root, or atvarlock.loadPath), the schema is kept as it is,varlockstays a dependency, andstars.config.tssetsenv.loader. - With only a
varlockdependency,varlockstays a dependency. - A
varlock.loadPathinpackage.jsonis kept.
.env.schema it did not write, with or without --env varlock. With the flag, it keeps the schema, reports it, and leaves Env hand-written, because that schema may not generate types. Rerunning without the flag over a project the generator scaffolded with varlock keeps varlock on. Delete .env.schema to turn it off.
Vite and Nitro
--build vite bundles the bot with Vite into a single dist/main.js. --build vite-nitro hands the bundle to Nitro, which writes a deployable .output/ directory using the node-server preset, pinned in stars.config.ts. Both options are TypeScript only and experimental. They turn on experimental.enableVite (and experimental.enableNitro for vite-nitro) in the generated stars.config.ts.
- A bundle has no
commandsdirectory to scan, sosrc/main.tsimports and loads the example commands explicitly. Add your own commands there. - With Nitro,
src/main.tsdefault-exports the client instead of callinglisten(). The port comes fromPORTin.envinstead ofHTTP_PORT. - The
mainfield andstartscript point to thenode-serverpreset’s output,.output/server/index.mjs. If you changenitro.presetto target another platform, deploy that platform’s.output/instead of runningnpm start. With--gateway, only a preset that keeps a server alive can hold the gateway connection open. - Nitro can’t be combined with
--sharder. The sharder’s manager process has no client for Nitro to forward requests to, so the CLI exits with an error.
Gateway, cache, and sharder
Use the gateway plugins when your bot also needs gateway events in addition to HTTP interactions. They require a long-lived process.--gatewaymakessrc/main.*create aGatewayClient. The bot still answers HTTP interactions.--cacheaddssrc/lib/cache.*, an in-memory cache by default.--redis(or the follow-up prompt) swaps the in-memory cache forioredis. It adds acompose.yamlthat starts a local Redis server, and addsREDIS_URL=redis://localhost:6379to.env.--sharderturnssrc/main.*into the shard manager and addssrc/shard.*, which runs in every cluster worker. Set the number of workers withSHARDER_CLUSTERSin.env(default:2).- Each flag turns on the flags it depends on:
--redisturns on--cache, and--cacheand--sharderboth turn on--gateway. - When the gateway is enabled, the generated
package.jsonsetsengines.nodeto>=24.17.0.
--redis project:
i18n type generation
When i18n is enabled, the generatedpackage.json includes a generate:i18n script that (re)generates src/@types/i18next.d.ts from the JSON files under src/locales/:
Requirements
- Node.js
>=20(>=24.17.0for projects using the gateway)