litclaude-ai 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/CHANGELOG.md +155 -0
  2. package/LICENSE +21 -0
  3. package/README.md +369 -0
  4. package/README_ko-KR.md +374 -0
  5. package/RELEASE_CHECKLIST.md +165 -0
  6. package/bin/litclaude-ai.js +643 -0
  7. package/cover.png +0 -0
  8. package/docs/agents.md +67 -0
  9. package/docs/hooks.md +134 -0
  10. package/docs/lsp.md +40 -0
  11. package/docs/migration.md +209 -0
  12. package/docs/workflow-compatibility-audit.md +119 -0
  13. package/generate_cover.py +123 -0
  14. package/package.json +48 -0
  15. package/plugins/litclaude/.claude-plugin/plugin.json +25 -0
  16. package/plugins/litclaude/.lsp.json +13 -0
  17. package/plugins/litclaude/.mcp.json +9 -0
  18. package/plugins/litclaude/agents/boulder-executor.md +12 -0
  19. package/plugins/litclaude/agents/librarian-researcher.md +15 -0
  20. package/plugins/litclaude/agents/oracle-verifier.md +16 -0
  21. package/plugins/litclaude/agents/prometheus-planner.md +13 -0
  22. package/plugins/litclaude/agents/qa-runner.md +16 -0
  23. package/plugins/litclaude/agents/quality-reviewer.md +17 -0
  24. package/plugins/litclaude/bin/litclaude-hook.js +110 -0
  25. package/plugins/litclaude/bin/litclaude-hud.js +271 -0
  26. package/plugins/litclaude/bin/litclaude-lsp-doctor.js +15 -0
  27. package/plugins/litclaude/bin/litclaude-mcp.js +70 -0
  28. package/plugins/litclaude/commands/deep-interview.md +21 -0
  29. package/plugins/litclaude/commands/dynamic-workflow.md +36 -0
  30. package/plugins/litclaude/commands/lit-loop.md +40 -0
  31. package/plugins/litclaude/commands/lit-plan.md +35 -0
  32. package/plugins/litclaude/commands/litgoal.md +30 -0
  33. package/plugins/litclaude/commands/review-work.md +35 -0
  34. package/plugins/litclaude/commands/start-work.md +36 -0
  35. package/plugins/litclaude/hooks/hooks.json +54 -0
  36. package/plugins/litclaude/lib/context-pressure.mjs +25 -0
  37. package/plugins/litclaude/lib/hud-accent-palette.mjs +58 -0
  38. package/plugins/litclaude/lib/litgoal/cli.mjs +266 -0
  39. package/plugins/litclaude/lib/litgoal/ledger.mjs +16 -0
  40. package/plugins/litclaude/lib/litgoal/paths.mjs +7 -0
  41. package/plugins/litclaude/lib/litgoal/state.mjs +67 -0
  42. package/plugins/litclaude/lib/mutated-file-paths.mjs +63 -0
  43. package/plugins/litclaude/lib/start-work-continuation.mjs +99 -0
  44. package/plugins/litclaude/lib/workflow-check.mjs +83 -0
  45. package/plugins/litclaude/skills/ai-slop-remover/SKILL.md +142 -0
  46. package/plugins/litclaude/skills/comment-checker/SKILL.md +55 -0
  47. package/plugins/litclaude/skills/debugging/SKILL.md +70 -0
  48. package/plugins/litclaude/skills/debugging/references/methodology/00-setup.md +108 -0
  49. package/plugins/litclaude/skills/debugging/references/methodology/02-investigate.md +126 -0
  50. package/plugins/litclaude/skills/debugging/references/methodology/04-oracle-triple.md +106 -0
  51. package/plugins/litclaude/skills/debugging/references/methodology/05-escalate.md +69 -0
  52. package/plugins/litclaude/skills/debugging/references/methodology/06-fix.md +116 -0
  53. package/plugins/litclaude/skills/debugging/references/methodology/08-qa.md +94 -0
  54. package/plugins/litclaude/skills/debugging/references/methodology/09-cleanup.md +164 -0
  55. package/plugins/litclaude/skills/debugging/references/methodology/partial-runtime-evidence.md +228 -0
  56. package/plugins/litclaude/skills/debugging/references/runtimes/bundled-js-binary.md +415 -0
  57. package/plugins/litclaude/skills/debugging/references/runtimes/go.md +252 -0
  58. package/plugins/litclaude/skills/debugging/references/runtimes/native-binary.md +484 -0
  59. package/plugins/litclaude/skills/debugging/references/runtimes/node.md +260 -0
  60. package/plugins/litclaude/skills/debugging/references/runtimes/python.md +248 -0
  61. package/plugins/litclaude/skills/debugging/references/runtimes/rust.md +234 -0
  62. package/plugins/litclaude/skills/debugging/references/tools/ghidra.md +212 -0
  63. package/plugins/litclaude/skills/debugging/references/tools/playwright-cli.md +194 -0
  64. package/plugins/litclaude/skills/debugging/references/tools/pwndbg.md +263 -0
  65. package/plugins/litclaude/skills/debugging/references/tools/pwntools.md +265 -0
  66. package/plugins/litclaude/skills/deep-interview/SKILL.md +323 -0
  67. package/plugins/litclaude/skills/deep-interview/scripts/render_progress.py +193 -0
  68. package/plugins/litclaude/skills/frontend-ui-ux/SKILL.md +62 -0
  69. package/plugins/litclaude/skills/lit-loop/SKILL.md +144 -0
  70. package/plugins/litclaude/skills/lit-plan/SKILL.md +125 -0
  71. package/plugins/litclaude/skills/litgoal/SKILL.md +219 -0
  72. package/plugins/litclaude/skills/lsp/SKILL.md +63 -0
  73. package/plugins/litclaude/skills/programming/SKILL.md +106 -0
  74. package/plugins/litclaude/skills/programming/references/go/README.md +90 -0
  75. package/plugins/litclaude/skills/programming/references/go/backend-stack.md +641 -0
  76. package/plugins/litclaude/skills/programming/references/go/bootstrap.md +328 -0
  77. package/plugins/litclaude/skills/programming/references/go/bubbletea-v2.md +360 -0
  78. package/plugins/litclaude/skills/programming/references/go/cobra-stack.md +468 -0
  79. package/plugins/litclaude/skills/programming/references/go/concurrency.md +362 -0
  80. package/plugins/litclaude/skills/programming/references/go/data-modeling.md +329 -0
  81. package/plugins/litclaude/skills/programming/references/go/error-handling.md +359 -0
  82. package/plugins/litclaude/skills/programming/references/go/golangci-strict.md +236 -0
  83. package/plugins/litclaude/skills/programming/references/go/grpc-connect.md +375 -0
  84. package/plugins/litclaude/skills/programming/references/go/libraries.md +337 -0
  85. package/plugins/litclaude/skills/programming/references/go/one-liners.md +202 -0
  86. package/plugins/litclaude/skills/programming/references/go/sqlc-pgx.md +471 -0
  87. package/plugins/litclaude/skills/programming/references/go/testing.md +467 -0
  88. package/plugins/litclaude/skills/programming/references/go/type-patterns.md +298 -0
  89. package/plugins/litclaude/skills/programming/references/python/README.md +314 -0
  90. package/plugins/litclaude/skills/programming/references/python/async-anyio.md +442 -0
  91. package/plugins/litclaude/skills/programming/references/python/data-modeling.md +233 -0
  92. package/plugins/litclaude/skills/programming/references/python/data-processing.md +133 -0
  93. package/plugins/litclaude/skills/programming/references/python/error-handling.md +218 -0
  94. package/plugins/litclaude/skills/programming/references/python/fastapi-stack.md +316 -0
  95. package/plugins/litclaude/skills/programming/references/python/httpx2-optimization.md +360 -0
  96. package/plugins/litclaude/skills/programming/references/python/libraries.md +307 -0
  97. package/plugins/litclaude/skills/programming/references/python/one-liners.md +268 -0
  98. package/plugins/litclaude/skills/programming/references/python/orjson-stack.md +378 -0
  99. package/plugins/litclaude/skills/programming/references/python/pydantic-ai.md +285 -0
  100. package/plugins/litclaude/skills/programming/references/python/pyproject-strict.md +232 -0
  101. package/plugins/litclaude/skills/programming/references/python/textual-tui.md +201 -0
  102. package/plugins/litclaude/skills/programming/references/python/type-patterns.md +176 -0
  103. package/plugins/litclaude/skills/programming/references/rust/README.md +317 -0
  104. package/plugins/litclaude/skills/programming/references/rust/async-tokio.md +299 -0
  105. package/plugins/litclaude/skills/programming/references/rust/axum-stack.md +467 -0
  106. package/plugins/litclaude/skills/programming/references/rust/cargo-strict.md +317 -0
  107. package/plugins/litclaude/skills/programming/references/rust/clap-stack.md +409 -0
  108. package/plugins/litclaude/skills/programming/references/rust/concurrency.md +375 -0
  109. package/plugins/litclaude/skills/programming/references/rust/libraries.md +439 -0
  110. package/plugins/litclaude/skills/programming/references/rust/one-liners.md +291 -0
  111. package/plugins/litclaude/skills/programming/references/rust/proptest-insta.md +429 -0
  112. package/plugins/litclaude/skills/programming/references/rust/type-state.md +354 -0
  113. package/plugins/litclaude/skills/programming/references/rust/unsafe-discipline.md +250 -0
  114. package/plugins/litclaude/skills/programming/references/rust/zero-cost-safety.md +527 -0
  115. package/plugins/litclaude/skills/programming/references/rust-ub/README.md +289 -0
  116. package/plugins/litclaude/skills/programming/references/rust-ub/miri-sanitizers-loom.md +411 -0
  117. package/plugins/litclaude/skills/programming/references/rust-ub/ub-taxonomy.md +269 -0
  118. package/plugins/litclaude/skills/programming/references/typescript/README.md +195 -0
  119. package/plugins/litclaude/skills/programming/references/typescript/backend-hono.md +672 -0
  120. package/plugins/litclaude/skills/programming/references/typescript/bootstrap.md +199 -0
  121. package/plugins/litclaude/skills/programming/references/typescript/data-modeling.md +202 -0
  122. package/plugins/litclaude/skills/programming/references/typescript/error-handling.md +169 -0
  123. package/plugins/litclaude/skills/programming/references/typescript/tsconfig-strict.md +152 -0
  124. package/plugins/litclaude/skills/programming/references/typescript/type-patterns.md +196 -0
  125. package/plugins/litclaude/skills/programming/scripts/go/check-no-excuse-rules.sh +173 -0
  126. package/plugins/litclaude/skills/programming/scripts/go/new-project.py +138 -0
  127. package/plugins/litclaude/skills/programming/scripts/go/templates/.editorconfig +13 -0
  128. package/plugins/litclaude/skills/programming/scripts/go/templates/.golangci.yml +95 -0
  129. package/plugins/litclaude/skills/programming/scripts/go/templates/AGENTS.md.tmpl +24 -0
  130. package/plugins/litclaude/skills/programming/scripts/go/templates/README.md.tmpl +12 -0
  131. package/plugins/litclaude/skills/programming/scripts/go/templates/Taskfile.yml +40 -0
  132. package/plugins/litclaude/skills/programming/scripts/go/templates/ci.yml +37 -0
  133. package/plugins/litclaude/skills/programming/scripts/go/templates/config.go +24 -0
  134. package/plugins/litclaude/skills/programming/scripts/go/templates/gitignore +15 -0
  135. package/plugins/litclaude/skills/programming/scripts/go/templates/main.go.tmpl +22 -0
  136. package/plugins/litclaude/skills/programming/scripts/go/templates/run.go +15 -0
  137. package/plugins/litclaude/skills/programming/scripts/python/check-no-excuse-rules.py +687 -0
  138. package/plugins/litclaude/skills/programming/scripts/python/new-project.py +172 -0
  139. package/plugins/litclaude/skills/programming/scripts/python/new-script.py +116 -0
  140. package/plugins/litclaude/skills/programming/scripts/rust/check-no-excuse-rules.py +296 -0
  141. package/plugins/litclaude/skills/programming/scripts/rust/check-no-excuse-rules.sh +158 -0
  142. package/plugins/litclaude/skills/programming/scripts/rust/new-project.py +175 -0
  143. package/plugins/litclaude/skills/programming/scripts/typescript/check-no-excuse-rules.ts +282 -0
  144. package/plugins/litclaude/skills/programming/scripts/typescript/new-project.ts +177 -0
  145. package/plugins/litclaude/skills/refactor/SKILL.md +73 -0
  146. package/plugins/litclaude/skills/remove-ai-slops/SKILL.md +52 -0
  147. package/plugins/litclaude/skills/review-work/SKILL.md +331 -0
  148. package/plugins/litclaude/skills/rules/SKILL.md +66 -0
  149. package/plugins/litclaude/skills/start-work/SKILL.md +132 -0
  150. package/scripts/audit-plan-checkboxes.mjs +37 -0
  151. package/scripts/doctor.mjs +41 -0
  152. package/scripts/inspect-agent-tools.mjs +27 -0
  153. package/scripts/postinstall.mjs +50 -0
  154. package/scripts/qa-claude-plugin-smoke.sh +60 -0
  155. package/scripts/qa-portable-install.sh +136 -0
  156. package/scripts/validate-plugin.mjs +72 -0
@@ -0,0 +1,337 @@
1
+ # Library Defaults — Full Decision Tree (Go 2026)
2
+
3
+ The opinionated, in-production stack for 2026 Go. Every entry has a one-line rationale and a canonical snippet so the agent does not relearn each library's idioms.
4
+
5
+ The biggest difference from Python/Rust/TypeScript: **Go has fewer "best" choices and more "boring" choices.** The standard library is the default; reach outside it only when the rationale below applies.
6
+
7
+ ---
8
+
9
+ ## HTTP framework — `gin` (default) or `chi` (minimalist) or `net/http` (no deps)
10
+
11
+ The reality of 2026 Go: **`gin` runs ~48% of new Go API projects** (Go Developer Survey 2024 + crawls of new repos), with `gorilla/mux` (~17%, in maintenance), `echo` (~16%), and `fiber` (~11%) the remaining quarter. The skill picks gin not because it is technically superior — it is not — but because:
12
+
13
+ 1. The ecosystem (middleware, examples, SO answers) is largest.
14
+ 2. The CLIProxyAPI codebase, which this skill's `backend-stack.md` is distilled from, uses gin in production for OpenAI/Gemini/Claude proxying including SSE streaming and WebSocket upgrades. That is real reference code, not a toy.
15
+ 3. Gin's `Context` API is the closest thing Go has to a framework-blessed "request-scoped object", which makes middleware composition straightforward.
16
+
17
+ ```go
18
+ import "github.com/gin-gonic/gin"
19
+
20
+ func main() {
21
+ r := gin.New()
22
+ r.Use(gin.Recovery(), middleware.RequestLogger(), middleware.RequestID())
23
+ r.GET("/healthz", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) })
24
+ _ = r.Run(":8080")
25
+ }
26
+ ```
27
+
28
+ **Pick `chi` instead** when:
29
+ - You want `net/http`-compatible handlers (you do, eventually — chi is closer to stdlib).
30
+ - The service is small and you do not need gin's binding helpers.
31
+
32
+ **Pick `net/http` (stdlib) directly** when:
33
+ - The service has fewer than 10 routes and zero auth complexity. Go 1.22's enhanced `ServeMux` (method+path patterns) eliminated 80% of the historical reason to use a framework.
34
+
35
+ **Never use** `gorilla/mux` (effectively in maintenance), `fiber` (uses `fasthttp` which is **not stdlib-compatible**, so middleware ecosystem is split), or `echo` (smaller eco than gin, no real advantage today).
36
+
37
+ See `backend-stack.md` for the gin canonical layout, middleware ordering, SSE, graceful shutdown, structured logging integration.
38
+
39
+ ---
40
+
41
+ ## RPC — `connectrpc/connect-go`
42
+
43
+ The default RPC layer. **Use Connect, not raw grpc-go**, unless you have a measured reason.
44
+
45
+ - Connect is wire-compatible with gRPC AND speaks HTTP/1.1 + HTTP/2 + Connect protocol. One server, three clients (gRPC, gRPC-Web, Connect-Web from browsers).
46
+ - No `grpcurl` needed for debugging — `curl -H "Content-Type: application/json" -d ...` works.
47
+ - Streaming, interceptors, deadlines, errors are first-class.
48
+ - Buf toolchain (`buf generate`, `buf lint`, `buf breaking`) for codegen is dramatically nicer than `protoc`.
49
+
50
+ ```go
51
+ // Server
52
+ mux := http.NewServeMux()
53
+ mux.Handle(elizav1connect.NewElizaServiceHandler(&elizaServer{}))
54
+ _ = http.ListenAndServe(":8080", h2c.NewHandler(mux, &http2.Server{}))
55
+
56
+ // Client
57
+ client := elizav1connect.NewElizaServiceClient(
58
+ http.DefaultClient,
59
+ "http://localhost:8080",
60
+ )
61
+ res, err := client.Say(ctx, connect.NewRequest(&elizav1.SayRequest{Sentence: "hi"}))
62
+ ```
63
+
64
+ **Use raw `grpc-go`** only when:
65
+ - You need server-streaming-from-multiple-services with a single gRPC mux.
66
+ - You are integrating with a strict gRPC-only environment (Envoy proxy with gRPC reflection, Istio strict-gRPC).
67
+
68
+ See `grpc-connect.md`.
69
+
70
+ ---
71
+
72
+ ## Database — `pgx/v5` + `sqlc` + `goose`
73
+
74
+ ```bash
75
+ go get github.com/jackc/pgx/v5
76
+ go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
77
+ go install github.com/pressly/goose/v3/cmd/goose@latest
78
+ ```
79
+
80
+ - **`pgx/v5`** is faster, more type-safe, and has better PostgreSQL feature coverage than `database/sql + lib/pq`. Use the `pgxpool` package for connection pooling. Avoid `database/sql` driver mode — it loses pgx's batch, COPY, listen/notify.
81
+ - **`sqlc`** generates type-safe Go from `.sql` files. Hand-written SQL with hand-written struct mapping is the #1 source of subtle DB bugs. sqlc eliminates the class.
82
+ - **`goose`** for migrations — small, command-line first, no global state.
83
+
84
+ **Never use** `gorm` (active record, slow, brings runtime reflection into hot paths, encourages N+1 queries). **Never use** `ent` (heavy, opinionated graph layer) unless you specifically want a graph-shaped data model.
85
+
86
+ See `sqlc-pgx.md`.
87
+
88
+ ---
89
+
90
+ ## Validation — three layers, three tools
91
+
92
+ Go has no Pydantic / Zod equivalent and **does not need one** — but only because you wire three layers properly:
93
+
94
+ | Layer | Tool | Pattern |
95
+ |---|---|---|
96
+ | HTTP boundary (gin/chi/net/http) | `go-playground/validator/v10` via struct tags | `binding:"required,email,min=3"` |
97
+ | RPC boundary (protobuf) | `bufbuild/protovalidate-go` | `(buf.validate.field).string.min_len = 3` in `.proto` |
98
+ | Domain core | **Smart constructor + unexported fields** | `NewEmail(s) (Email, error)` returns a type whose fields cannot be set from outside |
99
+
100
+ ```go
101
+ // HTTP boundary
102
+ type CreateUserReq struct {
103
+ Email string `json:"email" binding:"required,email"`
104
+ Username string `json:"username" binding:"required,alphanum,min=3,max=32"`
105
+ }
106
+
107
+ // Domain — once a value is of type Email it is provably valid
108
+ type Email struct{ raw string }
109
+ func NewEmail(s string) (Email, error) {
110
+ if !emailRegex.MatchString(s) { return Email{}, ErrInvalidEmail }
111
+ return Email{raw: strings.ToLower(s)}, nil
112
+ }
113
+ func (e Email) String() string { return e.raw }
114
+ ```
115
+
116
+ The boundary parses raw input into the domain type **once**. Inside the domain, no further validation is permitted — the types prove it. This is parse-don't-validate adapted to Go.
117
+
118
+ See `data-modeling.md` for the full pattern.
119
+
120
+ ---
121
+
122
+ ## Logging — `log/slog` (stdlib)
123
+
124
+ ```go
125
+ import "log/slog"
126
+
127
+ logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
128
+ Level: slog.LevelInfo,
129
+ AddSource: true,
130
+ }))
131
+ slog.SetDefault(logger)
132
+
133
+ slog.InfoContext(ctx, "request handled",
134
+ slog.String("path", r.URL.Path),
135
+ slog.Int("status", 200),
136
+ slog.Duration("elapsed", elapsed),
137
+ )
138
+ ```
139
+
140
+ - **stdlib since 1.21**, stable since 1.23. Performance is on par with zerolog for structured output, and faster than logrus by a wide margin.
141
+ - The `slog.Handler` interface is implemented by all major exporters (OpenTelemetry, Datadog, Honeycomb).
142
+ - The skill bans `logrus`, `zap`, `zerolog` for new code. They are not bad — they are simply superseded. Existing projects on those keep them; new files use slog.
143
+
144
+ Use the `sloglint` linter from `golangci-strict.md` to enforce attr style (`slog.String(...)` instead of `slog.Any(...)`).
145
+
146
+ ---
147
+
148
+ ## CLI — `cobra` + `pflag` + slog
149
+
150
+ ```bash
151
+ go install github.com/spf13/cobra-cli@latest
152
+ cobra-cli init mytool
153
+ cobra-cli add server
154
+ ```
155
+
156
+ `cobra` is the de facto Go CLI framework — Kubernetes, Docker CLI, Helm, GitHub CLI all use it. The companion `viper` for config-file-+-env-+-flag merging is **optional**: prefer `caarlos0/env/v11` for env-only configs (12-factor apps), reach for viper only when you genuinely need file-based config.
157
+
158
+ See `cobra-stack.md`.
159
+
160
+ ---
161
+
162
+ ## TUI — `bubbletea v2` + `bubbles v2` + `lipgloss v2`
163
+
164
+ Use **v2 RC** (`charm.land/bubbletea/v2`), not v1. The v2 model adds:
165
+
166
+ - `tea.View{Cursor: *tea.Cursor, ...}` for real-cursor positioning.
167
+ - `SetVirtualCursor(false)` on textareas — lets the terminal own the cursor, which is **required** for CJK IME (Korean Hangul composition, Japanese kana→kanji conversion, Chinese pinyin lookup).
168
+ - Granular mouse events (`MouseClickMsg`, `MouseMotionMsg`, `MouseReleaseMsg`) instead of v1's coarse `MouseMsg`.
169
+
170
+ This is not a preference. v1 has no way to position the IME candidate window correctly — Korean input shows up two cells to the left of where you typed, every time. **If your TUI accepts text input AND your users include CJK speakers, v1 is broken.**
171
+
172
+ See `bubbletea-v2.md` for the full IME-correct skeleton.
173
+
174
+ ---
175
+
176
+ ## HTTP client — stdlib + `hashicorp/go-retryablehttp`
177
+
178
+ Default: `net/http.Client` with a tuned `http.Transport`. The stdlib client is **already excellent** in 2026 — HTTP/2 by default, connection pooling, sane timeouts when configured.
179
+
180
+ ```go
181
+ client := &http.Client{
182
+ Timeout: 30 * time.Second,
183
+ Transport: &http.Transport{
184
+ MaxIdleConns: 200,
185
+ MaxIdleConnsPerHost: 40,
186
+ IdleConnTimeout: 90 * time.Second,
187
+ DisableCompression: false,
188
+ ForceAttemptHTTP2: true,
189
+ },
190
+ }
191
+ ```
192
+
193
+ For retry/backoff, add `github.com/hashicorp/go-retryablehttp` — small, single-purpose, integrates as a wrapper.
194
+
195
+ **Never use** `resty` (too much magic, hides headers, encourages wrong defaults). `req` is fine but adds dependency surface for marginal benefit over the stdlib + retry wrapper.
196
+
197
+ ---
198
+
199
+ ## JSON — stdlib (default), `goccy/go-json` (perf), `bytedance/sonic` (extreme perf)
200
+
201
+ Stdlib `encoding/json` improved dramatically in Go 1.21+. **Use it.**
202
+
203
+ Reach for `goccy/go-json` (~3x faster) only when you have measured a hot-path bottleneck:
204
+
205
+ ```go
206
+ import json "github.com/goccy/go-json"
207
+ // drop-in replacement — same API
208
+ ```
209
+
210
+ Reach for `bytedance/sonic` (~5x faster, requires amd64/arm64) for production proxies with thousands of RPS of JSON traversal. CLIProxyAPI uses `tidwall/gjson` + `tidwall/sjson` for **partial-tree mutation without full unmarshal** — a different optimization, useful when you transform large payloads. See `backend-stack.md`.
211
+
212
+ ---
213
+
214
+ ## Concurrency primitives — stdlib only
215
+
216
+ | Need | Use |
217
+ |---|---|
218
+ | Goroutine group with error propagation | `golang.org/x/sync/errgroup` |
219
+ | Semaphore | `golang.org/x/sync/semaphore` |
220
+ | Single-flight dedup | `golang.org/x/sync/singleflight` |
221
+ | Lazy init | **`sync.OnceValue` / `sync.OnceFunc`** (Go 1.21+, replaces `sync.Once` for typed values) |
222
+ | Atomic counter | `atomic.Int64` (Go 1.19+, typed atomics — don't use the old func-style) |
223
+ | Channel-based fanout | `chan T` with `errgroup` for shutdown |
224
+
225
+ The `x/sync` packages are stdlib-quality but live outside `std`. See `concurrency.md` for the discipline.
226
+
227
+ ---
228
+
229
+ ## Time — stdlib + `benbjohnson/clock` for tests
230
+
231
+ ```go
232
+ type Clock interface { Now() time.Time }
233
+ // Production
234
+ var realClock Clock = clockImpl{}
235
+ // Test
236
+ fake := clock.NewMock()
237
+ fake.Set(time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC))
238
+ ```
239
+
240
+ **Never call `time.Now()` directly inside domain code.** Inject a `Clock`. Tests become deterministic, no `time.Sleep` flakiness.
241
+
242
+ ---
243
+
244
+ ## IDs — `google/uuid` (UUID v4/v7) or `xid` (sortable short ID)
245
+
246
+ ```go
247
+ import "github.com/google/uuid"
248
+ id := uuid.Must(uuid.NewV7()) // sortable, time-ordered, 128-bit
249
+ ```
250
+
251
+ UUID v7 is the modern default — sortable like v6, random like v4. Use v4 only when leaking creation time is a privacy concern.
252
+
253
+ For short, URL-safe IDs (~12 bytes, sortable) use `rs/xid` — Kubernetes-style.
254
+
255
+ ---
256
+
257
+ ## Crypto — stdlib + `alecthomas/argon2id` for passwords
258
+
259
+ Stdlib `crypto/*` for everything. For password hashing, **argon2id is the 2026 standard** — bcrypt is acceptable but argon2 is OWASP's recommendation since 2023.
260
+
261
+ ```go
262
+ import "github.com/alecthomas/argon2id"
263
+ hash, err := argon2id.CreateHash("password", argon2id.DefaultParams)
264
+ ```
265
+
266
+ ---
267
+
268
+ ## Data — `apache/arrow-go/v18` + `marcboeker/go-duckdb` + `gonum`
269
+
270
+ Same philosophy as Python's "never pandas":
271
+
272
+ | Need | Use |
273
+ |---|---|
274
+ | Tabular over CSV/Parquet/JSON | DuckDB-Go bindings — zero-copy Arrow integration |
275
+ | In-memory frame | Arrow + custom code (Go has no pandas-equivalent and that's fine) |
276
+ | Numerical | `gonum.org/v1/gonum` |
277
+ | Stats | `gonum/stat` |
278
+
279
+ Go's data-science story is intentionally thin. For heavy data work, write the pipeline in Polars/DuckDB (see `python/data-processing.md`), expose the result via Parquet or Arrow, consume from Go.
280
+
281
+ ---
282
+
283
+ ## Testing — stdlib + selective additions
284
+
285
+ | Need | Use |
286
+ |---|---|
287
+ | Assertions | `stretchr/testify/require` (fail-fast) — `assert` only in table-driven loops |
288
+ | Snapshots / golden | `hexops/autogold/v2` (auto-updates with `-update`) |
289
+ | Property-based | `pgregory.net/rapid` (modern) or stdlib `testing/quick` |
290
+ | Mocks | `go.uber.org/mock` (gomock successor) |
291
+ | HTTP mocks | `h2non/gock` for outbound, stdlib `httptest` for inbound |
292
+ | Integration containers | `testcontainers/testcontainers-go` |
293
+ | Goroutine leak | `go.uber.org/goleak` |
294
+ | Benchmarks | stdlib `testing.B` + `perf.dev/benchstat` |
295
+
296
+ See `testing.md` for canonical patterns.
297
+
298
+ ---
299
+
300
+ ## Config — `caarlos0/env/v11`
301
+
302
+ ```go
303
+ type Config struct {
304
+ Port int `env:"PORT" envDefault:"8080"`
305
+ DatabaseURL string `env:"DATABASE_URL,required"`
306
+ Timeout time.Duration `env:"TIMEOUT" envDefault:"30s"`
307
+ }
308
+
309
+ var cfg Config
310
+ if err := env.Parse(&cfg); err != nil { log.Fatal(err) }
311
+ ```
312
+
313
+ Pure 12-factor. Defaults via struct tag, required marker, parsing for `time.Duration`, slices, maps. **Use viper only if you also need file-based config** — most services do not.
314
+
315
+ ---
316
+
317
+ ## Choosing an unfamiliar dependency — the checklist
318
+
319
+ Before `go get`-ing anything new:
320
+
321
+ 1. Is it maintained? Latest tag within 12 months? Owner active?
322
+ 2. Does it expose stdlib-compatible types (`io.Reader`, `context.Context`, `http.Handler`)? If it invents its own `Connection` or `Request` type, that's a yellow flag.
323
+ 3. Does it use `init()` for side effects? **REJECT.** `init()` ruins testability.
324
+ 4. Does it call `log.Fatal` / `panic` outside of true programmer-error paths? **REJECT.**
325
+ 5. Does it have a `context.Context` first-arg convention? If not, **REJECT** — cancellation is non-negotiable.
326
+ 6. Does adding it overlap with something already in your `go.mod`? Pick one.
327
+
328
+ ---
329
+
330
+ ## Sources
331
+
332
+ - 2024 Go Developer Survey: https://go.dev/blog/survey2024-h1-results
333
+ - Connect-Go docs: https://connectrpc.com/docs/go/getting-started
334
+ - sqlc: https://docs.sqlc.dev
335
+ - bubbletea v2 IME: see charmbracelet/bubbletea upstream (reference for `SetVirtualCursor(false)` pattern)
336
+ - CLIProxyAPI (gin + SSE + WebSocket in production): https://github.com/router-for-me/CLIProxyAPI
337
+ - slog blog: https://go.dev/blog/slog
@@ -0,0 +1,202 @@
1
+ # One-Liners and Disposable Scripts
2
+
3
+ Production hygiene with throwaway ergonomics. Go scripts get the same strict lints, the same type discipline, the same 250 LOC ceiling. The difference: they live as single `.go` files invoked via `go run`, not as full modules.
4
+
5
+ Python has PEP 723 + `uv run`. Rust has `rust-script`. **Go has `go run` directly** — no extra tooling needed.
6
+
7
+ ---
8
+
9
+ ## Pattern 1: Single-file `go run`
10
+
11
+ A `.go` file with a `main` package, run directly:
12
+
13
+ ```go
14
+ //go:build ignore
15
+ // fetch.go — fetch a URL and print body length.
16
+ //
17
+ // Usage:
18
+ // go run fetch.go <url>
19
+
20
+ package main
21
+
22
+ import (
23
+ "fmt"
24
+ "io"
25
+ "log"
26
+ "net/http"
27
+ "os"
28
+ )
29
+
30
+ func main() {
31
+ if len(os.Args) < 2 {
32
+ log.Fatal("usage: go run fetch.go <url>")
33
+ }
34
+ resp, err := http.Get(os.Args[1])
35
+ if err != nil { log.Fatal(err) }
36
+ defer resp.Body.Close()
37
+
38
+ body, err := io.ReadAll(resp.Body)
39
+ if err != nil { log.Fatal(err) }
40
+
41
+ fmt.Printf("%d bytes\n", len(body))
42
+ }
43
+ ```
44
+
45
+ Run: `go run fetch.go https://example.com`.
46
+
47
+ The `//go:build ignore` directive keeps this file out of `go build ./...` — it is a script, not part of the module. Without that line, every `.go` file in the package gets compiled into your binary.
48
+
49
+ ---
50
+
51
+ ## Pattern 2: Throwaway directory under `scripts/`
52
+
53
+ ```
54
+ myproject/
55
+ ├── go.mod
56
+ ├── internal/...
57
+ └── scripts/
58
+ ├── seed/
59
+ │ └── main.go # `go run ./scripts/seed`
60
+ ├── migrate/
61
+ │ └── main.go
62
+ └── one-time-fix/
63
+ └── main.go
64
+ ```
65
+
66
+ Each `scripts/<name>/main.go` is its own `main` package. Invoke as `go run ./scripts/seed/`. Dependencies are shared with the parent module — no separate `go.mod`.
67
+
68
+ This is the right pattern when:
69
+
70
+ - You need module deps (sqlc, pgx, your own internal packages).
71
+ - You want IDE support, type-checking, test coverage.
72
+ - The script lives alongside the project, runs in CI.
73
+
74
+ ---
75
+
76
+ ## Pattern 3: Inline `go run` from shell
77
+
78
+ ```bash
79
+ go run -mod=mod <(cat <<'EOF'
80
+ package main
81
+ import "fmt"
82
+ func main() { fmt.Println("hello") }
83
+ EOF
84
+ )
85
+ ```
86
+
87
+ Rare, but useful for one-shot terminal experiments. The `<(...)` is process substitution; `go run -mod=mod` reads from stdin.
88
+
89
+ ---
90
+
91
+ ## Hard rules for scripts
92
+
93
+ Even a 30-line script follows the philosophy:
94
+
95
+ 1. **Typed flags via `flag` or `pflag`**, not `os.Args` string parsing past 2 args.
96
+ ```go
97
+ var (
98
+ url = flag.String("url", "", "URL to fetch")
99
+ limit = flag.Int("limit", 100, "max bytes")
100
+ )
101
+ flag.Parse()
102
+ if *url == "" { log.Fatal("--url required") }
103
+ ```
104
+
105
+ 2. **`context.Context` propagation** wherever I/O happens.
106
+ ```go
107
+ ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
108
+ defer cancel()
109
+ req, _ := http.NewRequestWithContext(ctx, "GET", *url, nil)
110
+ ```
111
+
112
+ 3. **`log.Fatal` is fine in `main()`** of a script (programmer error / fatal path), but **never inside any function the script imports.** Library code returns errors.
113
+
114
+ 4. **Errors get wrapped.** Same rule as production code:
115
+ ```go
116
+ if err != nil { return fmt.Errorf("fetch %s: %w", *url, err) }
117
+ ```
118
+
119
+ 5. **Resources released via `defer`.** No "I'll fix it later".
120
+
121
+ 6. **slog for output if it must be parseable.** `fmt.Println` for one-shot terminal output is fine.
122
+
123
+ 7. **No more than 250 pure LOC.** If it grows, it stops being a script and becomes a subcommand of your CLI tool.
124
+
125
+ ---
126
+
127
+ ## Pattern 4: Standalone tool with deps — temporary module
128
+
129
+ Some scripts need deps the parent module does not have. Two options:
130
+
131
+ ### Option A — script in its own tiny module
132
+
133
+ ```bash
134
+ mkdir /tmp/migrate-tool && cd $_
135
+ go mod init scratch.local/migrate-tool
136
+ go get github.com/pressly/goose/v3
137
+ cat > main.go <<'EOF'
138
+ package main
139
+ import ... // use goose
140
+ func main() { ... }
141
+ EOF
142
+ go run .
143
+ ```
144
+
145
+ Run, then delete `/tmp/migrate-tool`. Throwaway.
146
+
147
+ ### Option B — `gorun` (community tool)
148
+
149
+ ```bash
150
+ go install github.com/erning/gorun@latest
151
+
152
+ cat > script.go <<'EOF'
153
+ //usr/bin/env gorun "$0" "$@"; exit
154
+ // /// go.mod
155
+ // module scratch
156
+ // go 1.23
157
+ // require github.com/spf13/cobra v1.8.0
158
+ // ///
159
+
160
+ package main
161
+ ...
162
+ EOF
163
+ chmod +x script.go
164
+ ./script.go
165
+ ```
166
+
167
+ `gorun` parses the inline `go.mod` block, materializes a temp module, runs the script. Niche tool — only if you want the executable-script experience.
168
+
169
+ ---
170
+
171
+ ## When a script becomes a CLI
172
+
173
+ If your script needs:
174
+
175
+ - More than one subcommand
176
+ - Long-term storage of state
177
+ - Help text more than a paragraph
178
+ - Repeated invocations from CI
179
+
180
+ ... promote it to a real CLI tool via `cobra` — see `cobra-stack.md`. The boundary is fuzzy; trust your judgment, but **a 500-line "script" is not a script.**
181
+
182
+ ---
183
+
184
+ ## Antipatterns
185
+
186
+ | Bad | Why | Good |
187
+ |---|---|---|
188
+ | `os.Args[1]` indexing without length check | Panics on missing arg | `flag.Parse()` with explicit checks |
189
+ | `log.Fatal` inside a function the script imports | Crashes caller's process | Return error |
190
+ | `panic(err)` for expected failures | Same as above | `log.Fatal` in `main`, error return elsewhere |
191
+ | Skipping `defer resp.Body.Close()` because "it's a script" | Leaks fd | Always close |
192
+ | One 800-LOC `main.go` "to keep it simple" | Now harder to read than a real CLI | Promote to `cmd/<name>/` with subcommands |
193
+ | `// TODO: handle error` | Production-grade hygiene means production-grade hygiene | Handle now or document why ignored |
194
+
195
+ ---
196
+
197
+ ## Sources
198
+
199
+ - `go run` docs: https://pkg.go.dev/cmd/go#hdr-Compile_and_run_Go_program
200
+ - `//go:build` constraints: https://pkg.go.dev/cmd/go#hdr-Build_constraints
201
+ - `signal.NotifyContext`: https://pkg.go.dev/os/signal#NotifyContext
202
+ - gorun: https://github.com/erning/gorun