⛯ tmux-path-store
Your project's directories and files, one short command away.
Quick start · Shell setup · Commands · Editors · Scripting · Development
Bookmark the directories and files you use for a project under its tmux window
name. Jump back with cdh, switch to a related directory with cd1, or open a
saved file with f0.
Built for engineering workflows where project files, reports, and shared resources live across the filesystem.
- 10 directory and 10 file slots per window name, numbered
0–9. - Shell shortcuts for navigating, editing, listing, swapping, and clearing bookmarks.
- Persistent local storage, backed by Python's standard library with no runtime Python dependencies.
Quick start
Use Linux or macOS with tmux on your PATH,
uv, and Python 3.11 or later.
Install from PyPI:
uv tool install tmux-path-store
Install from source or offline
Install from a checkout:
git clone https://github.com/smprather/tmux-path-store.git
cd tmux-path-store
uv tool install .
Use uv tool install --offline . once Python and the build requirements are
available locally.
Enable shortcuts in your current Bash session; see shell setup for other shells and permanent configuration:
eval "$(tmux-path-store --bash)"
Inside tmux, give your window a project name and try these commands with your own project paths:
tmux rename-window board-rev-a
cd /work/board-rev-a
shd # Save this project's home directory in slot 0
sd1 ./reports # Save a related directory in slot 1
sf0 ./constraints.sdc # Save an existing file in file slot 0
cd1 # Jump to the reports directory
cdh # Return to the project's home directory
f0 # Open the saved file in your editor
Shell setup
Add the matching initialization command to your shell's startup file, then reload it or open a new shell.
| Shell | Startup file | Initialization |
|---|---|---|
| Bash | ~/.bashrc |
eval "$(tmux-path-store --bash)" |
| Zsh | ~/.zshrc |
eval "$(tmux-path-store --zsh)" |
| sh, dash, ksh, mksh | ~/.profile for login shells, or the file configured by ENV |
eval "$(tmux-path-store --sh)" |
| csh, tcsh | ~/.cshrc or ~/.tcshrc |
eval `tmux-path-store --csh` |
| Fish | ~/.config/fish/config.fish |
tmux-path-store --fish | source |
--dash, --ksh, and --mksh select the same hooks as --sh;
--tcsh is an alias for --csh.
Nushell
Generate a hook file from Nushell:
mkdir $nu.default-config-dir
let hook = ($nu.default-config-dir | path join 'tmux-path-store.nu')
tmux-path-store --nu | save --force $hook
print $"source '($hook)'"
Add the printed source line to the configuration file at $nu.config-path.
Nushell needs this literal file path because it loads definitions while parsing.
Regenerate the hook file after upgrading. --nushell also works.
PowerShell on Unix
Add this line to your startup file at $PROFILE:
tmux-path-store --pwsh | Out-String | Invoke-Expression
--powershell also works. The tool requires tmux and Unix file locking, so native
Windows is not supported.
Xonsh
Add this line to ~/.xonshrc:
exec($(tmux-path-store --xonsh))
Commands
In the table below, replace N with a slot number from 0 to 9.
Directory and file slots are independent.
| Shortcut | Action |
|---|---|
shd, sdh |
Save the current directory as the project home (sd0) |
cdh |
Jump to the project home (cd0) |
sdN [directory] |
Save a directory; defaults to the current directory |
sfN [file] |
Save an existing file; defaults to the most recently modified regular file in the current directory |
cdN |
Jump to directory slot N |
fN |
Open file slot N in your editor |
ef <index> [index ...] |
Open multiple file slots, for example ef 0 2 |
ld [window ...], lf [window ...] |
List directories or files for the current or named windows |
lda, lfa |
List directories or files for all saved windows |
lw |
List window names with saved bookmarks |
recent [count] |
List recently used directories and files, most recent first |
rdN, rfN |
Clear a directory or file slot |
swd <a> <b>, swf <a> <b> |
Swap two directory or file slots |
dw [window ...] |
Remove saved bookmarks for named windows; defaults to the current window |
tps |
Show shortcut help (tmux-path-store --help) |
Directory arguments are made absolute when saved. File arguments are stored as absolute paths; files that do not exist yet are allowed. Each new window name needs a saved directory or file before you can navigate or edit its slots.
Editors
File shortcuts use EDITOR, falling back to vi. For example, in Bash or Zsh:
export EDITOR='code --wait'
Arguments follow POSIX quoting rules in every shell. Quote executable paths
containing spaces inside the value, for example
EDITOR='"/opt/My Editor/bin/editor" --wait'. Shell operators and variable
references in the value are not evaluated.
ef warns about empty slots and opens the defined ones; it fails if none are
defined. Missing files are opened anyway after a warning, so an editor can
create them. Editor exit codes are preserved. In PowerShell, inspect
$LASTEXITCODE.
Storage and scripting
Bookmarks persist across tmux restarts in
${XDG_STATE_HOME:-~/.local/state}/tmux_path_store/db.json. Writes are atomic,
coordinated with file locks, and use file permissions 0600. The file is a
versioned object; unset slots are simply absent, and stored slots record when
they were saved and last used:
{"version": 2, "windows": {"board-rev-a": {"dirs": {"0": {"path": "/work/board-rev-a", "saved_at": 1790000000000000000}}, "files": {}}}}
Older list and version-1 formats are migrated on the next write. recent ranks
the current window's entries by last_used, then saved_at.
The CLI also works without the shortcuts:
tmux-path-store set-dir 0 /work/board-rev-a
tmux-path-store set-file 0 /work/board-rev-a/constraints.sdc
tmux-path-store get-dir --json 0
tmux-path-store get-file --null 0
tmux-path-store open-files 0
get-dir and get-file return newline-terminated paths by default; use --json
for a JSON string or --null for NUL-terminated output. Check the exit status
before consuming output; diagnostics go to stderr.
Set TMUX_WINDOW to select a saved window explicitly in scripts:
TMUX_WINDOW=board-rev-a tmux-path-store get-dir 0
Otherwise, TMUX_PANE identifies the invoking pane's window when available.
Commands that only read saved data (lw, ld/lf with explicit windows) work
without a reachable tmux server. Resolving the active window outside tmux uses
the server's most recently used client, so scripts should set TMUX_WINDOW.
open-files launches the editor directly; data commands print data, not shell
code. csh/tcsh navigation is the exception: csh-cd returns the path of a
private, self-deleting source file.
Development
uv sync --locked
uv run python -m unittest discover -s tests -p 'test_*.py'
uv run ruff check tmux_path_store tests
uv run ty check tmux_path_store tests
Local integration tests exercise installed shells; CI requires all 12 supported
shell names. tmux tests use private sockets and clean up only their own sessions.
CLI and storage logic live in tmux_path_store/__init__.py;
shell hooks live in tmux_path_store/shell_templates/ and are loaded by
tmux_path_store/shells.py.
Versions and release tags use CalVer YYYY.M.N, with no v prefix or zero
padding. M is the month and N starts at 1 each month; for example,
2026.10.5, then 2026.11.1 at the next month's first release.
Run tmux-path-store --version to inspect the installed version.
Metadata
Release files for tmux-path-store 2026.10.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tmux_path_store-2026.10.5.tar.gz | 17.8 kB | Without provenance | Details for tmux_path_store-2026.10.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tmux_path_store-2026.10.5-py3-none-any.whl | Python 3 | none | any | Details for tmux_path_store-2026.10.5-py3-none-any.whl |
Total release size: 37.8 kB
Release files / tmux_path_store-2026.10.5.tar.gz
| Download URL | tmux_path_store-2026.10.5.tar.gz |
|---|---|
| Size | 17.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
670bd1bd50c9aa41bf59a7c8d98ecac280a1376fc6acd18fb1888ff116e6ea56
|
|
BLAKE2b-256 checksum How to use checksums |
d4aa7bd7cc3f368382131417372b88d232df613d714411a4d2ee5e409f4b77ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / tmux_path_store-2026.10.5-py3-none-any.whl
| Download URL | tmux_path_store-2026.10.5-py3-none-any.whl |
|---|---|
| Size | 20.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0907286a2f3f333cd133fc3be98c626bcb043e57881809f5cf22fce54c311bc6
|
|
BLAKE2b-256 checksum How to use checksums |
37098193ffe3cce2bd85576f7a708905d8159eed34f766adda3aa846bd3fae9e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for tmux-path-store 2026.10.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.