name: repo-archival-policy
description: Decide which repos in a fleet to archive, which to keep, what to do with archived repos (delete vs archive), and how to handle pull requests on archived repos. Use during fleet cleanup when the user has accumulated 50+ repos and many are stale. Cites real patterns: "10-day stale threshold", "Pareto by push recency", "archival vs deletion tradeoffs".
sources: github-archival
Repo Archival Policy
When a fleet grows to 50+ repos, many become stale. Archiving is the right move for repos that:
- Are not deployed
- Have no recent activity
- Are subsumed by a successor repo
- Were experiments that didn't pan out
The Staleness Threshold
Rule of thumb: archive if no push in 10+ days AND not deployed.
import json, subprocess, time
from datetime import datetime, timezone
cutoff_days = 10
cutoff = datetime.now(timezone.utc) - timedelta(days=cutoff_days)
candidates = []
r = subprocess.run(["gh", "repo", "list", "--limit", "200", "--no-archived", "--json", "name,pushedAt,isArchived"], capture_output=True, text=True)
repos = json.loads(r.stdout)
for repo in repos:
if repo["isArchived"]:
continue
pushed = datetime.fromisoformat(repo["pushedAt"].replace("Z", "+00:00"))
if pushed < cutoff:
candidates.append((repo["name"], repo["pushedAt"]))
candidates.sort(key=lambda x: x[1])
The "Is it Deployed?" Check
A repo that hasn't been pushed in 6 months but is the live production deployment should NOT be archived. Check for deployment indicators:
gh run list --repo camster91/<repo> --limit 1 --json createdAt,conclusion,event
gh api repos/camster91/<repo>/contents/README.md | jq -r '.content' | base64 -d | grep -oE 'https?://[^\s)]+' | grep -v localhost
gh api repos/camster91/<repo>/contents/package.json | jq -r '.content' | base64 -d | jq -r '.scripts.deploy // "none"'
If the repo has production URLs in the README, it's "deployed" — don't archive even if stale.
Archive vs Delete
Archive is reversible — you can unarchive. The repo becomes read-only and shows up in the "archived" filter.
Delete is permanent (within 90 days; after that, recovery requires GitHub support).
Default to archive, not delete. Delete only when:
- The repo contains secrets that need to be purged
- The repo is a duplicate of an active one
- The user explicitly asks for deletion
Archiving
gh repo edit camster91/<repo> --enable-archive
gh api -X PATCH /repos/camster91/<repo> \
-H "Accept: application/vnd.github+json" \
-d '{"archived": true}'
Verify:
gh repo view camster91/<repo> --json isArchived
Handling PRs on Archived Repos
When a repo is archived, no new PRs can be opened. Existing open PRs can still be merged, but pushing to the branch is disabled.
If a Dependabot PR exists on an archived repo:
- The PR stays open
- The auto-update fails (can't push to the branch)
- Manual cleanup: close the PR with a comment
If a human PR exists:
- Ask the user: merge before archive, or close before archive?
- If merging would deploy something the user didn't intend, close instead
The "10-day Rule" Output Format
**Archival candidates (10+ days no push):**
| Repo | Last push | Notes |
|------|-----------|-------|
| `glow-os` | 2026-05-25 | Static HTML, no deploy |
| `Rotman-Meeting-Rooms` | 2026-05-26 | Sub-replaced by `ashbi-platform` |
| `game-ideas` | 2026-05-28 | Solo experiment, never deployed |
Total candidates: 3 of 59 active repos
The user can then say "archive all 3" or "skip the X one, archive the others".
Related Skills & Chains
fleet-ci-audit — Use this to get the full fleet state before deciding what to archive
stack-version-audit — Repos that are way behind on stack versions (Node 14, etc.) are often good archive candidates
spending-limit-detector — Archived repos don't burn Actions minutes