denoland/deno
Read `CLAUDE.md`, `tools/x.ts`, `cli/lib.rs`, and `cli/factory.rs` first — those four give you the command surface, the dispatch table, and the service graph. Use `./x` rather than raw cargo: `./x check` for fast feedback, `./x build` for a binary, `./x test-spec <filter>` for integration tests (a filter is mandatory and the runner will panic without one under Claude Code), and `./x verify` (fmt + lint-js) before committing. The repo's conventions are enforced mechanically: dprint formatting, a copyright-header check, generated-workflow freshness, and a clippy `disallowed_methods` list that is why you see `#[allow(clippy::disallowed_methods, reason = "…")]` sprinkled through startup code. Keep diffs minimal and avoid drive-by changes — the CLAUDE.md git workflow says so explicitly, and PRs are squash-merged so never force-push.
- Read first, in order: `CLAUDE.md` (build/test/PR conventions), `tools/x.ts` (the command registry with long help strings), `cli/lib.rs` (`main()` at :863 and `run_subcommand` at :124), `cli/factory.rs` (`CliFactoryServices` at :302), and `runtime/worker.rs` (`common_extensions` at :1199).
- Never run the full spec suite: `tests/specs/mod.rs::main` panics when `CLAUDE_CODE_ENTRYPOINT` is set without a filter — always use `./x test-spec <filter>` or `./x test-spec --list`.
- Pre-commit is `./x fmt` then `./x lint-js` (bundled as `./x verify`) for JS/TS-only changes; if Rust changed, also run `./x lint` (includes clippy) and `./x check`.
- Unit tests must go through cargo, not the built binary: `./x test-unit <filter>` runs `cargo test -p unit_tests --test unit -- <filter>`; `CLAUDE.md` explicitly warns against `./target/debug/deno test` for `tests/unit/`.
- Formatting is dprint-driven with a repo config; do not hand-format. `tools/format.js` runs `npm:dprint@0.47.2 fmt --config .dprint.json`, and `--check` mode is available for verification.
- Every source file needs the copyright header `// Copyright 2018-2026 the Deno authors. MIT license.` — `checkCopyright()` runs as part of `tools/lint.js` whenever both JS and Rust linting are enabled.
- Clippy enforces a disallowed-methods/types list per crate via `clippy.toml` files (present in `cli/`, `runtime/`, `ext/*`, `libs/*`); bypassing one requires an `#[allow(clippy::disallowed_methods, reason = "...")]` with a written reason, as seen around `std::env::current_dir` and `std::env::var_os` in startup.
- Safe edit boundary for new native APIs: add ops inside the relevant `ext/<name>` crate, keep the `common_extensions` position stable, and remember the snapshot files (`runtime/snapshot.rs`, `runtime/snapshot_info.rs`, `runtime/web_worker.rs`) must stay in sync.
- Anything in `.github/workflows/*.generated.yml` is build output — edit the `.ts` sibling and regenerate, or `ensureWorkflowYmlsUpToDate()` in `tools/lint.js` will fail CI.
- Trap: adding a thread earlier in `main()` breaks the safety argument for the startup `env::set_var` calls; the node-shim setup, tunnel init, and `DENO_CONNECTED` assignment all carry comments stating they must run before any thread spawns.
- Trap: large futures overflow the stack on Windows debug builds. `spawn_subcommand` uses `boxed_local()`, several subcommands add explicit `.boxed_local()`, and `Deferred::get_or_try_init_async` documents boxing for the same reason — preserve these when refactoring.
- Git workflow per `CLAUDE.md`: branch off `main`, never force-push to a PR (commits are squashed on merge so incremental commits help reviewers), and keep changes scoped — no drive-by fixes in an unrelated PR.
- PR titles must match `type(scope): description` with types `feat|fix|perf|refactor|chore|docs|test|revert|BREAKING`; `tools/verify_pr_title.js` and the `review-pr` skill both gate on it.
- Debugging aids that already exist: `DENO_STARTUP_PHASES=1` for boot-phase timings, `DENO_LOG=debug` for module-level logging, and `DENO_AUDIT_PERMISSIONS=<file|otel>` to record every permission access.
- When touching Node compatibility, use the repo's own workflow: `./x test-compat <filter>` runs `cargo test --test node_compat`, and `.claude/skills/node-compat/SKILL.md` documents the fix/skip/ignore decision procedure.