@marcel91200 / caddy Mirror · read-only / commits / bd9f1453
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 12:15 UTC

chore: add `AGENTS.md` (#7652)

* chore: add `AGENTS.md` Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com> * Apply suggestions from code review Co-authored-by: Francis Lavoie <lavofr@gmail.com> Co-authored-by: Matt Holt <mholt@users.noreply.github.com> * review feedback Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com> --------- Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com> Co-authored-by: Francis Lavoie <lavofr@gmail.com> Co-authored-by: Matt Holt <mholt@users.noreply.github.com>

Mohammed Al Sahaf committed Apr 17, 2026 at 23:49 UTC bd9f1453219a2610c319192f23782abb01b96699
1 file changed +217
AGENTS.md new
+217
@@ -0,0 +1,217 @@
1 +# Caddy Project Guidelines
2 +
3 +## Mission
4 +
5 +**Every site on HTTPS.** Caddy is a security-first, modular, extensible server platform.
6 +
7 +## Code Style
8 +
9 +### Go Idioms
10 +
11 +Follow [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments):
12 +
13 +- **Error flow**: Early return, indent error handling—not else blocks
14 + ```go
15 + if err != nil {
16 + return err
17 + }
18 + // normal code
19 + ```
20 +- **Naming**: initialisms (`URL`, `HTTP`, `ID`—not `Url`, `Http`, `Id`)
21 +- **Receiver names**: 1–2 letters reflecting type (`c` for `Client`, `h` for `Handler`)
22 +- **Error strings**: Lowercase, no trailing punctuation (`"something failed"` not `"Something failed."`)
23 +- **Doc comments**: Full sentences starting with the name being documented
24 + ```go
25 + // Handler serves HTTP requests for the file server.
26 + type Handler struct { ... }
27 + ```
28 +- **Empty slices**: `var t []string` (nil slice), not `t := []string{}` (non-nil zero-length)
29 +- **Don't panic**: Use error returns for normal error handling
30 +
31 +### Caddy Patterns
32 +
33 +**Module registration**:
34 +```go
35 +func init() {
36 + caddy.RegisterModule(MyModule{})
37 +}
38 +
39 +func (MyModule) CaddyModule() caddy.ModuleInfo {
40 + return caddy.ModuleInfo{
41 + ID: "namespace.category.name",
42 + New: func() caddy.Module { return new(MyModule) },
43 + }
44 +}
45 +```
46 +
47 +**Module lifecycle**: `New()` → JSON unmarshal → `Provision()` → `Validate()` → use → `Cleanup()`
48 +
49 +**Interface guards** — compile-time verification that modules implement required interfaces:
50 +```go
51 +var (
52 + _ caddy.Provisioner = (*MyModule)(nil)
53 + _ caddy.Validator = (*MyModule)(nil)
54 + _ caddyfile.Unmarshaler = (*MyModule)(nil)
55 +)
56 +```
57 +
58 +**Structured logging** — use the module-scoped logger from context:
59 +```go
60 +func (m *MyModule) Provision(ctx caddy.Context) error {
61 + m.logger = ctx.Logger()
62 + m.logger.Debug("provisioning", zap.String("field", m.Field))
63 + return nil
64 +}
65 +```
66 +
67 +**Caddyfile support** — implement `UnmarshalCaddyfile(*caddyfile.Dispenser)` using the `Dispenser` API:
68 +```go
69 +// UnmarshalCaddyfile sets up the module from Caddyfile tokens. Syntax:
70 +//
71 +// directive [arg1] [arg2] {
72 +// subdir value
73 +// }
74 +func (m *MyModule) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
75 + d.Next() // consume directive name
76 + for d.NextArg() {
77 + // handle inline arguments
78 + }
79 + for nesting := d.Nesting(); d.NextBlock(nesting); {
80 + switch d.Val() {
81 + case "subdir":
82 + if !d.NextArg() {
83 + return d.ArgErr()
84 + }
85 + m.Field = d.Val()
86 + default:
87 + return d.Errf("unrecognized subdirective: %s", d.Val())
88 + }
89 + }
90 + return nil
91 +}
92 +```
93 +
94 +**Admin API**: Implement `caddy.AdminRouter` for custom endpoints.
95 +
96 +**Context**: Use `caddy.Context` for accessing other apps/modules and logging—don't store contexts in structs.
97 +
98 +## Architecture
99 +
100 +Caddy is built around a **module system** where everything is a module registered via `caddy.RegisterModule()`:
101 +
102 +- **Apps** (`caddy.App`): Top-level modules like `http`, `tls`, `pki` that Caddy loads and runs
103 +- **Modules** (`caddy.Module`): Extensible components with namespaced IDs (e.g., `http.handlers.file_server`)
104 +- **Configuration**: Native JSON with adapters (Caddyfile → JSON via `caddyconfig/httpcaddyfile`)
105 +
106 +| Directory | Purpose |
107 +|-----------|---------|
108 +| `modules/` | All standard modules (HTTP, TLS, PKI, etc.) |
109 +| `modules/standard/imports.go` | Standard module registry |
110 +| `caddyconfig/httpcaddyfile/` | Caddyfile → JSON adapter for HTTP |
111 +| `caddytest/` | Test utilities and integration tests |
112 +| `cmd/caddy/` | CLI entry point with module imports |
113 +
114 +### Critical Packages
115 +
116 +`caddyhttp` and `caddytls` require **extra scrutiny** in code review—these are security-critical.
117 +
118 +## Quality Gates
119 +
120 +
121 +**All required before PR is merge-ready:**
122 +
123 +| Gate | Command | Notes |
124 +|------|---------|-------|
125 +| Tests pass | `go test -race -short ./...` | Race detection enabled |
126 +| Lint clean | `golangci-lint run --timeout 10m` | No warnings in changed files |
127 +| Builds | `go build ./...` | Must compile |
128 +| Benchmarks | `go test -bench=. -benchmem` | Required for optimizations |
129 +
130 +CI runs tests on **Linux, macOS, and Windows**—ensure cross-platform compatibility.
131 +
132 +### Build & Test
133 +
134 +```bash
135 +# Build
136 +cd cmd/caddy && go build
137 +
138 +# Tests with race detection (matches CI)
139 +go test -race -short ./...
140 +
141 +# Integration tests
142 +go test ./caddytest/integration/...
143 +
144 +# Lint (matches CI)
145 +golangci-lint run --timeout 10m
146 +```
147 +
148 +## Testing Conventions
149 +
150 +**Table-driven tests** (preferred pattern):
151 +```go
152 +func TestFeature(t *testing.T) {
153 + for i, tc := range []struct {
154 + input string
155 + expected string
156 + wantErr bool
157 + }{
158 + {input: "valid", expected: "result", wantErr: false},
159 + {input: "invalid", expected: "", wantErr: true},
160 + } {
161 + actual, err := Function(tc.input)
162 + if tc.wantErr && err == nil {
163 + t.Errorf("Test %d: expected error but got none", i)
164 + }
165 + if !tc.wantErr && err != nil {
166 + t.Errorf("Test %d: unexpected error: %v", i, err)
167 + }
168 + if actual != tc.expected {
169 + t.Errorf("Test %d: expected %q, got %q", i, tc.expected, actual)
170 + }
171 + }
172 +}
173 +```
174 +
175 +**Integration tests** use `caddytest.Tester`:
176 +```go
177 +func TestHTTPFeature(t *testing.T) {
178 + tester := caddytest.NewTester(t)
179 + tester.InitServer(`
180 + {
181 + admin localhost:2999
182 + http_port 9080
183 + }
184 + localhost:9080 {
185 + respond "hello"
186 + }`, "caddyfile")
187 +
188 + tester.AssertGetResponse("http://localhost:9080/", 200, "hello")
189 +}
190 +```
191 +
192 +Use non-standard ports (9080, 9443, 2999) to avoid conflicts with running servers.
193 +
194 +## AI Contribution Policy
195 +
196 +Per [CONTRIBUTING.md](.github/CONTRIBUTING.md), AI-assisted code **MUST** be:
197 +
198 +1. **Disclosed** — Tell reviewers when code was AI-generated or AI-assisted, mentioning which agent/model is used
199 +2. **Fully comprehended** — You must be able to explain every line
200 +3. **Tested** — Automated tests when feasible, thorough manual tests otherwise
201 +4. **Licensed** — Verify AI output doesn't include plagiarized or incompatibly-licensed code
202 +5. **Contributor License Agreement (CLA)** — The CLA must be signed by the human user
203 +
204 +**Do NOT submit code you cannot fully explain.** Contributors are responsible for their submissions.
205 +
206 +## Dependencies
207 +
208 +- **Avoid new dependencies** — Justify any additions; tiny deps can be inlined
209 +- **No exported dependency types** — Caddy must not export types defined by external packages
210 +- Use Go modules; check with `go mod tidy`
211 +
212 +## Further Reading
213 +
214 +- [CONTRIBUTING.md](.github/CONTRIBUTING.md) — Full PR process and expectations
215 +- [Extending Caddy](https://caddyserver.com/docs/extending-caddy) — Module development guide
216 +- [JSON Config](https://caddyserver.com/docs/json/) — Native configuration reference
217 +- [Caddyfile](https://caddyserver.com/docs/caddyfile/concepts) — Caddyfile syntax guide