Repository navigation
Expand file tree
/
Copy path.cursorrules
More file actions
133 lines (88 loc) · 4.67 KB
/
Copy path.cursorrules
File metadata and controls
133 lines (88 loc) · 4.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# Dockerfiles Monorepo — Cursor Rules
## Repository Structure
This is a monorepo of Docker container projects. Each subdirectory is a self-contained project with its own `Dockerfile`, `run` script, and optionally `AGENTS.md`, `docker-compose.yml`, and test files.
## Conventions
### `./run` Script
Every project uses a `./run` bash script as the primary developer interface. Common commands across projects:
- `./run build` — Build a local image tagged `timjdfletcher/<project>:tmp`
- `./run clean` — Remove local images and prune buildx cache
- `./run release` — Test (if applicable), build multi-arch (`linux/amd64`, `linux/arm64`), and push to Docker Hub
All `run` scripts start with `set -eu -o pipefail`. When adding new commands, follow the existing `case` dispatch pattern.
### Tagging & Releases
Tags use the format `<project>-v<MAJOR>.<MINOR>.<PATCH>` (e.g., `timemachine-v3.8.3`, `gam-v0.1`). The release process requires the current commit to be tagged before running `./run release`. The release builds and pushes both the versioned tag and `latest` to Docker Hub.
To release:
1. `git tag <project>-v<VERSION>`
2. `./run release`
3. `git push && git push --tags`
### Dockerfiles
- Base images use pinned versions via `ARG` (e.g., `ARG DEBIAN_VERSION="trixie-20260406-slim"`).
- Build-time dependencies are installed then purged in the same `RUN` layer.
- Use `--no-install-recommends` for `apt-get install`.
- Prefer `COPY --chmod=` over separate `chmod` commands.
### Security
- **Avoid running as root when downloading from the internet.** Use non-root users for curl/wget operations. If volume permissions are needed, set them once with a minimal container, then download as non-root.
- Pin versions for reproducibility and security auditing.
### AGENTS.md
Per-project agent documentation lives in `<project>/AGENTS.md`. These files should contain:
- Project goal and core components
- Environment variables with defaults
- Developer workflow (./run commands)
- Testing methodology (if applicable)
- Pitfalls and gotchas specific to that project
- Dependency update instructions with URLs to check for new versions
Keep AGENTS.md concise — use tables over prose, avoid repeating what the code makes obvious.
### Test-Driven Development (TDD)
Use TDD when adding or modifying functionality. Follow the **red-green-refactor** loop:
**Tracer Bullet First**: Start with ONE test that proves the path works end-to-end.
```
RED: Write test for first behavior → test fails
GREEN: Write minimal code to pass → test passes
```
Then repeat for each additional behavior. One test at a time, one implementation at a time.
**Anti-Pattern: Horizontal Slicing**
DO NOT write all tests first, then all implementation. This produces bad tests that verify imagined behavior rather than actual behavior.
```
WRONG (horizontal):
RED: test1, test2, test3, test4, test5
GREEN: impl1, impl2, impl3, impl4, impl5
RIGHT (vertical):
RED→GREEN: test1→impl1
RED→GREEN: test2→impl2
...
```
**Refactoring Rules**
- Never refactor while RED — get to GREEN first
- Run tests after each refactor step
- If tests break during refactor but behavior hasn't changed, the test was testing implementation, not behavior
**Test Quality Checklist**
- [ ] Test describes behavior, not implementation
- [ ] Test uses public interface only (CLI, API, not internal functions)
- [ ] Test would survive internal refactor
- [ ] Code is minimal for this test
Example: To pin a dependency version, first add a test that checks for that version, verify it fails, then update the Dockerfile.
See the [TDD skill](https://github.com/mattpocock/skills/tree/b2039ab896a01ebcc539704f69974f7bcdfb1226/tdd) for detailed guidance.
## Working in This Repo
- Always `cd` into the project subdirectory before running `./run` commands.
- Run `./run test` (if it exists) before committing changes that affect the Dockerfile, entrypoint, or config templates.
- After updating dependency versions, run the full test suite to validate.
- Do not push to remote without being asked — the user will push when ready.
## Preflight Checks
Run these checks at the start of a session to catch issues early:
### GPG Signing
Before committing, verify GPG is working:
```bash
echo "test" | gpg --clearsign >/dev/null && echo "GPG OK" || echo "GPG BROKEN"
```
If GPG hangs or fails, see Troubleshooting below.
## Troubleshooting
### GPG Stale Lock
**Symptom**: `git commit` hangs with:
```
gpg: Note: database_open 134217901 waiting for lock (held by XXXX) ...
gpg: keydb_search failed: Operation timed out
```
**Cause**: Stale lock files from crashed/killed GPG processes.
**Fix**:
```bash
rm ~/.gnupg/public-keys.d/.#lk* ~/.gnupg/public-keys.d/pubring.db.lock
```