Repo Structure Conventions
Purpose
Ensure every managed repository has a consistent, navigable, industry-standard file organization. This skill is the primary owner for structural layout, naming, and build-artifact isolation.
When to invoke
- Creating a new repository.
- Restructuring an existing repository.
- Onboarding a repo that lacks clear organization.
- After
repo-onboarding-standards classifies the app type.
Scope boundary
Owns (primary authority)
- Root-level file layout and ordering.
- Directory naming conventions.
- App-type-specific directory structures.
- Build artifact isolation (.gitignore, .vscodeignore, .npmignore).
- CODEOWNERS patterns by project size and structure.
Delegates (do NOT duplicate)
| Concern |
Owner |
| Community health files (README, LICENSE, CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, SUPPORT) |
repo-profile-governance |
| Discoverability metadata (description, topics, social preview, homepage) |
repo-profile-governance |
| GitHub Actions security (SHA pinning, token permissions, OIDC) |
github-actions-security-hardening |
| Secret hygiene (.env, credentials, artifact leaks) |
secret-exposure-prevention |
| Documentation content quality and drift detection |
docs-drift-maintenance |
| Release versioning, tags, and publish integrity |
release-version-integrity |
| CI/CD workflow design and merge gates |
github-review-merge-admin |
Hard constraints
- No unbounded loops or recursive retries.
- Maximum one full repository audit per invocation.
- No silent file creation; produce explicit proposals for review.
- Never move or rename files without confirming the change won't break imports, CI, or published paths.
- Prefer the smallest structural change that achieves the convention.
Modes
- audit: Detect structural gaps and deviations. Return findings ranked by severity.
- scaffold: Generate the initial directory structure for a new project given an app type.
- remediate: Propose minimal file moves/renames to bring an existing repo into compliance.
A) Universal file layout
Root minimalism principle
A file belongs at the repository root only if at least one of these conditions is true:
| Condition |
Examples |
| Tool enforcement — a tool will not find the file elsewhere |
package.json, Cargo.toml, go.mod, .gitignore |
| Platform convention — GitHub/GitLab renders or processes it from root |
README.md, LICENSE, CHANGELOG.md, CODEOWNERS |
| Ecosystem standard name — the ecosystem's toolchain expects it at root |
tsconfig.json, pyproject.toml, .editorconfig, Makefile |
Primary entry point — the project has ≤ 3 source files and no src/ dir |
mem-watchdog.sh, install.sh, main.py |
All other files belong in a purpose-named directory (docs/, scripts/, test/, src/, .github/).
Audit behavior: Root files failing this test are flagged at low severity (informational). The finding recommends which directory the file should move to, but does not block merges.
Cross-ecosystem consensus: Rust (src/, tests/), Go (cmd/, internal/, test/), Python (src/<pkg>/, tests/), JS/TS (src/, test/), .NET (src/, test/), and the kriasoft Folder-Structure-Conventions standard (2k★, 5.8k forks) all converge on this layout: source and tests in subdirectories, root contains only files that must be there.
Every repository must have this root-level structure (files may be absent if N/A):
README.md ← required (content owned by repo-profile-governance)
LICENSE ← required when distributing
CHANGELOG.md ← required; Keep a Changelog format
.gitignore ← required
.github/
copilot-instructions.md ← repo-specific Copilot context
instructions/ ← stack-specific Copilot rules
ISSUE_TEMPLATE/ ← issue forms + config.yml
pull_request_template.md ← PR checklist
workflows/ ← CI/CD pipelines
CODEOWNERS ← ownership mapping
docs/ ← long-form documentation (architecture, guides, references)
scripts/ ← build, deploy, and maintenance scripts
test/ ← test suites (or tests/ — pick one, be consistent)
Root-level file ordering convention
When listing or organizing root files, follow this precedence:
- Community/metadata: README, LICENSE, CHANGELOG, CODE_OF_CONDUCT, CONTRIBUTING, SECURITY, SUPPORT
- Configuration: .gitignore, .editorconfig, package.json / pyproject.toml / Makefile
- Entry points: main source files at root only for simple projects
- Dot-directories: .github/, .vscode/ (if committed)
B) Naming conventions
| Rule |
Convention |
Example |
| Directories |
kebab-case, lowercase, no spaces |
test-fixtures/, docs/technical/ |
| Source files |
Language convention (camelCase for JS/TS, snake_case for Python/Shell) |
configWriter.js, mem_watchdog.sh |
| Config files |
Ecosystem standard name |
package.json, tsconfig.json, .eslintrc.json |
| Scripts |
kebab-case or snake_case, descriptive verb-noun |
prepare.js, docs-integrity-check.sh |
| Test files |
Match source name with .test. or _test. suffix |
utils.test.js, test_watchdog.sh |
| Documentation |
UPPER_SNAKE for community files, kebab-case for guides |
CONTRIBUTING.md, system-stability.md |
Naming anti-patterns (flag in audit mode)
- Spaces in file or directory names.
- Mixed case in directory names (
Tests/ vs test/).
- Generic names without context (
utils/, helpers/, misc/).
- Numbered prefixes for ordering (
01-setup/, 02-config/).
C) App-type-specific structures
VS Code Extension
package.json ← manifest (publisher, contributes, activationEvents)
extension.js (or src/) ← activation entry point
commands.js, utils.js ... ← feature modules
lifecycle.js ← vscode:uninstall hook (plain Node.js)
resources/ ← bundled non-JS assets (BUILD ARTIFACT — gitignored)
scripts/
prepare.js ← vscode:prepublish build step
test/
unit/ ← node:test or mocha unit tests
helpers/ ← test mocks (e.g., mockVscode.js)
bench/ ← benchmarks
stress/ ← stress/load tests
.vscodeignore ← exclude test/, scripts/, .env from .vsix
Key rules:
resources/ is a build artifact: listed in .gitignore, NOT in .vscodeignore.
test/ is listed in .vscodeignore but NOT in .gitignore.
.env and .env.example must be in BOTH .gitignore and .vscodeignore.
extensionKind: ["ui"] and scope: "machine" in package.json for local-only extensions.
Node Library / CLI Tool
src/ ← source code
dist/ or lib/ ← build output (gitignored)
test/ ← test suites
bin/ ← CLI entry points (referenced in package.json "bin")
package.json
tsconfig.json ← if TypeScript
Key rules:
dist/ or lib/ in .gitignore but included in npm package via "files" in package.json.
- Lock file (
package-lock.json) committed for applications, optional for libraries.
engines field in package.json specifies minimum Node.js version.
Shell Tool / Daemon
mem-watchdog.sh ← main script at root (simple projects)
mem-watchdog.service ← systemd unit file
install.sh ← installer
test-watchdog.sh ← test suite at root
test-pressure.sh ← specialized test suites
scripts/ ← auxiliary scripts (only if >3 scripts)
docs/
technical/ ← architecture, postmortems
workflow/ ← process docs, learnings
scratch/ ← ephemeral test output (gitignored or auto-pruned)
Key rules:
- Main scripts live at root when there are ≤3 of them.
scratch/ for ephemeral test output — auto-pruned via tmpfiles.d or test cleanup.
- No
/tmp writes from daemon scripts (testable constraint).
- Config files follow XDG:
${XDG_CONFIG_HOME:-$HOME/.config}/<tool>/.
Static Site / Web App
src/ ← source (components, pages, styles)
public/ ← static assets served as-is
dist/ or build/ ← build output (gitignored)
test/ or __tests__/ ← test suites (framework convention)
Key rules:
- Build output directory in
.gitignore.
- Framework config at root (
next.config.js, vite.config.ts, etc.).
- Environment files:
.env.example committed, .env and .env.local gitignored.
Python Project
src/<package_name>/ ← source package (src layout preferred)
tests/ ← test suites
docs/ ← documentation
pyproject.toml ← project metadata and build config (preferred over setup.py)
Key rules:
src/ layout prevents accidental imports from the working directory.
__pycache__/, *.pyc, .eggs/, *.egg-info/ in .gitignore.
- Virtual environment directory (
venv/, .venv/) in .gitignore.
D) Build artifact isolation
Ignore file strategy
| File |
Purpose |
Scope |
.gitignore |
Exclude from version control |
Build outputs, caches, secrets, env files, IDE settings |
.vscodeignore |
Exclude from .vsix package |
Tests, scripts, dev configs, .env |
.npmignore |
Exclude from npm package |
Tests, docs, CI configs, .env |
"files" in package.json |
Allowlist for npm package |
Preferred over .npmignore for libraries |
Mandatory .gitignore entries (all projects)
# Environment and secrets
.env
.env.local
.env.*.local
# OS files
.DS_Store
Thumbs.db
# IDE
.vscode/settings.json ← if contains user-specific paths
*.code-workspace ← unless shared intentionally
Audit check: no build artifacts in git history
Flag any committed files matching: dist/, build/, node_modules/, *.vsix, resources/ (for VS Code extensions), __pycache__/, *.pyc.
E) CODEOWNERS patterns
Solo maintainer (1 person)
# Single owner for everything
* @username
Small team (2–5 people)
# Default
* @org/core-team
# Specialized paths
.github/workflows/ @org/devops
docs/ @org/docs-team
Monorepo
# Package-level ownership
/packages/api/ @org/backend
/packages/web/ @org/frontend
/packages/shared/ @org/core-team
# Cross-cutting
.github/ @org/devops
Output format (audit mode)
STRUCTURE_AUDIT_REPORT
app_type: <detected or specified>
mode: <audit|scaffold|remediate>
findings:
- id: S1
severity: <low|medium|high>
area: <layout|naming|artifact-isolation|codeowners>
observation: <what exists>
expected: <what should exist>
fix: <specific change>
actions:
1) priority: <P1|P2|P3>
change: <specific file/directory operation>
rationale: <why>
risk: <what could break>
decision: <apply|defer|NO_CHANGE>
Stop conditions
Return NO_CHANGE when:
- Structure already matches conventions for the detected app type.
- Proposed moves would break published paths, imports, or CI.
- Insufficient context to determine the correct app type.
1---2name: repo-structure-conventions3description: Enforce file organization, naming conventions, and app-type-specific project layouts. Use when creating, restructuring, or onboarding a repository.4---5
6# Repo Structure Conventions
7
8## Purpose
9
10Ensure every managed repository has a consistent, navigable, industry-standard file organization. This skill is the **primary owner** for structural layout, naming, and build-artifact isolation.
11
12## When to invoke
13
14- Creating a new repository.
15- Restructuring an existing repository.
16- Onboarding a repo that lacks clear organization.
17- After `repo-onboarding-standards` classifies the app type.
18
19## Scope boundary
20
21### Owns (primary authority)
22
23- Root-level file layout and ordering.
24- Directory naming conventions.
25- App-type-specific directory structures.
26- Build artifact isolation (.gitignore, .vscodeignore, .npmignore).
27- CODEOWNERS patterns by project size and structure.
28
29### Delegates (do NOT duplicate)
30
31| Concern | Owner |
32|---|---|
33| Community health files (README, LICENSE, CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, SUPPORT) | `repo-profile-governance` |
34| Discoverability metadata (description, topics, social preview, homepage) | `repo-profile-governance` |
35| GitHub Actions security (SHA pinning, token permissions, OIDC) | `github-actions-security-hardening` |
36| Secret hygiene (.env, credentials, artifact leaks) | `secret-exposure-prevention` |
37| Documentation content quality and drift detection | `docs-drift-maintenance` |
38| Release versioning, tags, and publish integrity | `release-version-integrity` |
39| CI/CD workflow design and merge gates | `github-review-merge-admin` |
40
41## Hard constraints
42
431. No unbounded loops or recursive retries.
442. Maximum one full repository audit per invocation.
453. No silent file creation; produce explicit proposals for review.
464. Never move or rename files without confirming the change won't break imports, CI, or published paths.
475. Prefer the smallest structural change that achieves the convention.
48
49## Modes
50
51- **audit**: Detect structural gaps and deviations. Return findings ranked by severity.
52- **scaffold**: Generate the initial directory structure for a new project given an app type.
53- **remediate**: Propose minimal file moves/renames to bring an existing repo into compliance.
54
55---
56
57## A) Universal file layout
58
59### Root minimalism principle
60
61A file belongs at the repository root **only** if at least one of these conditions is true:
62
63| Condition | Examples |
64|---|---|
65| **Tool enforcement** — a tool will not find the file elsewhere | `package.json`, `Cargo.toml`, `go.mod`, `.gitignore` |
66| **Platform convention** — GitHub/GitLab renders or processes it from root | `README.md`, `LICENSE`, `CHANGELOG.md`, `CODEOWNERS` |
67| **Ecosystem standard name** — the ecosystem's toolchain expects it at root | `tsconfig.json`, `pyproject.toml`, `.editorconfig`, `Makefile` |
68| **Primary entry point** — the project has ≤ 3 source files and no `src/` dir | `mem-watchdog.sh`, `install.sh`, `main.py` |
69
70All other files belong in a purpose-named directory (`docs/`, `scripts/`, `test/`, `src/`, `.github/`).
71
72**Audit behavior**: Root files failing this test are flagged at `low` severity (informational). The finding recommends which directory the file should move to, but does not block merges.
73
74**Cross-ecosystem consensus**: Rust (`src/`, `tests/`), Go (`cmd/`, `internal/`, `test/`), Python (`src/<pkg>/`, `tests/`), JS/TS (`src/`, `test/`), .NET (`src/`, `test/`), and the kriasoft Folder-Structure-Conventions standard (2k★, 5.8k forks) all converge on this layout: source and tests in subdirectories, root contains only files that must be there.
75
76Every repository must have this root-level structure (files may be absent if N/A):
77
78```
79README.md ← required (content owned by repo-profile-governance)
80LICENSE ← required when distributing
81CHANGELOG.md ← required; Keep a Changelog format
82.gitignore ← required
83.github/
84 copilot-instructions.md ← repo-specific Copilot context
85 instructions/ ← stack-specific Copilot rules
86 ISSUE_TEMPLATE/ ← issue forms + config.yml
87 pull_request_template.md ← PR checklist
88 workflows/ ← CI/CD pipelines
89 CODEOWNERS ← ownership mapping
90docs/ ← long-form documentation (architecture, guides, references)
91scripts/ ← build, deploy, and maintenance scripts
92test/ ← test suites (or tests/ — pick one, be consistent)
93```
94
95### Root-level file ordering convention
96
97When listing or organizing root files, follow this precedence:
981. Community/metadata: README, LICENSE, CHANGELOG, CODE_OF_CONDUCT, CONTRIBUTING, SECURITY, SUPPORT
992. Configuration: .gitignore, .editorconfig, package.json / pyproject.toml / Makefile
1003. Entry points: main source files at root only for simple projects
1014. Dot-directories: .github/, .vscode/ (if committed)
102
103## B) Naming conventions
104
105| Rule | Convention | Example |
106|---|---|---|
107| Directories | kebab-case, lowercase, no spaces | `test-fixtures/`, `docs/technical/` |
108| Source files | Language convention (camelCase for JS/TS, snake_case for Python/Shell) | `configWriter.js`, `mem_watchdog.sh` |
109| Config files | Ecosystem standard name | `package.json`, `tsconfig.json`, `.eslintrc.json` |
110| Scripts | kebab-case or snake_case, descriptive verb-noun | `prepare.js`, `docs-integrity-check.sh` |
111| Test files | Match source name with `.test.` or `_test.` suffix | `utils.test.js`, `test_watchdog.sh` |
112| Documentation | UPPER_SNAKE for community files, kebab-case for guides | `CONTRIBUTING.md`, `system-stability.md` |
113
114### Naming anti-patterns (flag in audit mode)
115
116- Spaces in file or directory names.
117- Mixed case in directory names (`Tests/` vs `test/`).
118- Generic names without context (`utils/`, `helpers/`, `misc/`).
119- Numbered prefixes for ordering (`01-setup/`, `02-config/`).
120
121## C) App-type-specific structures
122
123### VS Code Extension
124
125```
126package.json ← manifest (publisher, contributes, activationEvents)
127extension.js (or src/) ← activation entry point
128commands.js, utils.js ... ← feature modules
129lifecycle.js ← vscode:uninstall hook (plain Node.js)
130resources/ ← bundled non-JS assets (BUILD ARTIFACT — gitignored)
131scripts/
132 prepare.js ← vscode:prepublish build step
133test/
134 unit/ ← node:test or mocha unit tests
135 helpers/ ← test mocks (e.g., mockVscode.js)
136 bench/ ← benchmarks
137 stress/ ← stress/load tests
138.vscodeignore ← exclude test/, scripts/, .env from .vsix
139```
140
141Key rules:
142- `resources/` is a build artifact: listed in `.gitignore`, NOT in `.vscodeignore`.
143- `test/` is listed in `.vscodeignore` but NOT in `.gitignore`.
144- `.env` and `.env.example` must be in BOTH `.gitignore` and `.vscodeignore`.
145- `extensionKind: ["ui"]` and `scope: "machine"` in `package.json` for local-only extensions.
146
147### Node Library / CLI Tool
148
149```
150src/ ← source code
151dist/ or lib/ ← build output (gitignored)
152test/ ← test suites
153bin/ ← CLI entry points (referenced in package.json "bin")
154package.json
155tsconfig.json ← if TypeScript
156```
157
158Key rules:
159- `dist/` or `lib/` in `.gitignore` but included in npm package via `"files"` in `package.json`.
160- Lock file (`package-lock.json`) committed for applications, optional for libraries.
161- `engines` field in `package.json` specifies minimum Node.js version.
162
163### Shell Tool / Daemon
164
165```
166mem-watchdog.sh ← main script at root (simple projects)
167mem-watchdog.service ← systemd unit file
168install.sh ← installer
169test-watchdog.sh ← test suite at root
170test-pressure.sh ← specialized test suites
171scripts/ ← auxiliary scripts (only if >3 scripts)
172docs/
173 technical/ ← architecture, postmortems
174 workflow/ ← process docs, learnings
175scratch/ ← ephemeral test output (gitignored or auto-pruned)
176```
177
178Key rules:
179- Main scripts live at root when there are ≤3 of them.
180- `scratch/` for ephemeral test output — auto-pruned via `tmpfiles.d` or test cleanup.
181- No `/tmp` writes from daemon scripts (testable constraint).
182- Config files follow XDG: `${XDG_CONFIG_HOME:-$HOME/.config}/<tool>/`.
183
184### Static Site / Web App
185
186```
187src/ ← source (components, pages, styles)
188public/ ← static assets served as-is
189dist/ or build/ ← build output (gitignored)
190test/ or __tests__/ ← test suites (framework convention)
191```
192
193Key rules:
194- Build output directory in `.gitignore`.
195- Framework config at root (`next.config.js`, `vite.config.ts`, etc.).
196- Environment files: `.env.example` committed, `.env` and `.env.local` gitignored.
197
198### Python Project
199
200```
201src/<package_name>/ ← source package (src layout preferred)
202tests/ ← test suites
203docs/ ← documentation
204pyproject.toml ← project metadata and build config (preferred over setup.py)
205```
206
207Key rules:
208- `src/` layout prevents accidental imports from the working directory.
209- `__pycache__/`, `*.pyc`, `.eggs/`, `*.egg-info/` in `.gitignore`.
210- Virtual environment directory (`venv/`, `.venv/`) in `.gitignore`.
211
212## D) Build artifact isolation
213
214### Ignore file strategy
215
216| File | Purpose | Scope |
217|---|---|---|
218| `.gitignore` | Exclude from version control | Build outputs, caches, secrets, env files, IDE settings |
219| `.vscodeignore` | Exclude from .vsix package | Tests, scripts, dev configs, .env |
220| `.npmignore` | Exclude from npm package | Tests, docs, CI configs, .env |
221| `"files"` in `package.json` | Allowlist for npm package | Preferred over `.npmignore` for libraries |
222
223### Mandatory .gitignore entries (all projects)
224
225```
226# Environment and secrets
227.env
228.env.local
229.env.*.local
230
231# OS files
232.DS_Store
233Thumbs.db
234
235# IDE
236.vscode/settings.json ← if contains user-specific paths
237*.code-workspace ← unless shared intentionally
238```
239
240### Audit check: no build artifacts in git history
241
242Flag any committed files matching: `dist/`, `build/`, `node_modules/`, `*.vsix`, `resources/` (for VS Code extensions), `__pycache__/`, `*.pyc`.
243
244## E) CODEOWNERS patterns
245
246### Solo maintainer (1 person)
247
248```
249# Single owner for everything
250* @username
251```
252
253### Small team (2–5 people)
254
255```
256# Default
257* @org/core-team
258
259# Specialized paths
260.github/workflows/ @org/devops
261docs/ @org/docs-team
262```
263
264### Monorepo
265
266```
267# Package-level ownership
268/packages/api/ @org/backend
269/packages/web/ @org/frontend
270/packages/shared/ @org/core-team
271
272# Cross-cutting
273.github/ @org/devops
274```
275
276---
277
278## Output format (audit mode)
279
280```text
281STRUCTURE_AUDIT_REPORT
282app_type: <detected or specified>
283mode: <audit|scaffold|remediate>
284
285findings:
286- id: S1
287 severity: <low|medium|high>
288 area: <layout|naming|artifact-isolation|codeowners>
289 observation: <what exists>
290 expected: <what should exist>
291 fix: <specific change>
292
293actions:
2941) priority: <P1|P2|P3>
295 change: <specific file/directory operation>
296 rationale: <why>
297 risk: <what could break>
298
299decision: <apply|defer|NO_CHANGE>
300```
301
302## Stop conditions
303
304Return `NO_CHANGE` when:
305- Structure already matches conventions for the detected app type.
306- Proposed moves would break published paths, imports, or CI.
307- Insufficient context to determine the correct app type.