Tips & Tricks (Diperbarui: 2/6/2026)

Generate Dokumentasi dengan Claude Code: README, API, ADR, dan Verifikasi

Buat README, OpenAPI, ADR, dan changelog dengan Claude Code, lalu verifikasi memakai script Node praktis.

Generate Dokumentasi dengan Claude Code: README, API, ADR, dan Verifikasi

Dokumentasi yang dibuat AI tetap harus berbasis bukti

README, spesifikasi API, ADR, dan changelog sering tertinggal dari kode. Tim biasanya fokus membuat fitur, memperbaiki bug, dan melakukan rilis. Dokumentasi baru terasa penting ketika orang baru mencoba menjalankan proyek, atau ketika pengguna API menemukan respons yang berbeda dari contoh di docs.

Claude Code bisa mempercepat pekerjaan ini karena dapat membaca codebase, mengedit file, dan menjalankan perintah. Hal itu dijelaskan di dokumentasi resmi Claude Code overview. Tetapi kemampuan yang sama juga bisa menghasilkan risiko: Claude Code dapat menulis perintah yang tidak ada, endpoint yang belum dibuat, atau alasan arsitektur yang terdengar masuk akal tetapi tidak pernah diputuskan tim.

Workflow yang aman bukan sekadar meminta “buatkan dokumentasi”. Kita perlu memberi bukti, membatasi scope perubahan, lalu memverifikasi hasilnya. Artikel ini menunjukkan cara membuat konteks repositori, menjalankan skill Claude Code, mengisi README/OpenAPI/ADR/CHANGELOG, dan mengecek semuanya dengan script Node. Untuk catatan akhir pekerjaan, gabungkan dengan workflow verification receipt Claude Code.

Alur kerja: konteks, generasi, verifikasi, keputusan manusia

Prompt “perbaiki README” terlalu luas. Claude Code bisa menebak berdasarkan file yang kebetulan sudah dibaca. Lebih stabil jika kita membuat ringkasan dari package.json, status git, commit terbaru, dan dokumentasi yang sudah ada.

flowchart LR
  A["Diff kode"] --> B["doc-context.mjs"]
  B --> C["Skill Claude Code"]
  C --> D["README / OpenAPI / ADR / CHANGELOG"]
  D --> E["verify-docs.mjs"]
  E --> F["Keputusan publish manusia"]

ADR adalah Architecture Decision Record, yaitu catatan singkat tentang alasan sebuah keputusan teknis. OpenAPI adalah format untuk menjelaskan route, request, dan response API secara terstruktur. Keduanya tidak perlu rumit di awal. Yang penting, isinya bisa diperiksa.

Membuat konteks repositori

Simpan script ini sebagai scripts/doc-context.mjs, lalu jalankan node scripts/doc-context.mjs dari root repositori. Output-nya adalah docs/_generated/doc-context.md, bahan kerja untuk Claude Code.

import { execSync } from "node:child_process";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import path from "node:path";

function run(command) {
  try {
    return execSync(command, {
      encoding: "utf8",
      stdio: ["ignore", "pipe", "pipe"],
    }).trim();
  } catch {
    return "";
  }
}

function readIfExists(filePath) {
  return existsSync(filePath) ? readFileSync(filePath, "utf8") : "";
}

const root = process.cwd();
const outDir = path.join(root, "docs", "_generated");
mkdirSync(outDir, { recursive: true });

const packageJson = readIfExists("package.json");
const packageSummary = packageJson
  ? JSON.stringify(JSON.parse(packageJson).scripts ?? {}, null, 2)
  : "{}";
const fence = String.fromCharCode(96, 96, 96);

const trackedFiles = run("git ls-files")
  .split(/\r?\n/)
  .filter(Boolean)
  .filter((file) => !file.startsWith("node_modules/"))
  .filter((file) => !file.startsWith("dist/"))
  .filter((file) => !file.startsWith(".git/"))
  .slice(0, 400);

const changedFiles = run("git status --short") || "(no uncommitted changes)";
const recentCommits = run("git log --oneline -8") || "(no commits found)";

const content = [
  "# Documentation Context",
  "",
  "## Package scripts",
  `${fence}json`,
  packageSummary,
  fence,
  "",
  "## Changed files",
  `${fence}text`,
  changedFiles,
  fence,
  "",
  "## Recent commits",
  `${fence}text`,
  recentCommits,
  fence,
  "",
  "## Tracked file sample",
  `${fence}text`,
  trackedFiles.join("\n"),
  fence,
  "",
].join("\n");

const outFile = path.join(outDir, "doc-context.md");
writeFileSync(outFile, content);
console.log(`Wrote ${outFile}`);

File ini bukan dokumentasi publik. Ini adalah konteks untuk agent. Menaruhnya di docs/_generated membantu reviewer membedakan bahan kerja AI dan dokumentasi yang memang ditulis untuk pembaca.

Membuat skill Claude Code untuk refresh dokumentasi

Claude Code memakai skill untuk prosedur yang berulang. Dokumentasi resmi skills and slash commands menjelaskan bahwa SKILL.md bisa membuat command seperti /docs-refresh; file lama di .claude/commands/ tetap didukung.

Buat .claude/skills/docs-refresh/SKILL.md:

---
description: Refresh README, OpenAPI, ADR, and changelog from current code and generated documentation context.
---

## Inputs to inspect first

- Repository context: @docs/_generated/doc-context.md
- README: @README.md
- Existing docs: @docs
- Package metadata: @package.json

## Task

Update documentation only where the current code, package scripts, or git diff prove that the text is stale.

Required outputs:

1. README: setup steps, commands, environment notes, and troubleshooting.
2. OpenAPI: update `docs/api/openapi.yaml` when API routes changed.
3. ADR: create `docs/adr/NNNN-short-title.md` when a new architectural decision is visible.
4. CHANGELOG: add a draft entry under `Unreleased` when user-facing behavior changed.

Rules:

- Do not invent endpoints, commands, environment variables, prices, or dates.
- If evidence is missing, write a short "needs confirmation" note instead of guessing.
- Keep secret names generic. Never copy `.env` values into docs.
- After editing, run `node scripts/verify-docs.mjs` and report the result.

Bagian “documentation only” penting agar tugas docs tidak berubah menjadi perubahan kode. Untuk kerja tim, baca juga panduan permissions Claude Code supaya jelas perintah mana yang boleh dijalankan dan file mana yang tidak boleh dibaca.

Contoh 1: README sebagai panduan onboarding

README yang baik bukan brosur. Ia harus membantu orang yang baru clone repositori: cara install, menjalankan server, menjalankan test, mengatasi error umum, dan membaca dokumen berikutnya.

# Task API

## Getting started

```bash
npm ci
npm run dev
```

## Commands

| Command | Purpose |
| --- | --- |
| `npm run dev` | Start the local server |
| `npm run test` | Run unit tests |
| `npm run docs:context` | Generate documentation context |
| `npm run docs:verify` | Verify documentation files |

## Troubleshooting

- If install fails, delete `node_modules` and run `npm ci` again.
- If API examples fail, confirm the server is running on the documented port.
- If generated docs mention unknown env vars, check `.env.example`, not `.env`.

Saat meminta Claude Code mengubah README, sebutkan pembacanya. “Developer baru setelah clone repo” jauh lebih jelas daripada “buat lebih bagus”.

Contoh 2: API spec dengan OpenAPI

Dokumentasi API dalam bentuk paragraf sulit diverifikasi. Minta Claude Code membaca route, schema validasi, dan test sebelum memperbarui docs/api/openapi.yaml.

openapi: 3.1.0
info:
  title: Task API
  version: 0.1.0
  description: API for creating and listing tasks.
paths:
  /api/tasks:
    get:
      summary: List tasks
      responses:
        "200":
          description: Task list
          content:
            application/json:
              schema:
                type: object
                properties:
                  tasks:
                    type: array
                    items:
                      type: object
                      required: [id, title, status]
                      properties:
                        id:
                          type: string
                        title:
                          type: string
                        status:
                          type: string
                          enum: [todo, doing, done]
    post:
      summary: Create a task
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [title]
              properties:
                title:
                  type: string
      responses:
        "201":
          description: Created task

Jebakan utamanya adalah overcompletion. Jika API asli mengembalikan open, tetapi spec menulis todo, dokumentasi itu salah walaupun terlihat rapi.

Contoh 3: ADR untuk menyimpan alasan keputusan

ADR bukan log pekerjaan. Ia mencatat konteks, keputusan, dan konsekuensi.

# ADR-0001: Keep generated documentation under docs/_generated

## Status

Accepted

## Context

Claude Code needs a compact summary of the repository before refreshing documentation.
Putting generated context beside hand-written docs can confuse reviewers.

## Decision

Generated context files will be written to `docs/_generated/`.
Hand-written documentation stays in `docs/api`, `docs/adr`, and root README files.

## Consequences

- Reviewers can separate generated context from authored documentation.
- The context file can be regenerated before each documentation refresh.
- The verification script must ignore unstable generated content when checking prose quality.

Claude Code dapat membuat draft, tetapi alasan akhirnya tetap harus dikonfirmasi manusia. ADR akan dibaca sebagai keputusan tim.

Contoh 4: CHANGELOG sebagai draft Unreleased

CHANGELOG lebih aman jika dibuat saat perubahan masih segar. Minta Claude Code menulis di bawah Unreleased dan jangan menetapkan versi atau tanggal sebelum rilis dikonfirmasi.

# Changelog

## Unreleased

### Added

- Added documentation context generation for README, API specs, ADRs, and changelog updates.

### Changed

- Updated the documentation refresh workflow to verify generated files before publication.

### Needs confirmation

- Confirm the final release version and release date before moving this entry out of `Unreleased`.

Dengan cara ini, informasi tetap tersimpan tanpa berpura-pura bahwa rilis sudah terjadi.

Memverifikasi dokumentasi yang dihasilkan

Simpan script berikut sebagai scripts/verify-docs.mjs. Script ini memeriksa file wajib, frasa wajib, heading ADR, code fence, dan placeholder yang jelas belum selesai.

import { existsSync, readdirSync, readFileSync } from "node:fs";
import path from "node:path";

const requiredFiles = [
  {
    file: "README.md",
    phrases: ["## Getting started", "## Commands"],
  },
  {
    file: "docs/api/openapi.yaml",
    phrases: ["openapi: 3.", "paths:"],
  },
  {
    file: "CHANGELOG.md",
    phrases: ["## Unreleased"],
  },
];

function read(file) {
  return readFileSync(file, "utf8");
}

function listMarkdownFiles(dir) {
  if (!existsSync(dir)) return [];
  return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
    const fullPath = path.join(dir, entry.name);
    if (entry.isDirectory()) return listMarkdownFiles(fullPath);
    return entry.isFile() && /\.(md|mdx)$/.test(entry.name) ? [fullPath] : [];
  });
}

const errors = [];

for (const item of requiredFiles) {
  if (!existsSync(item.file)) {
    errors.push(`${item.file}: missing file`);
    continue;
  }

  const source = read(item.file);
  for (const phrase of item.phrases) {
    if (!source.includes(phrase)) {
      errors.push(`${item.file}: missing phrase "${phrase}"`);
    }
  }
}

for (const adr of listMarkdownFiles("docs/adr")) {
  const source = read(adr);
  for (const heading of ["## Status", "## Context", "## Decision", "## Consequences"]) {
    if (!source.includes(heading)) {
      errors.push(`${adr}: missing ${heading}`);
    }
  }
}

for (const file of ["README.md", "CHANGELOG.md", ...listMarkdownFiles("docs")]) {
  if (!existsSync(file)) continue;
  const source = read(file);
  const fenceMarker = String.fromCharCode(96, 96, 96);
  const fenceCount = (source.match(new RegExp(fenceMarker, "g")) ?? []).length;
  if (fenceCount % 2 !== 0) errors.push(`${file}: unbalanced code fence`);
  if (/TODO|TBD|REPLACE_ME/.test(source)) {
    errors.push(`${file}: unresolved placeholder remains`);
  }
}

if (errors.length > 0) {
  console.error("Documentation verification failed:");
  for (const error of errors) console.error(`- ${error}`);
  process.exit(1);
}

console.log("Documentation verification passed.");

Tambahkan ke package.json:

{
  "scripts": {
    "docs:context": "node scripts/doc-context.mjs",
    "docs:verify": "node scripts/verify-docs.mjs"
  }
}

Dokumentasi resmi settings menjelaskan pemisahan setting project dan local. Awali dengan mengizinkan script docs dan menolak file rahasia.

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "Bash(node scripts/doc-context.mjs)",
      "Bash(node scripts/verify-docs.mjs)",
      "Read(README.md)",
      "Read(docs/**)",
      "Read(src/**)"
    ],
    "deny": [
      "Read(.env)",
      "Read(.env.*)",
      "Read(secrets/**)",
      "Bash(curl *)"
    ]
  }
}

Jika nanti ingin pemeriksaan otomatis setelah file diedit, baca referensi resmi hooks. Mulai dari manual dulu, lalu otomatisasi hanya hal yang benar-benar harus memblokir workflow.

Kesalahan yang sering terjadi

Pertama, mendokumentasikan command yang tidak ada. Command README harus berasal dari package.json, Makefile, atau CI.

Kedua, mengarang perilaku API. OpenAPI yang rapi tetapi salah akan membuat integrasi makin sulit.

Ketiga, membocorkan rahasia. .env, token, nama pelanggan, dan URL internal tidak boleh masuk dokumentasi.

Keempat, memublikasikan konteks internal. docs/_generated/doc-context.md adalah input untuk Claude Code, bukan manual pengguna.

Kelima, menjalankan verifikasi terlalu akhir. Jalankan docs:context dan docs:verify saat diff masih kecil.

Template, produk, dan konsultasi

Untuk proyek pribadi, dua script Node dan skill docs-refresh sudah cukup. Jika ingin instruksi jangka panjang, gabungkan dengan panduan praktik terbaik CLAUDE.md.

Untuk langkah ringan, gunakan cheat sheet Claude Code gratis agar command verifikasi mudah diingat. Jika setiap minggu kamu mengulang prompt README, review, debugging, dan dokumentasi, template Gumroad bisa menghemat waktu.

Untuk tim, tantangan utamanya adalah siapa yang menyetujui, error dokumentasi apa yang memblokir publikasi, dan bagaimana CTA Gumroad atau konsultasi dicek. Untuk itu, konsultasi implementasi lebih efektif karena aturan dibuat berdasarkan repositori nyata.

Hasil setelah saya coba

Saya mencoba workflow ini dengan membuat doc-context.md, memisahkan tanggung jawab README, OpenAPI, ADR, dan CHANGELOG, lalu menjalankan verify-docs.mjs. Dibanding prompt umum “tulis README”, command palsu berkurang dan ADR lebih mudah ditinjau. Spesifikasi API tetap perlu dibandingkan dengan respons nyata oleh manusia. Tujuan terbaiknya bukan dokumentasi yang sepenuhnya otomatis, melainkan draft cepat dengan bukti jelas dan titik verifikasi yang tegas.

#Claude Code #documentation #JSDoc #API specs #auto-generation
Gratis

PDF gratis: cheatsheet Claude Code

Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.

Kami menjaga datamu dan tidak mengirim spam.

Masa

Tentang penulis

Masa

Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.