Skip to content

Snipwise

Snipwise keeps text snippets in sync across files in a project. Provide a single source of truth for a fragment, and Snipwise will copy it into every README, documentation page or configuration file that repeats it, so that no copy has to be updated manually.

It is generally preferable to avoid redundant information, but sometimes it is unavoidable. The same paragraph on supported Python versions may belong in the README and in the documentation, and the same project summary may be required by several metadata formats. Snipwise works with any text format, because you write the markers yourself in the comment syntax of the file at hand. As a pre-commit hook, it keeps every commit consistent instead of leaving stale copies adrift until somebody notices.

Installation

pip install snipwise

Simple Example

Snipwise is configured by a snipwise.md file in the root of your project. This example shows how to define a snippet in snipwise.md and copy it into the README.md and docs/installation.md files.

# Snipwise Configuration

```toml
[[targets]]
patterns = ["README.md", "docs/*.md"]
```

## `python-versions`

```text
Snipwise requires Python 3.11 or later.
It is tested on Python 3.11, 3.12, 3.13 and 3.14.
```

Both README.md and docs/installation.md then contain a pair of markers:

<!-- snipwise.md BEGIN python-versions -->
<!-- snipwise.md END python-versions -->

Running snipwise fix writes the snippet between each pair of markers:

<!-- snipwise.md BEGIN python-versions -->
Snipwise requires Python 3.11 or later.
It is tested on Python 3.11, 3.12, 3.13 and 3.14.
<!-- snipwise.md END python-versions -->

From then on, snipwise reports any file that has drifted away from snipwise.md, and snipwise fix brings it back in line. The snippet is stored in three places, but only the copy in snipwise.md is meant to be edited. The others are verified (and fixed) mechanically.

The basic idea is simple, but Snipwise also packs a number of convenient features for when this simple approach falls short:

  • A snippet may be transformed on its way into a file, so that it can serve different file formats, such as Markdown, LaTeX, plain text or source code.
  • A file that cannot carry a comment can be reached with a regular expression or with a JSON pointer instead of a marker.
  • If a snippet is naturally defined by a specific file, there is no need to copy it into snipwise.md.

Where to Go Next

The documents under Using Snipwise are where to start, and the first three of them are the reference for what Snipwise does:

  • The snipwise.md Configuration File defines snippets and says which files receive them, in what shape, and which copy is the original.
  • Snippet Scanners covers the four ways a rule finds the regions of a file that it owns: the whole file, markers, a regular expression, or a JSON pointer.
  • Command-Line Interface covers the subcommands, the options, the exit codes and the pre-commit hook.
  • Snipwise in Practice discusses good practices, starting with which text is worth turning into a snippet.

The documents under Development are for working on Snipwise itself:

Example Repositories

The following repositories use Snipwise to keep various snippets in sync:

  • Snipwise itself uses snipwise.md to synchronize the list of dependencies and several sections shared by the README and the documentation home page.
  • StepUp Core uses snipwise.md to synchronize a tagline, abstract and keywords across several files.
  • STACIE uses snipwise.md to synchronize a tagline, abstract, keywords and literature references across several files.

Snipwise only copies text that you maintain by hand, and it never generates anything. That is a deliberate limit, so here is where to look when that limitation gets in the way.

  • To embed the output of a program, Cog runs a piece of Python and writes what it prints back into the file that holds it. embedme pulls the content of a source file into a fenced code block of a Markdown document.
  • To instantiate a project from a template, and to keep it in step with that template later, there are Cookiecutter and Copier. Snipwise has nothing to say about a file until that file carries markers of its own.
  • To include a fragment while a documentation site is built, there are the snippets extension of PyMdown Extensions for MkDocs, and the include and literalinclude directives of Sphinx. What differs is where the text ends up. Those mechanisms resolve during a build, so the text exists only in the generated site, while Snipwise writes it into the file itself, where GitHub, PyPI and a plain text editor all show it.

License

Snipwise is distributed under the terms of the LGPL-3.0-or-later license. Logo based on Google Noto Emoji, licensed under SIL OFL 1.1