DEV Community

Olivia Craft
Olivia Craft

Posted on

CLAUDE.md for Deno: 13 Rules That Stop AI from Writing Node.js in a Deno Project

The single biggest source of AI drift in Deno projects: Node.js muscle memory.

Every model has trained on years of Node.js patterns — require(), npm install, package.json, CommonJS modules, process.env via dotenv. When you start a Deno project, those patterns keep leaking in.

Deno has a distinct runtime model: URL imports (or deno.json import maps), built-in TypeScript, a permissions system, and standard library that replaces most npm packages. AI tools that don't know this produce Node.js code with a Deno filename.

A CLAUDE.md file at the repo root fixes this. Here are 13 rules that cover the most common failure modes.


Rule 1: No npm or package.json — declare this explicitly

This project uses Deno, not Node.js.
Do NOT generate:
- package.json or npm install commands
- require() or CommonJS syntax
- node_modules/ references
- npm run scripts
Use deno.json for tasks and import maps.
Enter fullscreen mode Exit fullscreen mode

This is the most important rule. Without it, AI will default to npm tooling on every project setup question.

Rule 2: Imports use URLs or import maps, not bare specifiers

Deno 1.x: import from URLs (https://deno.land/std@version/...)
Deno 2.x with npm compat: use import maps in deno.json
Do NOT use bare imports like 'import express from "express"'
without a corresponding entry in deno.json importMap.
Always pin versions in URLs or import maps.
Enter fullscreen mode Exit fullscreen mode

Rule 3: Built-in TypeScript — no tsconfig needed for basic use

Deno has built-in TypeScript support — no ts-node, no tsc step.
Do not generate tsconfig.json unless the project specifically
requires non-default compiler options.
Run TypeScript files directly: deno run file.ts
Enter fullscreen mode Exit fullscreen mode

Rule 4: Permissions are explicit, not granted by default

Deno denies all permissions by default.
When generating run commands, include required flags:
  --allow-net for network access
  --allow-read for file system reads
  --allow-write for file system writes
  --allow-env for environment variable access
Do not use --allow-all unless specifically requested.
Enter fullscreen mode Exit fullscreen mode

Rule 5: Standard library replaces most npm packages

Use Deno standard library for common utilities:
  std/path instead of the path npm package
  std/fs instead of fs-extra
  std/http instead of express for simple servers
  std/testing/asserts instead of jest/chai
Check deno.land/std before reaching for an npm equivalent.
Enter fullscreen mode Exit fullscreen mode

Rule 6: Deno.env replaces dotenv

Environment variables: Deno.env.get("VAR_NAME")
Do NOT install or import dotenv.
For .env file loading: use --env flag (Deno 1.38+) or
import { load } from "https://deno.land/std/dotenv/mod.ts"
Enter fullscreen mode Exit fullscreen mode

Rule 7: Task runner is deno.json, not npm scripts

Project tasks are defined in deno.json under "tasks":
  "start": "deno run --allow-net src/main.ts"
  "test": "deno test --allow-read"
Run with: deno task start
Do NOT create a Makefile or package.json scripts section.
Enter fullscreen mode Exit fullscreen mode

Rule 8: Testing uses Deno.test, not jest or mocha

Tests use the built-in test runner:
  Deno.test("description", () => { ... })
  import { assertEquals } from "https://deno.land/std/assert/mod.ts"
Run with: deno test
Do NOT generate jest.config.js or install testing libraries.
Enter fullscreen mode Exit fullscreen mode

Rule 9: HTTP servers use Deno.serve or std/http

For HTTP servers, use Deno.serve() (Deno 1.35+) or
import { serve } from "https://deno.land/std/http/server.ts"
For full web frameworks: use Fresh or Oak (not Express).
Do NOT use express, fastify, or koa without confirming
an npm compat import map is configured.
Enter fullscreen mode Exit fullscreen mode

Rule 10: File operations use Deno APIs

File I/O: Deno.readTextFile(), Deno.writeTextFile()
Not: fs.readFile(), fs.promises, or require('fs')
Path handling: import { join } from "https://deno.land/std/path/mod.ts"
Enter fullscreen mode Exit fullscreen mode

Rule 11: Formatting and linting are built-in

Format: deno fmt (no prettier config needed)
Lint: deno lint (no eslint config needed)
Do NOT generate .eslintrc, .prettierrc, or install these tools.
Deno's built-in formatter and linter are the project standard.
Enter fullscreen mode Exit fullscreen mode

Rule 12: Lock file is deno.lock, not package-lock.json

Dependency integrity: deno.lock (generated automatically)
Do NOT reference package-lock.json or yarn.lock.
To update lock file: deno cache --reload deps.ts
Enter fullscreen mode Exit fullscreen mode

Rule 13: Decision order for any Deno code

When generating code for this project, check in order:
1. Is there a Deno built-in? (Deno.*, Deno.serve, etc.) Use it.
2. Is there a std library module? Use it.
3. Is there a well-maintained Deno-native package? Use it.
4. Only then: use an npm package via import map.
Do not skip to step 4 because the npm package is familiar.
Enter fullscreen mode Exit fullscreen mode

The full CLAUDE.md block

# Deno Project Rules

## Runtime
- Deno, NOT Node.js
- No package.json, no npm, no node_modules
- No require() or CommonJS syntax

## Imports
- URL imports or deno.json import maps
- Always pin versions
- No bare specifiers without import map entry

## TypeScript
- Built-in — no tsconfig unless explicitly needed
- Run directly: deno run file.ts

## Permissions (always explicit)
- --allow-net, --allow-read, --allow-write, --allow-env
- No --allow-all unless requested

## Standard Library First
- std/path, std/fs, std/http, std/testing/asserts
- Check deno.land/std before using npm packages

## Environment Variables
- Deno.env.get("VAR") — no dotenv import

## Tooling (all built-in)
- Tasks: deno.json "tasks" section
- Tests: Deno.test() + deno test
- Format: deno fmt
- Lint: deno lint
- Lock: deno.lock

## HTTP
- Simple: Deno.serve()
- Framework: Fresh or Oak

## Decision Order
1. Deno built-in -> 2. std lib -> 3. Deno-native pkg -> 4. npm via import map
Enter fullscreen mode Exit fullscreen mode

Why Deno AI drift is so predictable

Node.js has 15+ years of ecosystem content. Deno 1.0 launched in 2020. The training data ratio is overwhelming — for every Deno tutorial, there are hundreds of Node.js equivalents covering the same pattern.

Without explicit instruction, AI will write what it knows. A CLAUDE.md file that declares the runtime model is the explicit instruction that prevents that drift.

The rules above don't require the AI to learn Deno — they require you to declare which ecosystem you're in, once, at the start of every session.


These 13 rules are part of a framework-specific CLAUDE.md series. The Cursor Rules Pack equivalent (50 production-tested rules across all stacks) is available at oliviacraftlat.gumroad.com/l/wyaeil — search "Olivia Craft Cursor Rules" on Gumroad.

Top comments (0)