@wolfstar/create-http-framework
v2.10.0
Published
Create a new WolfStar HTTP Framework bot project
Maintainers
Readme
@wolfstar/create-http-framework
Scaffold a new @wolfstar/http-framework bot in seconds.
Description
A CLI scaffolding tool for creating new WolfStar HTTP Framework bot projects.
Usage
npm create @wolfstar/http-framework@latest my-discord-bot
# or
pnpm create @wolfstar/http-framework my-discord-bot
# or
yarn create @wolfstar/http-framework my-discord-bot
# or
bun create @wolfstar/http-framework my-discord-botThe CLI will guide you through the following prompts:
- 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
- i18n — add
- Auto-install — install dependencies immediately after scaffolding
Options
| Flag | Alias | Description |
| ------------------------------------ | ----- | --------------------------------------------------------------------------- |
| --overwrite | | Overwrite the target directory if it already exists |
| --no-interactive | | Skip all prompts and use defaults / flags |
| --interactive | -i | Force interactive prompts even when an AI agent is detected |
| --package-manager <pm> | | Choose npm, yarn, pnpm, or bun |
| --language <lang> | | Choose TypeScript (ts) or JavaScript (js) |
| --build <tool> | | Choose tsc6, tsc7, tsdown, vite, or vite-nitro for TypeScript |
| --lint <linter> | | Choose none, eslint, or oxlint |
| --format <formatter> | | Choose none, prettier, or oxfmt |
| --port <number> | | Set the HTTP port (default: 3000) |
| --i18n / --no-i18n | | Enable or disable @wolfstar/plugin-i18next scaffolding |
| --subcommands / --no-subcommands | | Enable or disable the example subcommand command |
| --testing / --no-testing | | Enable or disable the Vitest + @wolfstar/http-framework-test-utils setup |
| --gateway / --no-gateway | | Enable or disable @wolfstar/plugin-gateway scaffolding |
| --cache / --no-cache | | Enable or disable @wolfstar/plugin-cache (turns --gateway on) |
| --redis / --no-redis | | Cache in Redis instead of memory (turns --cache on) |
| --sharder / --no-sharder | | Enable or disable @wolfstar/plugin-sharder (turns --gateway on) |
| --tunnel / --no-tunnel | | Open a cloudflared quick tunnel in stars dev (dev.tunnel in the config) |
| --env <loader> | | varlock: scaffold a .env.schema and derive Env from it |
| --install / --no-install | | Enable or disable dependency installation |
| --help | -h | Print usage and exit |
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:
create-http-framework my-discord-bot --no-interactiveGenerated project structure
my-discord-bot/
├── src/
│ ├── commands/
│ │ ├── ping.ts # Example ping command
│ │ └── math.ts # Example command with subcommands (--subcommands)
│ ├── lib/
│ │ ├── setup/
│ │ │ ├── all.ts # Aggregates setup imports
│ │ │ └── logger.ts # Logger configuration
│ │ ├── cache.ts # Gateway entity cache (--cache)
│ │ └── types/
│ │ └── augments.ts # Module augmentations (TypeScript only)
│ ├── locales/
│ │ └── en-US/
│ │ └── commands/
│ │ └── ping.json # Example locale resource (--i18n)
│ ├── @types/
│ │ └── i18next.d.ts # Generated i18next augmentation (--i18n)
│ ├── shard.ts # Gateway client run by each shard worker (--sharder)
│ └── main.ts # Entry point — starts the HTTP server
├── tests/
│ └── ping.test.ts # Example test (--testing)
├── vitest.config.ts # Vitest configuration (--testing)
├── vitest.setup.ts # Vitest setup file (--testing)
├── compose.yaml # Local Redis server (--redis)
├── README.md # Generated project README
├── AGENTS.md # The project's commands, layout and rules, for AI coding agents
├── llms.txt # The upstream documentation by topic, for AI coding agents
├── stars.config.ts # The `stars` CLI configuration (build, dev, tunnel)
├── .env # Environment variables (DISCORD_TOKEN, DISCORD_PUBLIC_KEY)
├── .gitignore
├── package.json
└── tsconfig.jsonsrc/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 and only describe the features the project was created with. When one already exists and is not this generator's own unedited output (you wrote it, or edited it), a rerun leaves it as it is and says so.- With a linter, the generated configuration (
.oxlintrc.jsonoreslint.config.mjs) enables the rules of@wolfstar/eslint-plugin-http-framework: decorator order, raw Discord fetches, dynamic translation keys and the other mistakes TypeScript cannot catch. --tunnel(or the Dev tunnel feature in the prompt) writesdev: { tunnel: true }tostars.config, sostars devopens a cloudflared quick tunnel and Discord reaches the bot on your machine. Without it, presstinstars devto open one on demand.
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 and whatever the other features need (REDIS_URL,SHARDER_CLUSTERS). The values stay in.env.varlockis added as a dependency, and@wolfstar/env-utilitiesloads the schema by itself (it picks varlock when a.env.schemaandvarlockare there).src/lib/types/augments.tsderivesEnvfromsrc/@types/env.d.tswithEnvFromVarlock(from@wolfstar/env-utilities/varlock) instead of declaring each variable by hand. The scaffold ships a stand-in for that file so the project type-checks right away;@generateTsTypesmakes varlock replace it, with the same shape, whenever it loads the schema (npm run dev, ornpx varlock load).- For
tsdownandviteprojectsstars.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. - Running it against a directory that already has a varlock
.env.schema(--ignore) needs no flag: the schema is kept as it is,varlockstays a dependency, andstars.config.tssetsenv.loader. An existing.env.schemathe generator did not write is never replaced, with or without--env varlock; with the flag it is kept and reported, andEnvstays hand-written because that schema may not generate types. Avarlock.loadPathinpackage.jsonis kept. Rerunning without the flag over a project this generator scaffolded with varlock keeps it on; delete.env.schemato turn it off.
Vite and Nitro
--build vite bundles the bot with Vite into a single dist/main.js, and --build vite-nitro hands it to Nitro, which writes a deployable .output/ (the node-server preset, pinned in stars.config.ts). Both are TypeScript only and turn on experimental.enableVite (and enableNitro) 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(), and the port comes fromPORTin.env. mainandstartare wired to thenode-serverpreset's output,.output/server/index.mjs. Changingnitro.presetto target another platform means deploying that platform's.output/instead of runningnpm start— and with--gateway, only a preset that keeps a server alive will hold the gateway connection open.- Nitro cannot be combined with
--sharder: the sharder's manager process has no client for Nitro to forward requests to.
Gateway, cache and sharder
The gateway plugins are for bots that also need gateway events, so they require a long-lived process and Node.js >=24.17.0.
--gatewaymakessrc/main.*create aGatewayClient(it still answers HTTP interactions).--cacheaddssrc/lib/cache.*, an in-memory cache by default.--redis(or the follow-up prompt) swaps it forioredis, adds acompose.yamlto start a local Redis, andREDIS_URLto.env.--sharderturnssrc/main.*into the shard manager and addssrc/shard.*, which runs in every cluster worker (SHARDER_CLUSTERSin.env).--cacheand--sharderswitch--gatewayon, and--redisswitches--cacheon.
i18n type generation
When i18n is enabled, the generated package.json includes a generate:i18n script that (re)generates src/@types/i18next.d.ts from the JSON files under src/locales/:
pnpm generate:i18nThe CLI runs this script automatically once at the end of scaffolding; re-run it manually whenever you add or edit locale keys so the generated types stay in sync.
Requirements
- Node.js
>=20(>=24.17.0for projects using the gateway)
