How to Configure Deno Using deno.json: Complete Guide to Configuration File Options

You can configure Deno by creating a deno.json or deno.jsonc file in your project root, which Deno automatically discovers to set compiler options, import maps, tasks, permissions, and runtime behavior without requiring CLI flags for every command.

Deno uses deno.json (or deno.jsonc for JSON with comments) as its native configuration file to centralize project settings. When present in your working directory, Deno automatically detects and applies these settings across all commands including deno run, deno test, and deno task. This guide explains how to configure Deno using deno.json based on the actual source code implementation in the denoland/deno repository.

Automatic Config File Discovery

Deno implements automatic configuration discovery through the ConfigFlag enum defined in cli/args/flags.rs at line 74. When you omit the --config flag, the CLI defaults to ConfigFlag::Discover, which triggers a directory tree walk. The discovery logic in cli/factory.rs (lines 1354-1364) searches upward from the working directory for deno.json or deno.jsonc files using ConfigFile::maybe_find_in_folder in libs/config/deno_json/mod.rs (lines 1325-1330).

You can control configuration loading through three distinct behaviors:

  • Automatic discovery: deno run script.ts finds the nearest config file automatically via ConfigFlag::Discover.
  • Explicit path: deno run --config ./my-config.json script.ts loads a specific file using ConfigFlag::Path.
  • Disabled: deno run --config=none script.ts skips configuration entirely using ConfigFlag::Disabled.

The file reader caches results in a ConfigFileRc and gracefully handles skippable I/O errors like permission denied, allowing Deno to continue searching up the directory hierarchy.

Core Configuration Structure

At the heart of Deno's configuration system lies the ConfigFile struct, which stores the absolute URL of the configuration file and its deserialized contents. The strongly typed ConfigFileJson struct (defined in libs/config/deno_json/mod.rs between lines 1110-1142) represents every valid top-level key using Option<Value> fields. Because the struct uses #[serde(deny_unknown_fields)], unknown keys trigger deserialization errors, ensuring strict validation.

Important Configuration Keys

The deno.json schema supports these primary configuration categories:

  • compilerOptions: TypeScript compiler settings (target, lib, types) equivalent to tsconfig.json.
  • importMap: Path to an import map file (file URLs only; remote URLs require the --import-map flag).
  • imports / scopes: Inline import map entries embedded directly in the config.
  • tasks: Named scripts executable via deno task <name>, processed by cli/tools/task.rs.
  • permissions: Default permission grants using allow, deny, and prompt arrays, parsed into PermissionsConfig.
  • lint and fmt: Configuration for deno lint and deno fmt commands.
  • nodeModulesDir: npm compatibility mode ("auto", "none", or "manual").
  • vendor: Boolean enabling automatic dependency vendoring into a vendor/ folder.
  • unstable: Array of unstable API flags to enable without CLI arguments.
  • lock: Path to a lockfile for deterministic dependency versions.

Practical Configuration Examples

Minimal Import Map Configuration

For projects requiring only import mapping, create a minimal deno.json:

{
  "importMap": "./import_map.json"
}

Deno resolves the path relative to the configuration file location. The ConfigFile::to_import_map_path method enforces that importMap values must be file specifiers; attempting to use a remote URL here throws an OnlyFileSpecifiersSupported error.

Complete Production Configuration

A comprehensive deno.json for a TypeScript project with tasks, permissions, and formatting rules:

{
  "compilerOptions": {
    "target": "es2022",
    "lib": ["es2022", "dom"]
  },
  "importMap": "./import_map.json",
  "lint": {
    "rules": { "exclude": ["no-explicit-any"] },
    "include": ["src/**/*.ts"]
  },
  "fmt": {
    "indentWidth": 2,
    "lineWidth": 80
  },
  "tasks": {
    "dev": "deno run -A src/main.ts",
    "test": "deno test --coverage"
  },
  "permissions": {
    "allow": ["read", "write", "net"],
    "deny": ["env"]
  },
  "nodeModulesDir": "auto",
  "vendor": true,
  "unstable": ["byonm"]
}

This configuration sets TypeScript compilation targets in runtime/tsc/mod.rs, defines reusable scripts for the task runner, establishes secure default permissions, and enables automatic node_modules generation for npm compatibility.

Runtime Configuration Application

Deno applies deno.json settings through a structured pipeline before executing user code. First, the configuration loads into the ConfigFile struct, with ConfigFile::to_import_map_path resolving import map references. The TypeScript compiler receives compilerOptions through runtime/tsc/mod.rs, while the permission system initializes using PermissionsConfig from the permissions object.

For task execution, cli/tools/task.rs expands environment variables in the tasks map and spawns subprocesses. Each subsystem—linting, formatting, testing—accesses its respective configuration slice (such as LintConfig or FmtConfig) derived from ConfigFileJson. This architecture ensures consistent behavior across deno run, deno test, deno compile, and deployment commands.

Summary

  • Automatic discovery: Deno walks up the directory tree to find deno.json or deno.jsonc unless you specify --config or --config=none.
  • Strict validation: The configuration parses into ConfigFileJson with #[serde(deny_unknown_fields)], rejecting unknown keys while validating compiler options, import maps, tasks, and permissions.
  • Single source of truth: All CLI commands respect the same configuration file, eliminating the need to repeat flags.
  • File-only import maps: The importMap key in deno.json requires local file paths; use CLI --import-map for remote URLs.
  • Task automation: Define project scripts in the tasks object to standardize development workflows across your team.

Frequently Asked Questions

What is the difference between deno.json and deno.jsonc?

Deno supports both deno.json (standard JSON) and deno.jsonc (JSON with comments). The jsonc variant allows you to include comments and trailing commas for better documentation, which the parser strips before processing. Both files are discovered automatically through the same ConfigFlag::Discover mechanism in cli/factory.rs and use identical schemas.

Can I use a remote URL for the importMap field in deno.json?

No, the importMap field in deno.json only supports local file paths. According to the source in libs/config/deno_json/mod.rs, the to_import_map_path method validates that import map specifiers are file URLs, and attempting to specify a remote URL triggers an OnlyFileSpecifiersSupported error. For remote import maps, use the --import-map CLI flag instead.

How do I disable automatic configuration discovery?

Use the --config=none flag to completely disable configuration file discovery. This sets ConfigFlag::Disabled in cli/args/flags.rs, preventing Deno from walking the directory tree for deno.json or deno.jsonc. Alternatively, the explicit --config /path/to/file.json flag bypasses automatic discovery and loads only the specified configuration via ConfigFlag::Path.

Where does Deno store the parsed configuration in memory?

Deno caches the parsed configuration in a ConfigFileRc (reference-counted ConfigFile instance) returned by ConfigFile::maybe_find_in_folder. The CliFactory in cli/factory.rs holds this reference and distributes configuration slices to subsystems: compilerOptions routes to the TypeScript compiler in runtime/tsc/mod.rs, permissions populate PermissionsConfig, and tasks feed into cli/tools/task.rs for execution.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →