Derive this project's actual conventions from its code and write them into a project-local rules file, so autodev enforces what this codebase already decided instead of a generic default.
Installs into .claude/skills of the current project.
Are you the author of Autodev Init?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/djnsty23-autodev-init)
---
name: autodev-init
description: Derive this project's actual conventions from its code and write them into a project-local rules file, so autodev enforces what this codebase already decided instead of a generic default.
when_to_use: "Invoked when the user says \"autodev init\", \"init autodev\", \"learn my conventions\", \"generate project rules\", or when review/audit findings keep contradicting how this codebase is actually written."
allowed-tools: Bash, Read, Write, Edit, Grep, Glob
model: opus
user-invocable: true
argument-hint: "[refresh]"
---
# autodev-init
Every other skill in this plugin ships someone else's conventions. This one reads
yours out of the code and writes them down, so `review`, `audit`, and `auto`
enforce what your project actually does.
Output goes to **`.claude/project-rules.md`** in the project — not into the
plugin. It is project-local, git-committed, and human-editable. The generic
`standards` and `rule-*` skills stay as the fallback for anything you have not
decided.
## Rule one: observe, never assume
Every line you write must be backed by a count from this codebase. If you cannot
produce evidence, the convention does not go in the file — write it in the
"Undecided" section instead. A generated rules file that guesses is worse than
none, because `review` will enforce the guess.
If `.claude/project-rules.md` already exists, this is a **refresh**: re-measure,
show a diff of what changed, and preserve every hand-edited line. Never silently
overwrite a human's edit.
## Step 1: Establish the stack
```bash
cat package.json 2>/dev/null | head -60
ls -d src app pages components lib server 2>/dev/null
cat tsconfig.json 2>/dev/null | head -30
```
Record: framework and major version, router style, package manager (from the
lockfile), TypeScript strictness, test runner, linter/formatter.
## Step 2: Measure the conventions
Run these and **keep the counts** — they are the evidence.
```bash
# Component style: function declarations vs arrow consts
grep -rEc "^export (default )?function [A-Z]" --include='*.tsx' src app 2>/dev/null | awk -F: '{n+=$2} END {print "fn components:", n+0}'
grep -rEc "^export const [A-Z][A-Za-z]* = \(" --include='*.tsx' src app 2>/dev/null | awk -F: '{n+=$2} END {print "arrow components:", n+0}'
# Data fetching
grep -rl "useQuery\|useSuspenseQuery" --include='*.tsx' --include='*.ts' src app 2>/dev/null | wc -l
grep -rl "useSWR" --include='*.tsx' --include='*.ts' src app 2>/dev/null | wc -l
grep -rl "await fetch(" --include='*.tsx' --include='*.ts' src app 2>/dev/null | wc -l
# Validation at boundaries
grep -rl "from ['\"]zod['\"]" --include='*.ts' --include='*.tsx' src app 2>/dev/null | wc -l
# Styling: tokens vs raw colors
grep -rEo "\b(bg|text|border)-(background|foreground|primary|secondary|muted|accent|destructive)\b" --include='*.tsx' src app 2>/dev/null | wc -l
grep -rEo "\b(bg|text|border)-(gray|slate|zinc|white|black|red|blue|green)-?[0-9]*\b" --include='*.tsx' src app 2>/dev/null | wc -l
# Error and state handling
grep -rc "catch" --include='*.ts' --include='*.tsx' src app 2>/dev/null | awk -F: '{n+=$2} END {print "catch blocks:", n+0}'
grep -rl "isLoading\|isPending" --include='*.tsx' src app 2>/dev/null | wc -l
# Test layout
ls **/*.test.* **/*.spec.* __tests__ 2>/dev/null | head -5
```
Read 3–5 of the most recently changed non-trivial components in full. Counts
tell you what is common; reading tells you what is *intended*.
```bash
git log --format= --name-only -50 -- '*.tsx' | grep -v '^$' | sort | uniq -c | sort -rn | head -10
```
## Step 3: Find the boundaries
These matter more than style, because getting them wrong is a security bug:
- Where does auth get enforced? Middleware, per-route, or per-component?
- Where does external data enter, and is it validated there?
- Which directories are server-only? What stops a secret reaching the client?
- If there is a database: where do RLS policies live, and is deny-by-default the pattern?
## Step 4: Resolve contradictions with the user
Where the codebase is split — say 60/40 between two patterns — do **not** pick the
majority silently. Ask, using AskUserQuestion, with the counts in the options:
> Components are 34 arrow-const and 22 function-declaration. Which is the
> convention going forward?
Ask about at most the four most consequential splits. Everything else goes to
"Undecided".
## Step 5: Write `.claude/project-rules.md`
```markdown
# Project Rules
Generated by autodev-init on <date> from <N> files. Hand edits are preserved on
refresh — edit freely.
## Stack
<framework, router, package manager, TS strictness, test runner>
## Conventions
- <rule> — observed in <N>/<M> files
- <rule> — decided by <user>, <date>
## Boundaries
- Auth enforced at: <where>
- External data validated at: <where> using <what>
- Server-only: <paths>
## Anti-patterns for this codebase
- <specific pattern>, because <project-specific reason>
## Undecided
- <split convention with counts> — no rule; do not flag either form in review.
```
Then tell the user, in one line each: what you measured, what you asked, and
what remains undecided.
## Step 6: Wire it in
Keep raw tooling state ignored and this one project-rules file committable.
Read the existing ignore rules first. A negation cannot re-include a file while
its parent directory is excluded. For a project currently using the exact
`.claude/` rule, change that rule to `.claude/*` and add
`!.claude/project-rules.md`; preserve all other exclusions and existing evidence
exceptions. Re-open any ignored ancestor required by the project's actual layout.
Verify the effective result after the edit:
```bash
git check-ignore -q --no-index -- .claude/project-rules.md
# exit 0 = still ignored; exit 1 = not ignored; any other exit = probe failure
git status --short -- .claude/project-rules.md .gitignore
```
Also verify a scratch report and a memory-session carrier remain ignored.
`git check-ignore -v` is diagnostic output, not an ignoredness verdict: a
matching negation is printed too. If the repo already uses selective ignore
rules, leave their structure intact and add only the needed exception.
Tell the user that `review`, `audit`, and `auto` should read
`.claude/project-rules.md` and that **it outranks the plugin's generic
`standards` skill wherever the two disagree** — the project's own observed
convention wins over a shipped default.
## What not to do
- Do not write a rule you did not measure.
- Do not restate general best practice. "Handle errors" is not a project rule;
"errors surface through `<ErrorState>`, never a toast" is.
- Do not reformat or refactor source. This skill writes project rules and the minimal ignore-rule wiring needed to preserve them.
- With few source files, record the small population and leave unsupported conventions Undecided. This limits the inferred rules; it does not stop other already-authorized work.
## Proving the run
**Observable:** every rule written to `.claude/project-rules.md` cites the file
it was measured from, and re-reading that file still supports the rule.
The failure mode of this skill is a confident convention nobody follows — a rule
inferred from two files and applied to two hundred. A citation makes that
checkable by someone who was not here. Before finishing, re-read three cited
files at random and confirm each still says what the rule claims. State how many
files the conventions were measured across; a rule derived from one file is a
guess and should say so.