Imported from wolfstar-project/plugins (
AGENTS.md). Install upstream withnpx skills add wolfstar-project/plugins. Copyright stays with the author.
AGENTS.md
Cursor Cloud specific instructions
What this repo is
wolfstar-project/plugins is a pnpm + Turborepo monorepo of publishable TypeScript libraries, under packages/:
@wolfstar/plugin-api— the core REST server (ApiServer).@wolfstar/plugin-i18next— i18next-powered internationalization for HTTP interactions.@wolfstar/plugin-logger— pluggable logger (console, Sentry, and optional consola/evlog/winston adapter subpaths) replacing the framework's built-in console logger.@wolfstar/plugin-subcommands-advanced— modularizes slash subcommands into separate command classes.
There is no runnable app, frontend, backend, dev server, or database. "Running" the project means build / typecheck / lint / test. Consumers embed the libraries into their own @wolfstar/http-framework Discord bot.
Toolchain notes (non-obvious)
mise.tomlpins Node 24 + pnpm 12 (matches CI), but the Cloud VM'snodeisv22.14.0from/exec-daemonand is first onPATH, so it cannot be overridden. Node 22 satisfies the rootengines(^22.11 || ^24 || >=26, raised from>=20by@changesets/cliv3 — the published packages still declare>=20.0.0), and build/test/lint/typecheck all pass on it.pnpmis provided viacorepack(version12.3.1, pinned bypackageManagerinpackage.json). Ifpnpmis ever missing, runcorepack enable.- TypeScript is on the
7.0.2major (bumped from~5.8.3). Typechecking no longer goes throughtsc/turbo run typecheck— see thepnpm typecheckentry below.
Commands (defined in root package.json)
pnpm build—turbo run build(tsdown →dist/esm/, shared options inscripts/tsdown.config.ts).pnpm test—vitest run(unit + in-process HTTP integration tests).pnpm typecheck—golar typecheck && golar tsc --noEmit -p packages/plugin-i18next/tsconfig.consumption.json(config in rootgolar.config.ts; replacedturbo run typecheck/ per-packagetsc --noEmitscripts).golar typecheckglob-checkspackages/*/src/**/*.tsdirectly and does not readtsconfig.json/projectoptions, so it can't resolveplugin-i18next's type-level consumption test (which importsnode:url) — that's why it's checked separately viagolar tsc, a real TypeScript-CLI passthrough, againsttsconfig.consumption.json.pnpm lint/pnpm lint:fix— oxlint + oxfmt.pnpm run docs— runstypedocviascripts/generate-docs.mjs(config in roottypedoc.json); note the explicitrunis required because plainpnpm docsis intercepted by pnpm's built-indocscommand and fails withERR_PNPM_MISSING_PACKAGE_NAME. The wrapper script installs typedoc against an isolatedtypescript@^5.9.3in a throwaway directory instead of this repo'stypescript@7.0.2: typedoc@0.28.20's peer range tops out at 6.0.x and crashes against the experimental TS 7 API, and pnpm has no way to give a single devDependency its own nested peer version. It generates API docs from each package'ssrc/index.tsandsrc/register.tsintoapi/(gitignored). Members marked@internalorprivateare excluded (excludeInternal/excludePrivate), so use that tag deliberately when adding public exports you don't want documented. CI publishes the same output (as JSON) towolfstar-project/docson pushes tomain/v*tags via.github/workflows/documentation.yml.- Turbo's
testtaskdependsOn: ["^build"], so a build is triggered as needed.typecheckis no longer a Turbo task (removed fromturbo.json) — it now runs once at the repo root viagolar, independent of package builds.
Gotchas
pnpm cleanis broken: it runsnode scripts/clean.mjs, but that file does not exist (onlyscripts/tsdown.config.tsis present). Do not rely on it.- Git hooks are active (husky):
pre-commitruns nano-staged (oxfmt +oxlint --fix) andcommit-msgruns commitlint. Commit messages must follow Conventional Commits. - Vitest is not pinned to a specific Vite major anymore (the
pnpm-workspace.yamloverrides forcing Vite 6 were dropped); it currently resolves Vite 6 naturally.vitest.config.tsstill forcesesbuild.tsconfigRaw.compilerOptions.experimentalDecoratorsforplugin-subcommands-advanced's legacy-decorator tests — Vite 8 defaults to oxc, which ignores that esbuild option in favor ofoxc.typescript.decorators, so migrate to that setting before letting Vite resolve past 7. - CI runs on GitHub-hosted runners (
ubuntu-24.04-armforci.ymlandpkg-pr-new.yml,ubuntu-latestforrelease.yml) — not Blacksmith, despite some now-superseded PR history. - When adding a new package, add a matching
packages:<name>entry to both.github/labels.yml(label sync) and.github/labeler.yml(path-based auto-labeling on PRs) — these can drift independently (e.g.plugin-subcommands-advancedcurrently has a label defined but nolabeler.ymlpath mapping, so it's never auto-applied). - Releases publish via CI (
release.yml) using npm trusted publishing (OIDC, no long-lived token) so npm provenance/Sigstore attestation is attached; localchangeset publishcan't mint attestations. See.changeset/README.md. pnpm run publish:snapshot(scripts/publish-snapshot.mjs, run by thesnapshotjob on every push tomaintouchingpackages/) wrapschangeset publishinscripts/run-with-retry.mjs, retrying up to 3 times (20s apart) becausechangeset publishfires one concurrent OIDC token exchange per package and npm intermittently 404s a subset instead of rate-limiting; already-published versions are skipped on retry.pnpm run publish(the tagged-release path, invoked bychangesets/actionviarelease.yml) does not use this retry wrapper yet.- Every push to any branch (see
.github/workflows/pkg-pr-new.yml) builds the packages and publishes preview tarballs to pkg.pr.new viapnpm exec pkg-pr-new publish, so unreleased changes from any branch/PR can be installed directly without waiting for a real release.
Exercising the core functionality (ApiServer)
The library's core is ApiServer, a standalone REST server (default port 4000). To run it end-to-end: pnpm build, then instantiate ApiServer, register the route/middleware stores on container.stores, loadMiddlewares(), loadListeners(), load a Route, container.stores.load(), then server.connect(). See packages/plugin-api/tests/ApiServer.test.ts for the exact pattern.
