# Autodev Init

> 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.

- Skill: `djnsty23/autodev-init` (Agent Skill)
- Install (CLI): `npx skillmds@latest add djnsty23/autodev-init`
- Raw SKILL.md: https://api.skillmd.com/api/skills/djnsty23/autodev-init/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: djnsty23 (https://skillmd.com/u/djnsty23)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/djnsty23/autodev-init

---


# 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

`.claude/` is ephemeral tooling state and should be ignored — but this one file
is worth committing. A bare `!.claude/project-rules.md` negation only works if
`.claude/` is ignored as a directory, so add both, and check the result rather
than assuming:

```bash
grep -q "^\.claude/$" .gitignore || printf '\n# autodev tooling state\n.claude/\n' >> .gitignore
grep -q "project-rules" .gitignore || printf '# ...except the project rules, which are committed\n!.claude/project-rules.md\n' >> .gitignore
git check-ignore -v .claude/project-rules.md && echo "STILL IGNORED — fix the negation before continuing"
```

If the repo already ignores only specific paths inside `.claude/` rather than
the whole directory, leave that alone and just confirm `project-rules.md` is
committable. Do not restructure someone's `.gitignore`.

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 anything. This skill only reads and writes one file.
- Do not run on a repo with fewer than ~10 source files — there is no convention
  to observe yet. Say so and stop.

## 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.

