karpathy/nanoGPT
The simplest, fastest repository for training/finetuning medium-sized GPTs.
Slowing — last commit 6mo ago
no tests detected; no CI workflows detected
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ⚠Slowing — last commit 6mo ago
- ⚠Concentrated ownership — top contributor handles 66% of recent commits
- ⚠No CI workflows detected
- ⚠No test directory detected
- ✓Last commit 6mo ago
- ✓26+ active contributors
- ✓MIT licensed
What would improve this?
- →Use as dependency Mixed → Healthy if: add a test suite
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/karpathy/nanogpt)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card
This card auto-renders when someone shares https://repopilot.app/r/karpathy/nanogpt on X, Slack, or LinkedIn.
Ask AI about karpathy/nanogpt
Grounded in the actual source code. Pick a starter question or write your own.
Onboarding doc
Onboarding: karpathy/nanoGPT
Generated by RepoPilot · 2026-06-20 · Source
🎯Verdict
WAIT — Slowing — last commit 6mo ago
- Last commit 6mo ago
- 26+ active contributors
- MIT licensed
- ⚠ Slowing — last commit 6mo ago
- ⚠ Concentrated ownership — top contributor handles 66% of recent commits
- ⚠ No CI workflows detected
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
⚡TL;DR
nanoGPT is a minimal, production-oriented PyTorch implementation for training and fine-tuning GPT-2 scale transformer models (up to 1.3B parameters) on single or multi-GPU nodes. It reproduces OpenAI's GPT-2 124M model on OpenWebText in ~4 days on a single 8×A100 node, with the entire training loop contained in ~300 lines of Python (train.py) and the model definition in another ~300 lines (model.py). The project prioritizes simplicity and hackability over pedagogical clarity, making it ideal for practitioners who want to train or fine-tune medium-scale language models without framework overhead. Flat structure optimized for readability: train.py (training loop entrypoint), model.py (GPT transformer definition), sample.py (inference/generation), configurator.py (config override system). Configs live in config/ as Python files (train_gpt2.py, train_shakespeare_char.py, finetune_shakespeare.py, eval_gpt2*.py). Data preparation scripts in data/openwebtext/, data/shakespeare/, data/shakespeare_char/ each with prepare.py. Minimal overhead—no src/, no packages, no pipelines.
👥Who it's for
ML practitioners and researchers who need to train or fine-tune GPT-scale transformer models and want readable, minimal boilerplate code rather than heavy frameworks. This includes people fine-tuning on custom datasets (Shakespeare, domain-specific corpora), researchers studying scaling laws, and engineers who want to load OpenAI's pre-trained GPT-2 weights and adapt them.
🌱Maturity & risk
Deprecated but widely used. The README explicitly notes (Nov 2025) that nanoGPT is 'very old and deprecated' and recommends users switch to nanochat instead. However, the core code is stable—the training loop successfully reproduces GPT-2 124M with published loss curves, and the model can load OpenAI's official weights. Karpathy left it up for posterity, so expect no active maintenance or new features.
Low risk for research/hobby projects, medium risk for production. Dependencies are minimal and stable (torch, numpy, transformers, datasets, tiktoken, wandb, tqdm), but the repo is unmaintained—no active CI/CD visible, no test suite, and the maintainer explicitly directs users elsewhere. Breaking changes in PyTorch or HuggingFace's transformers library could silently corrupt training runs. Single-maintainer (Karpathy) with no clear governance for critical bug fixes.
Active areas of work
The repository is in maintenance mode. The README update (Nov 2025) redirects users to karpathy/nanochat, which is the active successor. No ongoing feature development is visible; the stable GPT-2 reproduction is complete. This repo remains available as historical reference and for users who specifically want the minimal nanoGPT approach rather than nanochat's extended feature set.
🚀Get running
git clone https://github.com/karpathy/nanoGPT.git
cd nanoGPT
pip install torch numpy transformers datasets tiktoken wandb tqdm
python data/shakespeare_char/prepare.py
python train.py config/train_shakespeare_char.py
python sample.py --out_dir=out-shakespeare-char
This trains a character-level GPT on Shakespeare (3 minutes on A100, 1.4697 validation loss) and generates samples.
Daily commands:
For quick start: python train.py config/train_shakespeare_char.py (trains on Shakespeare, 3 min on A100). For full GPT-2 reproduction: python train.py config/train_gpt2.py (requires OpenWebText dataset via data/openwebtext/prepare.py, ~4 days on 8×A100). For evaluation: python train.py config/eval_gpt2.py --init_from=gpt2. For sampling: python sample.py --out_dir=<checkpoint_dir>.
🗺️Map of the codebase
train.py— ~300-line training loop entry point; all contributors must understand the core training flow, checkpointing, and distributed setup.model.py— ~300-line GPT transformer architecture definition; defines the forward pass, can load OpenAI GPT-2 weights, and is the core model abstraction.config/train_gpt2.py— Primary training configuration for reproducing GPT-2 124M on OpenWebText; essential reference for hyperparameters and data pipeline setup.data/openwebtext/prepare.py— Data preprocessing pipeline that converts raw OpenWebText into tokenized training data; defines train/val split and tokenization strategy.configurator.py— Dynamic configuration loader that merges CLI args with config files; controls how all parameters flow through the training pipeline.sample.py— Inference/sampling entry point that loads checkpoints and generates text; shows how to use trained models post-training.
🧩Components & responsibilities
- train.py (Trainer) (torch.nn, torch.optim, torch.distributed.launch, torch.cuda) — Orchestrates training loop: dataloader iteration, loss computation, backward pass, optimizer step, checkpointing, DDP synchronization
- Failure mode: OOM on GPU if batch size too large; training diverges if LR misconfigured; checkpoints corrupt if disk full
- model.py (GPT) (torch.nn modules, torch.utils.checkpoint (gradient checkpointing)) — Implements transformer architecture with embedding, positional encoding, multi-head attention, and MLP blocks; loads OpenAI weights on demand
- Failure mode: Shape mismatches if config changed; weight loading fails if checkpoint incompatible; attention overflow if logits not scaled properly
- configurator.py (Config) (Python dataclass, argparse) — Singleton config object that merges config file attributes with CLI argument overrides; exposes all hyperparameters
- Failure mode: Invalid hyperparameter ranges not caught; conflicting CLI args silently override config file without warning
- data/*/prepare.py (DataPreprocessor) (tiktoken, numpy, os.path) — Reads raw text, tokenizes with tiktoken, splits into train/val, writes binary files for fast loading
- Failure mode: Tokenization mismatch if tiktoken version changes; dataset splits not reproducible if random seed not set
- sample.py (Sampler) — Loads checkpoint, runs autoregressive forward passes to generate text; supports temperature
🛠️How to make changes
Train a new model from scratch with custom config
- Create a new config file in config/ directory (e.g., config/train_custom.py) with model size, learning rate, batch size, and data paths (
config/train_custom.py) - Prepare your dataset using data/*/prepare.py as a template; output should be train.bin and val.bin in your data directory (
data/your_dataset/prepare.py) - Run training with: python train.py config/train_custom.py --data_dir=data/your_dataset --out_dir=./checkpoints (
train.py)
Finetune a pretrained GPT-2 checkpoint on new data
- Create a finetune config in config/ that inherits GPT-2 params but sets init_from='gpt2' and lower learning_rate (
config/finetune_custom.py) - Prepare tokenized train/val data using data/*/prepare.py pattern for your domain (
data/your_domain/prepare.py) - Run: python train.py config/finetune_custom.py --init_from=gpt2 --data_dir=data/your_domain (
train.py) - After training, sample with: python sample.py --out_dir=./checkpoints --init_from=gpt2 --start='Your prompt' (
sample.py)
Modify the model architecture
- Edit the GPT class in model.py to adjust n_layer, n_head, n_embd, or add new attention/MLP variants (
model.py) - Update your config file to reflect new model_args (e.g., increase n_embd, n_head, dropout) (
config/train_custom.py) - Run training; the model will initialize from scratch since weight shapes changed. Existing checkpoints will not load (
train.py)
🔧Why these technologies
- PyTorch — Industry-standard deep learning framework with native DDP distributed training support and seamless GPU acceleration
- tiktoken (OpenAI tokenizer) — Exact tokenizer used by GPT-2/GPT-3; ensures reproducibility when loading OpenAI weights and aligns with production token counts
- Plain Python (no Lightning/Hugging Face Trainer) — Prioritizes simplicity and readability; ~300 lines of boilerplate train.py allows easy customization without framework abstraction overhead
- Distributed Data Parallel (DDP) — Minimal multi-GPU synchronization with negligible overhead; enables scaling across 8xA100 nodes in production
⚖️Trade-offs already made
-
~300-line train.py instead of framework (Lightning/Hugging Face Trainer)
- Why: Maximizes clarity and hackability for researchers wanting to modify training loops
- Consequence: Contributors responsible for implementing their own gradient accumulation, mixed precision, distributed sync logic; higher cognitive load but full control
-
Static config files + CLI override via configurator.py instead of YAML/hydra
- Why: Lightweight, Python-native, no external dependency; config values are actual Python imports
- Consequence: Requires editing .py files or CLI args; less flexible than YAML for complex nested configs but simpler mental model
-
Binary token files (train.bin/val.bin) instead of streaming from disk or HuggingFace datasets
- Why: Fast random access and no encoding/decoding overhead during training loop
- Consequence: Requires upfront preprocessing; uses disk space for tokenized data; not suitable for infinite/streaming data sources
-
Single-node training as primary path (can scale to multi-node via DDP)
- Why: Simplest common case (fits on 1×8XA100); easy to iterate locally
- Consequence: Multi-node setup requires manual torch.distributed configuration and NCCL setup; not as seamless as SLURM-integrated frameworks
🚫Non-goals (don't propose these)
- Does not provide distributed data loading optimizations (e.g., no pre-fetching, no multi-worker data pipeline); uses single PyTorch DataLoader with num_workers=0
- Does not implement model parallelism or pipeline parallelism; assumes model fits in GPU memory
- Does not support mixed-precision training (fp16/bf16) in core loop; requires manual AMP wrapper if needed
- Does not include evaluation on downstream tasks; only tracks training/validation perplexity
- Does not integrate with Weights & Biases, MLflow, or other experiment trackers (uses console logging only)
🪤Traps & gotchas
- Config files are Python, not YAML/JSON — they are exec'd with configurator.py, so they must be valid Python and imports must match available packages. 2. Tokenizer mismatch risk — train.py uses tiktoken (OpenAI BPE), but the model can load GPT-2 checkpoints from transformers which may expect a different tokenizer; ensure consistency. 3. Data format is binary — train.py expects data//train.bin and data//val.bin as memmap'd uint16 arrays; prepare.py scripts must be run before training or train.py will crash with obscure file not found. 4. Flash attention is optional but changes numerics — the code supports torch's flash_attention_2 but does not default to it; enabling it mid-run may cause validation loss divergence. 5. No gradient checkpointing by default — large models on small GPUs will OOM; you must manually add it to model.py's Block class if memory is tight.
🏗️Architecture
💡Concepts to learn
- Causal self-attention (masked attention) — nanoGPT's core: model.py implements causal attention to ensure tokens only attend to previous tokens during training and generation, fundamental to autoregressive language modeling.
- Byte-pair encoding (BPE) tokenization — train.py uses tiktoken (OpenAI's BPE) to convert raw text to token IDs; understanding BPE vocab size, merges, and special tokens is critical for tokenizer swaps and data preparation.
- Gradient accumulation — train.py accumulates gradients over micro-batches before a backward pass to simulate larger effective batch sizes on memory-constrained GPUs; essential for reproducing GPT-2 on single nodes.
- Learning rate scheduling (cosine annealing) — train.py uses cosine annealing with warmup to control learning rate during training; affects final validation loss and is configurable per config file.
- Distributed data parallelism (DDP) — train.py supports torch.distributed for multi-GPU training (8×A100 setups mentioned in README); understanding rank, world_size, and synchronization is needed to scale beyond single GPU.
- Memory-mapped I/O (numpy memmap) — Data is stored as binary .bin files and loaded via np.memmap in train.py; avoids loading entire datasets into RAM, critical for OpenWebText (~15GB tokenized).
- Checkpoint resuming and early stopping — train.py saves model state at intervals and tracks best validation loss for early stopping; understanding checkpoint structure (model_state_dict, optimizer_state_dict, step count) is needed for resuming interrupted runs.
🔗Related repos
karpathy/nanochat— Official successor to nanoGPT (2025); recommended by the repo maintainer as the active, improved version with additional features for chat models.karpathy/minGPT— Direct predecessor (mentioned in README); minGPT prioritized education, nanoGPT prioritized production. Users coming from minGPT will recognize the architecture.pytorch/pytorch— Core dependency; understanding PyTorch's autograd, distributed training (torch.nn.parallel.DistributedDataParallel), and nn.Module is essential to modify train.py and model.py.huggingface/transformers— Provides GPT-2 checkpoint loading (model.from_pretrained('gpt2')); users fine-tuning or loading pre-trained weights depend on this library's API stability.huggingface/datasets— Used in data preparation scripts to download and tokenize large corpora (OpenWebText); understanding its streaming API is helpful for custom data pipelines.
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for model.py weight loading and forward pass
The repo currently has no tests directory despite having a critical model.py (~300 lines) that loads GPT-2 weights from OpenAI and performs forward passes. Given that users may load pretrained weights via model.py, there should be automated tests verifying: (1) weight loading from OpenAI GPT-2 checkpoints works correctly, (2) forward pass shapes are correct for different batch sizes, (3) sampling produces valid token sequences. This prevents regressions when model.py is modified.
- [ ] Create tests/ directory with test_model.py
- [ ] Add test for loading GPT-2 weights into model.py (e.g., test_load_gpt2_weights)
- [ ] Add test for forward pass output shapes with various input dimensions
- [ ] Add test for sample.py integration with model.py to ensure token generation works
- [ ] Integrate pytest into a GitHub Actions workflow (see below)
Add GitHub Actions CI workflow for training reproducibility validation
The README claims train.py reproduces GPT-2 (124M) with specific convergence curves shown in assets/gpt2_124M_loss.png, but there's no automated CI to catch regressions. Add a lightweight GitHub Action that runs a small-scale training job (e.g., 10 steps on Shakespeare data) on every PR to catch breakages in train.py, configurator.py, and model.py before merging.
- [ ] Create .github/workflows/test-training.yml
- [ ] Add workflow step to run: python train.py config/train_shakespeare_char.py --max_iters=10
- [ ] Add workflow step to verify model.py can load and inference with sample.py
- [ ] Configure workflow to run on push to main and all PRs
- [ ] Document expected runtime in PR comment to manage CI costs
Create data loading benchmark utility and document in README
The repo has data/ subdirectories (openwebtext, shakespeare, shakespeare_char) with prepare.py scripts but no visibility into data loading performance. Given that train.py and bench.py exist, add a dedicated data_benchmark.py script that measures throughput of the data loading pipeline and documents it in data/README.md. This helps contributors optimize the critical data loading path and understand bottlenecks.
- [ ] Create data_benchmark.py to measure tokens/sec from each data source (openwebtext, shakespeare, shakespeare_char)
- [ ] Benchmark both file I/O and DataLoader throughput
- [ ] Add results and methodology to data/README.md with guidance on dataset selection
- [ ] Document which dataset is recommended for different training scales
🌿Good first issues
- Add unit tests for model.py: The model definition has no tests; a new contributor could add pytest tests verifying GPT forward pass shapes, attention head dimensions, and weight loading from OpenAI's GPT-2 checkpoints.
- Document the config override system and add examples: configurator.py is powerful but undocumented. A PR explaining how CLI args override config files, with 2–3 worked examples (e.g., 'override learning_rate from CLI'), would lower the onboarding barrier.
- Add integration test for Shakespeare training end-to-end: No automated test verifies that data/shakespeare_char/prepare.py → train.py → sample.py works in CI. A GitHub Actions workflow running the Shakespeare quick-start and asserting that validation loss decreases would catch regressions.
⭐Top contributors
Click to expand
Top contributors
- @karpathy — 66 commits
- @apivovarov — 4 commits
- @adambala — 2 commits
- @okuvshynov — 2 commits
- @gnobre — 2 commits
📝Recent commits
Click to expand
Recent commits
3adf61e— Update README to mention nanochat and deprecation (karpathy)93a43d9— Merge pull request #578 from devin-open-source/devin/1733728337-fix-warmup-lr (karpathy)dc81cb3— fix: ensure non-zero learning rate during warmup at iteration 0 (devin-ai-integration[bot])9755682— Merge pull request #463 from goswamig/test1 (karpathy)3ab86ce— Merge branch 'master' into test1 (karpathy)7c7e627— Merge pull request #487 from jellehak/patch-1 (karpathy)5cb16fe— Update README.md (jellehak)1ab9ec1— Fixing eval path in README (goswamig)325be85— Merge pull request #420 from vinjn/fix-371-enc-is-not-defined (karpathy)a022d02— Merge pull request #429 from adambala/fixes (karpathy)
🔒Security observations
nanoGPT is a research/educational codebase with moderate security posture. Primary concerns are around unsafe model weight deserialization, lack of input validation in data processing pipelines, and missing dependency management. The project is deprecated (as of Nov 2025), reducing active maintenance risk but increasing risk for users still relying on it. No critical vulnerabilities were identified, but the medium-severity issues around data handling and model loading should be addressed before using this in production environments. The simple, minimal architecture reduces attack surface compared to complex frameworks.
- Medium · Potential Unsafe Data Deserialization —
model.py. The codebase loads pre-trained GPT-2 weights from external sources. If the weight loading mechanism (likely in model.py) uses pickle or similar unsafe deserialization methods without validation, it could be exploited to execute arbitrary code when loading compromised model files. Fix: Use safe serialization formats (e.g., safetensors, ONNX) or validate checksums/signatures of downloaded model weights. Implement strict deserialization controls and avoid pickle for untrusted sources. - Medium · No Input Validation on Data Preparation Scripts —
data/openwebtext/prepare.py, data/shakespeare/prepare.py, data/shakespeare_char/prepare.py. Data preparation scripts in data/*/prepare.py likely process raw input files. Without proper validation and sanitization, malformed or malicious input data could cause crashes, excessive memory consumption, or other denial-of-service conditions. Fix: Implement robust input validation, size limits, and error handling in all data preparation scripts. Add sanity checks for file formats and data integrity. - Low · Missing Dependency Pinning —
Repository root. No package dependency file (requirements.txt, pyproject.toml, setup.py) is visible in the provided structure. Without pinned versions, the code could be vulnerable to supply chain attacks through compromised or malicious dependency updates. Fix: Create and maintain a requirements.txt or pyproject.toml file with pinned dependency versions. Use hash verification for critical dependencies. Consider using tools like pip-audit to check for known vulnerabilities. - Low · Potential Path Traversal in Data Loading —
train.py, configurator.py. If train.py or config files accept user-supplied file paths without validation, path traversal attacks could allow reading arbitrary files from the system. Fix: Validate and sanitize all file paths. Use os.path.abspath() and ensure paths are within expected directories. Implement allowlist-based path validation. - Low · No Security Documentation —
README.md, root directory. The README indicates this is deprecated and unmaintained code. There is no security policy, vulnerability disclosure process, or guidance on secure usage patterns. Fix: Add a SECURITY.md file with vulnerability disclosure guidelines. Document any security considerations for users, especially regarding model weight sourcing and data preparation.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/karpathy/nanoGPT shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live karpathy/nanoGPT
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/karpathy/nanoGPT.
What it runs against: a local clone of karpathy/nanoGPT — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in karpathy/nanoGPT | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 207 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of karpathy/nanoGPT. If you don't
# have one yet, run these first:
#
# git clone https://github.com/karpathy/nanoGPT.git
# cd nanoGPT
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of karpathy/nanoGPT and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "karpathy/nanoGPT(\\.git)?\\b" \\
&& ok "origin remote is karpathy/nanoGPT" \\
|| miss "origin remote is not karpathy/nanoGPT (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "train.py" \\
&& ok "train.py" \\
|| miss "missing critical file: train.py"
test -f "model.py" \\
&& ok "model.py" \\
|| miss "missing critical file: model.py"
test -f "config/train_gpt2.py" \\
&& ok "config/train_gpt2.py" \\
|| miss "missing critical file: config/train_gpt2.py"
test -f "data/openwebtext/prepare.py" \\
&& ok "data/openwebtext/prepare.py" \\
|| miss "missing critical file: data/openwebtext/prepare.py"
test -f "configurator.py" \\
&& ok "configurator.py" \\
|| miss "missing critical file: configurator.py"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 207 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~177d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/karpathy/nanoGPT"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.
Similar Python repos
Other mixed-signal Python repos by stars.
Embed this chat in your README →
Drop this iframe anywhere — the widget runs against the same live analysis cache as the main app.
<iframe src="https://repopilot.app/embed/karpathy/nanogpt" width="100%" height="500" style="border:1px solid #d0d7de; border-radius:8px;" allow="microphone" loading="lazy" ></iframe>