Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Deno Administrator & Developer Guide

Generated May 2026 from denoland/deno at 7529c84

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is the operator-and-developer reference for the Deno runtime: how it is built, how the source is organized, how to deploy and operate it, what its security model guarantees, and how to extend or contribute to it. Every fact is taken from the source tree at commit 7529c84 (Deno CLI version 2.7.12).


1. Executive Summary

Deno is a JavaScript / TypeScript / WebAssembly runtime distributed as a single self-contained binary. The codebase is a 70+ crate Rust workspace combining V8 (the JavaScript engine), Tokio (the async runtime), and a substantial set of in-house Rust crates that implement Web APIs, Node compatibility, the package management system, the language tooling, and the editor language server. The whole binary statically links V8.

Top-level facts:

Item Value
License MIT
Primary languages Rust, TypeScript, JavaScript
Build system Cargo workspace (resolver = "2")
Edition Rust 2024
JavaScript engine V8 (v8 crate, currently v147.x)
Async runtime Tokio
TypeScript transpiler deno_ast (SWC-based) + deno_typescript_go_client (TypeScript-Go for type-checking)
Distribution Single-binary releases for 5 target triples; install scripts; brew/winget/scoop/chocolatey
Workspace member count ~70 (cli, runtime, ext/, libs/, tests/*)
CLI subcommand count 38 (see Subcommand Architecture below)
Permission categories 9 (read, write, net, env, sys, run, ffi, hrtime, import + all/scripts)
Documented env vars 26 (see Environment Variables in User Guide)
Web platform extensions (ext/) 32 crates
Shared library crates (libs/) 24 crates

The Deno CLI binary (cli/main.rs) is just deno::main() — a thin wrapper that calls into the deno library crate (cli/lib.rs). Everything else is layered crates.

Note

This guide focuses on the project as it is checked in. Deno Deploy (the hosted runtime) is a separate product and is treated here only as a destination for deno deploy.


2. Architecture

2.1 Layered Architecture

+----------------------------------------------------------------------+
|                            cli/ (binary)                             |
|  CLI parsing (clap), tools/* (run, fmt, lint, test, compile, ...),   |
|  factory wiring, LSP, type-checker driver                            |
+----------------------------------------------------------------------+
|                    runtime/ (deno_runtime crate)                     |
|  MainWorker, WebWorker, Deno.* namespace, permissions enforcement,   |
|  bootstrap JS, integrates ext/* into a JsRuntime                     |
+----------------------------------------------------------------------+
|     ext/ (32 crates: web/fetch/net/http/fs/crypto/node/webgpu/...)   |
|  Each crate contributes ops + JS/TS bindings for one Web API or      |
|  Node compatibility surface; loaded as deno_core::Extension          |
+----------------------------------------------------------------------+
|                    libs/core/ (deno_core crate)                      |
|  JsRuntime, ExtensionBuilder, op2 macro, ModuleLoader, snapshotting, |
|  the ops bridge between JS and Rust                                  |
+----------------------------------------------------------------------+
|                              v8 crate                                |
|  Rust bindings to the V8 JavaScript engine (statically linked)       |
+----------------------------------------------------------------------+

Below the engine, Tokio drives all async I/O. Above the CLI, no other layers exist — the binary IS the user interface.

2.2 Component Inventory

cli/ — the user-facing binary

Module Purpose
main.rs Entry point. Calls deno::main().
lib.rs Top-level orchestration: parse flags, build CliFactory, dispatch to subcommand tools.
args/flags.rs Clap definitions for every subcommand and flag (~15 KLOC). The single source of truth for the CLI surface.
args/mod.rs CliOptions, CliLockfile, env-var resolution, config file discovery.
factory.rs CliFactory — lazy DI container that builds the resolver, module loader, npm installer, type checker, etc. on demand.
tools/ One module per subcommand: run.rs, serve.rs, task.rs, repl.rs, compile/, bundle/, bench.rs, lint/, init.rs, installer.rs, jupyter.rs, pm.rs (add/remove/install/outdated), publish/.
lsp/ The deno lsp language server (Tower-LSP).
tsc/ TypeScript compiler integration (TS-Go IPC + the legacy deno_tsc wrapper).
module_loader.rs Implements deno_core::ModuleLoader for the CLI: handles JSR / npm / HTTPS / file URLs.
npm.rs, node.rs, jsr.rs Per-scheme resolvers built atop the libs/resolver crate.
cache/ Disk caches (deps, type-check, emit, npm, codecov).
worker.rs Constructs the LibMainWorkerFactory from deno_lib.
standalone/ Loader for deno compile binaries (reads the eszip appended to the executable).
rt/ denort runtime variant — minimal CLI used inside compiled binaries.

runtime/ — the embeddable runtime (deno_runtime crate)

Item Purpose
worker.rs MainWorker — the foreground JS worker. Wraps JsRuntime, sets up the Deno namespace, runs bootstrap JS.
web_worker.rs WebWorker — implements the standard Worker Web API in a dedicated OS thread.
worker_bootstrap.rs The Rust side of the bootstrap (passes runtime metadata to JS).
js/ Bootstrap JavaScript files (99_main.js, etc.) executed before user code to construct the Deno namespace.
permissions.rs, permissions/ deno_permissions integration: parsing flags, enforcing checks for ops.
ops/ Ops registered directly by the runtime (FS metadata, OS info hooks).
cpu_profiler/ V8 CPU profiler integration.
subprocess_windows/ Windows-specific subprocess infrastructure (CreateProcessW wrapper).
transpile.rs Optional in-runtime TS→JS transpilation (HMR, REPL).
snapshot.rs Build-time and load-time V8 snapshot machinery.

The runtime/README.md notes that this crate is deliberately a slimmed-down version of the CLI: it omits TypeScript type-checking, the doc/lint/fmt tools, and CLI argument parsing — it provides only "JavaScript execution with Deno's operating system bindings (ops)." Third parties embed this crate to get a Deno-compatible MainWorker without dragging in the whole cli/.

ext/ — Web platform and Node compatibility extensions (32 crates)

Each ext/<name> crate contributes ops + JS bindings for one Web API surface (or Node-compatibility surface). They are loaded as deno_core::Extension instances when the JsRuntime is built.

Crate Surface
ext/web DOM-style globals: URL, URLSearchParams, TextEncoder, TextDecoder, Blob, File, FileReader, EventTarget, Event, MessageEvent, AbortController, AbortSignal, structured-clone, performance timeline, queueMicrotask.
ext/console The console global.
ext/url URL/URLSearchParams (separate so ext/web can compose).
ext/webidl IDL conversion helpers used by other ext crates.
ext/fetch fetch, Request, Response, Headers, Body. Backed by reqwest/hyper.
ext/net Deno.connect, Deno.listen, TCP/UDP/Unix sockets.
ext/tls TLS configuration shared between fetch and net.
ext/http The Hyper-based HTTP server backing Deno.serve.
ext/websocket WebSocket client and server.
ext/webstorage localStorage / sessionStorage (SQLite-backed).
ext/broadcast_channel BroadcastChannel Web API.
ext/crypto Web Crypto API (crypto.subtle).
ext/fs Filesystem ops (Deno.readFile, Deno.writeFile, etc.).
ext/io Stream IO primitives.
ext/cache Web Cache API.
ext/cron Deno.cron (unstable).
ext/kv Deno.openKv (unstable, SQLite-backed locally).
ext/os OS info / Deno.osRelease, Deno.hostname, etc.
ext/process Deno.Command, Deno.spawn.
ext/signals Signal handling (Deno.addSignalListener).
ext/ffi Deno.dlopen (foreign-function interface).
ext/napi, ext/napi/sym N-API for native Node addons.
ext/node Node compatibility — node:fs, node:http, node:buffer, etc. polyfills + ops. The largest single ext crate.
ext/node_crypto Node crypto module (separated for size).
ext/node_sqlite Node sqlite built-in.
ext/image Image decode (powers createImageBitmap).
ext/webgpu WebGPU.
ext/telemetry OpenTelemetry tracing/metrics for the runtime.
ext/bundle Bundling APIs (powers deno bundle).
ext/rt_helper Internal helpers for denort (compiled-binary runtime).

The naming convention is consistent: ext/<name>/lib.rs defines an Extension via deno_core::Extension::builder(); ext/<name>/<name>.js (or .ts) is the JS portion; ops are written in Rust with the #[op2] macro from libs/ops.

libs/ — shared library crates (24 crates)

These are the crates that the CLI and the runtime depend on. Several are also published independently to crates.io (deno_core, deno_ast, deno_lockfile, etc.).

Crate Purpose
libs/core deno_core — the JsRuntime, op infrastructure, snapshotting, the ModuleLoader trait. The foundation of everything.
libs/core_testing, libs/core/examples, libs/core/io, libs/core/arena, libs/core/runtime, libs/core/modules deno_core sub-modules and helpers.
libs/ops, libs/ops/op2, libs/ops/conversion, libs/ops/webidl, libs/ops/compile_test_runner The op2! proc-macro and op-definition machinery used by every ext/ crate.
libs/serde_v8, libs/serde_v8/magic, libs/serde_v8/utilities, libs/serde_v8/examples Zero-copy serialization between V8 values and Rust types.
libs/resolver, libs/resolver/loader, libs/resolver/cache, libs/resolver/cjs, libs/resolver/npm Module resolution: deno.json discovery, import map application, JSR / npm / file resolution.
libs/config, libs/config/deno_json, libs/config/workspace, libs/config/glob Parses and validates deno.json[c], manages workspaces, resolves include/exclude globs.
libs/lockfile deno.lock parsing, integrity checking, and rewriting.
libs/cache_dir, libs/cache_dir/global, libs/cache_dir/file_fetcher The $DENO_DIR cache implementation (deps, npm, type-check, emit).
libs/npm, libs/npm/resolution, libs/npm/examples npm package resolution and metadata.
libs/npm_cache Disk caching of npm packages.
libs/npm_installer Installs packages into node_modules/ (when --node-modules-dir=auto).
libs/npmrc .npmrc parser for registry/auth config.
libs/node_resolver Implements Node's resolution algorithm (extensionless imports, package.json exports/imports).
libs/node_shim Provides Node-compatible globals where necessary.
libs/package_json package.json parsing.
libs/dotenv .env file loader.
libs/dcore, libs/dcore/src Lower-level deno helpers shared between cli and runtime.
libs/eszip, libs/eszip/examples The eszip format used by deno compile and the bundler.
libs/inspector_server Standalone V8 inspector server.
libs/typescript_go_client, libs/typescript_go_client/src Rust client that talks to TypeScript-Go (the Go-based TS type checker bundled with the CLI).
libs/crypto Crypto helpers shared by ext/crypto and ext/node_crypto.
libs/maybe_sync Cross-thread synchronization helpers.
libs/napi_sys, libs/napi_sys/src Low-level N-API definitions.

tests/ — integration test infrastructure

Folder Purpose
tests/integration The Rust-side integration test runner used by cargo test.
tests/specs The spec-based "files in directory = one test" suite (~5000+ specs). Each spec has a __test__.jsonc describing args, env, expected stdout/stderr/exit.
tests/unit, tests/unit_node JS/TS unit tests run inside Deno itself.
tests/wpt Web Platform Tests subset.
tests/napi N-API addon test programs.
tests/ffi, tests/sqlite_extension FFI and sqlite-extension test addons.
tests/bench Microbenchmarks.
tests/registry Local mock JSR/npm registry used by tests.
tests/util/server, tests/util/lib Test HTTP servers and helpers.
tests/node_compat Subset of upstream Node tests run for compatibility coverage.

2.3 Request Lifecycle: deno run main.ts

$ deno run --allow-net main.ts
        |
        v
cli/main.rs::main()  --> deno::main() (cli/lib.rs)
        |
        v
flags_from_vec_with_initial_cwd(args)   parses clap, returns Flags struct
        |
        v
CliFactory::from_flags(flags)           lazy DI container
        |
        v
factory.create_main_worker_factory()    builds LibMainWorkerFactory
        |   - Resolves deno.json (if present)
        |   - Builds module loader (handles file://, https://, jsr:, npm:, node:)
        |   - Builds permission set from flags + deno.json
        |   - Builds NPM installer if needed
        |
        v
worker.create_main_worker(...)          MainWorker (deno_runtime)
        |   - Constructs JsRuntime (deno_core)
        |   - Loads all ext/* extensions (web, fetch, net, http, fs, crypto, node, ...)
        |   - Snapshot is loaded if available, otherwise extensions are bootstrapped fresh
        |   - Runs runtime/js/99_main.js to set up the Deno namespace
        |   - Applies bootstrap options (args, location, runtime version)
        |
        v
main_worker.execute_main_module(specifier)
        |   - Module loader fetches main.ts (from disk)
        |   - If TS/TSX, deno_ast transpiles to JS (cached in $DENO_DIR/gen)
        |   - JsRuntime instantiates and evaluates the module graph
        |   - Top-level await is awaited
        |
        v
main_worker.run_event_loop(false)       drives Tokio + V8 microtasks until idle
        |
        v
Process exits with main_worker.exit_code()

The same orchestration drives every executed-script subcommand (run, serve, test, bench, eval, repl, task). Each builds slightly different WorkerOptions and may register additional setup (test runner installs Deno.test, REPL installs the REPL state, etc.).

2.4 Subcommand Architecture

Every subcommand has:

  1. A clap Command::new(...) builder in cli/args/flags.rs (lines 2219+, one fn <cmd>_subcommand() per subcommand).
  2. A <cmd>_parse(...) function (also in flags.rs) that consumes the parsed ArgMatches and writes into Flags.
  3. A handler in cli/tools/<cmd>.rs (or cli/tools/<cmd>/mod.rs for multi-file subcommands).

The 38 subcommands defined in the root command (flags.rs:2140-2179):

Group Subcommands
Execution run, serve, task, repl, eval
Dependency mgmt add, install, uninstall, outdated, approve-scripts, remove, update
Tooling bench, bundle, cache, check, clean, compile, coverage, doc, fmt, info, init, create, jupyter, lint, test, publish, vendor
Cloud / sandbox deploy, sandbox
Lifecycle upgrade, lsp, types, completions
Aliases / hidden x (alias for npm:), json_reference (hidden, used for docs site generation)

Aliases: When the CLI is invoked as dx, denox, or dnx, flags_from_vec_with_initial_cwd rewrites the args to insert x as the first argument (flags.rs:1697-1711). This makes dx eslint . equivalent to deno x eslint . (which itself is deno run npm:eslint .).

2.5 The op2 Bridge: How JS Calls Rust

Every Deno API that does I/O goes through an op — an asynchronous or synchronous function defined in Rust and exposed to JS through V8 fast-call bindings.

// ext/fs/lib.rs (illustrative)
#[op2(async)]
async fn op_read_file_async(
  #[state] state: &PermissionsContainer,
  #[string] path: String,
) -> Result<Vec<u8>, AnyError> {
  state.check_read(Path::new(&path), "Deno.readFile()")?;
  tokio::fs::read(path).await.map_err(Into::into)
}

The #[op2] macro generates V8 fast-call entry points and serde_v8 bindings. The op is registered with an Extension:

deno_core::extension!(
  deno_fs,
  deps = [deno_web, deno_io],
  ops = [op_read_file_async, op_write_file_async, ...],
  esm_entry_point = "ext:deno_fs/30_fs.js",
  esm = ["30_fs.js"],
  options = { fs: Arc<dyn FileSystem> },
);

When the CLI builds a JsRuntime, it passes a list of these extensions. At snapshot time, the JS portions are evaluated and snapshotted. At runtime, only the Rust ops + any non-snapshotted extensions remain to load.

2.6 Snapshotting

Building the binary involves a build-time JavaScript snapshot: all bootstrap JS for deno_core + every ext/* is parsed and serialized into a binary blob that ships inside the executable. At startup, V8 deserializes the snapshot, skipping the cost of parsing and evaluating ~2 MB of JS. The cli Cargo.toml enables include_js_files_for_snapshotting only on its build-dependencies, so the snapshot is generated by build.rs and the embedded blob is the only JS that ships.

Disable with the hmr Cargo feature for development: this drops the snapshot and reloads JS from disk, which is slower but allows live editing.


3. System Requirements

3.1 Runtime requirements (running deno)

Resource Minimum Notes
OS Linux 4.18+, macOS 11+, Windows 10+ x86_64 and ARM64 supported on Linux/macOS; x86_64 only on Windows
RAM 64 MB free V8 baseline; real apps need more
Disk ~150 MB for binary + cache headroom in $DENO_DIR deno compile outputs are 80–100 MB each
libc (Linux) glibc 2.28+ Pre-built binaries are linked against glibc; for older systems build from source or use musl

The pre-built binary is statically linked against V8 and the bundled C++ runtime; it does not depend on any system JS engine.

3.2 Build requirements (building from source)

Tool Why
Rust toolchain pinned in rust-toolchain.toml The workspace requires a specific channel
Python 3 V8 build scripts
C++ toolchain (clang preferred; MSVC on Windows; gcc supported) Compiles V8
protoc Some workspace crates use Protocol Buffers
Git Source control; builds use git revision metadata
~10 GB free disk V8 build artefacts
8 GB+ RAM Linker memory pressure on V8

V8 itself may compile for 30+ minutes on first build. Subsequent incremental builds are minutes.

3.3 Platform targets supported by deno compile

Target OS / arch
x86_64-unknown-linux-gnu Linux x86_64
aarch64-unknown-linux-gnu Linux ARM64
x86_64-pc-windows-msvc Windows x86_64
x86_64-apple-darwin macOS Intel
aarch64-apple-darwin macOS Apple Silicon

Cross-compile by passing --target to deno compile. The denort runtime for the target is downloaded and cached automatically on first use.


4. Configuration Mastery

4.1 Configuration Discovery Order

Deno resolves configuration in this order (highest to lowest precedence):

  1. Command-line flags (--config, --lock, --import-map, --allow-*).
  2. Environment variables (DENO_DIR, DENO_NO_PACKAGE_JSON, etc.).
  3. Per-task --env-file if specified.
  4. deno.json / deno.jsonc discovered by walking from --initial-cwd (or the current working directory) upward.
  5. package.json discovered the same way (when not disabled by DENO_NO_PACKAGE_JSON).
  6. Built-in defaults.

Use --no-config to disable deno.json discovery entirely; --config=path to pin a specific file.

Important

In workspace setups, each member's deno.json inherits the root imports map but can override individual specifiers. Task definitions do not inherit — each member must declare its own tasks.

4.2 The deno.json Schema

The full JSON schema is cli/schemas/config-file.v1.json (~600 lines). The top-level keys, exhaustively:

Key Type Purpose
name string Package name (for JSR publish)
version string Package version (semver)
exports string | object Module entry point(s)
imports object Bare specifier → URL/spec mapping
scopes object Per-prefix import map overrides
tasks object Named scripts for deno task
fmt object Formatter settings
lint object Linter settings
test object Test discovery and runner settings
bench object Benchmark discovery and runner settings
compilerOptions object TypeScript compiler options (subset of tsc)
compile object deno compile defaults: include, exclude, permissions
permissions object Named permissionSets reusable across commands
allowScripts boolean | array | object npm lifecycle script policy
nodeModulesDir "auto" | "manual" | "none" node_modules/ strategy
unstable array of strings Enable unstable feature flags
workspace array of strings Member directories for monorepos
lock string | boolean Lockfile path or false to disable
vendor string Vendor directory for deno vendor
license string SPDX license identifier
publish object include / exclude for JSR publish
links array Local development links (workspace siblings via path)

permissionSet schema (excerpt)

"permissionSet": {
  "all": boolean,
  "read":   true | false | string[] | { allow: ..., deny: ..., ignore: ... },
  "write":  true | false | string[] | { allow: ..., deny: ... },
  "import": true | false | string[] | { allow: ..., deny: ... },
  "env":    true | false | string[] | { allow: ..., deny: ..., ignore: ... },
  "net":    true | false | string[] | { allow: ..., deny: ... },
  "run":    true | false | string[] | { allow: ..., deny: ... },
  "ffi":    true | false | string[] | { allow: ..., deny: ... },
  "sys":    true | false | string[] | { allow: ..., deny: ... }
}

The asymmetry — only read, env, sys accept the ignore key — reflects which categories support being silently no-op'd vs. denied.

4.3 Workspace (Monorepo) Configuration

A root deno.json declares workspace:

{ "workspace": ["./packages/core", "./packages/cli", "./packages/web"] }

Each member has its own deno.json with name / version / exports. Commands operate over the full workspace:

Behavior Detail
deno test Runs tests in every member
deno fmt / deno lint Operates on every member
deno publish Publishes every member to JSR
--filter <pattern> Restrict to matching member names
imports resolution Workspace members resolve each other by their name automatically

libs/config/workspace implements discovery and member resolution.

4.4 Lockfile (deno.lock)

libs/lockfile defines the format. Top-level keys:

Key Purpose
version Lockfile schema version (currently 4)
specifiers Map of jsr: / npm: specifier → resolved version
jsr Per-package integrity hashes
npm npm dependency graph with integrity, dist tarball URL, dependencies
redirects Recorded HTTP redirects for stable resolution
remote Integrity hashes for https:// imports
workspace Per-workspace-member resolved deps

Pass --frozen to fail when the lockfile would change (CI default for reproducible builds). --no-lock disables lockfile use entirely.

4.5 compilerOptions — TypeScript Settings

A subset of tsconfig.json. Notable supported keys:

strict, strictNullChecks, noImplicitAny, noFallthroughCasesInSwitch, noImplicitOverride, noImplicitThis, noUnusedLocals, noUnusedParameters, useDefineForClassFields, experimentalDecorators, emitDecoratorMetadata, lib, jsx, jsxFactory, jsxFragmentFactory, jsxImportSource, jsxImportSourceTypes, target, types, checkJs, allowJs.

Notably not supported: outDir, rootDir, module, moduleResolution, paths, baseUrl — Deno controls module resolution itself via imports / scopes.

compilerOptions.lib defaults are derived from the unstable flags. With no flags, ["deno.window"] is used. Adding "dom" enables browser globals; "deno.unstable" adds typings for unstable APIs.

4.6 Environment Variable Precedence

Some env vars have CLI flag equivalents. Where both are set:

Env var CLI override Winner
DENO_DIR none env
DENO_INSTALL_ROOT deno install --root=PATH CLI
DENO_COVERAGE_DIR --coverage=DIR CLI
DENO_NO_UPDATE_CHECK none env
DENO_AUTH_TOKENS none env
DENO_CERT none env (combined with system store via DENO_TLS_CA_STORE)
HTTP_PROXY / HTTPS_PROXY none env
NO_COLOR none env
FORCE_COLOR none env (overrides NO_COLOR if both set)

Full list of supported env vars: see User Guide Section 7 (sourced from cli/args/flags.rs:1452-1591).


5. Security

5.1 Threat Model

Deno's primary security posture is to make a script safe for the user to run, not to make the host machine safe for the user. Untrusted code runs inside the V8 sandbox and can only escape via Deno-controlled ops, all of which are gated by the permission system. Secondary properties:

  • The V8 process is the security boundary; there is no in-process privilege separation.
  • Permissions are checked at op-call time, not at module-load time. A malicious module loaded with --allow-net can still attempt FS reads — the check fires when it tries.
  • Permissions cannot be widened at runtime. They can only be narrowed via --deny-* or via Deno.permissions.revoke().
  • The permission prompt is interactive and bypassable in CI by --no-prompt.

5.2 Permission Model Internals

runtime/permissions/lib.rs defines PermissionsContainer, the central state for a worker. Each permission category is a struct (e.g. UnaryPermission<NetDescriptor>) holding allow-list, deny-list, ignore-list, and prompted state.

Op call flow:

  1. The op extracts &PermissionsContainer from the OpState.
  2. It calls a typed check method, e.g. state.check_net(&host, port, "Deno.connect").
  3. The check evaluates: deny list → prompted-deny → granted-allow → allow-list → prompted-allow → prompt user (or deny if --no-prompt).
  4. On allow, the op proceeds; on deny, it returns PermissionDenied to JS.

is_allow_all() short-circuits to true when --allow-all was used. Without -A, every op call goes through the full check.

Warning

Permissions are checked at op-call time, not at module-load time. A module imported with --allow-net can still attempt file system reads — the denial fires only when the syscall-level op is invoked. Always apply the principle of least privilege.

5.3 Known Security Considerations

Area Note
--allow-import Required to fetch new remote modules. Without it, only cached modules can be imported. This is a meaningful supply-chain control.
--allow-net=* / bare --allow-net Grants all hosts. Always pass an allow-list in production.
Permission grants in deno compile Baked into the binary; cannot be widened. Reduces attack surface for shipped binaries.
npm lifecycle scripts Disabled by default (allowScripts: false). Approve explicitly via deno approve-scripts or deno install --allow-scripts=npm:foo.
FFI (--allow-ffi) Loads arbitrary dynamic libraries; equivalent to running native code. Treat as --allow-all.
Subprocess (--allow-run) Spawned children inherit no Deno permissions but full OS capabilities of the parent process. The child is outside Deno's sandbox.
HTTPS module integrity Lockfile records hashes; --frozen fails on mismatch.
DENO_TRACE_PERMISSIONS=1 Adds stack traces to prompts. Useful for debugging supply-chain issues.

5.4 Hardening Recommendations

  • Use --no-prompt in CI and in production binaries to convert silent denials into errors.
  • Use --allow-net= with explicit hosts; never bare --allow-net.
  • Use --allow-read= and --allow-write= with explicit paths.
  • Set unstable only to the features actually needed; do not blanket-enable.
  • Pin Deno versions in CI (actions/setup-deno@vN with deno-version: vX.Y.Z).
  • Commit deno.lock and run deno install --frozen (or rely on the --frozen default in CI mode).
  • Use DENO_NO_UPDATE_CHECK=1 in air-gapped environments.
  • For network apps, run behind a reverse proxy and set DENO_TRUST_PROXY_HEADERS=1 only when the proxy is trusted to set the client address.
  • Approve npm lifecycle scripts package-by-package, never globally.

Caution

--allow-ffi loads arbitrary native dynamic libraries, effectively granting the same capabilities as --allow-all. Treat any FFI usage as a full trust boundary escape.


6. Operations and Maintenance

6.1 Cache Layout ($DENO_DIR)

Default path: $HOME/.cache/deno (Linux), $HOME/Library/Caches/deno (macOS), %LOCALAPPDATA%\deno (Windows). Override with DENO_DIR.

$DENO_DIR/
  deps/                 HTTPS module cache (URL → file)
  npm/                  npm package cache (registry → tarball)
  registries/           jsr:/npm: metadata cache
  gen/                  Transpiled JS for TS modules (keyed by source hash)
  check/                Type-check artefacts and diagnostics cache
  emit/                 Emit cache (build outputs)
  binary/               Downloaded denort runtimes for `deno compile --target`
  binary_versions.json  Tracker for downloaded denort versions
  kv/                   Default storage for Deno.openKv() (SQLite files)
  webcache/             Web Cache API storage
  webstorage/           localStorage / sessionStorage SQLite files
  repl.log              REPL history (override with DENO_REPL_HISTORY)
  upgrade_check/        Last-update-check timestamp

deno clean removes the entire $DENO_DIR. To selectively reload, use --reload[=URL].

Tip

Set DENO_DIR to a shared network path for team-wide cache sharing. The cache is content-addressed and safe for concurrent access from multiple Deno processes.

6.2 Logging

Deno respects RUST_LOG (Rust env_logger syntax):

RUST_LOG=info deno run main.ts
RUST_LOG=deno=debug,deno_runtime=trace deno run main.ts
RUST_LOG=deno_core::module_loader=trace deno run main.ts

Useful target prefixes: deno, deno_runtime, deno_core, deno_npm, deno_resolver, deno_lsp, tokio. Combine with DENO_TRACE_PERMISSIONS=1 to debug permission issues.

6.3 Monitoring (OpenTelemetry)

ext/telemetry exposes the runtime via OpenTelemetry. Configure with standard OTel env vars:

Var Purpose
OTEL_DENO_TRACING true/false to toggle tracing
OTEL_DENO_METRICS true/false to toggle metrics
OTEL_DENO_CONSOLE ignore / capture / replace — controls console.* trace export
DENO_UNSTABLE_OTEL_DETERMINISTIC Integer seed for deterministic span IDs (testing)
Standard OTEL_EXPORTER_OTLP_* Endpoint, headers, etc.

The runtime exports HTTP request spans, op spans, and JS-emitted spans (when user code uses @opentelemetry/api).

Note

OpenTelemetry support requires --unstable-otel or adding "otel" to the unstable array in deno.json. Without this flag, the OTEL_* environment variables are ignored.

6.4 Inspector and Debugging

deno run --inspect main.ts                # listen on 127.0.0.1:9229
deno run --inspect-brk main.ts            # break before user code
deno run --inspect-wait main.ts           # wait for debugger to attach
deno run --inspect=0.0.0.0:9229 main.ts   # listen on all interfaces (BE CAREFUL)

Open chrome://inspect in Chrome to attach. The inspector speaks the standard V8 Debugger Protocol.

The standalone inspector server (libs/inspector_server) is also used by deno lsp for IDE debugging integration.

Warning

Never expose the inspector on 0.0.0.0 in production. The V8 inspector protocol allows arbitrary code execution — an attacker with network access to the inspector port gains full control of the process.

6.5 Upgrade and Rollback

deno upgrade                # latest stable
deno upgrade canary         # canary
deno upgrade <version>      # specific version
deno upgrade --output PATH  # specify output binary path
deno upgrade --dry-run      # show what would happen, don't change anything
deno upgrade --force        # overwrite when target version equals current

The upgrade subcommand downloads from https://github.com/denoland/deno/releases, verifies the SHA256, and atomically replaces the binary. To roll back to a known version: deno upgrade <previous-version>. There is no built-in version manager; for multi-version coexistence use a tool like dvm or install side-by-side via different DENO_INSTALL_ROOT directories.

6.6 Cron and Long-Running Servers

For production HTTP servers using Deno.serve:

  • Run with --parallel to spawn one worker per CPU.
  • Use a process supervisor (systemd, supervisord, Docker restart policies) — Deno does not daemonize.
  • For Linux, set DENO_USR2_MEMORY_TRIM=1 to allow SIGUSR2 to free memory.
  • Use DENO_USE_CGROUPS=1 so V8's heap limit reflects container memory limits, not host RAM.

For scheduled work: Deno.cron("name", "* * * * *", handler) (requires --unstable-cron). State for cron is stored in Deno KV.

6.7 Backup

Item Backup target
Deno KV data $DENO_DIR/kv/*.db (SQLite) — copy with KV closed, or use SQLite .backup
Web storage $DENO_DIR/webstorage/
Web cache $DENO_DIR/webcache/
deno.lock Always commit to source control

The dependency cache (deps/, npm/) is reproducible from deno.lock + network and does not need backup.

6.8 Deployment Topologies

Single-process: a deno serve instance behind nginx/Caddy. Set --port, --host=127.0.0.1, and proxy.

Multi-process: spawn N instances bound to different ports, load-balance with the proxy. Deno does not provide cluster-mode; use OS-level process management.

Single-binary deployment: deno compile -A --output app main.ts produces a self-contained executable. Ship it directly. The binary embeds the runtime, so the target machine needs no Deno installation.

Container: denoland/deno:latest is the official image. For minimal images, use gcr.io/distroless/cc and copy a deno compiled binary in.


7. Build and Distribution

7.1 Cargo Workspace

Root Cargo.toml declares the workspace with resolver = "2" and lists all 70+ members. Workspace-level package metadata (authors, edition, license, repository) is inherited by all crates. Workspace-level dependencies pin every external dependency version once and inject path = "./..." for internal crates so they are always built from source.

Build the binary:

cargo build --release -p deno
./target/release/deno --version

Build with debug symbols and dhat heap profiling:

cargo build --profile=release-with-debug --features=dhat-heap -p deno

Build the slim runtime crate alone (for embedding):

cargo build -p deno_runtime

7.2 Cargo Features (cli crate)

Feature Default Purpose
upgrade yes Enables deno upgrade and the background update check. Disabled by Linux distros that ship Deno as a system package.
__vendored_zlib_ng yes Vendor zlib as zlib-ng for performance.
dhat-heap no Enables dhat heap profiling.
hmr no Disables snapshot loading; re-evaluates JS sources on every run for live editing.
lsp-tracing no Adds tracing/OpenTelemetry instrumentation to deno lsp.
panic-trace no Custom panic backtrace via deno_panic.

7.3 Build-Time Snapshot

cli/build.rs builds a V8 startup snapshot. The snapshot embeds:

  • deno_core infrastructure JS
  • All ext/* JS bootstrap code (each Extension contributes its esm files at snapshot time)
  • runtime/js/99_main.js — the Deno namespace setup

Without snapshotting, startup parses ~2 MB of JS on every invocation. With it, V8 mmap-loads a binary blob and starts in milliseconds.

cli/snapshot/ holds the persisted snapshot artifacts pulled into the binary by include_bytes!.

7.4 Release Process

  1. Tag a commit with vX.Y.Z on main.
  2. CI (GitHub Actions) builds binaries for all 5 target triples.
  3. Each binary is signed and uploaded to a GitHub Release.
  4. The install scripts (install.sh, install.ps1) detect the latest release and download the appropriate binary.
  5. deno upgrade queries the same GitHub Releases API.

Releases.md in the repo root is the canonical changelog.

7.5 Dependency Management for the Workspace

External dependencies are pinned in the root [workspace.dependencies] block. Internal deno crates use path references so workspace builds always use local source. Deno-specific helper crates (deno_ast, deno_lockfile, deno_doc, deno_lint, etc.) are pinned to exact versions via =X.Y.Z.

To upgrade an internal crate: bump the =X.Y.Z line in [workspace.dependencies], run cargo update -p <crate>, and verify with cargo check --workspace.

7.6 Cross-Compile

Cargo cross-compile setup is in .cargo/config.toml. CI uses cross and platform-specific runners (Apple Silicon and ARM Linux are native; Windows is MSVC).

Cross-compile a deno compile binary (different from cross-compiling deno itself):

deno compile --target aarch64-unknown-linux-gnu --output myapp-arm64 main.ts

The denort runtime for the target architecture is downloaded to $DENO_DIR/binary/ on first cross-compile.


8. Module Reference

8.1 The deno_core Trinity

deno_core is the foundation. The three central types:

JsRuntime

libs/core/runtime/jsruntime.rs. Owns a V8 Isolate and Context. Provides:

  • new(options) — construct a runtime with extensions, snapshot, module loader, op state seed.
  • execute_script(name, source) — synchronously execute JS, returns the V8 value.
  • load_main_module(specifier, code) — load a module graph rooted at specifier.
  • mod_evaluate(module_id) — evaluate a loaded module; returns a future for the result.
  • run_event_loop(opts) — drive Tokio + microtasks until idle.

Extension

libs/core/extensions.rs. Bundles ops, ESM modules, and state seed for a feature. Built via the extension! macro:

extension!(deno_my,
  deps = [deno_web, deno_url],
  ops = [op_foo, op_bar],
  esm_entry_point = "ext:deno_my/01_main.js",
  esm = ["01_main.js", "02_helpers.js"],
  options = { foo: Arc<dyn FooSrv> },
);

deps enforces extension-load ordering. options are passed at runtime via MyExtensionOptions { ... }.

ModuleLoader

Trait in libs/core/modules/. Implementors handle resolve() (specifier → URL) and load() (URL → source). The CLI's loader at cli/module_loader.rs handles HTTPS, JSR, npm, file, data, and node schemes.

8.2 The op2 Macro

libs/ops/op2/. The #[op2] proc-macro generates V8 fast-call entry points. Variants:

Form Purpose
#[op2] Sync op
#[op2(async)] Async op (returns Future)
#[op2(fast)] Force fast-call code path (sync only, restricted parameter types)
#[op2(reentrant)] Allows re-entering JS from within the op (rare)
#[op2(stack_trace)] Capture JS stack trace at call site (perf cost)
#[op2(no_side_effects)] Hint to V8 for further optimization

Parameter attributes:

Attr Meaning
#[string] Cheap string conversion
#[buffer] Treat as Uint8Array/Buffer, no copy
#[serde] Use serde_v8 for serialization
#[state] Inject from OpState
#[smi] Small integer fast path
#[bigint] BigInt as i64/u64

8.3 Module Graph and Resolution

The graph is built by deno_graph (an external crate, but wholly authored by the Deno team). It traverses imports starting from the entry point, applies the import map, resolves npm/jsr specifiers via the local resolver, and produces a module graph used for type-checking, bundling, vendoring, publishing, and execution.

Key types:

Type Purpose
ModuleGraph The full graph: nodes (modules), edges (imports), deps, redirects.
ModuleSpecifier A normalized URL (url::Url).
WorkspaceResolver Resolves bare specifiers within a workspace.
NpmResolver npm version resolution + node_modules layout.
JsrResolver JSR resolution + version selection.

8.4 The Type-Checking Pipeline

cli/type_checker.rs and cli/tsc/. As of v2, Deno uses TypeScript-Go (a Go port of tsc) for type-checking. The Rust client (libs/typescript_go_client/) talks to the Go process over IPC.

Flow:

  1. deno check main.ts builds the module graph.
  2. The graph is serialized and sent to the TS-Go subprocess.
  3. TS-Go runs the type checker and returns diagnostics.
  4. Diagnostics are formatted and printed by deno_runtime::fmt_errors.
  5. Successful type-check results are cached in $DENO_DIR/check/.

The legacy tsc integration (in cli/tsc/) remains for cases where TS-Go cannot handle the graph (some experimental syntax, compilerOptions.experimentalDecorators interactions). Both paths produce the same diagnostic format.

8.5 The Language Server (deno lsp)

cli/lsp/. A Tower-LSP server that implements the standard LSP plus Deno-specific extensions:

Custom request Purpose
deno/cache Cache deps for the workspace
deno/performance Performance metrics
deno/reloadImportRegistries Refresh JSR/npm completion data
deno/task List runnable tasks
deno/testing/* Test discovery, run requests, results
deno/virtualTextDocument Read transient documents (e.g. opened from a URL)

The LSP shares the resolver, type-checker, and module loader with the rest of the CLI; opening a workspace in an editor exercises the same resolution path as deno run.

8.6 The Standalone Runtime (denort)

cli/rt/. A reduced binary that ships inside deno compile outputs. It contains the runtime + ext extensions but omits the type checker, formatter, linter, doc generator, REPL, and LSP. The eszip appended to the executable contains the user's bundled module graph; on startup, denort loads the eszip into memory and executes the entry point.

ext/rt_helper provides shared helpers between cli/ and cli/rt/.

8.7 The Bundler

ext/bundle + cli/tools/bundle/. The bundler is built on esbuild (via WASM). It produces ESM bundles for browser/Deno targets and is the engine behind:

Use Mechanism
deno bundle main.ts Direct user invocation
deno compile Bundler produces the eszip embedded in the binary
Deno.bundle(...) Programmatic API (unstable)

8.8 The Package Manager (cli/tools/pm)

cli/tools/pm/. Implements deno add, deno remove, deno install, deno uninstall, deno outdated, deno update, and deno approve-scripts. Backed by:

  • libs/npm — npm package resolution
  • libs/npm_cache — disk cache
  • libs/npm_installer — node_modules layout
  • libs/npmrc — registry/auth config
  • libs/resolver/npm — runtime npm resolution

9. Code Patterns

9.1 Cargo Conventions

  • Workspace-pinned everything. Every external dep is in [workspace.dependencies]. Crates use workspace = true.
  • Per-crate features for slim builds. deno_runtime has transpile, snapshot, hmr features so embedders can opt in/out of features that pull in heavy deps.
  • Internal crates ship to crates.io. deno_core, deno_ast, deno_lockfile, deno_doc, deno_lint, etc. are independently versioned and published.

9.2 Async Patterns

  • The runtime is single-threaded Tokio (current_thread flavor) — V8 isolates are not Send.
  • WebWorker spawns a fresh OS thread with its own Tokio runtime.
  • Long-running ops yield via tokio::spawn_blocking for FS-heavy work; otherwise they run on the main thread.
  • Cancellation is cooperative via CancelHandle (a deno_core type).

9.3 Error Handling

deno_error::JsErrorBox and AnyError are the universal error types crossing the JS/Rust boundary. Errors implement JsError for proper translation to JS exception classes (TypeError, RangeError, Deno.errors.PermissionDenied, etc.). Most ops return Result<T, AnyError>.

9.4 Snapshot-Friendly Code

Anything in an ext/ JS file that runs at extension load runs at snapshot time (during the build), not at runtime. This means:

  • No I/O, no Tokio.
  • No date/time captures (would freeze build time into the snapshot).
  • No network access — URLs constructed at snapshot time embed the build host's machine state.

Code that must run per-process (e.g. reading env vars, getting Date.now()) goes in the 99_main.js bootstrap or in lazily-evaluated code paths.

9.5 State Management

OpState is a per-JsRuntime typemap (keyed by Rust type) that ops draw from. Idiomatic pattern: store an Arc<MyService> in OpState, pull it via #[state] in op signatures.

PermissionsContainer lives in OpState and is mutated only by the runtime (not by ops).


10. Testing Strategy

10.1 Test Categories

Type Where Run with
Rust unit tests cli/, runtime/, ext/*, libs/* cargo test --workspace
Spec-based integration tests tests/specs/*/__test__.jsonc cargo test --test integration -- specs::
JS unit tests tests/unit/* (run inside Deno) tools/test.ts
Node compatibility tests tests/unit_node/*, tests/node_compat/* tools/node_compat/run_all_test_unmodified.ts
WPT (Web Platform Tests) tests/wpt/ tools/wpt.ts
FFI / NAPI / SQLite extension tests tests/ffi, tests/napi, tests/sqlite_extension Compiled and exercised by spec tests
Benchmarks tests/bench/ cargo bench or deno bench

The spec format: each test directory has a __test__.jsonc describing args, env, expected exit code, expected stdout pattern, expected stderr pattern. The integration test runner discovers them recursively.

10.2 Local Mock Registries

tests/registry/ ships a self-contained JSR-shaped and npm-shaped registry served by the tests/util/server HTTP server during tests. This allows tests to reference deterministic packages like npm:@denotest/cjs-multiple-exports without hitting npm.org.

10.3 Adding a Spec Test

  1. Create tests/specs/<group>/<test_name>/.

  2. Add __test__.jsonc:

    { "args": "run -A main.ts", "output": "main.out" }
    
  3. Add main.ts and main.out (the expected stdout/stderr).

  4. Run cargo test --test integration -- specs::<group>::<test_name>.


11. Operating in Production

11.1 Container Image

FROM denoland/deno:2.7.12 AS build
WORKDIR /app
COPY deno.json deno.lock ./
RUN deno install --frozen
COPY . .
RUN deno cache --frozen main.ts
CMD ["deno", "run", "--no-prompt", "--allow-net", "--allow-read=./data", "main.ts"]

For minimal image size, use deno compile and a distroless base:

FROM denoland/deno:2.7.12 AS build
WORKDIR /app
COPY . .
RUN deno compile --output myapp -A main.ts

FROM gcr.io/distroless/cc
COPY --from=build /app/myapp /usr/local/bin/myapp
ENTRYPOINT ["/usr/local/bin/myapp"]

11.2 systemd Unit

[Unit]
Description=My Deno Service
After=network.target

[Service]
ExecStart=/usr/local/bin/deno run --no-prompt --allow-net --allow-read=/var/lib/myapp /var/lib/myapp/main.ts
Restart=on-failure
RestartSec=5
User=myapp
Environment=DENO_DIR=/var/cache/deno
Environment=DENO_NO_UPDATE_CHECK=1
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

11.3 Kubernetes

Run deno serve --parallel --host 0.0.0.0 --port 8080 main.ts in the container. Expose port 8080. The pod's CPU limit governs the parallel worker count when DENO_USE_CGROUPS=1 is set.

For graceful shutdown: Deno.serve already handles SIGTERM. Kubernetes' default terminationGracePeriodSeconds: 30 is sufficient for most workloads.

11.4 Resource Limits

Setting How
V8 heap limit --v8-flags=--max-old-space-size=4096 (MB)
File descriptor limit OS-level (ulimit -n or systemd LimitNOFILE)
CPU pinning OS-level (taskset, cgroups, k8s cpu limits)
Memory pressure response DENO_USR2_MEMORY_TRIM=1 + kill -USR2 <pid> to free memory (Linux only)

12. Troubleshooting (Operator-Focused)

For developer-side troubleshooting, see the User Guide. This section covers operational issues.

Warning

Production Deno processes should always run with --no-prompt to convert interactive permission prompts into hard denials. An unattended process that blocks on a prompt will stall indefinitely.

Issue: Deno binary updates itself unexpectedly in a Linux distro package

Cause: deno upgrade overwrites the binary. The distro tracks a different version. Solution: Build with cargo build --release --no-default-features --features __vendored_zlib_ng -p deno to disable the upgrade feature.

Issue: Type-check is slow in CI

Cause: Cold cache; TypeScript-Go starting up; remote modules being fetched. Solution: Cache $DENO_DIR/check/ and $DENO_DIR/deps/ between CI runs. Use deno cache main.ts as a separate step before deno test.

Issue: V8 process exceeds container memory

Cause: Default heap limit ignores cgroups. Solution: Set DENO_USE_CGROUPS=1 so V8 sees the container limit. Alternatively, pass --v8-flags=--max-old-space-size=<MB>.

Issue: deno compile binary fails on target with "GLIBC_X.YZ not found"

Cause: The pre-built denort for Linux is built against newer glibc than the target. Solution: Build denort from source on a matching glibc base, or target a musl variant via cross-compilation.

Issue: Module fetch fails behind corporate proxy

Cause: Proxy credentials or CA cert. Solution: Set HTTPS_PROXY and HTTP_PROXY. For private CA: DENO_CERT=/path/to/ca-bundle.pem and possibly DENO_TLS_CA_STORE=system,mozilla.

Issue: deno serve --parallel only spawns one worker

Cause: --parallel without an integer defaults to detected CPU count from cgroups; a misconfigured cgroup may report 1. Solution: Pass an explicit count: --parallel=8. Verify cgroup with nproc inside the container.

Issue: Inspector is reachable from outside the container

Cause: --inspect=0.0.0.0:9229 was used. Deno's inspector has no auth. Solution: Always use --inspect=127.0.0.1:9229 and tunnel via SSH or kubectl port-forward. Never expose the inspector publicly.

Tip

When debugging CI cache misses, run deno info --json main.ts to dump the full module graph with resolved URLs and cache paths. Compare against the previous run to identify what changed.

Issue: KV database corruption after kill -9

Cause: SQLite WAL not checkpointed. Solution: Use kill -TERM and let Deno's signal handler close KV cleanly. For recovery, open the SQLite file with sqlite3 and run PRAGMA wal_checkpoint(TRUNCATE);.

Issue: Lockfile drift across team members

Cause: Different platforms resolve packages slightly differently (npm optional deps). Solution: Commit the lockfile as-is and use --frozen in CI. For platform-specific optional deps, use npmrc settings.

Issue: deno upgrade fails with "could not download release"

Cause: GitHub rate-limited the unauthenticated request, or the network blocks github.com. Solution: Set GH_TOKEN (or GITHUB_TOKEN) for an authenticated request. For air-gapped environments, mirror releases internally and use --canary-url=... or deno upgrade --output PATH after manual download.


13. Contributing

13.1 Where to Start

13.2 Local Development

git clone https://github.com/denoland/deno.git
cd deno
cargo build -p deno              # debug build (~5 min after V8 caches)
./target/debug/deno --version
cargo test -p deno_runtime       # unit tests for runtime crate
cargo test --test integration -- specs::run::  # integration specs for `run`

For tight iteration on JS bootstrap code, use the hmr Cargo feature: cargo build --features hmr -p deno. With HMR, edits to runtime/js/* and ext/*/*.js take effect on the next deno run without rebuilding the snapshot.

13.3 Style and Lint

  • Rust: cargo fmt --check and cargo clippy -- -D warnings. CI fails on either.
  • JS/TS: deno fmt and deno lint. CI runs both.
  • Spec tests: copyright header is mandatory (// Copyright 2018-2026 the Deno authors. MIT license.).

13.4 PR Process

  1. Branch from main.
  2. Open a PR with a clear description and (where relevant) a spec test.
  3. CI runs the full matrix: build on all 5 targets + spec tests + WPT subset + lint + format.
  4. Maintainers review. Most PRs require one approval; substantial changes require two.
  5. Squash-merge into main with a Conventional Commits-style message.

13.5 Architecture for New Contributors

Want to add Start here
A new Deno.* API ext/<closest_existing>/lib.rs + JS in same crate. Add ops with #[op2]. Wire from runtime/lib.rs.
A new CLI subcommand cli/args/flags.rs (clap definition + parse) + cli/tools/<cmd>.rs (handler).
A new node:* polyfill ext/node/polyfills/<module>.ts. Wire in ext/node/polyfill_proxy.ts.
A new lint rule deno_lint external crate (https://github.com/denoland/deno_lint).
A new lockfile field libs/lockfile/lib.rs. Bump schema version if breaking.

14. Quick Reference

14.1 Rebuild After Pulling

cargo build -p deno --release

14.2 Run Specific Spec Test

cargo test --test integration -- specs::run::specific_test_name

14.3 Re-Generate the JSON Schema for deno.json

The schema lives at cli/schemas/config-file.v1.json and is hand-maintained. Update it whenever a new top-level key is added.

14.4 Useful Files

Concern Path
All CLI flags and subcommands cli/args/flags.rs
All env vars Deno reads cli/args/flags.rs:1452-1591 (ENV_VARS)
Permission model runtime/permissions/lib.rs
Module loader cli/module_loader.rs
deno.json schema cli/schemas/config-file.v1.json
Lockfile format libs/lockfile/
ext extension contract libs/core/extensions.rs
op2 macro libs/ops/op2/
Workspace member list Cargo.toml (root)

14.5 GitHub Issues Referenced in Troubleshooting

Issue Topic
#33291 crypto.verify Invalid PEM
#33296 TLS to Postgres via npm:pg@8 times out
#33254 Windows writeFileSync EEXIST
#32821 deno compile binary hang on 2.7.5+
#33288 node:http Server vs node:net Server inheritance
#33284 LSP Test Explorer divergence with --env-file
#33289 LSP global types not recognized until file is opened