text
| 1 | # Repo Onboarding — Workflow |
| 2 | |
| 3 | Turns an unfamiliar codebase into a working mental model, written down as |
| 4 | `ONBOARDING.md` in the repo root. The goal is a document that lets the next person (or |
| 5 | the next agent session) become productive without re-doing this exploration. |
| 6 | |
| 7 | Inputs: `root_dir` (default `.`), `depth` (`quick` | `standard` | `deep`, default |
| 8 | `standard`). |
| 9 | |
| 10 | ## Step 1 — Orient at the surface |
| 11 | |
| 12 | 1. Read root-level files first, in this order: `README.md`, `package.json` / |
| 13 | `pyproject.toml` / `Cargo.toml` / `go.mod` (whichever exists), `CONTRIBUTING.md`, |
| 14 | any `AGENTS.md` / `CLAUDE.md`, CI config (`.github/workflows/*.yml`, `.gitlab-ci.yml`). |
| 15 | 2. From these, extract: language(s) and version, package manager, framework(s), and the |
| 16 | scripts/commands already defined for build/test/lint/dev (don't guess these — quote |
| 17 | them from `package.json` `scripts`, `Makefile` targets, etc.). |
| 18 | 3. Run `git log --oneline -20` and skim recent commits — this tells you what part of |
| 19 | the codebase is actively changing and often surfaces naming conventions in commit |
| 20 | messages. |
| 21 | |
| 22 | ## Step 2 — Map the directory structure |
| 23 | |
| 24 | 1. List top-level directories (`ls`, or a depth-limited tree). For each one, form a |
| 25 | one-line hypothesis of its purpose from its name and a peek at 2-3 files inside. |
| 26 | 2. Identify the "core" directories vs. generated/vendored ones (`node_modules`, |
| 27 | `dist`, `build`, `.next`, `target`, `vendor`) — exclude the latter from further |
| 28 | exploration. |
| 29 | 3. For `quick` depth, stop here after Step 3. For `standard`/`deep`, continue. |
| 30 | |
| 31 | ## Step 3 — Find the entrypoints |
| 32 | |
| 33 | Entrypoints are where execution starts or where an external actor (HTTP client, CLI |
| 34 | user, message queue) first touches the code. Find them by: |
| 35 | - Checking the `main`/`bin` fields in the package manifest. |
| 36 | - Searching for `if __name__ == "__main__"`, `func main()`, `app.listen(`, |
| 37 | `createServer(`, route/handler registration, or a CLI framework's entry command. |
| 38 | - For web apps: the routing layer (file-based routes, or a router config file) — list |
| 39 | the actual routes/endpoints, not just "there's a router." |
| 40 | - For libraries: the public API surface — what's exported from the package root |
| 41 | (`index.ts`/`__init__.py`/etc.). |
| 42 | |
| 43 | Record each entrypoint with its file path and a one-line description of what triggers it. |
| 44 | |
| 45 | ## Step 4 — Extract conventions |
| 46 | |
| 47 | Look for patterns that a new contributor needs to match, not invent: |
| 48 | - Naming conventions (files, functions, components) — infer from 5-10 examples, don't |
| 49 | assume from one. |
| 50 | - Where tests live relative to source, and what test framework/assertion style is used. |
| 51 | - Error handling pattern (exceptions vs. result types vs. error codes) — check 2-3 |
| 52 | different modules to confirm it's consistent, not a one-off. |
| 53 | - State management / data flow pattern, if applicable (e.g. a specific store pattern, |
| 54 | a particular ORM usage pattern). |
| 55 | - Linting/formatting config (`.eslintrc`, `pyproject.toml` `[tool.ruff]`, etc.) — quote |
| 56 | any non-default rules that would surprise a newcomer. |
| 57 | - Any explicit rules already written down (`CLAUDE.md`, `AGENTS.md`, `CONTRIBUTING.md`) |
| 58 | — summarize, don't just point at them, so `ONBOARDING.md` is self-contained. |
| 59 | |
| 60 | ## Step 5 — Determine how to run and test it |
| 61 | |
| 62 | Do not guess these — verify by running them (or, if execution isn't available/safe in |
| 63 | this context, quote the exact commands from CI config, since CI is a working |
| 64 | ground-truth of "how this project builds/tests"). |
| 65 | - Install: exact command (`npm ci`, `poetry install`, etc.) and any prerequisite |
| 66 | (Node version, a `.env` file, a running database/service). |
| 67 | - Run locally: exact command and what port/URL it serves, if applicable. |
| 68 | - Run tests: exact command, and whether there are sub-suites (unit vs. integration vs. |
| 69 | e2e) that run differently. |
| 70 | - Lint/typecheck: exact command(s). |
| 71 | - Anything that commonly trips people up (a required local service, a seed-data step, |
| 72 | a specific Node/Python version pinned in `.nvmrc`/`.python-version`). |
| 73 | |
| 74 | `deep` depth only: actually attempt the install + test commands and note the real |
| 75 | result (pass/fail, time taken, anything that needed a workaround). |
| 76 | |
| 77 | ## Step 6 — Write ONBOARDING.md |
| 78 | |
| 79 | Structure: |
| 80 | |
| 81 | ```markdown |
| 82 | # Onboarding: <repo name> |
| 83 | |
| 84 | ## What this is |
| 85 | <2-4 sentences: what the project does, who it's for> |
| 86 | |
| 87 | ## Architecture |
| 88 | <the mental model: major components/services and how they relate. |
| 89 | A short list or simple diagram-in-prose is fine — this is not a full design doc.> |
| 90 | |
| 91 | ## Entrypoints |
| 92 | - `path/to/entry` — <what triggers it> |
| 93 | ... |
| 94 | |
| 95 | ## Directory guide |
| 96 | - `src/foo/` — <purpose> |
| 97 | ... |
| 98 | |
| 99 | ## Conventions |
| 100 | - <naming, testing, error handling, etc. — the things a new contributor must match> |
| 101 | |
| 102 | ## Running it |
| 103 | - Install: `<command>` |
| 104 | - Dev/run: `<command>` |
| 105 | - Test: `<command>` |
| 106 | - Lint/typecheck: `<command>` |
| 107 | - Gotchas: <anything non-obvious> |
| 108 | |
| 109 | ## Open questions |
| 110 | <anything you couldn't determine confidently from the code alone — |
| 111 | flag these rather than guessing, so a human can fill them in> |
| 112 | ``` |
| 113 | |
| 114 | Write this file to `<root_dir>/ONBOARDING.md`. If one already exists, do not silently |
| 115 | overwrite it — show a diff/summary of what changed and let the user confirm, since it |
| 116 | may contain hand-maintained context this pass can't infer. |
| 117 | |
| 118 | ## Stop conditions |
| 119 | |
| 120 | - Repo has no discoverable package manifest or build config → say so and produce a |
| 121 | best-effort structural summary rather than fabricating run instructions. |
| 122 | - Monorepo with multiple independently-runnable projects → produce one top-level |
| 123 | overview plus a short per-package pointer rather than merging them into one |
| 124 | undifferentiated document. |
| 125 | - Explored surface area is large enough that `deep` would take a very long time → |
| 126 | fall back to `standard` and say so explicitly rather than silently truncating. |
| 127 |