# nbstrip


[](https://crates.io/crates/nbstrip)
[](https://docs.rs/nbstrip)
[](LICENSE)
Fast Jupyter notebook output stripper and git clean filter, in Rust with only two
dependencies (`serde`, `serde_json`). Cell outputs, execution counts, and
transient UI metadata never reach git; your working tree keeps everything for
Jupyter. Diffs stay readable, repositories stay small, and megabytes of
embedded plotly figures stop hiding real changes.
## Install
```bash
cargo install nbstrip
```
## Wire a repository (once per clone)
```bash
cd your-repo
nbstrip install
```
This registers the binary as the repository's clean filter for `*.ipynb`
(`filter.nbstrip.clean` + `filter.nbstrip.required` in the repo's git config,
the attribute line in `.git/info/attributes`). Nothing needs committing. From
then on `git add` stages notebooks stripped, `git diff`/`git status` compare
through the filter, and the working tree keeps its outputs.
Because git config never travels with a clone — by design — **every clone runs
`nbstrip install` once**. A clone that skipped it strips nothing and warns
about nothing. Teams can commit `*.ipynb filter=nbstrip` to `.gitattributes`
so the *routing* travels with the repo; each clone still needs the one-time
`nbstrip install` to define the filter itself (it is idempotent, and
`filter.nbstrip.required=true` then makes an unwired clone fail the `git add`
loudly instead of silently committing outputs).
## What gets stripped
- **cell outputs** — cleared
- **execution counts** — nulled (the key stays, as the nbformat schema requires)
- **transient metadata** — notebook-level `signature`, `widgets`, `vscode`;
cell-level `collapsed`, `scrolled`, `execution`, `ExecuteTime`,
`heading_collapsed`, `hidden`
Sources, markdown cells, and authored metadata pass through untouched. Output
is byte-compatible with how `nbformat` writes files (1-space indent, sorted
keys, trailing newline preserved) and stripping is idempotent, so the filter
never churns.
**Keeping an output deliberately:** tag a cell `keep_output` (or set
`keep_output: true` in its metadata; notebook-level metadata keeps every cell).
An explicit `keep_output: false` beats a tag. This is the `nbstripout`
convention, so notebooks move between the two tools cleanly.
## Other modes
```bash
nbstrip notebooks/*.ipynb # rewrite files in place (Clear All Outputs, but scriptable)
nbstrip -t nb.ipynb # print the stripped notebook to stdout
nbstrip < in.ipynb > out.ipynb # stdin to stdout (what git calls)
```
In-place mode is handy when the *local* file should shrink too — e.g. after a
heavy plotting session; re-running the notebook regenerates everything.
## Development
```bash
cargo fmt --all --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
```
The lint policy is strict (`pedantic`/`nursery`/`cargo` plus
`unwrap_used`/`expect_used`/`panic`); fix findings rather than allowing them.
Releases follow [docs/crate_release_process.md](docs/crate_release_process.md)
via [scripts/release.sh](scripts/release.sh).
## License
Apache-2.0. Modeled on [nbstripout](https://github.com/kynan/nbstripout) and
[nbstripout-fast](https://github.com/deshaw/nbstripout-fast); reimplemented
from scratch.