Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
23 Sep 2026 · 21 mnt baca ·Artikel 51 / 208
Go

Context Files AI Tools Golang: CLAUDE.md, .cursorrules, Copilot Instructions Perbandingan

Cara menulis context files yang optimal untuk semua AI coding tools. CLAUDE.md, .cursorrules, copilot-instructions.md, dan .windsurf/rules.md untuk Golang project production.

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

Context Files: CLAUDE.md vs .cursorrules vs Copilot Instructions

Context files adalah leverage terbesar dalam menggunakan AI coding tools untuk Golang. Benchmark kami menunjukkan bahwa CLAUDE.md yang baik meningkatkan Claude Code score dari 62/100 ke 94/100 — lompatan yang tidak bisa didapat dari mengganti model atau tool. Artikel ini adalah panduan definitif menulis context files yang optimal untuk setiap tool: CLAUDE.md, .cursorrules, copilot-instructions.md, hingga .windsurf/rules.md.


11.1 Mengapa Context Files Sangat Penting

Tanpa context file, setiap AI coding tool mulai dari nol setiap sesi. Perbandingan berikut menunjukkan selisih output yang dihasilkan untuk perintah yang sama persis.

text
1Tanpa context file:
2  AI: "Implement error handling"
3  → Generates: return errors.New("failed")
4  Developer edit: butuh 5-10 menit
5
6Dengan context file yang baik:
7  AI: "Implement error handling"
8  → Generates: return fmt.Errorf("orderRepo.GetByID: %w", err)
9  Developer edit: 30 detik (review saja)

Selisih 5 menit per edit terlihat kecil, tapi berlipat: 50 kali per hari = 250 menit = 4+ jam per hari, atau 80+ jam per developer per bulan. Context file adalah multiplier, bukan nice-to-have.


11.2 Comparison: Semua Context Files

Setiap tool punya nama file, format, dan model persistensi sendiri. Tabel berikut merangkum keenamnya agar kamu tahu file mana yang harus dibuat untuk tool yang dipakai.

text
1Tool              File Name                    Format      Persistence
2────────────────────────────────────────────────────────────────────
3Claude Code       CLAUDE.md                    Markdown    Per-session + CLAUDE.md
4Cursor            .cursorrules                 Text        Per-session + file
5GitHub Copilot    .github/copilot-instructions Markdown    Per-query + file
6AWS Kiro          .kiro/steering/*.md          Markdown    Always-on
7Windsurf          .windsurf/rules.md           Markdown    Per-session + Cascade
8Gemini            STYLE_GUIDE.md (implicit)    Markdown    Per-query (implicit)

Perhatikan kolom Persistence: hanya Kiro yang “always-on”, sisanya dibaca per-session atau per-query — inilah alasan CLAUDE.md yang dibaca eksplisit di awal sesi menjadi yang paling powerful.


11.3 CLAUDE.md: Struktur yang Optimal

CLAUDE.md paling powerful karena Claude Code membacanya secara eksplisit di awal setiap sesi. Template lengkap berikut adalah kerangka yang bisa langsung kamu adaptasi untuk Go project production.

text
  1# CLAUDE.md — Template Optimal untuk Go Project
  2
  3## Identity & Purpose (REQUIRED)
  4Project ini adalah [deskripsi singkat].
  5Go version: [exact version].
  6Production service dengan [traffic scale].
  7
  8## Architecture (CRITICAL — violating this = production bug)
  9
 10### Layer Structure
 11delivery/http/handler/    ← HTTP request/response only
 12internal/usecase/         ← business logic only
 13internal/repository/      ← data access only
 14internal/domain/          ← entities, interfaces, errors (pure Go)
 15
 16### Import Rules (STRICT)
 17- handler: ONLY import usecase interfaces (never impl)
 18- usecase: ONLY import domain types + repository INTERFACES
 19- repository impl: ONLY import domain + database drivers
 20- domain: ZERO external imports (stdlib only)
 21
 22VIOLATION EXAMPLE (NEVER do this):
 23  // in usecase — WRONG
 24  import "github.com/jackc/pgx/v5"  // infrastructure in usecase
 25
 26CORRECT:
 27  // usecase only sees interface
 28  type OrderRepository interface {
 29      GetByIDAndUserID(ctx context.Context, orderID, userID uuid.UUID) (*domain.Order, error)
 30  }
 31
 32## Error Handling (CRITICAL)
 33
 34### Repository Layer
 35// NOT FOUND — return (nil, nil) ALWAYS, never error
 36if errors.Is(err, pgx.ErrNoRows) {
 37    return nil, nil
 38}
 39// DB ERROR — wrap dengan exact format
 40return nil, fmt.Errorf("orderRepository.GetByIDAndUserID: %w", err)
 41
 42### Usecase Layer
 43// Check nil from repo (= not found case)
 44order, err := uc.repo.GetByIDAndUserID(ctx, input.OrderID, input.UserID)
 45if err != nil {
 46    return fmt.Errorf("cancelOrder.Execute: %w", err)
 47}
 48if order == nil {
 49    return domain.ErrOrderNotFound  // domain error type
 50}
 51// Business rule error
 52if !order.CanBeCancelled() {
 53    return &domain.OrderNotCancellableError{Status: order.Status}
 54}
 55
 56### Handler Layer
 57// Map domain errors to HTTP
 58if errors.Is(err, domain.ErrOrderNotFound) {
 59    return c.JSON(http.StatusNotFound, map[string]string{
 60        "error": "ORDER_NOT_FOUND",  // UPPERCASE_SNAKE_CASE always
 61    })
 62}
 63
 64## Type Rules (ABSOLUTE)
 65- Monetary: ALWAYS int64 cents
 66  WRONG: Price float64 = 50000.0
 67  RIGHT: PriceIDR int64 = 5000000  // Rp 50,000 = 5,000,000 cents
 68- IDs: ALWAYS uuid.UUID (github.com/google/uuid)
 69- Never use: float32, float64 for money
 70
 71## Context Propagation
 72- ctx is ALWAYS first parameter: func(ctx context.Context, ...)
 73- ALWAYS pass ctx to all downstream calls (repo, cache, kafka)
 74- For background operations: context.Background() with timeout
 75  ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 76  defer cancel()
 77
 78## Testing
 79Framework: testify/suite (github.com/stretchr/testify/suite)
 80Mocking: gomock (go.uber.org/mock/gomock)
 81
 82// REQUIRED pattern for usecase tests:
 83type CancelOrderSuite struct {
 84    suite.Suite
 85    ctrl     *gomock.Controller
 86    mockRepo *mock.MockOrderRepository
 87    uc       *CancelOrderUseCase
 88}
 89
 90func (s *CancelOrderSuite) SetupTest() {
 91    s.ctrl = gomock.NewController(s.T())
 92    s.mockRepo = mock.NewMockOrderRepository(s.ctrl)
 93    s.uc = NewCancelOrderUseCase(s.mockRepo)
 94}
 95
 96func (s *CancelOrderSuite) TearDownTest() {
 97    s.ctrl.Finish()
 98}
 99
100func TestCancelOrderSuite(t *testing.T) {
101    suite.Run(t, new(CancelOrderSuite))
102}
103
104Test naming: Test[Subject]_[Scenario]_[ExpectedResult]
105Example: TestCancelOrder_PendingStatus_ReturnSuccess
106
107## Go Version Constraints
108Go 1.22 ONLY. DO NOT USE:
109- range-over-func (Go 1.23)
110- slices.Collect (Go 1.23)
111- iter.Seq (Go 1.23)
112
113## Exact Package Imports
114// Always use these exact paths:
115"github.com/jackc/pgx/v5"           // NOT pgx/v4
116"github.com/redis/go-redis/v9"       // NOT v8
117"github.com/labstack/echo/v4"
118"github.com/confluentinc/confluent-kafka-go/v2"
119"github.com/google/uuid"
120"github.com/rs/zerolog"
121"go.uber.org/mock/gomock"            // NOT github.com/golang/mock
122
123## HTTP Response Format
124// Success 200/201:
125{"id": "uuid", "status": "PENDING", ...}
126
127// Error 4xx/5xx:
128{"error": "UPPERCASE_SNAKE_CASE_CODE"}
129
130// Error codes: ORDER_NOT_FOUND, ORDER_NOT_CANCELLABLE,
131//              CANCEL_WINDOW_EXPIRED, UNAUTHORIZED,
132//              FORBIDDEN, INVALID_REQUEST, INTERNAL_ERROR
133
134## What NOT to do (ABSOLUTE)
1351. NEVER float64/float32 for money
1362. NEVER ignore errors with _  (except explicitly tested)
1373. NEVER return DB-specific error from repository (expose nil, nil or wrapped)
1384. NEVER create interface > 5 methods (split to smaller interfaces)
1395. NEVER import infrastructure from domain
1406. NEVER hardcode config values (use env vars via config struct)
1417. NEVER use global mutable state (use DI via constructor)

Yang membuat template ini efektif bukan panjangnya, tapi setiap aturan disertai pasangan WRONG vs CORRECT dan contoh kode konkret — inilah yang membuat AI mengikuti konvensi project sejak generasi pertama.


11.4 .cursorrules: Style yang Berbeda, Content yang Sama

.cursorrules paling efektif dengan gaya conversational plus contoh. Versi berikut memuat aturan yang sama dengan CLAUDE.md, tapi ditulis sebagai instruksi persona senior developer.

text
 1# .cursorrules — Santekno Shop Go Project
 2
 3You are a senior Go developer working on Santekno Shop, a production 
 4e-commerce platform. Always follow these rules:
 5
 6## Architecture
 7Clean Architecture with strict layer separation:
 8  delivery/http/handler → usecase → repository → domain
 9
10The HANDLER layer only speaks to usecases (via interface).
11The USECASE layer only speaks to repositories (via interface) and domain.
12The REPOSITORY layer only speaks to databases and domain types.
13The DOMAIN layer has ZERO external dependencies.
14
15If you violate this, the code will not compile OR will create 
16circular dependencies that are hard to debug.
17
18## Error Handling — Follow This EXACTLY
19
20When writing repository code:
21  - If record not found: return nil, nil — NEVER return an error
22  - If database error: return nil, fmt.Errorf("repoName.MethodName: %w", err)
23
24Example (CORRECT):
25  if errors.Is(err, pgx.ErrNoRows) {
26      return nil, nil  // correct: not found is not an error
27  }
28  return nil, fmt.Errorf("orderRepository.GetByID: %w", err)
29
30When writing usecase code:
31  - Check for nil (= not found from repo) BEFORE business logic
32  - Use domain error types, not raw errors
33
34Example (CORRECT):
35  order, err := uc.repo.GetByID(ctx, id)
36  if err != nil {
37      return fmt.Errorf("cancelOrder.Execute: %w", err)
38  }
39  if order == nil {
40      return domain.ErrOrderNotFound  // this is a domain error
41  }
42
43## Money — CRITICAL
44NEVER use float64 or float32 for monetary values.
45ALWAYS use int64 representing cents.
46
47WRONG: Price float64 = 50000.0
48RIGHT: PriceIDR int64 = 5000000  // 50000 rupiah = 5000000 cents
49
50## Testing Pattern
51Always use this structure for usecase tests:
52  type [Name]Suite struct {
53      suite.Suite
54      ctrl *gomock.Controller
55      mock[Repo] *mock.Mock[Interface]
56      uc *[UseCase]
57  }
58  func (s *[Name]Suite) SetupTest() {
59      s.ctrl = gomock.NewController(s.T())
60      // setup mocks
61  }
62  func (s *[Name]Suite) TearDownTest() { s.ctrl.Finish() }
63  func Test[Name]Suite(t *testing.T) { suite.Run(t, new([Name]Suite)) }
64
65## Go Version
66This is Go 1.22. Do NOT use Go 1.23 features.
67Do not use: range-over-func, slices.Collect, iter.Seq.
68
69## Package Imports
70Use exact versions:
71  - DB: github.com/jackc/pgx/v5
72  - Cache: github.com/redis/go-redis/v9
73  - HTTP: github.com/labstack/echo/v4
74  - Mocking: go.uber.org/mock/gomock

Perhatikan pembukaan “You are a senior Go developer…” — gaya persona plus imperatif (“NEVER”, “ALWAYS”) inilah yang membuat Cursor lebih patuh dibanding daftar aturan datar.


11.5 copilot-instructions.md: Format untuk Copilot

GitHub Copilot membaca .github/copilot-instructions.md. Versi berikut memadatkan aturan yang sama menjadi format terstruktur dengan penanda “violation = production incident”.

text
 1# .github/copilot-instructions.md
 2# Santekno Shop — Copilot Instructions
 3
 4## Overview
 5Production Go 1.22 e-commerce service. High-traffic, Clean Architecture.
 6Every suggestion must match these standards or it creates production bugs.
 7
 8## CRITICAL RULES (violation = production incident)
 9
10### 1. Error Handling
11Repository not-found: MUST return (nil, nil)
12// CORRECT:
13if errors.Is(err, pgx.ErrNoRows) {
14    return nil, nil
15}
16// INCORRECT:
17return nil, pgx.ErrNoRows
18return nil, errors.New("not found")
19
20### 2. Monetary Types
21MUST use int64 cents. NEVER float64.
22// CORRECT: PriceIDR int64 = 5000000 (Rp 50,000)
23// INCORRECT: Price float64 = 50000.0
24
25### 3. Error Wrapping
26MUST wrap with function context:
27// CORRECT:
28return fmt.Errorf("orderRepository.GetByID: %w", err)
29// INCORRECT:
30return err
31return errors.New("database error")
32
33### 4. Context
34MUST pass ctx as first parameter to ALL functions.
35MUST propagate ctx to all downstream calls (repo, cache, kafka).
36
37### 5. HTTP Response Format
38MUST use: {"error": "UPPERCASE_SNAKE_CASE_CODE"}
39NEVER use: {"message": "..."} or {"error": "lowercase"}
40
41## Architecture
42Clean Architecture. Layers: handler → usecase → repository → domain.
43No cross-layer imports. Domain has zero external dependencies.
44
45## Testing
46testify/suite + gomock pattern ALWAYS.
47No real database in unit tests.
48
49## Packages
50pgx/v5, go-redis/v9, echo/v4, confluent-kafka-go/v2, uuid, zerolog.
51
52## Go: 1.22 only. No 1.23+ features.

Karena Copilot membaca per-query (bukan per-session penuh), format ringkas dengan CRITICAL RULES di atas ini memastikan aturan terpenting selalu tertangkap meski konteksnya dipangkas.


11.6 .windsurf/rules.md: Format untuk Windsurf

Windsurf membaca .windsurf/rules.md secara terpisah dan mengandalkan Cascade untuk retensi antar sesi. Format berikut sengaja dibuat paling ringkas dari semua tool.

text
 1# .windsurf/rules.md
 2# Santekno Shop — Windsurf Rules
 3
 4## Project
 5Go 1.22 production e-commerce. Echo v4, pgx/v5, Redis, Kafka.
 6Clean Architecture (handler → usecase → repository → domain).
 7
 8## Architecture Rules
 9- handler: only import usecase interfaces
10- usecase: only import domain + repository interfaces
11- repository: only import domain + database drivers
12- domain: ZERO external imports
13
14## Error Handling
15Repository layer:
16  - Not found: return nil, nil  (this is correct, not a bug)
17  - DB error: return nil, fmt.Errorf("repoName.Method: %w", err)
18
19Usecase layer:
20  - Check nil from repo → return domain error type
21  - Wrap upstream errors: fmt.Errorf("usecase.Method: %w", err)
22
23Handler layer:
24  - Map domain errors to HTTP codes
25  - Response: {"error": "UPPERCASE_ERROR_CODE"}
26
27## Types
28Money: int64 cents ONLY (50000 Rp = 5000000 int64)
29IDs: uuid.UUID from github.com/google/uuid
30
31## Testing
32testify/suite + gomock. No real DB in unit tests.
33Pattern: Suite struct → SetupTest → TearDownTest → Suite.Run
34
35## Imports
36Use exactly: pgx/v5, go-redis/v9, echo/v4, kafka-go/v2
37
38## Go 1.22 only
39No: range-over-func, slices.Collect, iter.Seq

Karena Cascade sudah menangani retensi konteks antar sesi, kamu bisa menulis rules Windsurf lebih ringkas daripada CLAUDE.md tanpa kehilangan efektivitas.


11.7 Sync: Satu Source, Multiple Formats

Tim yang memakai banyak tool harus menjaga banyak context file tetap sinkron. Script berikut men-derive semua file tool dari satu sumber CLAUDE.md.

bash
 1#!/bin/bash
 2# scripts/sync-context-files.sh
 3# Sync dari CLAUDE.md ke semua tools
 4
 5# 1. Extract sections dari CLAUDE.md
 6ARCH=$(sed -n '/^## Architecture/,/^## /p' CLAUDE.md | head -n -2)
 7ERRORS=$(sed -n '/^## Error Handling/,/^## /p' CLAUDE.md | head -n -2)
 8TYPES=$(sed -n '/^## Type Rules/,/^## /p' CLAUDE.md | head -n -2)
 9TESTING=$(sed -n '/^## Testing/,/^## /p' CLAUDE.md | head -n -2)
10IMPORTS=$(sed -n '/^## Exact Package/,/^## /p' CLAUDE.md | head -n -2)
11
12# 2. Update .cursorrules (convert headers to conversational)
13python3 scripts/convert_to_cursorrules.py CLAUDE.md > .cursorrules
14
15# 3. Update .github/copilot-instructions.md
16python3 scripts/convert_to_copilot.py CLAUDE.md > .github/copilot-instructions.md
17
18# 4. Update .windsurf/rules.md
19python3 scripts/convert_to_windsurf.py CLAUDE.md > .windsurf/rules.md
20
21# 5. Update .kiro/steering/
22python3 scripts/convert_to_kiro.py CLAUDE.md > .kiro/steering/project.md
23
24echo "✅ All context files synced from CLAUDE.md"

Jika tidak ingin memelihara script konversi, pendekatan praktisnya: jadikan CLAUDE.md sebagai single source of truth, salin bagian relevan secara manual saat setup tool baru, dan review konsistensinya setiap kuartal.


11.8 Kualitas Context File: Checklist

Context file yang baik memenuhi kriteria terukur, bukan sekadar “lengkap”. Checklist berikut memisahkan yang wajib, yang bagus dimiliki, dan yang harus dihindari — termasuk panduan panjang optimal.

text
 1Context file yang baik memenuhi checklist ini:
 2
 3MUST HAVE:
 4□ Go version yang exact (1.22, bukan "recent Go")
 5□ Architecture rules dengan contoh WRONG vs CORRECT
 6□ Error handling rules dengan code examples
 7□ Money type rules (int64 cents)
 8□ Exact package import paths
 9□ Testing framework dan pattern
10□ "What NOT to do" list
11
12GOOD TO HAVE:
13□ Project context (bukan generic)
14□ HTTP response format
15□ Context propagation rules
16□ Naming conventions
17□ Comment style (godoc format)
18
19AVOID:
20□ Rules tanpa code examples
21□ Context file yang terlalu panjang (> 300 baris mulai counter-productive)
22□ Generic rules yang sudah jelas (e.g., "write clean code")
23□ Outdated information (package v4 padahal sudah v5)
24□ Sensitive information (API keys, passwords)
25
26LENGTH GUIDE:
27  Minimum viable: 50-80 baris (basic rules)
28  Recommended: 150-200 baris (with examples)
29  Maximum effective: 300 baris
30  > 300 baris: diminishing returns, model bisa "forget" early sections

Catat angka kuncinya: 150-200 baris adalah sweet spot, dan di atas 300 baris justru kontra-produktif karena model mulai “melupakan” aturan di bagian awal file.


11.9 Context File untuk Specific Go Patterns

Beberapa pattern Go layak masuk context file tapi sering terlupa. Kumpulan berikut menambahkan interface design, constructor, concurrency, dan urutan middleware ke CLAUDE.md.

text
 1## Golang-specific Patterns (tambahkan ke CLAUDE.md)
 2
 3### Interface Design (Go Proverbs: accept interfaces, return structs)
 4Define interfaces at consumer side, NOT at producer side:
 5// CORRECT: interface di consumer (usecase)
 6type OrderRepository interface {
 7    GetByIDAndUserID(ctx context.Context, orderID, userID uuid.UUID) (*domain.Order, error)
 8    CancelWithStockRestore(ctx context.Context, orderID uuid.UUID) error
 9}
10
11// INCORRECT: interface di producer (repository)
12// Don't put interface in the repository package itself
13
14### Constructor Pattern
15Always use New[Name] constructor:
16// CORRECT:
17func NewCancelOrderUseCase(repo OrderRepository) *CancelOrderUseCase {
18    return &CancelOrderUseCase{repo: repo}
19}
20// INCORRECT:
21uc := &CancelOrderUseCase{}  // direct struct init without interface
22uc.repo = &postgresOrderRepository{...}  // direct impl, not interface
23
24### Goroutine and Concurrency
25Always handle goroutine lifecycle:
26// CORRECT:
27g, ctx := errgroup.WithContext(ctx)
28g.Go(func() error {
29    return processOrder(ctx, order)
30})
31if err := g.Wait(); err != nil {
32    return fmt.Errorf("worker group: %w", err)
33}
34
35// INCORRECT:
36go processOrder(ctx, order)  // fire and forget, no error handling
37
38### HTTP Middleware Order
39Echo middleware order matters (add to CLAUDE.md):
40// CORRECT order:
41e.Use(middleware.Recover())   // 1. panic recovery first
42e.Use(middleware.Logger())    // 2. then logging
43e.Use(middleware.CORS())      // 3. then CORS
44// Auth middleware: per-route, not global

Pattern seperti “accept interfaces, return structs” dan penanganan goroutine lifecycle sering diabaikan AI kecuali ditulis eksplisit — memasukkannya ke context file mencegah kelas bug konkurensi yang mahal.


11.10 Context File sebagai Onboarding Tool

CLAUDE.md yang baik juga berfungsi ganda sebagai dokumen onboarding developer baru. Bagian berikut menunjukkan format instruksi onboarding yang bisa ditambahkan ke file.

text
 1## Developer Onboarding (tambahkan ke CLAUDE.md)
 2
 3### Untuk Developer Baru
 4
 5Baca ini terlebih dahulu sebelum menulis kode apapun:
 6
 71. BACA arsitektur (section Architecture)
 82. BACA error handling (section Error Handling) — ini sangat penting
 93. JALANKAN existing tests: make test
104. IMPLEMENTASIKAN fitur paling kecil dulu:
11   Lihat existing [simple feature] sebagai referensi
125. TANYA jika ada yang tidak jelas:
13   Architecture violations adalah yang paling sering terjadi
14
15### Contoh Feature yang Bisa Dijadikan Referensi
16- Simple CRUD: [link ke existing feature]
17- Feature dengan Kafka: [link ke existing feature]
18- Feature dengan Redis cache: [link ke existing feature]
19
20### Common Mistakes (yang paling sering terjadi)
211. Return error dari repository untuk not-found (harusnya nil, nil)
222. Float64 untuk harga (harusnya int64 cents)
233. Import repository impl dari usecase (architecture violation)
244. Lupa context timeout untuk external calls

Keuntungan ganda ini nyata: satu file yang sama menyelaraskan AI dan manusia — developer baru dan AI tool sama-sama membaca aturan yang identik, jadi tidak ada divergensi konvensi.


11.11 Tools untuk Maintain Context Files

Context file bisa jadi usang tanpa disadari. Tiga perintah berikut membantu memvalidasi syntax dan mendeteksi package path yang tidak lagi cocok dengan go.mod.

bash
 1# Tool 1: Validate CLAUDE.md syntax
 2npx markdownlint CLAUDE.md
 3
 4# Tool 2: Check context file tidak outdated
 5# Check apakah package paths di CLAUDE.md masih match go.mod:
 6grep -oP 'github\.com/\S+' CLAUDE.md | while read pkg; do
 7    if ! grep -q "$pkg" go.mod; then
 8        echo "WARNING: $pkg in CLAUDE.md but not in go.mod"
 9    fi
10done
11
12# Tool 3: Check CLAUDE.md sudah cover semua domain packages
13for domain_pkg in $(find internal/domain -name "*.go" | head -5); do
14    pkg_name=$(grep "^package" $domain_pkg | awk '{print $2}')
15    echo "Checking if $pkg_name is mentioned in CLAUDE.md..."
16    grep -q "$pkg_name" CLAUDE.md && echo "✅ Found" || echo "⚠️ Not found"
17done

Otomasi kecil ini menutup celah paling umum: context file yang menyebut pgx/v4 padahal go.mod sudah pgx/v5 akan menyesatkan AI — validasi terhadap go.mod mencegahnya.


11.12 Context File Anti-Patterns yang Harus Dihindari

Sama pentingnya dengan tahu apa yang harus ditulis adalah tahu apa yang harus dihindari. Lima anti-pattern berikut disertai pasangan BAD vs GOOD agar mudah dikenali.

text
 1Anti-pattern 1: Too Generic
 2BAD:
 3  "Write clean, maintainable Go code"
 4  "Follow best practices"
 5
 6GOOD:
 7  "Use fmt.Errorf('package.Method: %w', err) for ALL error wrapping"
 8  "Return (nil, nil) for not-found from repository — never error"
 9
10Anti-pattern 2: No Code Examples
11BAD:
12  "Handle errors properly in repository"
13
14GOOD:
15  if errors.Is(err, pgx.ErrNoRows) {
16      return nil, nil
17  }
18  return nil, fmt.Errorf("repo.Method: %w", err)
19
20Anti-pattern 3: Outdated Rules
21BAD:
22  "Use github.com/golang/mock" (deprecated)
23
24GOOD:
25  "Use go.uber.org/mock/gomock (replaces golang/mock)"
26
27Anti-pattern 4: Too Long (>300 lines)
28  - Model attention dilutes untuk rules di awal file
29  - Prioritize yang paling sering violated
30  - Split ke multiple files jika perlu (CLAUDE.md dapat reference file lain)
31
32Anti-pattern 5: Conflicting Rules
33BAD:
34  "Always return error for not-found" (di satu section)
35  "Repository: return nil, nil for not-found" (di section lain)
36
37Review context file untuk consistency sebelum commit.

Anti-pattern yang paling berbahaya adalah nomor 5 (conflicting rules): aturan yang saling bertentangan membuat output AI tidak terprediksi — selalu review konsistensi sebelum commit.


11.13 Evolusi Context File: Cara Maintain

Context file adalah living document, bukan sekali tulis lalu ditinggal. Ritme review berikut menjaga file tetap relevan dari level sprint hingga kuartal.

text
 1Sprint-based evolution:
 2
 3Sprint end review:
 4  "Apa AI output yang paling sering perlu diedit minggu ini?"
 5  → Itu yang perlu ditambahkan ke context file
 6
 7Monthly review:
 8  □ Apakah semua package paths masih benar di go.mod?
 9  □ Apakah ada pattern baru yang established bulan ini?
10  □ Apakah ada rule yang tidak lagi relevant?
11  □ Apakah context file tetap di bawah 300 baris?
12  □ Apakah ada inconsistency antar tools (CLAUDE.md vs .cursorrules)?
13
14Quarterly review:
15  □ Go version update yang perlu update CLAUDE.md?
16  □ Architecture decision yang berubah?
17  □ New patterns yang worth documenting?
18
19PR workflow untuk CLAUDE.md updates:
20  → Perubahan ke CLAUDE.md perlu PR approval dari tech lead
21  → Bukan karena bureaucracy, tapi karena CLAUDE.md affects semua developer
22  → Treat seperti ADR — keputusan yang dokumented

Sinyal paling berharga ada di sprint review: apa pun yang berulang kali harus kamu edit dari output AI adalah kandidat langsung untuk ditambahkan ke context file.


11.14 Advanced: CLAUDE.md dengan Multiple Tool Support

Satu CLAUDE.md bisa memuat catatan spesifik per tool agar tim multi-tool tetap konsisten. Bagian advanced berikut menunjukkan cara menyisipkan instruksi per tool di dalam satu file.

text
 1# CLAUDE.md — Advanced Section
 2
 3## Tool-Specific Notes
 4
 5### Jika menggunakan Claude Code
 6Session ini diasumsikan pakai Claude Code CLI.
 7Kamu bisa langsung jalankan bash commands:
 8  go build ./...
 9  go test -race ./...
10  go generate ./...
11Lakukan ini setelah setiap implementation step.
12
13### Jika menggunakan Cursor
14Gunakan @file untuk reference specific files saat context dibutuhkan:
15  @file internal/usecase/order/cancel_order.go
16Cursor Agent Mode: gunakan untuk bulk implementation tapi selalu review diff.
17
18### Jika menggunakan Copilot
19Reference @workspace untuk project-level context.
20/tests untuk generate tests dari selected function.
21/explain untuk understand complex code.
22
23### Jika menggunakan Windsurf
24Windsurf baca rules.md secara terpisah di .windsurf/rules.md.
25Cascade akan maintain context antar sessions.

Pola ini menjaga aturan inti tetap satu, sementara nuansa tiap tool (misalnya @file untuk Cursor, /tests untuk Copilot) didokumentasikan di tempat yang sama — tidak ada pengetahuan yang tercecer di kepala masing-masing developer.


11.15 Context File ROI Calculator

Investasi menulis context file mudah dibenarkan dengan angka. Perhitungan berikut menunjukkan titik impas dan nilai tahunan per developer.

text
 1Hitung ROI dari investasi waktu setup context file:
 2
 3Setup time:
 4  Basic context file (100 baris): 1 jam
 5  Comprehensive (200 baris): 2-3 jam
 6  Full (300 baris dengan code examples): 4-5 jam
 7
 8Value per edit yang di-save:
 9  Tanpa context file: 5-10 menit edit AI output
10  Dengan context file: 30-60 detik review
11  Saving per edit: 4-9 menit
12
13Break-even calculation (comprehensive, 3 jam setup):
14  3 jam = 180 menit
15  Saving per edit: 5 menit average
16  Break-even: 180/5 = 36 edits
17
18Typical daily edits: 20-50 (coding day dengan heavy AI)
19Break-even: dalam 1-2 hari kerja!
20
21After break-even: pure savings.
22  20 edits/day × 5 menit × 250 working days/year = 25,000 menit = 416 jam/year
23
24Jika hourly rate = Rp 150,000/jam:
25  Value = 416 × 150,000 = Rp 62,400,000/tahun/developer
26  vs Setup cost = 3 jam × 150,000 = Rp 450,000
27
28ROI = 62,400,000 / 450,000 = 13,867%

Angkanya ekstrem tapi jujur: break-even dalam 1-2 hari kerja, lalu sisanya pure saving — inilah alasan context file adalah satu investasi engineering dengan ROI tertinggi yang bisa kamu lakukan minggu ini.


11.16 Template Repository: Context Files

Untuk tim, membuat template repository mempercepat setup project baru. Struktur berikut mengumpulkan semua template context file dalam satu repo.

bash
 1# Buat template repository untuk context files
 2# github.com/santekno/ai-context-templates
 3
 4├── golang/
 5│   ├── CLAUDE.md.template
 6│   ├── .cursorrules.template
 7│   ├── copilot-instructions.template.md
 8│   ├── windsurf-rules.template.md
 9│   └── kiro-steering.template.md
10├── scripts/
11│   ├── sync-context-files.sh
12│   └── validate-context-files.sh
13└── README.md
14
15# Usage:
16# 1. Copy template ke project
17cp ai-context-templates/golang/CLAUDE.md.template ./CLAUDE.md
18# 2. Customize dengan project-specific details
19# 3. Run sync script untuk generate tool-specific files

Dengan template repo terpusat, setiap project baru langsung mewarisi konvensi tim yang sudah teruji — tidak ada lagi CLAUDE.md yang ditulis ulang dari nol dengan kualitas yang tidak konsisten.


11.17 Tips & Gotchas

💡 Tip 1: Code examples > prose untuk setiap rule. “Return nil, nil for not-found” + code example = 2× lebih efektif dibanding prosa saja.

💡 Tip 2: WRONG vs CORRECT pairs. Tunjukkan secara eksplisit apa yang salah dan apa yang benar. AI lebih baik menghindari pattern yang eksplisit ditandai sebagai wrong.

💡 Tip 3: Update context file saat ada tech debt. Jika AI terus men-generate hal yang harus diedit, itu sinyal context file perlu update.

⚠️ Gotcha 1: Sensitive info. Jangan masukkan API keys, database passwords, atau internal URLs ke context file. File ini di-commit ke repo, jadi visible ke semua yang punya akses.

⚠️ Gotcha 2: Tool-specific syntax. CLAUDE.md yang bagus tidak otomatis berarti .cursorrules yang bagus — formatnya berbeda dan perlu adaptasi.


11.18 Context File untuk Open Source Go Projects

Project open source punya pertimbangan tambahan karena context file-nya publik. Poin-poin berikut menjelaskan bagaimana memanfaatkannya sebagai contribution guide.

text
 1Special considerations untuk open source:
 2
 31. Context file bisa public (aman)
 4   CLAUDE.md di-commit ke repo public
 5   → Contributors bisa lihat conventions
 6   → AI tools yang digunakan contributor juga akan follow rules
 7
 82. Gunakan untuk CONTRIBUTION GUIDE
 9   CLAUDE.md + CONTRIBUTING.md bisa overlap
10   AI tools akan follow CLAUDE.md
11   Humans bisa baca CONTRIBUTING.md
12
133. Versi di CLAUDE.md
14   Sama seperti dokumentasi, context file perlu versi
15   # CLAUDE.md v2.1 — last updated: 2026-07
16
174. Community-driven evolution
18   Contributors bisa PR update ke CLAUDE.md
19   Maintain sebagai living document

Untuk project open source, CLAUDE.md publik justru jadi aset: kontributor sekaligus AI tool mereka mengikuti konvensi yang sama, sehingga PR dari luar lebih konsisten dengan gaya proyek.


11.19 Checklist: Sebelum Context File “Production Ready”

Sebelum menandai context file siap pakai, lakukan verifikasi akhir. Checklist berikut memastikan setiap aturan sudah teruji, bukan sekadar tertulis.

text
 1□ Semua package paths di-verify dengan go.mod
 2□ Semua code examples valid Go syntax (test compile)
 3□ Architecture rules di-test: coba violation, apakah AI catch it?
 4□ Error handling rules di-test: coba generate repo, apakah return nil, nil?
 5□ Money type rules di-test: coba generate struct dengan price, float64 atau int64?
 6□ Testing pattern di-test: generate test, apakah pakai testify/suite?
 7□ File tidak ada sensitive information
 8□ File < 300 baris (jika lebih, prioritize atau split)
 9□ Reviewed oleh minimal 1 senior developer lain
10□ Di-commit ke repo dan di-mention di README

Poin yang paling sering dilewat adalah “di-test”: jangan hanya menulis aturan — coba picu pelanggarannya dan pastikan AI benar-benar menangkapnya sebelum context file dianggap production ready.


11.20 Ringkasan

Context files adalah investasi terbaik untuk tim yang menggunakan AI coding tools. ROI-nya luar biasa — break-even dalam 1-2 hari, lalu murni menjadi productivity gain.

Key takeaways:

  • CLAUDE.md: paling powerful, dibaca eksplisit di awal session
  • .cursorrules: conversational style dengan code examples
  • copilot-instructions.md: structured, code examples per rule
  • .windsurf/rules.md: concise, Cascade yang handle retention
  • STYLE_GUIDE.md: Gemini baca implicitly

Rekomendasi universal: Buat CLAUDE.md yang komprehensif sebagai single source of truth, lalu derive tools lain dari sana. Di artikel berikutnya kita naik satu level: memakai context file ini dalam workflow Test-Driven AI Development.

Artikel Terkait

💬 Komentar