Skip to content

Commit 64b65a7

Browse files
committed
docs: add guide for coding agents to assist in database entry creation
1 parent 82c54da commit 64b65a7

2 files changed

Lines changed: 164 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# Agent Guide for `why` Database Entries
2+
3+
This file helps coding agents (Claude, Copilot, Cursor, etc.) create correct `why` database entries. Read this before generating YAML files.
4+
5+
## Project context
6+
7+
`why` is a CLI tool that captures stderr from failed commands and explains the error in plain English. The error database lives in `db/` as YAML files — one file per error, organized by tool.
8+
9+
## Directory structure
10+
11+
```
12+
db/
13+
TEMPLATE.yaml # universal template — copy this
14+
rust/ # rustc compiler errors (E0499.yaml)
15+
python/ # Python exceptions (TypeError.yaml)
16+
c_cpp/ # gcc/clang errors (undefined-reference.yaml)
17+
go/ # Go compiler errors (undefined.yaml)
18+
git/ # git CLI errors (merge-conflict.yaml)
19+
docker/ # Docker CLI errors (daemon-not-running.yaml)
20+
npm/ # npm CLI errors (eresolve.yaml)
21+
cargo/ # Cargo build errors (could-not-compile.yaml)
22+
why/ # errors from the why tool itself
23+
```
24+
25+
To add a new tool, just create the directory. No code changes needed.
26+
27+
## Creating an entry
28+
29+
### Filename
30+
31+
- Must match the `id` field exactly: `id: merge-conflict``merge-conflict.yaml`
32+
- Rust errors use the error code: `E0499.yaml`
33+
- Python errors use the exception name: `TypeError.yaml`
34+
- Everything else uses lowercase slugs: `daemon-not-running.yaml`
35+
36+
### Required fields
37+
38+
```yaml
39+
id: merge-conflict # matches filename without .yaml
40+
tool: git # the CLI/compiler that produces this error
41+
language: git # matches the parent directory name
42+
title: Merge conflict # under 60 characters
43+
explain: | # plain English, 3-6 sentences
44+
...
45+
fix: | # concrete steps, 2-4 actions
46+
...
47+
```
48+
49+
### Patterns (required for auto-detection)
50+
51+
The `patterns` field is how `why` matches stderr output to this entry. Each pattern is a list of substrings that must ALL appear in the same stderr line (AND logic). Multiple patterns give OR logic.
52+
53+
```yaml
54+
patterns:
55+
- ["Automatic merge failed"] # matches this exact substring
56+
- ["CONFLICT", "Merge conflict"] # both must appear in same line
57+
- ["fix conflicts and then commit"] # OR this matches
58+
```
59+
60+
Rules:
61+
62+
- Use the most specific substring possible — avoid single common words
63+
- Copy-paste from real error output when possible
64+
- No regex — plain substring matching only
65+
- Patterns are case-sensitive
66+
- Each pattern group is checked against each line independently
67+
- First match wins across the entire database, so be specific enough to avoid collisions
68+
69+
When two tools produce similar errors, use `exclude`:
70+
71+
```yaml
72+
# C/C++ "too many arguments" would also match Go errors
73+
patterns:
74+
- ["too many arguments"]
75+
exclude:
76+
- "go"
77+
```
78+
79+
Tools with structured error codes (`rustc`, `python`) don't need patterns — detection works via regex on the error code / exception name.
80+
81+
### Optional fields
82+
83+
```yaml
84+
tags: [merge, conflict, branches] # for search/filtering
85+
exclude: ["text that must NOT appear"] # avoid false matches
86+
example_error: | # real error output
87+
Auto-merging src/main.rs
88+
CONFLICT (content): Merge conflict in src/main.rs
89+
example_code: | # minimal reproduction
90+
// code that triggers the error
91+
links: # official docs
92+
- https://git-scm.com/docs/git-merge
93+
```
94+
95+
## Style rules
96+
97+
These are strict — entries that violate them need revision:
98+
99+
1. **`explain` uses second person.** "You tried to..." not "The user tried to..."
100+
2. **`explain` is plain English.** If you use a technical term, define it briefly.
101+
3. **`fix` gives concrete commands/steps.** "Run `git pull --rebase`" not "update your branch."
102+
4. **No filler.** Don't start with "This error occurs when..." — just explain what happened.
103+
5. **No emoji.** Anywhere.
104+
6. **`language` must match the directory name exactly.** `db/c_cpp/` → `language: c_cpp`, not `language: cpp`.
105+
7. **`id` must match the filename exactly.** No exceptions.
106+
107+
## Validation
108+
109+
After creating entries, run:
110+
111+
```sh
112+
python scripts/validate.py
113+
```
114+
115+
This checks: required fields, id/filename match, language/directory match, patterns structure, duplicate IDs, unknown fields, and empty values.
116+
117+
Also run the Rust tests to make sure detection still works:
118+
119+
```sh
120+
cargo test
121+
```
122+
123+
## Common mistakes to avoid
124+
125+
- Setting `language: cpp` when the directory is `c_cpp` — must match exactly
126+
- Writing patterns that are too generic (e.g., `["error"]`) — will match everything
127+
- Forgetting the `|` after `explain:` and `fix:` — these must be YAML block scalars
128+
- Adding fields not in the schema — the validator rejects unknown fields
129+
- Putting patterns on entries in `db/rust/` or `db/python/` — not needed, detection uses regex for those
130+
131+
## Full example
132+
133+
```yaml
134+
id: port-already-in-use
135+
tool: docker
136+
language: docker
137+
title: Port is already allocated
138+
tags: [port, networking, bind]
139+
patterns:
140+
- ["port is already allocated"]
141+
- ["address already in use"]
142+
- ["Bind for", "failed"]
143+
144+
explain: |
145+
Docker tried to bind a container port to a host port that is already in use by
146+
another container or a process running on your machine.
147+
148+
fix: |
149+
1. Find what is using the port: lsof -i :<port> or ss -tlnp | grep <port>
150+
2. Stop the conflicting container: docker stop <container>
151+
3. Or use a different host port: docker run -p 8081:80 instead of -p 8080:80
152+
4. To see all running containers: docker ps
153+
154+
example_error: |
155+
docker: Error response from daemon: driver failed programming external connectivity
156+
on endpoint mycontainer: Bind for 0.0.0.0:8080 failed: port is already allocated.
157+
158+
links:
159+
- https://docs.docker.com/engine/reference/run/#expose-incoming-ports
160+
```

CONTRIBUTING.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ python scripts/validate.py
159159

160160
This runs the same checks as CI. Fix any errors it reports before submitting.
161161

162+
## Using a coding agent?
163+
164+
If you are using a coding agent (Claude, Copilot, Cursor, etc.) to generate entries, point it at [AGENTS.md](AGENTS.md). It has the exact conventions, field rules, and common mistakes laid out in a format agents work well with.
165+
162166
## Code of conduct
163167

164168
Be kind. Be helpful. We're all here to make error messages less miserable.

0 commit comments

Comments
 (0)