Skip to content
Merged
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
5 changes: 3 additions & 2 deletions .claude/commands/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ check:
`.claude/commands/*.md`, `.claude/skills/*/SKILL.md`, `.clinerules/workflows/*.md` — these must
describe the same behavior; if one changed, the other three need the matching edit (see
`.github/instructions/prompts.instructions.md`).
6. **`properties.example.yml`** and any other example/config file describing setup — if `setup.sh`,
`setup.ps1`, or `modules/setup/properties.py` changed what gets generated.
6. **`properties.yml`'s built-in template fragments** (`modules/setup/templates/properties/*.yml`) and
any other example/config file describing setup — if `setup.sh`, `setup.ps1`, or
`modules/setup/properties.py` changed what gets generated.
7. Any other `*.md` file that references a file, command, module, or behavior touched by the diff.

For each stale doc you find, fix it directly — this is a repo-local consistency sweep, not a
Expand Down
22 changes: 22 additions & 0 deletions .claude/commands/repos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
description: Show this repo's related-repos map (org/repo list + template lineage) from properties.yml, or apply a change to all of them.
subtask: false
agent: general
slash_command: /repos
---

First, read `.github/instructions/repos.instructions.md` in full — it's the source of truth for
both what the `repos` map means and the Cross-Repo Change Workflow.

Then read `properties.yml` at the repo root and resolve its `repos` key (the org/repo list) and
`lineage` sub-key (parent → child chain). If `properties.yml` doesn't exist yet, tell the user to
run `/setup` first.

- If the user just wants to know what the related repos are, summarize the map and stop there.
- If the user wants a change applied to the related repos (e.g. "apply this to the related repos" /
"update the related repos with this"), follow the Cross-Repo Change Workflow in
`repos.instructions.md` against each repo in scope.

This command doubles as a recognition trigger: whenever the user says "related repos", "the repos",
or "other repos" about this repo's family (not generic talk about "the repository"), read
`repos.instructions.md` and act on it — even if they didn't explicitly run `/repos`.
6 changes: 3 additions & 3 deletions .claude/skills/docs/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ uv run --no-sync invoke repo.pr_diff
```

Then sweep every doc/AI-config surface the prompt lists (root `README.md`, module `README.md`s,
`.github/instructions/*.md`, `AGENTS.md`/`CLAUDE.md`, the synced command dirs, `properties.example.yml`)
and fix anything stale directly — this is a repo-local consistency sweep, so no confirmation is
needed before editing.
`.github/instructions/*.md`, `AGENTS.md`/`CLAUDE.md`, the synced command dirs, `properties.yml`'s
built-in template fragments) and fix anything stale directly — this is a repo-local consistency
sweep, so no confirmation is needed before editing.
13 changes: 13 additions & 0 deletions .claude/skills/repos/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
name: repos
description: Use for showing this repo's related-repos map (org/repo list + template lineage) from properties.yml, or applying a change to all related repos. Also a TRIGGER — read .github/instructions/repos.instructions.md whenever the user says "related repos"/"the repos"/"other repos"/"all of the repos" about this repo's family, even without running /repos. Equivalent to /repos.
---

# Repos Workflow

Use this file as source of truth: `.github/prompts/repos.prompt.md`

When the user asks about this repo's related repos, wants a change applied across them, or runs
`/repos`, read `.github/instructions/repos.instructions.md` in full and follow it — it covers both
the `repos`/`lineage` map and the two-phase (apply, then checkpoint, then ship) Cross-Repo Change
Workflow.
5 changes: 3 additions & 2 deletions .clinerules/workflows/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ check:
`.claude/commands/*.md`, `.claude/skills/*/SKILL.md`, `.clinerules/workflows/*.md` — these must
describe the same behavior; if one changed, the other three need the matching edit (see
`.github/instructions/prompts.instructions.md`).
6. **`properties.example.yml`** and any other example/config file describing setup — if `setup.sh`,
`setup.ps1`, or `modules/setup/properties.py` changed what gets generated.
6. **`properties.yml`'s built-in template fragments** (`modules/setup/templates/properties/*.yml`) and
any other example/config file describing setup — if `setup.sh`, `setup.ps1`, or
`modules/setup/properties.py` changed what gets generated.
7. Any other `*.md` file that references a file, command, module, or behavior touched by the diff.

For each stale doc you find, fix it directly — this is a repo-local consistency sweep, not a
Expand Down
15 changes: 15 additions & 0 deletions .clinerules/workflows/repos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
First, read `.github/instructions/repos.instructions.md` in full — it's the source of truth for
both what the `repos` map means and the Cross-Repo Change Workflow.

Then read `properties.yml` at the repo root and resolve its `repos` key (the org/repo list) and
`lineage` sub-key (parent → child chain). If `properties.yml` doesn't exist yet, tell the user to
run `/setup` first.

- If the user just wants to know what the related repos are, summarize the map and stop there.
- If the user wants a change applied to the related repos (e.g. "apply this to the related repos" /
"update the related repos with this"), follow the Cross-Repo Change Workflow in
`repos.instructions.md` against each repo in scope.

This command doubles as a recognition trigger: whenever the user says "related repos", "the repos",
or "other repos" about this repo's family (not generic talk about "the repository"), read
`repos.instructions.md` and act on it — even if they didn't explicitly run `/repos`.
5 changes: 5 additions & 0 deletions .github/instructions/git.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,8 @@ description: "Use when creating a git branch or drafting a Pull Request for this
This is the canonical PR format for this repo — `.github/prompts/pr.prompt.md` and
`pr-notes.prompt.md` (and their `.claude/commands/`/`.clinerules/workflows/` mirrors) implement it;
see `prompts.instructions.md` for how those commands are kept in sync.

## Pull Request Assignee
Always assign the PR to the user who asked for it — `gh pr create --assignee @me` (the currently
authenticated `gh` user). `modules/repo/pr_create.py` does this automatically; if you ever create a
PR by hand (not through that module), pass `--assignee @me` yourself.
3 changes: 2 additions & 1 deletion .github/instructions/index.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ scoped to one concern — load only the ones relevant to the task at hand:
- `tests.instructions.md` — testing requirements and workflow
- `style.instructions.md` — Markdown style and alphabetical-ordering rules
- `docs.instructions.md` — README and inline-comment conventions
- `repos.instructions.md` — `properties.yml`'s `repos`/lineage key and the "related repos" trigger

## Project Structure
```
Expand All @@ -35,7 +36,7 @@ tests/
modules/
common/ # cli.py, properties.py, route_utils.py, utils.py — shared helpers
repo/ # pull.py, push.py, squash.py, rebase.py, pr_*.py — git/PR workflow modules
setup/ # properties.py — creates/stamps properties.yml, called by setup.sh/setup.ps1
setup/ # properties.py — creates properties.yml (no-op if it exists), called by setup.sh/setup.ps1; templates/properties/*.yml — tier fragments
template/ # ignore.py, naming.py, pull.py, push.py, resolve.py, route.py, scope.py — sync shared tooling with the parent template repo for /template
versioning/ # libs.py, python.py, workflows.py, upgrade.py, project.py — check pyproject.toml deps & workflow action refs vs. latest releases, bump the repo's VERSION file
tasks/
Expand Down
82 changes: 82 additions & 0 deletions .github/instructions/repos.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
applyTo: "**"
---
# Repos Instructions
Rules for the `repos` key in `properties.yml` — the map of GitHub repos related to this repository.

## Purpose
`properties.yml`'s `repos` key records which other GitHub repos are part of this repo's family
(grouped by org), plus a `lineage` sub-key recording parent → child template-stamping
relationships — e.g. `LevonBecker/template_ai_vault: LevonBecker/template_python` means
`template_ai_vault` was stamped from `template_python`.

It's built additively, tier by tier, from `modules/setup/templates/properties/*.yml` — one fragment
file per repo in the lineage, each named after itself. This repo (`template_python`) is the root:
its own fragment, `template_python.yml`, holds just its own `repos` entry (no lineage edge, since it
has no parent). Each fragment contributes only its own org/repo + the lineage edge to its parent; a
repo only ever ends up knowing its own ancestor chain, never a sibling branch it isn't descended
from. See `modules/setup/README.md` for the build mechanism.

## "Related Repos" Trigger
When the user says **"related repos"**, **"the repos"**, **"other repos"**, **"all of the repos"**,
**"all the repos"**, or similar in the context of this repo's family — not generic talk about "the
repository" — **read this file in full before acting**, then read the `repos` key in
`properties.yml` to know which other repos are part of this repo's family and how they're related.
This applies whether or not the user ran `/repos` — the phrase itself is the trigger.

Two distinct requests look similar but aren't:
- **"What are the related repos?"** — just resolve and show the `repos`/`lineage` map (`/repos`
does this).
- **"Apply this to the related/other repos"** vs. **"apply this to all of the repos"** — both run
the Cross-Repo Change Workflow below, but scope differs:
- "related repos" / "other repos" — the *other* repos in the family; this repo is assumed already
handled (e.g. its own PR already exists).
- "all of the repos" / "all the repos" — **includes this repo too**. If this repo's own change
isn't committed/pushed/PR'd yet, do that first (same format as every other repo — commit, push,
PR), then continue through the rest of the family in lineage order.

## Cross-Repo Change Workflow
When the user asks to apply a change (already made in this repo, or described fresh) to the related
repos, run it as **two phases with a checkpoint in between** — don't pipeline straight through to
pushing/PRs for every repo unattended.

### Phase 1 — Apply (no pushing yet)
1. Resolve which repos are in scope from `repos`/`lineage`. If the request is ambiguous about scope
(all of them? just this branch? a specific sub-tree?), ask.
2. For each repo in scope, **in root-to-leaf lineage order** (a child repo may depend on its parent
having the change first — e.g. `/template` pulling it down):
a. Confirm its local clone exists (sibling path convention, e.g. `$HOME/Development/<org>/<repo>`
— check `repo.local` in this repo's own `properties.yml` for the pattern actually in use).
b. `git status` — if there are uncommitted changes, stash them (`git stash push -u`) rather than
losing or clobbering in-progress work.
c. Switch to the repo's default branch (usually `main`).
d. `git fetch --prune`, then pull the default branch up to date.
e. Create a feature branch for this change.
f. Apply the change in that repo — either port the actual diff/pattern from the source repo/PR,
or run the specific command/action the user named (e.g. `/update`), whichever the request
calls for. If it's unclear what a given repo's own tier fragment or config should contain
(e.g. what's generic to that repo's product line vs. real business config), **ask rather than
guessing**.

### Checkpoint
Once the change is applied (uncommitted) in every repo in scope, stop and ask the user, e.g.: "Made
the changes in all N repos — ready to ship them, or is there more to add first?" Don't proceed to
Phase 2 until they confirm.

### Phase 2 — Ship
For each repo (same order), run the equivalent of `/ship-it`: fix, test, commit, push, draft PR
notes, open the PR (assigned to the user per `git.instructions.md`'s Pull Request Assignee rule).
Report each repo's PR URL back to the user. Never merge a PR yourself, and never push directly to a
shared/default branch across multiple repos without being asked.

**Example:** "run `/update` on all the related repos" → Phase 1: for each repo in scope, cd in,
stash/switch/pull, branch, run `/update`. Checkpoint: confirm ready to ship. Phase 2: ship each
one — end state is one PR per repo, each showing that repo's own `/update` result, not one combined
PR.

No dedicated automation exists for this yet (as of 2026-08-01) — each step above is done directly
(git commands, the repo's own test/push/PR tooling), not via a single script.

## Module Implementation
For the build mechanism (tier fragments, additive `repos` merge, no-op-if-exists behavior), see
`modules/setup/README.md` and `modules/setup/properties.py`.
38 changes: 38 additions & 0 deletions .github/instructions/style.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,46 @@ applyTo: "**"

Rules for all markdown files created across this repository.

## Horizontal Rules

**Never use a standalone `---` line as a section divider in the body of a `.github/instructions/*.md`
file.** The only place `---` belongs is the YAML frontmatter delimiter (the opening and closing
`---` around `applyTo: "**"`) — never between headers. Headers and blank lines alone are enough
visual separation.

```markdown
# ✅ CORRECT
---
applyTo: "**"
---
# File Title
Intro sentence.

## Section One
Content.

## Section Two
Content.
```

```markdown
# ❌ WRONG
---
applyTo: "**"
---
# File Title

---

## Section One
Content.

---

## Section Two
Content.
```

## Headers

**Do not add a blank line after any header (`#`, `##`, `###`, etc.).** Content begins on the very next line.
Expand Down
5 changes: 3 additions & 2 deletions .github/prompts/docs.prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ check:
`.claude/commands/*.md`, `.claude/skills/*/SKILL.md`, `.clinerules/workflows/*.md` — these must
describe the same behavior; if one changed, the other three need the matching edit (see
`.github/instructions/prompts.instructions.md`).
6. **`properties.example.yml`** and any other example/config file describing setup — if `setup.sh`,
`setup.ps1`, or `modules/setup/properties.py` changed what gets generated.
6. **`properties.yml`'s built-in template fragments** (`modules/setup/templates/properties/*.yml`) and
any other example/config file describing setup — if `setup.sh`, `setup.ps1`, or
`modules/setup/properties.py` changed what gets generated.
7. Any other `*.md` file that references a file, command, module, or behavior touched by the diff.

For each stale doc you find, fix it directly — this is a repo-local consistency sweep, not a
Expand Down
22 changes: 22 additions & 0 deletions .github/prompts/repos.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
name: repos
description: Show this repo's related-repos map (org/repo list + template lineage) from properties.yml, or apply a change to all of them.
argument-hint: no arguments required
agent: agent
---

First, read `.github/instructions/repos.instructions.md` in full — it's the source of truth for
both what the `repos` map means and the Cross-Repo Change Workflow.

Then read `properties.yml` at the repo root and resolve its `repos` key (the org/repo list) and
`lineage` sub-key (parent → child chain). If `properties.yml` doesn't exist yet, tell the user to
run `/setup` first.

- If the user just wants to know what the related repos are, summarize the map and stop there.
- If the user wants a change applied to the related repos (e.g. "apply this to the related repos" /
"update the related repos with this"), follow the Cross-Repo Change Workflow in
`repos.instructions.md` against each repo in scope.

This command doubles as a recognition trigger: whenever the user says "related repos", "the repos",
or "other repos" about this repo's family (not generic talk about "the repository"), read
`repos.instructions.md` and act on it — even if they didn't explicitly run `/repos`.
14 changes: 14 additions & 0 deletions .github/skills/repos/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
name: repos
description: Use for showing this repo's related-repos map (org/repo list + template lineage) from properties.yml, or applying a change to all related repos. Equivalent to /repos. Also triggered by the phrases "related repos", "the repos", "other repos", or "all of the repos".
---

# Repos Trigger

Use this file as source of truth: `.github/prompts/repos.prompt.md`

When the user says "related repos", "the repos", "other repos", "all of the repos", or otherwise
asks about this repo's family — even without running `/repos` — read
`.github/instructions/repos.instructions.md` in full and follow it. It covers both the
`repos`/`lineage` map and the two-phase (apply, then checkpoint, then ship) Cross-Repo Change
Workflow.
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ changes:
- **Tests & linters**: `.github/instructions/tests.instructions.md`
- **Markdown style**: `.github/instructions/style.instructions.md`
- **Docs**: `.github/instructions/docs.instructions.md`
- **`properties.yml`'s `repos`/lineage key**: `.github/instructions/repos.instructions.md`

**Source of truth: `.github/instructions/` and `.github/prompts/`** — all rules and slash commands
live there. Never duplicate rules into this file or any tool-specific entrypoint — update
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ tests/
modules/
common/ # cli.py, properties.py, route_utils.py, utils.py — shared helpers
repo/ # pull.py, push.py, squash.py, rebase.py, pr_*.py — git/PR workflow modules
setup/ # properties.py — creates/stamps properties.yml, called by setup.sh/setup.ps1
setup/ # properties.py — creates properties.yml (no-op if it exists), called by setup.sh/setup.ps1; templates/properties/*.yml — tier fragments
template/ # ignore.py, naming.py, pull.py, push.py, resolve.py, route.py, scope.py — sync shared tooling with the parent template repo for /template
versioning/ # libs.py, python.py, workflows.py, upgrade.py, project.py — check pyproject.toml deps & workflow action refs vs. latest releases, bump the repo's VERSION file
tasks/
Expand Down Expand Up @@ -119,7 +119,7 @@ uv run --no-sync invoke setup.properties # Create/stamp properties.yml
|--------|---------|
| [`modules/common/`](modules/common/README.md) | CLI helpers, `properties.yml` config reader, output/utility helpers |
| [`modules/repo/`](modules/repo/README.md) | Git workflow (pull, push, squash, rebase, PR) |
| [`modules/setup/`](modules/setup/README.md) | Creates/stamps `properties.yml`, called by `setup.sh`/`setup.ps1` |
| [`modules/setup/`](modules/setup/README.md) | Creates `properties.yml` (no-op if it exists) from tier fragments, called by `setup.sh`/`setup.ps1` |
| [`modules/template/`](modules/template/README.md) | Sync shared, generic tooling with the parent template repo for `/template` |
| [`modules/versioning/`](modules/versioning/README.md) | Check `pyproject.toml` deps and workflow action refs vs. latest releases, update locks; bump the repo's `VERSION` file for deploys/releases |

Expand Down
Loading