Use this skill when working with TypeScript/JavaScript files (.ts, .tsx, .js, .jsx, .mts, .cts, .mjs, .cjs) in Deno projects, or when the user asks about Deno-specific patterns, imports, configuration, testing, or tooling.
This skill inherits all available tools. When active, it can use any tool Claude has access to.
Deno is the primary TypeScript/JavaScript runtime and language server. It replaces the entire Node.js toolchain: no tsc, eslint, prettier, jest, webpack needed.
deno.json, never direct imports.ts extensions in relative importsSingle source of truth for all project configuration:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true
},
"imports": {
"@/": "./src/",
"@std/assert": "jsr:@std/assert@^1.0.14",
"@std/fs": "jsr:@std/fs@^1.0.19",
"zod": "npm:zod@^3.23.8"
},
"tasks": {
"dev": "deno run --watch --allow-net --allow-read src/main.ts",
"test": "deno test --allow-all --coverage=coverage",
"check": "deno check src/**/*.ts",
"lint": "deno lint",
"fmt": "deno fmt"
},
"exclude": ["coverage/", "node_modules/"],
"lock": true
}
CRITICAL: Never use direct JSR/npm imports in source files.
// ✅ GOOD - Use import map aliases
import { assertEquals } from "@std/assert";
import { z } from "zod";
import { Agent } from "@/domain/agent.ts";
import { helper } from "./utils.ts"; // Extension required!
// ❌ BAD - Direct registry imports
import { z } from "npm:zod@^3.23.8";
import { assertEquals } from "jsr:@std/assert";
Import Order:
@std/*)zod, etc.)@/domain/...)./utils.ts)Version Pinning: Always pin versions in deno.json. No floating @latest.
jsr: registry - First choice for TypeScript modulesnpm: specifier - When JSR unavailable, prefer ESM-compatible{
"imports": {
"@std/assert": "jsr:@std/assert@^1.0.14",
"zod": "npm:zod@^3.23.8"
}
}
Co-locate unit tests with source:
src/
└── domain/
├── agent.ts
└── agent.test.ts # Test file next to source
Test file naming: Always use .test.ts suffix.
AAA Pattern (Arrange-Act-Assert):
import { assertEquals } from "@std/assert";
Deno.test("agent processes valid input", () => {
// Arrange
const agent = new Agent({ name: "Test" });
// Act
const result = agent.process("hello");
// Assert
assertEquals(result.status, "success");
});
Coverage requirements:
Use @std/testing for test utilities:
import { FakeTime } from "@std/testing/time";
import { stub, spy } from "@std/testing/mock";
Deno.test("timer behavior", () => {
using time = new FakeTime();
time.tick(1000);
// Deterministic time control
});
Default to minimum required permissions:
# ❌ BAD
deno run --allow-all script.ts
# ✅ GOOD
deno run --allow-read=./data --allow-net=api.example.com script.ts
Common flags:
--allow-read[=<path>] - File system read--allow-write[=<path>] - File system write--allow-net[=<domain>] - Network access--allow-env[=<var>] - Environment variables--allow-run[=<program>] - Subprocess execution# Development
deno run --watch src/main.ts # Watch mode
deno check src/**/*.ts # Type-check
deno fmt # Format
deno lint # Lint
# Testing
deno test # Run tests
deno test --watch --fail-fast # Watch mode
deno test --coverage=coverage # With coverage
deno coverage coverage --html # Generate report
# Dependencies
deno add jsr:@std/path # Add dependency
deno cache --reload # Update cache
deno cache --lock=deno.lock --lock-write # Update lockfile
# Tasks
deno task dev # Run defined task
Use JSR standard library for common utilities:
@std/assert - Testing assertions@std/fs - File system utilities@std/path - Path manipulation@std/http - HTTP server/client@std/async - Async utilities (debounce, retry, etc.)@std/testing - Mock, spy, FakeTime@std/ulid - ULID generation// ❌ Direct registry imports in source
import { z } from "npm:zod@^3.23.8";
// ❌ Missing file extension
import { helper } from "./utils";
// ❌ Node.js APIs
import * as fs from "node:fs";
const fs = require("fs");
// ❌ Unnecessary async wrapper
async function validate(input: string): Promise<boolean> {
return input.length > 0; // No await needed
}
// ❌ Test delays instead of FakeTime
await new Promise(r => setTimeout(r, 100));
deno.lock to version controldeno cache --lock=deno.lock --lock-writedeno run --lock=deno.lock --lock-write=false