Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .claude/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Per-machine permission overrides (each contributor curates their own)
settings.local.json

# Scratch space written by skills (sources.md, slack.md, report.html, etc.)
tmp/*
!tmp/.gitkeep
158 changes: 158 additions & 0 deletions .claude/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# .claude — Agents, Skills, and Drafts

Claude Code configuration for the Trunk docs (Mintlify) repo. Skills are documentation-focused: scaffolding new pages, processing notes into PRs, reviewing changes, verifying PRs against production.

## Structure

```
.claude/
├── agents/ # Subagent definitions (spawned via the Agent tool)
│ └── doc-researcher.md # Gathers Linear/PR/Slite/docs context before writing
├── skills/ # User-invoked workflows (triggered via /skill-name)
│ ├── docs-research/ # Audit existing docs to find gaps and placement
│ ├── outline-docs/ # Scaffold a new docs page from scratch
│ ├── write-docs/ # Trunk2 context → PR pipeline (9 phases)
│ └── verify-docs-pr/ # Verify a docs PR's feature is live in prod
├── drafts/ # Optional input notes files for write-docs
│ └── TEMPLATE.md # Scaffold for new draft notes
├── tmp/ # Scratch outputs (gitignored)
├── settings.json # Shared permissions (committed)
└── settings.local.json # Per-machine overrides (gitignored)
```

## Mental model

The flow is **research → write → verify**:

| Phase | Skill |
|---|---|
| Research | `/docs-research` (existing-coverage audit) + `doc-researcher` agent (Linear/PR/Slite context) |
| Write | `/outline-docs` (blank-page scaffold) or `/write-docs` (full PR pipeline) |
| Verify | `/verify-docs-pr` (is the feature actually live in prod?) |

## Agents vs. Skills

**Agents** (`agents/`) are autonomous subprocesses spawned by the `Agent` tool. They run with a specific model and limited toolset, do their work, and return results to the parent conversation. Use agents for parallelizable research tasks.

**Skills** (`skills/`) are user-invoked workflows triggered with `/skill-name`. They run in the main conversation with full tool access and follow a structured multi-phase pipeline. Use skills for end-to-end tasks that produce artifacts (PRs, tickets, reports).

| Type | How to invoke | Runs where | Best for |
|---|---|---|---|
| Agent | Spawned via the `Agent` tool | Background subprocess | Research, context gathering, parallel work |
| Skill | `/skill-name` | Main conversation | Multi-step workflows with user checkpoints |

## Skill reference

### `/docs-research`

**When:** Before writing a new doc (or right after a deploy) to audit existing coverage, find gaps, and decide where new content should live.

**What it does:** Five-phase audit:
1. Maps the relevant product-area group in `docs.json` and lists candidate `.mdx` files
2. Searches existing docs (hosted search + local grep) for the topic and synonyms
3. Classifies each hit as `covered`, `partial`, or `adjacent`
4. Recommends placement for new content — defaulting to extending an existing page over creating a new one
5. Generates a structured report with existing coverage, gaps, suggested placement, and cross-links to add

**Inputs:** A topic / feature name / product area. Optional: a feature description, PR body, or Linear ticket. `full` for a site-wide audit.

**Outputs:** A research report that feeds directly into `/outline-docs` or `/write-docs`.

---

### `/outline-docs`

**When:** Starting a brand-new docs page from scratch with no prior spec.

**What it does:** Asks page type (Overview / Reference / Guide), title, and save path. Generates a scaffolded `.mdx` file with sections pre-filled with 1-2 sentences plus focused `<!-- TODO -->` markers. Adds the page to `docs.json` navigation. Runs `trunk fmt`.

**Inputs:** Conversation context (title, page type, topic) — asks only for what's missing.

**Outputs:** A new `.mdx` file ready for content, plus a post-checklist.

---

### `/write-docs`

**When:** Given a draft notes file, trunk2 PR numbers, Linear ticket IDs, a deploy tag, or Slite links — anything that says "document this feature."

**What it does:** Full 9-phase pipeline:
1. Overlap detection (Phase 0) — checks GitHub for existing or conflicting docs PRs **and** Linear for existing planning tickets before starting work; asks the user if anything matches
2. Research across Linear, Slite, Slack, trunk2 PR diffs, and existing docs
3. Drafts new content or in-place edits, updating `docs.json` if adding pages
4. Creates a branch, commits, opens a **draft** PR with author tags
5. Updates Linear (links the existing ticket from Phase 0 or creates a new one) and writes a Slack post draft
6. Invokes `/verify-docs-pr` to check whether the feature is actually live in prod

**Inputs:** Trunk2 PR refs, Linear ticket IDs, a deploy tag, Slite links, or an optional `.claude/drafts/<topic>.md` file for batch workflows.

**Outputs:** Branch, draft PR, Linear update, Slack post in `tmp/<topic>/slack.md`.

**Discipline:** One feature = one PR. Always opens as draft for human review.

---

### `/verify-docs-pr`

**When:** A docs PR is open and you need to confirm the feature it documents is actually shipped to customers before publishing.

**What it does:** Classifies a PR as `live`, `staged`, `pending`, `blocked`, or `unknown` using indirect signals: linked eng PR merge state, follow-up PRs in trunk2, Slack rollout chatter, e2e flag defaults, and legacy code presence. Posts the verdict as a comment on the docs PR and the linked Linear ticket. Updates the PR title with a verdict prefix (`[ready to merge]`, `[blocked]`, etc.) and flips non-live PRs to draft.

**Inputs:** A PR number (single mode), or no arg for a sweep across all open PRs.

**Outputs:** PR comment, Linear comment, title prefix update, draft state.

**Auto-invoked:** by `/write-docs` Phase 4 after PR creation.

---

## Agent reference

### `doc-researcher`

Subagent (not a slash command). Spawned via the `Agent` tool with `subagent_type: doc-researcher`.

**Model:** Sonnet 4.6 (chosen for speed).

**Tools:** `Read`, `Grep`, `Glob`, `Bash` — read-only.

**When:** Before `/write-docs` when the scope is unclear or multiple tickets need surveying.

**What it does:** Reads Linear tickets, linked PRs, and existing docs pages. Returns a structured research brief: feature summary, source PRs (with GitHub author handles), current docs coverage, key technical details pulled from code, and a suggested doc structure.

**Use it in parallel** with other research (Slack, Slite searches) to save time.

## Drafts

`drafts/` is optional scratch space for batch workflows. `/write-docs` accepts trunk2 PR / Linear / deploy-tag refs directly, so most invocations skip drafts entirely. Use a draft file when you want to curate notes by hand before processing — for example, post-deploy when several features ship and you want to triage which ones need docs first.

- **`TEMPLATE.md`** — scaffold for new drafts. Don't edit; copy it.
- **`<featurename>.md`** — one per feature. Author manually, then run `/write-docs <featurename>`.

If you do use a draft file, treat it as input: never modify or delete it mid-pipeline.

## Tmp

`tmp/` is scratch space written by skills during execution:

- `tmp/<draft-name>/sources.md` — research audit trail for the reviewer
- `tmp/<draft-name>/slack.md` — Slack post draft (mrkdwn format, ready to paste)
- `tmp/report.html` — cumulative HTML report from `/write-docs` runs

Everything under `tmp/` is gitignored except `.gitkeep`.

## Settings

- **`settings.json`** — shared permissions baseline. Committed. Curate carefully; anything in here is auto-approved for every contributor on this repo.
- **`settings.local.json`** — per-machine overrides. Gitignored. Each contributor curates their own.

## Source of truth

Generic versions of these skills live in `~/Developer/gutils/claude-code/skills/trunk/` (the canonical personal-use copy). The versions in this directory are **project-tuned for Mintlify**:

- `docs-research` — audits `docs.json` groups, reads `.mdx` files, defaults to extending existing pages over creating new ones
- `outline-docs` — uses `.mdx`, updates `docs.json` nav, generates Mintlify callouts
- `write-docs` — updates `docs.json` instead of `summary.md`
- `verify-docs-pr` — hardcoded to `trunk-io/docs2`

When updating one of these skills, decide whether the change is generic (also update gutils) or project-specific (only update here). Intentional drift between the two is fine and expected.
49 changes: 49 additions & 0 deletions .claude/agents/doc-researcher.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
name: doc-researcher
description: "Researches Linear tickets, PRs, and existing docs to compile context for documentation work. Use PROACTIVELY before write-docs when the scope is unclear or when multiple tickets need to be surveyed."
model: claude-sonnet-4-6
tools: Read, Grep, Glob, Bash
---

You are a documentation researcher for Trunk.io. Your job is to gather
and organize all available context about a feature before docs are written.

You are working inside the local Mintlify-powered Trunk docs repository (`trunk-io/docs2`). Pages are `.mdx` files organized by product area, with site navigation defined in `docs.json`.

## Process
1. Look up all provided Linear ticket IDs — extract descriptions,
comments, linked PRs, related tickets
2. Explore the local filesystem to find any current docs coverage of the topic
3. For each linked trunk2 PR, note: what changed, who authored it,
any inline comments or review discussion that explains behavior
4. Check if the feature has any existing changelog entries or roadmap mentions

## Output Format

Produce a structured research brief:

### Feature Summary
2-3 sentence plain-English summary of what shipped and why.

### Source Tickets
List of Linear ticket IDs with their status and one-line description.

### Source PRs
| PR | Author (GitHub handle) | Status | Key changes |
|----|------------------------|--------|-------------|

### Current Docs Coverage
- What exists already (file paths + one-line summary of content)
- What's missing or stale

### Key Technical Details
Bullet list of specific behaviors, defaults, flag names, API shapes,
edge cases — pulled directly from PR code/comments, not inferred.

### Suggested Doc Structure
Where new/updated content should live, and what sections it needs.

### Handoff Note for doc-writer
Any context the writer needs that isn't obvious from the tickets —
e.g., "the UI was redesigned; old screenshots in existing docs are wrong"
or "this feature is gated behind a settings toggle, document that clearly."
44 changes: 44 additions & 0 deletions .claude/drafts/TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# [Feature/Change Title]

## Type

<!-- Pick one: new-feature | update | fix | deprecation | explainer -->

## Priority

<!-- Pick one: P1 | P2 | P3 | P4 -->

## Linear Tickets

<!-- Optional. List any related ticket IDs -->

- TRUNK-XXXXX

## What Changed

<!-- Brief description of the product change, if you know it.
If you only have context below, leave this blank
and the skills will figure it out. -->

## GitHub PRs

<!-- Optional. Link any relevant PRs that implemented the feature/change.
The skills will read PR descriptions and diffs for additional context. -->

## Context Links

<!-- Optional. Paste links to any relevant context — Slack threads, Slite docs,
Loom videos, Google Docs, Notion pages, external references, etc.
All links will be attached to the Linear ticket and included in the PR body. -->

## Target Docs

<!-- Optional. If you know which docs page(s) need updating, list them.
Otherwise the skills will determine this from the repo structure. -->

## Context

<!-- Paste Slack messages, engineer notes, screenshots descriptions,
or anything else that explains what changed and why.
Don't worry about formatting — raw paste is fine.
Keep appending new info to the bottom of this section. -->
95 changes: 95 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"permissions": {
"allow": [
"Bash(claude mcp list:*)",
"Bash(echo:*)",
"Bash(date:*)",
"Bash(ls:*)",
"Bash(chmod:*)",
"Bash(open:*)",
"Bash(code:*)",

"Bash(git add:*)",
"Bash(git branch:*)",
"Bash(git checkout:*)",
"Bash(git cherry-pick:*)",
"Bash(git check-ignore:*)",
"Bash(git clean:*)",
"Bash(git commit:*)",
"Bash(git config:*)",
"Bash(git diff:*)",
"Bash(git fetch:*)",
"Bash(git log:*)",
"Bash(git pull:*)",
"Bash(git push:*)",
"Bash(git rebase:*)",
"Bash(git reset:*)",
"Bash(git revert:*)",
"Bash(git rm:*)",
"Bash(git stash:*)",
"Bash(git status:*)",
"Bash(git worktree:*)",

"Bash(gh api:*)",
"Bash(gh auth:*)",
"Bash(gh issue:*)",
"Bash(gh pr:*)",
"Bash(gh pr comment:*)",
"Bash(gh pr create:*)",
"Bash(gh pr edit:*)",
"Bash(gh pr ready:*)",
"Bash(gh pr view:*)",
"Bash(gh release:*)",
"Bash(gh repo:*)",
"Bash(gh run:*)",
"Bash(gh search:*)",

"Bash(npm:*)",
"Bash(npx:*)",
"Bash(mint:*)",
"Bash(trunk:*)",
"Bash(curl:*)",
"Bash(jq:*)",
"Bash(xargs:*)",
"Bash(find:*)",
"Bash(grep:*)",
"Bash(awk:*)",
"Bash(python3:*)",

"WebFetch(domain:trunk.io)",
"WebFetch(domain:docs.trunk.io)",
"WebFetch(domain:mintlify.com)",
"WebSearch",

"mcp__claude_ai_trunk_docs__searchDocumentation",

"mcp__claude_ai_Linear__list_teams",
"mcp__claude_ai_Linear__list_issues",
"mcp__claude_ai_Linear__list_issue_labels",
"mcp__claude_ai_Linear__list_comments",
"mcp__claude_ai_Linear__get_issue",
"mcp__claude_ai_Linear__get_project",
"mcp__claude_ai_Linear__save_issue",
"mcp__claude_ai_Linear__save_comment",
"mcp__claude_ai_Linear__create_comment",

"mcp__claude_ai_Trunk_Slite__search-notes",
"mcp__claude_ai_Trunk_Slite__list-channels",
"mcp__claude_ai_Trunk_Slite__get-note",
"mcp__claude_ai_Trunk_Slite__get-note-children",
"mcp__claude_ai_Trunk_Slite__create-note",
"mcp__claude_ai_Trunk_Slite__append-blocks",

"mcp__claude_ai_Slack__slack_search_public_and_private",
"mcp__claude_ai_Slack__slack_search_channels",
"mcp__claude_ai_Slack__slack_read_thread",
"mcp__claude_ai_Slack__slack_send_message",

"Skill(write-docs)",
"Skill(outline-docs)",
"Skill(docs-research)",
"Skill(verify-docs-pr)",
"Skill(schedule)"
]
}
}
Loading