Guidelines for AI agents and contributors working in this Turborepo monorepo.
CLAUDE.md is a symlink to this file. Never edit CLAUDE.md directly.
| Name | Filter | Description |
|---|---|---|
| operator | @repo/operator |
Telegram operator Cloudflare Worker (Hono, D1) |
| browser-scraper | @repo/browser-scraper |
Headless-browser scraping Cloudflare Worker |
| alerts | @repo/alerts |
Scheduled market alerts Cloudflare Worker |
| Name | Filter | Description |
|---|---|---|
| alpha-vantage | @repo/alpha-vantage |
Alpha Vantage market data client |
| http-client | @repo/http-client |
Fetch wrapper with Zod response validation |
| logger | @repo/logger |
Structured JSON logger |
| telegram | @repo/telegram |
Telegram Bot API client |
| typescript | @repo/typescript |
Shared tsconfig presets (base, node, react) |
| url-validator | @repo/url-validator |
Safety policy checks for user-supplied URLs |
CI helpers are not workspaces: the composite setup action lives in
.github/actions/setup/ and the gitleaks script in .github/scripts/.
Apps may import packages; packages must never import apps. oxlint bans ../
imports and deep @repo/*/src imports: import other workspaces by package name,
and inside an app use the ~/ alias (src/*) to go up the tree.
Prerequisites: Node.js 24 (exact version in .nvmrc), pnpm 12.12.0 (packageManager in root package.json).
pnpm install # Install all dependencies
pnpm dev # turbo run dev (all workers)
pnpm lint # oxlint, one process over the whole repo
pnpm knip # unused files, exports and dependencies
pnpm typecheck # turbo run typecheck
pnpm test # turbo run test
pnpm build # turbo run build
pnpm format # oxfmt, writes in place
pnpm format:check # oxfmt --check (no writes)
pnpm secrets:scan # gitleaks over the full git history
pnpm clean # turbo run clean
pnpm --filter @repo/operator set-webhook <url> [-- --prod]lint and knip do not go through Turbo — each is a single process over the whole
repo. oxlint is configured by the root .oxlintrc.json (including import/no-cycle)
and prints nothing when there are no findings, so silent output means clean. Knip is
configured by the root knip.jsonc and exits 0 when clean. Formatting is oxfmt
(Prettier-compatible), configured by the root .oxfmtrc.jsonc, which also sorts
imports.
There is no post-edit formatting hook: run pnpm format yourself before committing.
secrets:scan runs gitleaks (.github/scripts/secrets-scan.sh, version pinned
there) using a local gitleaks v8.19+ if one is on PATH, otherwise the pinned Docker image.
It exits 0 when clean and 1 when it finds a leak.
CI checks are defined once, in the reusable .github/workflows/checks.yml: typecheck,
lint, knip, format:check, test, secrets-scan, CodeQL code scanning
(javascript-typescript) and workflow-lint. workflow-lint calls the reusable workflow
from valuecodes/automation: actionlint (with shellcheck) and zizmor over the workflow
and action files. Each tool reads .github/actionlint.yaml / zizmor.yml if added. The
typecheck and test jobs restore Turbo's .turbo cache from the previous run of the same
task, so unchanged packages replay instead of rerunning. Two workflows call it:
feature.yml(PRs) runs the checks and fans them intoall-passed, the one check to require in branch protection.main.yml(push tomain) runs the checks, then thedeployjob deploys the three workers to Cloudflare through theproductionenvironment.
D1 migrations are a separate workflow (migrations.yml): it runs on push to main when
apps/operator/migrations/** changes and does not wait for CI or the deploy.
Dependabot (.github/dependabot.yml) bumps the SHA-pinned actions and reusable workflows
monthly in one grouped PR; npm dependencies are updated by hand.
maintenance-dashboard.yml calls the maintenance dashboard workflow from
valuecodes/automation daily.
It keeps one issue, Maintenance dashboard (label maintenance-dashboard), listing
what is due: catalog: updates, pnpm (packageManager), gitleaks (GITLEAKS_VERSION
in the secrets-scan script), Node.js (.nvmrc) and pnpm audit findings. Like
minimumReleaseAge, a release shows up only once it is 14 days old; a Node.js security
release shows up right away and is flagged. It never opens PRs or commits; doing the
updates stays manual. For a Node.js bump, change only .nvmrc (the one place that
holds the exact version). If GITLEAKS_VERSION moves out of
.github/scripts/secrets-scan.sh, pass the new path as the gitleaks-script input.
The dashboard and workflow-lint callers pin the same valuecodes/automation commit, so
bump them together.
- Keep diffs tight and focused; no drive-by refactors or new tooling without discussion.
- Never commit secrets, credentials,
.env,.dev.varsor.prod.varsfiles. - Add dependencies to the correct workspace with
pnpm --filter <package> add <dep>. Every external version lives in thecatalog:block ofpnpm-workspace.yamland manifests reference it ascatalog:;@repo/*deps stayworkspace:*. Update withpnpm up --latest -r;updateConfig.ignoreDependenciesholds@types/nodeto the.nvmrcmajor, so bump it by hand. - Every install enforces the supply-chain settings in
pnpm-workspace.yaml(minimumReleaseAge,trustPolicy: no-downgrade) plus pnpm 12's defaultblockExoticSubdeps. When one fails, investigate: never disable it, and never exclude a whole package to get past it. - Run
pnpm typecheck,pnpm lint,pnpm knip,pnpm format:checkandpnpm testbefore committing. Update docs when architecture or behavior changes.