Gsd-skill-creator aminet-mirror
Selective Aminet package mirroring: single-package fetch, integrity verification, mirror state tracking, bulk download, and sync detection. Use when downloading, verifying, or managing mirrored packages.
git clone https://github.com/Tibsfox/gsd-skill-creator
T=$(mktemp -d) && git clone --depth=1 https://github.com/Tibsfox/gsd-skill-creator "$T" && mkdir -p ~/.claude/skills && cp -r "$T/infra/packs/aminet/skills/aminet-mirror" ~/.claude/skills/tibsfox-gsd-skill-creator-aminet-mirror && rm -rf "$T"
infra/packs/aminet/skills/aminet-mirror/SKILL.mdAminet Mirror
Purpose
Manages selective mirroring of Aminet packages to the local filesystem. Handles single-package fetching with ordered mirror fallback, SHA-256 integrity verification, persistent mirror state tracking with 7-state status enum, concurrent bulk downloads with rate limiting, and sync detection comparing local state against the INDEX.
Capabilities
- Single-package fetch with ordered mirror fallback
- Directory hierarchy preservation matching Aminet structure
- Non-fatal .readme download (best-effort alongside archive)
- User-Agent header on all HTTP requests
- SHA-256 integrity verification via node:crypto
- Size verification with +/-1 KB tolerance for Aminet metadata rounding
- Combined integrity result (hash + size) in single check
- 7-state PackageStatus enum tracking full lifecycle
- Atomic write-then-rename for mirror state persistence
- Immutable updateEntry pattern for safe concurrent access
- Bulk download with async semaphore concurrency control
- Global rate limiting gate between requests
- Resume from interruption (skips already-mirrored packages)
- Serialized state writes via Promise chain mutex
- Sync detection comparing mirror state vs INDEX by sizeKb
- O(1) Map lookup for efficient change detection
- Only change-eligible statuses compared (mirrored+)
Key Modules
| Module | Purpose |
|---|---|
| Single-package fetch with ordered mirror fallback and .readme |
| 7-state status enum, atomic persistence, immutable updateEntry |
| SHA-256 hash and size verification with combined IntegrityResult |
| Concurrent downloads with semaphore, rate limiting, resume support |
| Detects INDEX changes against local mirror state via Map lookup |
Usage Examples
Fetch a single package:
import { fetchPackage } from './package-fetcher.js'; const result = await fetchPackage({ entry: indexEntry, mirrors: ['https://aminet.net', 'https://de.aminet.net'], outputDir: './mirror', }); // Downloads archive + .readme, preserves directory structure
Verify integrity:
import { verifyIntegrity } from './integrity.js'; const result = await verifyIntegrity(filePath, { expectedSha256: hash, expectedSizeKb: 42 }); // result.valid, result.hashMatch, result.sizeMatch
Bulk download with concurrency:
import { bulkDownload } from './bulk-downloader.js'; await bulkDownload({ entries: selectedPackages, mirrors, outputDir: './mirror', concurrency: 4, rateLimit: 500, // ms between requests onProgress: (completed, total) => console.log(`${completed}/${total}`), });
Detect sync changes:
import { detectChanges } from './sync-detector.js'; const changes = detectChanges(mirrorState, currentIndex); // changes: { added: [], updated: [], removed: [] }
Dependencies
- Node.js
for SHA-256 hashingnode:crypto - Node.js
for mirror state persistence and file I/Onode:fs - HTTP client for mirror downloads
- Aminet mirror network (ordered fallback list)
Token Budget Rationale
1.0% budget reflects the 5 modules covering fetch, state, integrity, bulk download, and sync detection. The concurrency control, rate limiting, and atomic state persistence patterns require moderate context for safe operation.