A personal CLI tool for managing a local stash of reusable Python code snippets. Browse, copy, and curate snippets across projects with a single command.
pipx install python-snacks
snack stash create default ~/snack-stash
snack unpack auth/google_oauth.pyRecommended (pipx):
pipx install python-snacksAlternative (pip):
pip install python-snacksRequires Python 3.10+.
Updating:
pipx upgrade python-snacks # if installed with pipx
pip install --upgrade python-snacks # if installed with pipCreate a stash directory and register it:
snack stash create default ~/snack-stashThis creates ~/snack-stash, writes ~/.snackstashrc, and sets default as the active stash.
export SNACK_STASH=~/snack-stashAdd to ~/.zshrc or ~/.bashrc to make it permanent. Takes priority over everything else.
Created automatically by snack stash create. You can also edit it by hand:
[config]
active = default
[stash.default]
path = ~/snack-stash
[stash.work]
path = ~/work-stashPriority order: SNACK_STASH env var → ~/.snackstashrc active stash → error.
A stash is a plain directory of .py files, organized into subdirectories by category:
~/snack-stash/
├── auth/
│ ├── google_oauth_fastapi.py
│ ├── google_oauth_flask.py
│ └── jwt_helpers.py
├── forms/
│ ├── contact_form.py
│ └── newsletter_signup.py
└── email/
└── smtp_sender.py
You can manage the directory with Git, Dropbox, or any sync tool independently of this CLI.
List all snippets in the active stash.
snack list # all snippets
snack list auth # filtered by category (subdirectory)Search snippet filenames for a keyword (case-insensitive).
snack search oauth
# auth/google_oauth_fastapi.py
# auth/google_oauth_flask.pyCopy a snippet from the stash into the current working directory.
snack unpack auth/google_oauth_fastapi.py
# → ./auth/google_oauth_fastapi.py
snack unpack auth/google_oauth_fastapi.py --flat
# → ./google_oauth_fastapi.py (no subdirectory)
snack unpack auth/google_oauth_fastapi.py --force
# Overwrites without promptingCopy a file from the current directory back into the stash. Use this when you've improved a snippet on a project and want to update the canonical version.
snack pack auth/google_oauth_fastapi.py
snack pack auth/google_oauth_fastapi.py --forceRegister a new named stash. Creates the directory if it doesn't exist.
snack stash create default ~/snack-stash
snack stash create work ~/work-stash --no-activateThe first stash created is automatically set as active. Use --no-activate to add a stash without switching to it.
Show all configured stashes and which one is active.
snack stash list
# default /Users/you/snack-stash ← active
# work /Users/you/work-stashMove a stash to a new location. Moves the directory on disk and updates the config.
snack stash move default ~/new-location/snack-stashCopy Python snippets from a public GitHub repository into the active stash. Downloads the repo as a tarball and copies all .py files, preserving directory structure.
snack stash add-remote owner/repo
snack stash add-remote https://github.com/owner/repo
snack stash add-remote owner/repo --subdir auth # only copy files under auth/
snack stash add-remote owner/repo --force # overwrite without prompting| Situation | Behaviour |
|---|---|
| No stash configured | Error with setup instructions |
| Stash path doesn't exist | Error with the attempted path |
| Snippet not found in stash | Error — use snack list or snack search |
| Source file not found | Error |
| Destination file already exists | Prompt to confirm, or skip with --force |
| Named stash already exists | Error |
| Move target already exists | Error |
| GitHub repo not found (HTTP 404) | Error with status code |
python-snacks/
├── pyproject.toml
├── snacks/
│ ├── main.py # Typer app, all command definitions
│ ├── config.py # SnackConfig class, stash path resolution
│ └── ops.py # File copy logic (pack, unpack, add_remote)
└── tests/
├── test_commands.py # snippet commands
└── test_stash_commands.py # stash management commands
- CI: Tests run on every push and PR to
mainacross Python 3.10, 3.11, and 3.12. - Publish: Push a
v*tag to trigger a build, PyPI publish, and GitHub Release.
git tag v0.2.0 && git push origin v0.2.0