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