Agent Skills: Script Commands

Monorepo scripts, package boilerplate, conventions. Use when: "how do I run", "bun run", "build this", "run tests", "typecheck", "create a new package", linting, scaffolding packages.

UncategorizedID: EpicenterHQ/epicenter/monorepo

Repository

EpicenterHQLicense: NOASSERTION
4,678359

Install this agent skill to your local

pnpm dlx add-skill https://github.com/EpicenterHQ/epicenter/tree/HEAD/.agents/skills/monorepo

Skill Files

Browse the full folder contents for monorepo.

Download Skill

Loading file tree…

.agents/skills/monorepo/SKILL.md

Skill Metadata

Name
monorepo
Description
'Monorepo scripts, package boilerplate, conventions. Use when: "how do I run", "bun run", "build this", "run tests", "typecheck", "create a new package", linting, scaffolding packages.'

Script Commands

The monorepo uses consistent script naming conventions.

Commands

| Command | Purpose | When to use | | ------------------ | ---------------------------------------------- | ----------- | | bun format | Fix formatting (biome) | Development | | bun format:check | Check formatting | CI | | bun lint | Fix lint issues (biome) | Development | | bun lint:check | Check lint issues | CI | | bun typecheck | Type checking (tsc, svelte-check, astro check) | Both | | bun test | Run unit tests (*.test.ts only) | Both | | bun bench | Run benchmarks (*.bench.ts; reports, no assertions) | Manual |

Convention

  • No suffix = fix (modifies files)
  • :check suffix = check only (for CI, no modifications)
  • typecheck alone = type checking (separate concern, cannot auto-fix)
  • test runs only *.test.ts; bench runs only *.bench.ts. A file is one or the other : never both. Benchmarks print reports; tests assert.

Dev Scripts

Start apps from the repo root, not by cd-ing into the app. Root bun dev:<app> runs every process the app needs; for apps that talk to the hosted API (tab-manager, honeycrisp, opensidian, vocab, whispering, and the api dashboard), it also starts @epicenter/api on localhost:8787 via bun run --filter. Root bun dev:<app>:ui runs the app's frontend alone when that split exists; for Tauri apps, it maps to the package's dev:web. bun dev:api runs just the backend. Local Books, Local Mail, and Super Chat have their own multi-process flows documented in their READMEs; they have no root dev:* target.

Inside a single package, the conventions are:

Non-Tauri apps use a single dev script that runs the underlying tool directly (vite dev, astro dev, wrangler dev, wxt). Tauri desktop apps (honeycrisp, whispering, matter) have two dev surfaces and name them explicitly: dev launches the desktop shell (aliasing dev:desktop), and dev:web runs Vite alone, which each app's tauri.conf.json invokes as its beforeDevCommand. The suffix convention applies primarily to database commands:

| Script | Meaning | | --- | --- | | dev | The default local workflow. May still require Infisical login for app secrets (e.g. API keys), but only ever talks to local infrastructure at runtime. | | dev:web | Tauri apps: the Vite dev server alone, no desktop shell. Invoked by tauri.conf.json as beforeDevCommand. | | dev:desktop | Tauri apps: launches the native desktop app (tauri dev). dev aliases this. | | db:*:local | Runs against local Postgres. Works without Infisical login. | | db:*:remote | Wraps with infisical run --env=prod. Production data; treat as admin. |

There is no dev:remote. Production data is reached only through :remote db scripts and deploy, never through a development server.

CLI (epicenter)

From the monorepo root, target the local API with bun run cli:local (it sets EPICENTER_API_URL=http://localhost:8787); bun run cli runs from source against the default hosted target.

bun run cli:local auth login
bun run cli:local up -C playground/opensidian-e2e

The full targeting matrix (prod, published binary, per-target token storage) lives in packages/cli/README.md. Keep it there so this section cannot drift.

After Completing Code Changes

Run type checking to verify:

bun typecheck

This runs bun run --filter '*' typecheck which executes the typecheck script in each package (e.g., tsc --noEmit, svelte-check).

New Package Boilerplate

When creating a new package in packages/, follow this exact structure.

package.json

{
  "name": "@epicenter/<package-name>",
  "version": "0.0.1",
  "exports": {
    ".": "./src/index.ts"
  },
  "license": "AGPL-3.0-or-later",
  "scripts": {
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {},
  "devDependencies": {
    "@types/bun": "catalog:",
    "typescript": "catalog:"
  }
}

Key conventions:

  • exports only, no main/types: modern resolvers ignore main/types when exports is present. The entry point is ./src/index.ts; there is no build step, consumers import the source directly.
  • Use "workspace:*" for internal deps (e.g., "@epicenter/workspace": "workspace:*").
  • Use "catalog:" for shared versions managed in the root package.json catalogs.
  • peerDependencies for packages consumers must also install (e.g., yjs).
  • license: default AGPL-3.0-or-later (everything Epicenter ships or runs). Use MIT only if the package is meant for third-party developers to embed in their own software (the toolkit). See docs/licensing/licensing-strategy.md; bun run check:licenses fails if an MIT package can reach an AGPL one.

tsconfig.json

A leaf config picks a tier and adds nothing that repeats a base. For a Bun library:

{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "types": ["bun"],
    "noUnusedLocals": true,
    "noUnusedParameters": true
  }
}

A Svelte or browser library extends ../../tsconfig.dom.json instead. For all eight leaf tiers, the never-redeclare list, and the module strategy, see the tsconfig skill.

After creating the package, run bun install from the repo root to register it in the workspace.