This repository is an automated indexing system for Daniel's GitHub repositories. It pulls public repositories, categorizes them by topic and time, and generates comprehensive index files for easy browsing.
The main goals of this system are:
- Automatically discover and categorize new GitHub repositories
- Maintain organized index files by topic and creation date
- Generate comprehensive README files with repository statistics
- Provide multiple views of the repository collection (by-topic, by-time, main index)
.
├── scripts/ # All indexing and generation scripts
│ ├── sync-all.sh # Master sync script (runs everything)
│ ├── pull-and-index.py # Pulls repos & auto-categorizes
│ ├── generate-index.py # Generates index.md
│ ├── update-time-indexes.py # Updates time-based indexes
│ ├── build-hierarchical-readme.py # Builds main README
│ ├── generate-category-indexes.py # Generates category indexes
│ ├── hierarchy-schema.json # Category hierarchy and keywords
│ └── run-*.sh # Individual script wrappers
├── sections/ # Organized repository sections
│ ├── by-topic/ # Topical categorization
│ │ ├── ai-ml/ # AI & Machine Learning
│ │ ├── data-tools/ # Data processing tools
│ │ ├── development/# Development tools
│ │ └── ...
│ └── by-time/ # Chronological organization (by creation date)
│ ├── 2025/ # Year directories
│ │ └── 01_25.md, 02_25.md, etc.
│ └── README.md # Time index overview
├── repo-data/ # Cached repository data from GitHub
│ ├── all-repos-YYYYMMDD-HHMMSS.json # Timestamped snapshots
│ └── latest.json # Symlink to most recent data
├── index.md # Main index (all repos by update date)
└── README.md # Main readme with navigation
Run the master sync script to update everything:
./scripts/sync-all.shThis runs all steps in order:
- Pulls latest repos from GitHub
- Auto-categorizes new repos into sections
- Generates main index.md
- Updates time-based indexes
- Generates category indexes
- Builds README.md
If you need to run specific steps:
# 1. Pull and categorize new repos only
./scripts/run-indexer.sh
# 2. Generate main index only
./scripts/run-index-generator.sh
# or with fresh GitHub data:
python3 scripts/generate-index.py --refresh
# 3. Update time indexes only
python3 scripts/update-time-indexes.py
# 4. Build README only
python3 scripts/build-hierarchical-readme.py
# 5. Generate category indexes only
python3 scripts/generate-category-indexes.pyLocation: scripts/sync-all.sh
Runs the complete workflow in correct order. Use this for most updates.
Location: scripts/pull-and-index.py
- Pulls all public repos using
ghCLI - Scans existing section files to find indexed repos
- Auto-categorizes new repos based on keywords from
hierarchy-schema.json - Generates indexing report showing:
- High confidence matches (auto-added)
- Low confidence matches (need manual review)
Location: scripts/generate-index.py
- Creates
index.mdwith ALL repos sorted by update date (newest first) - Includes: description, stars, forks, topics, dates
- Use
--refreshflag to pull fresh GitHub data first
Location: scripts/update-time-indexes.py
- Creates/updates chronological organization in
sections/by-time/ - Organizes by CREATION date (not update date)
- Creates year directories with monthly files (01_25.md, 02_25.md, etc.)
- Updates year and main time index READMEs
Location: scripts/build-hierarchical-readme.py
- Generates the main
README.mdfromhierarchy-schema.json - Creates category structure with badges
- Adds navigation links
Location: scripts/generate-category-indexes.py
- Creates
index.mdfiles for each category directory - Lists subcategories and their files
Categories are defined in scripts/hierarchy-schema.json:
Main Categories:
- AI & Machine Learning - AI agents, LLM tools, prompt engineering
- Data Tools - Data processing, analysis, visualization
- Development - Code generation, IDEs, GitHub tools
- Infrastructure - Automation, backups, Linux tools
- Platforms & Services - Platform-specific integrations
- Tools & Utilities - General CLI/GUI utilities
- Project Types - Templates, experiments, awesome lists, misc
Each category has:
- Keywords: Used for auto-categorization matching
- Subsections: Nested organization
- Files: Individual
.mdfiles for each subcategory
# Run complete sync
./scripts/sync-all.sh
# Review changes
git status
git diff
# Commit
git add .
git commit -m "Update repository index"
git pushIf repos have low confidence matches:
- Check the indexing report in
scripts/indexing-report-*.json - Manually add repo to appropriate section file
- Update
hierarchy-schema.jsonkeywords if needed - Re-run sync to regenerate indexes
- Edit
scripts/hierarchy-schema.json - Run
./scripts/sync-all.sh - Review and commit
- GitHub CLI (
gh): Must be authenticatedgh auth login gh auth status
- Python 3: For running scripts
- Git: For version control
# Activate
source .venv/bin/activate
# Install dependencies
pip install -r requirements.txt- Timestamped JSON files:
all-repos-YYYYMMDD-HHMMSS.json latest.jsonsymlink → most recent snapshot- Contains full repo metadata from GitHub API
- Created after each pull-and-index run
- Format:
indexing-report-YYYYMMDD-HHMMSS.json - Shows categorization results and confidence scores
- Lists low-confidence matches for manual review
index.md- Main index (all repos by update date)README.md- Main readme with category navigationsections/by-topic/*/*.md- Category filessections/by-time/YYYY/*.md- Monthly chronological files
./scripts/sync-all.shls -lt scripts/indexing-report-*.json | head -1 | xargs cat | jq- Find repo in wrong section file
- Remove entry from that file
- Add to correct section file
- Update
hierarchy-schema.jsonkeywords if needed - Run
./scripts/sync-all.sh - Commit changes
- Edit
scripts/hierarchy-schema.json - Add new category with keywords
- Create corresponding
.mdfile insections/by-topic/ - Run
./scripts/sync-all.sh - Commit changes
- Use sync-all.sh for most updates (keeps everything consistent)
- Review low-confidence matches before committing
- Keep hierarchy-schema.json up to date with new categories/keywords
- Check git diff to review categorization accuracy
- Don't manually edit generated files (index.md, README.md, time indexes)
- Only edit section files manually when fixing miscategorized repos
GitHub API
↓ (via gh CLI)
repo-data/all-repos-*.json
↓
pull-and-index.py
↓
sections/by-topic/*/*.md (categorized repos)
↓
┌──────────────┬──────────────────┬────────────────┐
│ │ │ │
generate- update-time- build- generate-
index.py indexes.py hierarchical- category-
│ readme.py indexes.py
↓ ↓ ↓
index.md sections/ README.md sections/*/
by-time/ index.md
- The system is designed to be mostly automated with manual review
- Auto-categorization uses keyword matching with confidence scoring
- Low confidence matches (score < 2.0) require manual categorization
- The hierarchy schema is the single source of truth for categories
- All scripts are idempotent (safe to re-run)
- Time indexes use CREATION date, main index uses UPDATE date
Public repositories, forks included. hierarchy-schema.json has a
deliberate project-types/forks.md category, so do not add --source to the
gh repo list calls to filter forks out — it empties that category. Private
repos are excluded; this repo is public.
As of 2026-08-10 that is 1059 repos, which matches gh api users/danielrosehill --jq .public_repos. Use that as the cross-check after a sync: if index.md
disagrees with it, the pull is wrong.
sync-all.sh only ever adds. pull-and-index.py appends newly seen repos
to the section files and never removes anything, so deleted, renamed and
newly-private repos accumulate. cleanup-deleted-repos.py is what prunes them
and it is not wired into sync-all.sh. The full correct sequence is:
./scripts/sync-all.sh # add new
python3 scripts/cleanup-deleted-repos.py # dry run, review
python3 scripts/cleanup-deleted-repos.py --execute # prune stale
./scripts/sync-all.sh # regenerateSkipping the middle two is how the index reached 345 stale entries by 2026-08-10.
A round number in the repo count means truncation. gh repo list defaults
to 30 and caps at whatever --limit says; the scripts asked for exactly 1000
and got exactly 1000 back, silently losing the rest. The account has ~2450
repos including forks and private, so --limit must stay comfortably above
that. Any total that is exactly 1000, or exactly matches the limit, is a
truncated pull, not a real count.
Indexing repos come from Subindices. sync-indexing-repos.py pulls
indices.json from danielrosehill/Subindices (formerly Index-Of-Indices;
the old name still works via GitHub's rename redirect, which is why the stale
reference went unnoticed for months). Over there indices.json is generated
from README.md — to add an index repo, edit that repo's README, not anything
here.
Renamed repos look healthy. GitHub answers on the old slug indefinitely, so
a stale link returns 200. Compare .full_name against the slug you requested,
not the status code.
The keyword matcher leaves some repos unfiled — 29 at the 2026-08-10 sync, most
of them hardware, label-printing and Eurobox repos whose vocabulary the schema
does not cover. They still appear in index.md and the time indexes; they are
just absent from sections/by-topic/. Fix by adding keywords to
hierarchy-schema.json and re-running, rather than by hand-editing sections.
The report naming these lands in scripts/indexing-report-*.json (gitignored);
note its name field is currently always null, so match on description.