Runtime & Tooling

Deno mit Claude Code: Moderne JavaScript-Runtime 2026

Deno 2.0 als sichere JavaScript-Runtime mit Node.js-Kompatibilität — Claude Code baut APIs, nutzt Deno KV und deployt auf Deno Deploy.

📅 6. Mai 2026 ⏱ 10 min Lesezeit 🏷 Runtime & Tooling
Deno 2.0 Deno KV Fresh Deploy TypeScript npm compat

Deno hat sich seit der ersten Version von Ryan Dahl stark gewandelt. Mit Deno 2.0 ist die Runtime produktionsreif: npm-Pakete laufen nativ, TypeScript ist eingebaut, und das Security-Modell macht Exploits strukturell schwieriger. Claude Code versteht Deno-Projekte vollständig — von deno.json über Import-Maps bis hin zu Deno.openKv().

Dieser Guide zeigt, wie du Deno 2.0 mit Claude Code produktiv einsetzt: von den ersten Schritten über Deno KV als eingebettete Datenbank, das Fresh Framework für SSR-Apps, bis hin zur vollständigen Migration von bestehenden Node.js-Projekten.

1. Deno 2.0 Basics

Deno ist eine sichere JavaScript- und TypeScript-Runtime, die auf V8 und Rust basiert. Im Gegensatz zu Node.js läuft Code standardmäßig ohne Dateisystem- oder Netzwerkzugriff — Berechtigungen müssen explizit gesetzt werden.

Installation und erste Schritte

# Deno installieren (Linux/macOS)
curl -fsSL https://deno.land/install.sh | sh

# Version prüfen
deno --version
# deno 2.1.4 (release, x86_64-unknown-linux-gnu)

# TypeScript direkt ausführen — kein Kompilieren nötig
deno run main.ts

# Mit Netzwerkzugriff
deno run --allow-net server.ts

# Alle Permissions (Entwicklung)
deno run --allow-all dev.ts

Wichtige CLI-Befehle

⚡ Deno CLI Toolchain

  • deno run — Skript ausführen (mit Permission-Flags)
  • deno task — Tasks aus deno.json ausführen (wie npm run)
  • deno fmt — Code formatieren (eingebaut, kein Prettier nötig)
  • deno lint — Linting (eingebaut, kein ESLint nötig)
  • deno test — Tests ausführen (eingebaut, kein Jest nötig)
  • deno compile — Standalone-Binary erstellen
  • deno info — Dependency-Graph anzeigen
  • deno doc — Dokumentation generieren

deno.json — Das Konfigurationsformat

// deno.json
{
  "name": "my-app",
  "version": "1.0.0",
  "tasks": {
    "dev": "deno run --allow-net --allow-read --watch main.ts",
    "start": "deno run --allow-net --allow-read main.ts",
    "test": "deno test --allow-net",
    "fmt": "deno fmt",
    "lint": "deno lint"
  },
  "imports": {
    "@std/http": "jsr:@std/http@^1.0.0",
    "@std/path": "jsr:@std/path@^1.0.0",
    "zod": "npm:zod@^3.22.0"
  },
  "compilerOptions": {
    "strict": true,
    "lib": ["deno.window"]
  }
}

Permission-System — Sicherheit by Default

// Deno blockiert unerlaubte Operationen zur Laufzeit
// ❌ Fehler ohne --allow-net:
const res = await fetch("https://api.example.com");
// PermissionDenied: Requires net access to "api.example.com"

// Granulare Permissions:
deno run --allow-net=api.example.com,cdn.example.com main.ts
deno run --allow-read=/tmp,/var/data main.ts
deno run --allow-write=/tmp main.ts
deno run --allow-env=DATABASE_URL,PORT main.ts
deno run --allow-run=git,curl main.ts
Claude Code + Deno: Claude versteht das Permission-System vollständig. Gib ihm eine Beschreibung deiner App, und er schlägt die minimalen notwendigen Flags vor — kein --allow-all in Production.

TypeScript nativ — kein Build-Step

// types.ts
interface User {
  id: string;
  name: string;
  email: string;
  createdAt: Date;
}

// main.ts — direkt ausführbar, keine tsconfig.json nötig
import type { User } from "./types.ts";

async function getUser(id: string): Promise<User> {
  const res = await fetch(`/api/users/${id}`);
  return res.json();
}

// deno run --allow-net main.ts

2. npm-Kompatibilität

Deno 2.0 kann nahezu alle npm-Pakete direkt verwenden — ohne separaten Install-Schritt. Der npm:-Specifier lädt Pakete on-demand und cached sie lokal.

npm: Specifier

// Direkte npm-Imports ohne Installation
import express from "npm:express@4";
import { z } from "npm:zod@^3.22";
import _ from "npm:lodash";
import dayjs from "npm:dayjs";
import { marked } from "npm:marked";

// Oder via JSR (Deno's eigene Registry)
import { serve } from "jsr:@std/http@^1.0";
import { join } from "jsr:@std/path@^1.0";

package.json Support

Deno 2.0 erkennt package.json automatisch. Das ermöglicht schrittweise Migration ohne Breaking Changes:

// package.json wird automatisch erkannt
{
  "dependencies": {
    "express": "^4.18.0",
    "zod": "^3.22.0"
  }
}

// Deno nutzt node_modules falls vorhanden
// oder löst direkt via npm-Registry auf
deno run --allow-net --allow-read main.ts

# Oder explizit mit node_modules:
deno install    # erstellt node_modules
deno run main.ts

Node Built-ins Kompatibilität

// Node.js built-ins funktionieren mit node: prefix
import { readFileSync, writeFileSync } from "node:fs";
import { join, dirname } from "node:path";
import { createServer } from "node:http";
import crypto from "node:crypto";
import { EventEmitter } from "node:events";
import { Buffer } from "node:buffer";

// Globale Node-Variablen sind verfügbar
console.log(process.version);  // Node.js compat
console.log(process.env.PORT);
Import Maps in deno.json: Statt langer npm:packagename@version-URLs überall empfiehlt sich der imports-Abschnitt in deno.json als zentrale Dependency-Liste. Claude Code pflegt diese Datei automatisch mit.
Ökosystem Deno Support Specifier
npm packages ✓ nativ npm:package@version
JSR (Deno Registry) ✓ nativ jsr:@scope/package
Node built-ins ✓ nativ node:fs, node:path
URL imports ✓ nativ https://deno.land/x/...
CommonJS (require) ⚠ teilweise via npm: wrapper
Native Addons (.node) ✗ nicht unterstützt

3. Deno KV

Deno KV ist eine eingebettete Key-Value-Datenbank, die direkt in die Deno-Runtime integriert ist. Sie basiert auf SQLite (lokal) und FoundationDB (Deno Deploy). Kein Setup, keine externe Datenbank — einfach Deno.openKv() aufrufen.

Grundlegende Operationen

// Deno KV öffnen (eingebettet, kein Server nötig)
const kv = await Deno.openKv();

// SET: Wert speichern
await kv.set(["users", "user-1"], {
  name: "Alice",
  email: "alice@example.com",
  createdAt: new Date().toISOString()
});

// GET: Wert abrufen
const result = await kv.get(["users", "user-1"]);
console.log(result.value);  // { name: "Alice", ... }

// DELETE: Wert löschen
await kv.delete(["users", "user-1"]);

// LIST: Alle User auflisten
const entries = kv.list({ prefix: ["users"] });
for await (const entry of entries) {
  console.log(entry.key, entry.value);
}

Atomic Transactions

// Atomare Transaktionen — entweder alles oder nichts
const userKey = ["users", "user-1"];
const counterKey = ["counters", "users"];

const currentUser = await kv.get(userKey);

const res = await kv
  .atomic()
  .check({ key: userKey, versionstamp: currentUser.versionstamp })
  .set(userKey, { ...currentUser.value, name: "Bob" })
  .sum(counterKey, 1n)  // BigInt-Increment
  .commit();

if (!res.ok) {
  console.log("Conflict! Retry needed.");
}

KV als Session-Store

// Praktisches Beispiel: Session Management
import { serve } from "jsr:@std/http";

const kv = await Deno.openKv();

async function createSession(userId: string): Promise<string> {
  const sessionId = crypto.randomUUID();
  await kv.set(
    ["sessions", sessionId],
    { userId, createdAt: Date.now() },
    { expireIn: 86_400_000 }  // TTL: 24h in ms
  );
  return sessionId;
}

async function getSession(sessionId: string) {
  const res = await kv.get(["sessions", sessionId]);
  return res.value;  // null wenn abgelaufen oder nicht vorhanden
}
Deno KV + Claude Code: Claude kann vollständige CRUD-APIs mit Deno KV als Backend generieren — inklusive Pagination via kv.list(), Cursor-basiertem Blättern und Atomic-Updates für Race-Condition-Sicherheit.

4. Fresh Framework

Fresh ist das offizielle Web-Framework für Deno: SSR-first, keine Build-Pipeline, Islands Architecture für selektive Client-Hydration. Claude Code generiert komplette Fresh-Apps mit typsicheren Routes und Preact-Komponenten.

Projekt erstellen

# Fresh-Projekt scaffolden
deno run -A -r https://fresh.deno.dev my-app
cd my-app

# Entwicklungsserver starten
deno task start
# → http://localhost:8000

Projektstruktur

my-app/
├── routes/           # File-based routing
│   ├── index.tsx     # → /
│   ├── blog/
│   │   ├── index.tsx # → /blog
│   │   └── [slug].tsx# → /blog/:slug
│   └── api/
│       └── users.ts  # → /api/users (REST API)
├── islands/          # Client-side Preact Komponenten
│   ├── Counter.tsx
│   └── SearchBar.tsx
├── components/       # Shared SSR Komponenten
│   └── Layout.tsx
├── static/           # Statische Assets
└── deno.json

Route mit API Handler

// routes/blog/[slug].tsx
import { Handlers, PageProps } from "$fresh/server.ts";

interface Post {
  slug: string;
  title: string;
  content: string;
}

export const handler: Handlers<Post> = {
  async GET(req, ctx) {
    const { slug } = ctx.params;
    const kv = await Deno.openKv();
    const post = await kv.get(["posts", slug]);

    if (!post.value) {
      return ctx.renderNotFound();
    }

    return ctx.render(post.value as Post);
  }
};

export default function BlogPost({ data }: PageProps<Post>) {
  return (
    <article>
      <h1>{data.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: data.content }} />
    </article>
  );
}

Islands Architecture

// islands/Counter.tsx — wird CLIENT-SEITIG hydriert
import { useSignal } from "@preact/signals";

export default function Counter() {
  const count = useSignal(0);

  return (
    <div class="counter">
      <button onClick={() => count.value--}>-</button>
      <span>{count}</span>
      <button onClick={() => count.value++}>+</button>
    </div>
  );
}

// routes/index.tsx — Island einbinden
import Counter from "../islands/Counter.tsx";

export default function Home() {
  return (
    <main>
      <h1>Willkommen</h1>
      {/* Nur Counter wird client-seitig geladen */}
      <Counter />
    </main>
  );
}
Performance by Default: Fresh sendet initial nur SSR-HTML. JavaScript wird nur für Islands geladen — das macht Fresh-Apps deutlich schneller als klassische SPA-Frameworks.

5. Deno Deploy

Deno Deploy ist die Edge-Cloud-Plattform von Deno Land, optimiert für Fresh und Deno-Services. Code läuft in über 35 Regionen weltweit, Deno KV ist automatisch integriert — kein Infrastruktur-Setup nötig.

Deployment mit deployctl

# deployctl installieren
deno install -gArf jsr:@deno/deployctl

# Direkt deployen
deployctl deploy --project=my-app main.ts

# Mit Environment Variables
deployctl deploy \
  --project=my-app \
  --env=DATABASE_URL=postgres://... \
  --env=API_KEY=secret \
  main.ts

# Status prüfen
deployctl deployments list --project=my-app

GitHub Actions CI/CD

# .github/workflows/deploy.yml
name: Deploy to Deno Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Deno Deploy
        uses: denoland/deployctl@v1
        with:
          project: my-app
          entrypoint: main.ts
          root: .

Edge-Funktionen mit KV

// main.ts — Edge-ready API mit Deno KV
import { serve } from "jsr:@std/http";

const kv = await Deno.openKv();
// Auf Deno Deploy: nutzt automatisch FoundationDB

serve(async (req) => {
  const url = new URL(req.url);

  // Rate limiting via KV
  const ip = req.headers.get("x-forwarded-for") || "unknown";
  const rateKey = ["rate", ip, Math.floor(Date.now() / 60000)];
  const rate = await kv.get<number>(rateKey);

  if ((rate.value || 0) > 100) {
    return new Response("Rate limit exceeded", { status: 429 });
  }

  await kv.atomic()
    .sum(rateKey, 1n)
    .commit();

  return new Response("OK");
});

Deploy Deno Deploy Features

  • 35+ Edge-Regionen weltweit, automatisches Routing
  • Deno KV mit FoundationDB-Backend (repliziert, konsistent)
  • Custom Domains + automatisches TLS
  • GitHub-Integration (Preview Deployments per Branch)
  • Zero Cold Starts (V8 Isolates, kein Container-Overhead)
  • Kostenloser Tier: 1M Requests/Monat, 512 MB KV-Storage

6. Migration von Node.js

Deno 2.0 ist auf maximale Node.js-Kompatibilität ausgelegt. Viele Projekte laufen mit minimalen Änderungen. Claude Code analysiert ein Node.js-Projekt und erstellt einen strukturierten Migrationsplan.

Typische Unterschiede im Überblick

Aspekt Node.js Deno
TypeScript ts-node / tsc nötig nativ, kein Setup
Packages npm install + node_modules npm: Specifier / JSR
Konfiguration package.json + tsconfig deno.json (alles in einem)
Linting/Formatting ESLint + Prettier deno lint + deno fmt
Tests Jest / Vitest deno test (eingebaut)
Permissions vollen Zugriff explizit, granular
__dirname / __filename nativ import.meta.dirname

Häufige Migration-Patterns

// ❌ Node.js: CommonJS require
const express = require("express");
const path = require("path");

// ✅ Deno: ESM imports
import express from "npm:express";
import { join } from "node:path";

// ❌ Node.js: __dirname
const dir = __dirname;

// ✅ Deno: import.meta
const dir = import.meta.dirname;

// ❌ Node.js: process.env ohne Permission
const port = process.env.PORT;

// ✅ Deno: mit --allow-env Flag
// deno run --allow-env=PORT main.ts
const port = Deno.env.get("PORT");

Deno Compat Layer

// deno.json — Node.js Compat aktivieren
{
  "nodeModulesDir": "auto",
  "unstable": ["bare-node-builtins"]
}

# Für maximale Kompatibilität:
deno run --unstable-bare-node-builtins \
         --unstable-byonm \
         main.ts

Express App migrieren

// Node.js Express → Deno (praktisch identisch!)
import express from "npm:express@4";
import cors from "npm:cors";
import { z } from "npm:zod";

const app = express();
app.use(express.json());
app.use(cors());

const kv = await Deno.openKv();  // Deno KV statt Redis/MongoDB

app.get("/users/:id", async (req, res) => {
  const user = await kv.get(["users", req.params.id]);
  if (!user.value) {
    return res.status(404).json({ error: "Not found" });
  }
  res.json(user.value);
});

app.listen(3000, () => console.log("Server läuft"));

// deno run --allow-net --allow-read main.ts
Native Addons: Node.js-Pakete mit nativen .node-Dateien (wie bcrypt, sharp in manchen Versionen) laufen nicht in Deno. Verwende Pure-JS-Alternativen oder die Deno-eigenen APIs wie crypto.subtle statt bcrypt.

Migrationsstrategie mit Claude Code

Schrittweise Migration (empfohlen)

  • Schritt 1: deno check main.ts — TypeScript-Fehler identifizieren
  • Schritt 2: CommonJS require → ESM import (Claude Code erledigt das automatisch)
  • Schritt 3: node_modules durch npm:/jsr: Specifier ersetzen
  • Schritt 4: __dirname/__filename auf import.meta umstellen
  • Schritt 5: deno.json mit Tasks, Imports und Permissions erstellen
  • Schritt 6: Tests mit deno test ausführen (Jest-Syntax wird erkannt)
  • Schritt 7: Deployment via deployctl oder Dockerfile (Deno-Base-Image)
Deno 2.0 TypeScript Deno KV Fresh Framework Deno Deploy npm-Kompatibilität Edge Runtime Node.js Migration JavaScript Runtime Claude Code

Deno-Projekte mit Claude Code aufbauen

Claude Code versteht Deno vollständig — von deno.json über Deno KV bis zu Fresh Routes und Deno Deploy CI/CD. Starte jetzt kostenlos und baue sichere, moderne JS/TS-Apps.

Kostenlos testen →