{"id":13468640,"url":"https://github.com/kynan/nbstripout","last_synced_at":"2026-10-19T12:44:23.472Z","repository":{"id":41225831,"uuid":"42377037","full_name":"kynan/nbstripout","owner":"kynan","description":"strip output from Jupyter and IPython notebooks","archived":false,"fork":false,"pushed_at":"2026-04-11T18:16:00.000Z","size":342,"stargazers_count":1490,"open_issues_count":11,"forks_count":102,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-10-18T08:16:09.079Z","etag":null,"topics":["filter","git","hacktoberfest","hooks","ipython","ipython-notebook","jupyter","jupyter-notebook"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kynan.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"claude":null,"gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null}},"created_at":"2015-09-12T23:36:59.000Z","updated_at":"2026-10-15T03:14:09.000Z","dependencies_parsed_at":"2026-08-25T01:14:15.276Z","dependency_job_id":"644ed0ca-23e8-4886-b352-c82f86590b29","html_url":"https://github.com/kynan/nbstripout","commit_stats":{"total_commits":375,"total_committers":46,"mean_commits":8.152173913043478,"dds":0.2586666666666667,"last_synced_commit":"c6c106713d403865b2d5bc22ed0d8faa3d7b0f0e"},"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/kynan/nbstripout","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kynan%2Fnbstripout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kynan%2Fnbstripout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kynan%2Fnbstripout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kynan%2Fnbstripout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kynan","download_url":"https://codeload.github.com/kynan/nbstripout/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kynan%2Fnbstripout/sbom","scorecard":{"id":575520,"data":{"date":"2025-08-11","repo":{"name":"github.com/kynan/nbstripout","commit":"e28d3210005e2512538a0868460278336a1f5a99"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":1,"reason":"Found 3/30 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/tests.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/kynan/nbstripout/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/kynan/nbstripout/tests.yml/main?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/tests.yml:21","Warn: pipCommand not pinned by hash: .github/workflows/tests.yml:22","Warn: pipCommand not pinned by hash: .github/workflows/tests.yml:23","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 0.8.1 not signed: https://api.github.com/repos/kynan/nbstripout/releases/185802296","Warn: release artifact 0.8.0 not signed: https://api.github.com/repos/kynan/nbstripout/releases/183266143","Warn: release artifact 0.7.1 not signed: https://api.github.com/repos/kynan/nbstripout/releases/139823862","Warn: release artifact 0.7.0 not signed: https://api.github.com/repos/kynan/nbstripout/releases/139808617","Warn: release artifact 0.6.2 not signed: https://api.github.com/repos/kynan/nbstripout/releases/139799773","Warn: release artifact 0.8.1 does not have provenance: https://api.github.com/repos/kynan/nbstripout/releases/185802296","Warn: release artifact 0.8.0 does not have provenance: https://api.github.com/repos/kynan/nbstripout/releases/183266143","Warn: release artifact 0.7.1 does not have provenance: https://api.github.com/repos/kynan/nbstripout/releases/139823862","Warn: release artifact 0.7.0 does not have provenance: https://api.github.com/repos/kynan/nbstripout/releases/139808617","Warn: release artifact 0.6.2 does not have provenance: https://api.github.com/repos/kynan/nbstripout/releases/139799773"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T17:35:46.383Z","repository_id":41225831,"created_at":"2025-08-20T17:35:46.383Z","updated_at":"2025-08-20T17:35:46.383Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":344872684,"owners_count":38337588,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-18T02:00:06.448Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["filter","git","hacktoberfest","hooks","ipython","ipython-notebook","jupyter","jupyter-notebook"],"created_at":"2024-07-31T15:01:15.497Z","updated_at":"2026-10-19T12:44:23.459Z","avatar_url":"https://github.com/kynan.png","language":"Python","funding_links":[],"categories":["Python","git"],"sub_categories":[],"readme":"\u003c!-- markdownlint-disable MD030 --\u003e\n\u003c!-- markdownlint-disable MD041 --\u003e\n\u003c!-- markdownlint-disable MD046 --\u003e\n[![tests](https://github.com/kynan/nbstripout/actions/workflows/tests.yml/badge.svg)](https://github.com/kynan/nbstripout/actions/workflows/tests.yml)\n[![downloads](https://img.shields.io/pypi/dm/nbstripout)](https://pypi.org/project/nbstripout)\n[![PyPI version](https://img.shields.io/pypi/v/nbstripout)](https://pypi.org/project/nbstripout)\n[![conda-forge version](https://img.shields.io/conda/vn/conda-forge/nbstripout)](https://anaconda.org/conda-forge/nbstripout)\n[![supported Python versions](https://img.shields.io/pypi/pyversions/nbstripout)](https://pypi.org/project/nbstripout)\n[![Python package formats](https://img.shields.io/pypi/format/nbstripout)](https://pypi.org/project/nbstripout)\n[![license](https://img.shields.io/pypi/l/nbstripout)](https://raw.githubusercontent.com/kynan/nbstripout/main/LICENSE.txt)\n[![GitHub stars](https://img.shields.io/github/stars/kynan/nbstripout?style=social)](https://github.com/kynan/nbstripout/stargazers)\n[![GitHub forks](https://img.shields.io/github/forks/kynan/nbstripout?style=social)](https://github.com/kynan/nbstripout/network/members)\n\n# nbstripout: strip output from Jupyter and IPython notebooks\n\nReads a notebook from a file or stdin, strips output and some metadata, and\nwrites the \"cleaned\" version of the notebook to the original file or stdout.\n\nIntended to be used as a Git filter or pre-commit hook for users who don't want\nto track output in Git.\n\nRoughly equivalent to the \"Clear All Output\" command in the notebook UI, but\nonly \"visible\" to Git: keep your output in the file on disk, but don't commit\nthe output to Git. This helps minimizing diffs and reduce file size.\n\nOriginally based on \u003chttps://gist.github.com/minrk/6176788\u003e.\n\n## Python 3 only\n\nAs of version 0.4.0, nbstripout supports Python 3 *only*. If you need to use\nPython 2.7, install nbstripout 0.3.10:\n\n    pip install nbstripout==0.3.10\n\n## Screencast\n\nThis screencast demonstrates the use and working principles behind the\nnbstripout utility and how to use it as a Git filter:\n\n[![image](https://i.imgur.com/7oQHuJ5.png)](https://www.youtube.com/watch?v=BEMP4xacrVc)\n\n## Installation\n\nYou can download and install the latest version of `nbstripout` from the Python\npackage index [PyPI](https://pypi.org/project/nbstripout/) as follows:\n\n    pip install --upgrade nbstripout\n\nWhen using the [Anaconda](https://www.anaconda.com/download) Python\ndistribution, install `nbstripout` via the [conda](https://docs.conda.io)\npackage manager from [conda-forge](https://conda-forge.org):\n\n    conda install -c conda-forge nbstripout\n\n## Usage\n\nStrip output from IPython / Jupyter / Zeppelin notebook (modifies the file\nin-place):\n\n    nbstripout FILE.ipynb [FILE2.ipynb ...]\n    nbstripout FILE.zpln\n\nForce processing of non `.ipynb` files:\n\n    nbstripout -f FILE.ipynb.bak\n\nFor using Zeppelin mode while processing files with other extensions use:\n\n    nbstripout -m zeppelin -f \u003cfile.ext\u003e\n\nWrite to stdout e.g. to use as part of a shell pipeline:\n\n    cat FILE.ipynb | nbstripout \u003e OUT.ipynb\n    cat FILE.zpln | nbstripout -m zeppelin \u003e OUT.zpln\n\nor\n\n    nbstripout -t FILE.ipynb | other-command\n\nDo a dry run and only list which files would have been stripped:\n\n    nbstripout --dry-run FILE.ipynb [FILE2.ipynb ...]\n\nor\n\nDo a verification run, which works like dry run but will fail\nif any files would have been stripped:\n\n    nbstripout --verify FILE.ipynb [FILE2.ipynb ...]\n\nOperate on all `.ipynb` files in the current directory and subdirectories\nrecursively:\n\n    find . -name '*.ipynb' -exec nbstripout {} +\n\nPrint the version:\n\n    nbstripout --version\n\nShow help and usage instructions:\n\n    nbstripout --help\n\n### Using as a Git filter\n\nSet up the [git filter](https://git-scm.com/docs/gitattributes#_filter) and\nattributes as described in the manual installation instructions below:\n\n    nbstripout --install\n\nNote: The filter is declared as `required`, meaning the filter *must* succeed.\nFailures and misconfigurations will not simply cause the filter to be ignored.\n\nSet up the git filter using `.gitattributes`:\n\n    nbstripout --install --attributes .gitattributes\n\nSpecify a different path to the Python interpreter to be used for the git\nfilters (default is the path to the Python interpreter used when `nbstripout` is\ninstalled). This is useful if you have Python installed in different or unusual\nlocations across machines, e.g. `/usr/bin/python3` on your machine vs\n`/usr/local/bin/python3` in a container or elsewhere.\n\n    nbstripout --install --python python3\n\nUsing just `python3` lets each machine find its Python itself. However, keep in\nmind that depending on your setup this might not be the Python version you want\nor even fail because an absolute path is required.\n\nSet up the git filter in your global `~/.gitconfig`:\n\n    nbstripout --install --global\n\nSet up the git filter in your system-wide `$(prefix)/etc/gitconfig` (most\ninstallations will require you to `sudo`):\n\n    [sudo] nbstripout --install --system\n\nRemove the git filter and attributes:\n\n    nbstripout --uninstall\n\nRemove the git filter from your global `~/.gitconfig` and attributes:\n\n    nbstripout --uninstall --global\n\nRemove the git filter from your system-wide `$(prefix)/etc/gitconfig` and\nattributes:\n\n    [sudo] nbstripout --uninstall --system\n\nRemove the git filter and attributes from `.gitattributes`:\n\n    nbstripout --uninstall --attributes .gitattributes\n\nCheck if `nbstripout` is installed in the current repository (exits with code 0\nif installed, 1 otherwise):\n\n    nbstripout --is-installed\n\nPrint status of `nbstripout` installation in the current repository and\nconfiguration summary of filter and attributes if installed (exits with code 0\nif installed, 1 otherwise):\n\n    nbstripout --status\n\n### Configuration files\n\nThe following table shows in which files the `nbstripout` filter and attribute\nconfiguration is written to for given extra flags to `--install` and\n`--uninstall`:\n\n| flags                                    | filters                     | attributes                      |\n| ---------------------------------------- | --------------------------- | ------------------------------- |\n| none                                     | `.git/config`               | `.git/info/attributes`          |\n| `--global`                               | `~/.gitconfig`              | `~/.config/git/attributes`      |\n| `--system`                               | `$(prefix)/etc/gitconfig`   | `$(prefix)/etc/gitattributes`   |\n| `--attributes=.gitattributes`            | `.git/config`               | `.gitattributes`                |\n| `--global --attributes=.gitattributes`   | `~/.gitconfig`              | `.gitattributes`                |\n\n### Install globally\n\nUsually, `nbstripout` is installed per repository so you can choose where to use\nit or not. You can choose to set the attributes in `.gitattributes` and commit\nthis file to your repository, however there is no way to have git set up the\nfilters automatically when someone clones a repository. This is by design, to\nprevent you from executing arbitrary and potentially malicious code when cloning\na repository.\n\nTo install `nbstripout` for all your repositories such that you no longer need\nto run the installation once per repository, install as follows:\n\n    mkdir -p ~/.config/git  # This folder may not exist\n    nbstripout --install --global --attributes=~/.config/git/attributes\n\nThis will set up the filters and diff driver in your `~/.gitconfig` and instruct\ngit to apply them to any `.ipynb` file in any repository.\n\nNote that you need to uninstall with the same flags:\n\n    nbstripout --uninstall --global --attributes=~/.config/git/attributes\n\n### Install system-wide\n\nTo install `nbstripout` system-wide so that it applies to all repositories for\nall users, install as follows (most installations will require you to `sudo`):\n\n    [sudo] nbstripout --install --system\n\nThis will set up the filters and diff driver in `$(prefix)/etc/gitconfig` and\ninstruct git to apply them to any `.ipynb` file in any repository for any user.\n\nNote that you need to uninstall with the same flags:\n\n    [sudo] nbstripout --uninstall --system\n\n### Apply retroactively\n\n`nbstripout` can be used to rewrite an existing Git repository using\n[`git filter-repo`](https://github.com/newren/git-filter-repo) to strip output\nfrom existing notebooks. This invocation operates on all `.ipynb` files in the repo:\n\n```bash\n#!/bin/bash\ngit-filter-repo \\\n--file-info-callback \"\nif filename.endswith(b'.ipynb'):\n    print(f'\\nProcessing {filename.decode()}')\n    \n    import copy\n    \n    try:\n        import nbformat\n        from nbstripout import strip_output\n        \n        # Get the file contents using the blob_id\n        contents = value.get_contents_by_identifier(blob_id)\n\n        nb = nbformat.reads(contents.decode('utf-8'), as_version=nbformat.NO_CONVERT)\n        nb_original = copy.deepcopy(nb)\n\n        # Customize parameters as needed:\n        nb_stripped = strip_output(\n            nb,\n            keep_output=False,\n            keep_count=False,\n            keep_id=False,\n            extra_keys=[\n                'metadata.signature',\n                'metadata.widgets', \n                'cell.metadata.collapsed',\n                'cell.metadata.ExecuteTime',\n                'cell.metadata.execution',\n                'cell.metadata.heading_collapsed',\n                'cell.metadata.hidden',\n                'cell.metadata.scrolled'\n            ],\n            drop_empty_cells=False,\n            drop_tagged_cells=[],\n            strip_init_cells=False,\n            max_size=0\n        )\n        \n        if nb_original != nb_stripped:\n            # Convert cleaned notebook back to bytes\n            new_contents = nbformat.writes(nb_stripped).encode('utf-8')\n            \n            print(f'  → Cleaned {filename.decode()}: {len(contents)} → {len(new_contents)} bytes')\n            \n            new_blob_id = value.insert_file_with_contents(new_contents)\n            return (filename, mode, new_blob_id)\n        else:\n            print(f'  → No changes needed for {filename.decode()}')\n    except Exception as e:\n        print(f'Error processing {filename.decode()}: {e}')\n        import traceback\n        traceback.print_exc()\n        # Return unchanged file on error\n        return (filename, mode, blob_id)\n# Return unchanged file if it's not a notebook\nreturn (filename, mode, blob_id)\n\"\n```\n\n\u003e [!WARNING]\n\u003e\n\u003e This will affect the history of the repository, so use with caution!\n\n### Removing empty cells\n\nDrop empty cells i.e. cells where `source` is either empty or only contains\nwhitespace:\n\n    nbstripout --drop-empty-cells\n\n### Removing [init]{.title-ref} cells\n\nBy default `nbstripout` will keep cells with `init_cell: true` metadata. To\ndisable this behavior use:\n\n    nbstripout --strip-init-cells\n\n### Removing entire cells\n\nIn certain conditions it might be handy to remove not only the output, but the\nentire cell, e.g. when developing exercises.\n\nTo drop all cells tagged with \"solution\" run:\n\n    nbstripout --drop-tagged-cells=\"solution\"\n\nThe option accepts a list of tags separated by whitespace.\n\n### Forcing UNIX newlines\n\nForce UNIX (LF) newlines in the output (useful on Windows to keep consistent\nline endings in filtered output or textconv diffs):\n\n    nbstripout --unix-newlines FILE.ipynb\n\n### Keeping some output\n\nDo not strip the execution count/prompt number:\n\n    nbstripout --keep-count\n\nDo not strip outputs that are smaller that a given max size (useful for removing\nonly large outputs like images):\n\n    nbstripout --max-size 1k\n\nDo not strip the output, only metadata:\n\n    nbstripout --keep-output\n\n#### Output Types\n\nWhen keeping the output, drop a specific\n[`output_type`](https://ipython.readthedocs.io/en/3.x/notebook/nbformat.html#code-cell-outputs),\nlike `error` or `stream`\n\n    nbstripout --drop-output-type error stream\n\nDrop all output except specific output types:\n\n    nbstripout --keep-output-type execute_result\n\n**Note: `--keep-output-type` will override `--max-size` for outputs that match.**\n\nFor stripping certain outputs that have names (like `stream` which can be\n`stderr` or `stdout`) you can use a colon to specify the name. The following\nwould strip all `stderr` output.\n\n    nbstripout --drop-output-type stream:stderr\n\n`stream:stdout` would strip all `stdout` output, including print statements.\n\n#### Cell IDs\n\nDo not reassign the cell ids to be sequential (which is the default behavior):\n\n    nbstripout --keep-id\n\n#### Keeping Output on Specific Cells\n\nTo mark special cells so that the output is not stripped, you can either:\n\n1.  Set the `keep_output` tag on the cell. To do this, enable the tags toolbar\n    (View \u003e Cell Toolbar \u003e Tags) and then add the `keep_output` tag for each\n    cell you would like to keep the output for.\n\n2.  Set the `\"keep_output\": true` metadata on the cell. To do this, select the\n    \"Edit Metadata\" Cell Toolbar, and then use the \"Edit Metadata\" button on\n    the desired cell to enter something like:\n\n        {\n          \"keep_output\": true,\n        }\n\nYou can also keep output for an entire notebook. This is useful if you want to\nstrip output by default in an automated environment (e.g. CI pipeline), but want\nto be able to keep outputs for some notebooks. To do so, add the option above to\nthe *notebook* metadata instead. (You can also explicitly remove outputs from a\nparticular cell in these notebooks by adding a cell-level metadata entry.)\n\nAnother use-case is to preserve initialization cells that might load customized\nCSS etc. critical for the display of the notebook. To support this, we also keep\noutput for cells with:\n\n    {\n      \"init_cell\": true,\n    }\n\nThis is the same metadata used by the\n[init_cell nbextension](https://github.com/ipython-contrib/jupyter_contrib_nbextensions/tree/master/src/jupyter_contrib_nbextensions/nbextensions/init_cell).\n\n### Stripping metadata\n\nThe following metadata is stripped by default:\n\n-   Notebook metadata: `signature`, `widgets`\n-   Cell metadata: `ExecuteTime`, `collapsed`, `execution`, `heading_collapsed`,\n    `hidden`, `scrolled`\n\nAdditional metadata to be stripped can be configured via either\n\n-   `git config (--global/--system) filter.nbstripout.extrakeys`, e.g. :\n\n        git config --global filter.nbstripout.extrakeys '\n          metadata.celltoolbar\n          metadata.kernelspec\n          metadata.language_info.codemirror_mode.version\n          metadata.language_info.pygments_lexer\n          metadata.language_info.version\n          metadata.toc\n          metadata.notify_time\n          metadata.varInspector\n          cell.metadata.heading_collapsed\n          cell.metadata.hidden\n          cell.metadata.code_folding\n          cell.metadata.tags\n          cell.metadata.init_cell'\n\n-   the `--extra-keys` flag, which takes a space-delimited string as an\n    argument, e.g. :\n\n        --extra-keys=\"metadata.celltoolbar cell.metadata.heading_collapsed\"\n\nNote: Only notebook and cell metadata is currently supported and every key\nspecified via `filter.nbstripout.extrakeys` or `--extra-keys` must start with\n`metadata.` for notebook and `cell.metadata.` for cell metadata.\n\nYou can keep certain metadata that would be stripped by default with either\n\n-   `git config (--global/--system) filter.nbstripout.keepmetadatakeys`, e.g.:\n\n        git config --global filter.nbstripout.keepmetadatakeys '\n          cell.metadata.collapsed\n          cell.metadata.scrolled'\n\n-   the `--keep-metadata-keys` flag, which takes a space-delimited string as an\n    argument, e.g.:\n\n        --keep-metadata-keys=\"cell.metadata.collapsed cell.metadata.scrolled\"\n\nNote: Previous versions of Jupyter used `metadata.kernel_spec` for kernel\nmetadata. Prefer stripping `kernelspec` entirely: only stripping some attributes\ninside `kernelspec` may lead to errors when opening the notebook in Jupyter (see\n[#141](https://github.com/kynan/nbstripout/issues/141)).\n\n### Excluding files and folders\n\nTo exclude specific files or folders from being processed by the `nbstripout`\nfilters, add the path and exception to your filter specifications defined in\n`.git/info/attributes` or `.gitattributes`:\n\n    docs/** filter= diff=\n\nThis will disable `nbstripout` for any file in the `docs` directory.:\n\n    notebooks/Analysis.ipynb filter= diff=\n\nThis will disable `nbstripout` for the file `Analysis.ipynb` located in the\n`notebooks` directory.\n\nTo check which attributes a given file has with the current config, run:\n\n    git check-attr -a -- path/to/file\n\nFor a file to which the filter applies you will see the following:\n\n    $ git check-attr -a -- foo.ipynb\n    foo.ipynb: diff: ipynb\n    foo.ipynb: filter: nbstripout\n\nFor a file in your excluded folder you will see the following:\n\n    $ git check-attr -a -- docs/foo.ipynb\n    foo.ipynb: diff:\n    foo.ipynb: filter:\n\n## Manual filter installation\n\nSet up a git filter and diff driver using nbstripout as follows:\n\n    git config filter.nbstripout.clean '/path/to/nbstripout'\n    git config filter.nbstripout.smudge cat\n    git config filter.nbstripout.required true\n    git config diff.ipynb.textconv '/path/to/nbstripout -t'\n\nThis will add a section to the `.git/config` file of the current repository.\n\nIf you want the filter to be installed globally for your user, add the\n`--global` flag to the `git config` invocations above to have the configuration\nwritten to your `~/.gitconfig` and apply to all repositories.\n\nIf you want the filter to be installed system-wide, add the `--system` flag to\nthe `git config` invocations above to have the configuration written to\n`$(prefix)/etc/gitconfig` and apply to all repositories for all users.\n\nCreate a file `.gitattributes` (if you want it versioned with the repository) or\n`.git/info/attributes` (to apply it only to the current repository) with the\nfollowing content:\n\n    *.ipynb filter=nbstripout\n    *.ipynb diff=ipynb\n\nThis instructs git to use the filter named `nbstripout` and the diff driver\nnamed `ipynb` set up in the git config above for every `.ipynb` file in the\nrepository.\n\nIf you want the attributes be set for `.ipynb` files in any of your git\nrepositories, add those two lines to `~/.config/git/attributes`. Note that this\nfile and the `~/.config/git` directory may not exist.\n\nIf you want the attributes be set for `.ipynb` files in any git repository on\nyour system, add those two lines to `$(prefix)/etc/gitattributes`. Note that\nthis file may not exist.\n\n## Using `nbstripout` as a pre-commit hook\n\n[pre-commit](https://pre-commit.com) is a framework for managing git\n[pre-commit hooks](https://git-scm.com/docs/githooks).\n\nOnce you have [pre-commit](https://pre-commit.com) installed, add the following\nto the `.pre-commit-config.yaml` in your repository:\n\n    repos:\n    - repo: https://github.com/kynan/nbstripout\n      rev: 0.9.1\n      hooks:\n        - id: nbstripout\n\nThen run `pre-commit install` to activate the hook.\n\nWhen passing parameters to the hook, be aware that arguments with spaces such as\n`--extra-keys` need to be quoted as a whole:\n\n    repos:\n    - repo: https://github.com/kynan/nbstripout\n      rev: 0.9.1\n      hooks:\n        - id: nbstripout\n          args: ['--extra-keys=metadata.celltoolbar cell.metadata.heading_collapsed']\n\n\u003e [!WARNING]\n\u003e\n\u003e In this mode, `nbstripout` is used as a git hook to strip any `.ipynb` files\n\u003e before committing. This also modifies your working copy!\n\u003e\n\u003e In its regular mode, `nbstripout` acts as a filter and only modifies what git\n\u003e gets to see for committing or diffing. The working copy stays intact.\n\n## Guard PRs with a GitHub Action\n\n`nbstripout` offers a re-usable GitHub action that verifies notebooks are properly stripped of output before merging. This is useful for enforcing clean notebooks in your CI/CD pipeline without modifying local files.\n\n### Basic usage\n\n```yaml\nname: Check Notebooks Output\n\non:\n  pull_request:\n    paths:\n      - '**.ipynb'\n  push:\n    branches:\n      - main\n    paths:\n      - '**.ipynb'\n  workflow_dispatch:\n\njobs:\n  check-notebooks:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v6\n      \n      - name: Check notebooks are stripped\n        uses: kynan/nbstripout@main\n        with:\n          paths: '**/*.ipynb'\n```\n\n### Action inputs\n\nAll inputs are optional and have sensible defaults:\n\n| Input | Description | Default |\n| ----- | ----------- | ------- |\n| `python-version` | Python version to use (supports versions, ranges, or \"3.x\") | `'3.x'` |\n| `paths` | Newline-separated list of paths to check (supports wildcards) | `'**/*.ipynb'` |\n| `extra-keys` | Extra metadata keys to strip (space-separated) | `''` |\n| `keep-output` | Keep output in notebooks | `'false'` |\n| `keep-count` | Keep execution counts | `'false'` |\n| `strip-init-cells` | Strip init cells | `'false'` |\n\n### Usage examples\n\n#### Check specific paths\n\n```yaml\n- name: Check notebooks are stripped\n  uses: kynan/nbstripout@main\n  with:\n    paths: |\n      notebooks/*.ipynb\n      examples/*.ipynb\n```\n\n#### Strip extra metadata keys\n\n```yaml\n- name: Check notebooks are stripped\n  uses: kynan/nbstripout@main\n  with:\n    extra-keys: 'metadata.celltoolbar cell.metadata.heading_collapsed'\n```\n\n#### Keep execution counts\n\n```yaml\n- name: Check notebooks are stripped\n  uses: kynan/nbstripout@main\n  with:\n    keep-count: 'true'\n```\n\n#### Use specific Python version\n\n```yaml\n- name: Check notebooks are stripped\n  uses: kynan/nbstripout@main\n  with:\n    python-version: '3.11'\n```\n\n#### Combine multiple options\n\n```yaml\n- name: Check notebooks are stripped\n  uses: kynan/nbstripout@main\n  with:\n    paths: |\n      notebooks/**/*.ipynb\n    keep-count: 'true'\n    extra-keys: 'metadata.widgets cell.metadata.tags'\n```\n\n### How it works\n\nThe action runs `nbstripout --verify` on the specified notebooks, which performs a dry-run check without modifying files. If any notebook would be modified by stripping, the action fails and reports which files need to be cleaned.\n\nThis approach ensures that:\n\n- Notebooks in pull requests are properly stripped before merging\n- The check is non-destructive (doesn't modify your working copy)\n- Developers are notified when they forgot to strip output\n- Your Git history stays clean without large diffs from notebook outputs\n\n### Combining with pre-commit hooks\n\nFor the best developer experience, use both:\n\n1. **Git filter or pre-commit hook** (local): Automatically strips output before committing\n2. **GitHub Action** (CI): Guards against accidentally pushed non-stripped notebooks\n\nThis provides defense in depth and catches cases where local filters weren't installed.\n\n## Troubleshooting\n\n### Known issues\n\nCertain Git workflows are not well supported by `nbstripout`:\n\n-   Local changes to notebook files that are made invisible to Git due to the\n    `nbstripout` filter do still cause conflicts when attempting to sync\n    upstream changes (`git pull`, `git merge` etc.). This is because Git has no\n    way of resolving a conflict caused by a non-stripped local file being merged\n    with a stripped upstream file.  Addressing this issue is out of scope for\n    `nbstripout`. Read more and find workarounds in\n    [#108](https://github.com/kynan/nbstripout/issues/108).\n\n### Show files processed by nbstripout filter\n\nGit has [no builtin support](https://stackoverflow.com/a/52065333/396967) for\nlisting files a clean or smudge filter operates on. As a workaround, change the\nsetup of your filter in `.git/config`, `~/.gitconfig` or\n`$(prefix)/etc/gitconfig` as follows to see the filenames either filter operates\non:\n\n    [filter \"nbstripout\"]\n        clean  = \"f() { echo \u003e\u00262 \\\"clean: nbstripout $1\\\"; nbstripout; }; f %f\"\n        smudge = \"f() { echo \u003e\u00262 \\\"smudge: cat $1\\\"; cat; }; f %f\"\n        required = true\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkynan%2Fnbstripout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkynan%2Fnbstripout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkynan%2Fnbstripout/lists"}