Write Docs
Contribute documentation that a maintainer would write — accurate, audience-aware, and verified against the actual code. Docs contributions have different mechanics than code PRs: you need to understand who reads the docs, verify every claim against source code, and test every example.
Purpose
Documentation contributions are undervalued by contributors and overvalued by maintainers. Most contributors skip docs because they don't feel like "real" contributions. But outdated docs cause more user frustration than most bugs, and maintainers rarely have time to keep docs current. This skill guides you through finding real documentation gaps, verifying accuracy against the code, and writing docs that match the repo's voice and style.
When to Use
- You've found outdated setup instructions (you followed them and they didn't work)
- Public API methods or functions lack documentation
- README assumes knowledge that new users don't have
- Code examples in docs don't run or produce wrong output
- Error messages reference docs that don't exist
- NOT for writing docs for your own project
- NOT for adding inline code comments — that's part of code contributions
- NOT when the repo has no docs infrastructure at all — discuss with maintainers first
Prerequisites
- Repo forked, cloned, and set up (from
oss-prep-to-contribute) - You've actually tried to USE the docs and found problems (not just skimming)
- Understanding of the area you're documenting (or willingness to build it)
Process
1. Identify documentation gaps
The best doc contributions come from actually using the docs and finding where they fail.
# Find docs files
find . -name "*.md" -not -path "*/node_modules/*" -not -path "*/.git/*" | head -30
ls docs/ doc/ documentation/ wiki/ 2>/dev/null
# Check for docs framework
ls docusaurus.config.* mkdocs.yml conf.py book.toml .readthedocs.yml 2>/dev/null
# Find broken links in docs
grep -rn '\[.*\](.*\.md)' docs/ README.md | while read line; do
file=$(echo "$line" | sed -n 's/.*(\([^)]*\.md\)).*/\1/p')
[ -n "$file" ] && [ ! -f "$file" ] && echo "Broken link: $line"
done
# Find code examples and check if they reference current APIs
grep -rn '```' docs/ README.md --include="*.md" | head -20
High-value doc gaps (prioritize these):
- Setup instructions that don't work (you tried them)
- API methods with no docs but active usage in the codebase
- Examples that reference renamed or removed functions
- Config options documented nowhere
- Error messages that say "see docs" but the docs don't exist
Low-value doc gaps (skip these):
- Typos in low-traffic pages
- Style inconsistencies (unless extreme)
- Adding docs for internal/private APIs
2. Understand the docs system
Every repo has documentation conventions. Learn them before writing.
# Check how docs are built
cat package.json 2>/dev/null | grep -i "doc\|docs\|build.*doc"
cat Makefile 2>/dev/null | grep -i doc
cat pyproject.toml 2>/dev/null | grep -i doc
# Read the docs contribution guide (if separate from CONTRIBUTING.md)
cat docs/CONTRIBUTING.md docs/contributing.md 2>/dev/null
# Check the docs config
cat docusaurus.config.js mkdocs.yml conf.py 2>/dev/null | head -50
Document:
- Docs framework: Docusaurus, MkDocs, Sphinx, mdBook, rustdoc, JSDoc, plain markdown?
- File structure: how are docs organized? (by topic, by API, by tutorial?)
- Build process: how to preview locally?
- Style guide: formal or casual? second person ("you") or imperative? code-heavy or prose-heavy?
- Versioning: are docs versioned alongside releases?
3. Verify the gap by reading code
Every documentation claim must be traceable to actual code. Don't write docs from memory or assumption.
# If documenting a function, read its implementation
grep -rn "function functionName\|def functionName\|func functionName" src/ --include="*.ts" --include="*.py" --include="*.go"
# If documenting config options, find where they're read
grep -rn "config\.\|getenv\|process\.env\." src/ --include="*.ts" --include="*.py"
# If documenting CLI flags, find the argument parser
grep -rn "argparse\|commander\|clap\|flag\." src/ --include="*.py" --include="*.ts" --include="*.rs" --include="*.go"
For each claim you plan to write:
- Find the source code that implements the behavior
- Note the file and line number (for your own reference, not for the docs)
- Check if the behavior has changed since the last docs update
# When was this doc last updated vs when was the code last changed?
git log --oneline -5 -- "docs/path/to/page.md"
git log --oneline -5 -- "src/path/to/implementation.ts"
4. Thinking gate — user explains the audience
"Before writing anything:
- Who reads this documentation? (New users? API consumers? Contributors? Ops/deploy engineers?)
- What do they already know when they arrive at this page?
- What are they trying to accomplish? (Not 'learn about X' — what task are they doing?)
- What's the single most important thing this page should communicate?"
Wait for their answer. If they say "everyone" or "developers in general," push back: "Look at the existing docs — who is the implicit audience? What level of knowledge do they assume?"
5. User writes the docs
The user drafts the documentation. The LLM helps with:
- Verifying claims against source code ("you wrote that this accepts 3 arguments, but the function signature shows 4")
- Checking code examples actually work
- Matching the repo's documentation voice and style
- Pointing to similar pages as format reference
What the LLM DOES:
- Fact-check every claim against the source code
- Test code examples mentally (or by running them if possible)
- Review for clarity — flag jargon the target audience wouldn't know
- Point to existing docs pages as style reference
What the LLM DOES NOT DO:
- Write the documentation for the user
- Add promotional language ("this amazing feature...")
- Expand scope beyond what the user identified
6. Test and verify
Before submitting, verify everything:
# Build docs locally
# {repo-specific docs build command — found in step 2}
# If the docs framework supports link checking
# {repo-specific link check command}
Manual verification:
- Click every link in your changes — both internal and external
- Run every code example and verify the output matches what you documented
- Read the page as if you're the target audience — does it answer their question?
- Check that your page is reachable from the navigation/sidebar (not an orphan)
# Verify code examples work
# Copy-paste each example and run it
7. Thinking gate — user reviews their own writing
"Read your docs one more time and answer:
- Can the target user accomplish their task using only what you wrote? (No unstated prerequisites?)
- Is every code example copy-paste-runnable? (No missing imports, no assumed setup?)
- Does anything you wrote contradict what the code actually does? (Check the source again)
- If the function changes next release, which parts of your docs would break?"
This catches the most common doc bugs: assumed context, stale examples, and version-coupled language.
Related Skills
- Previous step: ←
oss-prep-to-contribute— set up the repo - Alternative entry: ←
oss-find-real-issues— if you found doc gaps while exploring - Next step: →
oss-submit-pr— submit the docs PR - If unfamiliar with the code: →
oss-learn-stackoross-explore-repo— understand the feature before documenting it
Common Rationalizations
| Shortcut | Why It Fails |
|---|---|
| "I'll just fix the typos I found" | Typo-only PRs are low-signal. They're welcome, but they don't build trust or demonstrate understanding. Pair typo fixes with substantive improvements. |
| "I know how this feature works, I don't need to read the code" | You know how you THINK it wor |