Skip to main content

gwarchive

A command-line tool for organizing folders under the GWArchive naming standard.

Five categories, each a directory, each with a letter:

Letter Directory For
P Project active work with an end
R Recurring work that comes back
M Material reference that is not a project
A Archive finished, kept
O Old retired, date-stamped

Folders are named P0001 Descriptor, subfolders P0001.01 Descriptor, and retired folders YYYY-MM-DD-P0001-Descriptor.

A prefix is a permanent identifier: allocated once, never reissued, and kept across category moves, so P0001 stays P0001 in Archive. A copy gets a fresh one. There is no index; the filesystem is the source of truth.

Install

uv tool install gwarchive

Or run g.pyz, a self-contained zipapp, with no install:

./g.pyz --help

Or, with no Python at all, download the executable for your platform from the latest release: gwarchive-linux-x86_64, gwarchive-linux-arm64, gwarchive-macos-arm64, gwarchive-macos-x86_64, gwarchive-windows-x86_64.exe or gwarchive-windows-arm64.exe. SHA256SUMS sits beside them.

curl -LO https://github.com/biosafetylvl5/gwarchive/releases/latest/download/gwarchive-linux-x86_64
chmod +x gwarchive-linux-x86_64
./gwarchive-linux-x86_64 --help

Use

gwarchive init                        # create the five category directories
gwarchive create P "Thesis draft"     # -> Project/P0001 Thesis draft
gwarchive mksub P1 "Figures"          # -> Project/P0001 Thesis draft/P0001.01 Figures
gwarchive list P                      # a table, or --json
gwarchive find thesis                 # exits 1 on no match, so it composes like grep
gwarchive mv P1 Archive               # the prefix comes along
gwarchive oldify P1                   # retire into Old/ with today's date
gwarchive verify                      # audit the whole tree

Every mutating command takes --dry-run, whose output matches the real run's (Would move vs Moved).

Shell navigation

eval "$(gwarchive shell-init)"
gcd P1        # cd to the folder with that prefix, wherever it now lives
gwarchive here   # the folder you're in, short: P28:GWArchive

shell-init also sets the terminal title from here at each prompt:

Where you are Title
Project/P0028 GWArchive/src/... P28:GWArchive
Project/P0028 GWArchive/P0028.01 Docs P28:GWArchive (here --deepest: P28.01:Docs)
Old/2026-01-05-P0001-Beta Old:Beta
Project/ G:Project
the archive root G:
anywhere else the directory name

It runs only when the directory changes, and not on TERM=dumb. Put the eval after any prompt framework that sets titles (oh-my-zsh does), or pass --no-title.

Remote sync

Backed by rclone; set $GWARCHIVE_REMOTE or pass --remote:

gwarchive push P1        # upload, keep the local copy
gwarchive offload P1     # upload, delete locally, leave a tombstone
gwarchive pull P1        # fetch back
gwarchive restore P1     # fetch back and clear the tombstone
gwarchive restore P1 --keep-local   # clear the tombstone, fetch nothing

An offloaded folder keeps its name on disk while its bytes live on the remote. Its tombstone, .gwarchive-offload.json, is also the version index; the remote is never listed.

push refuses a folder marked offloaded that still holds local files (pulled then edited, or an interrupted offload). restore --keep-local resolves it from disk; restore fetches the remote's copy over it.

pull and restore ask once before overwriting local files. -y/--yes skips the prompt; --json without --yes refuses instead.

Each folder is pushed as one tar.zst (tar.gz without zstd) beside its mirror path. Even without the tombstone it is a plain archive: zstd -d < x.tar.zst | tar -tvf -.

Exit codes

Code Meaning
0 success
1 runtime failure — not found, ambiguous prefix, refused overwrite, no matches
2 invalid input — a bad category, a bad date, a malformed --remote

Errors go to stderr. Under --json, stdout carries only the JSON.

Environment

Variable Effect
GWARCHIVE_BASE archive root (default ~/gwarchive)
GWARCHIVE_REMOTE default rclone target
GWARCHIVE_CODEC force zstd or gzip
GWARCHIVE_COMPRESS default for --no-compress
GWARCHIVE_KEEP archived copies retained per remote
GWARCHIVE_POKEMON sprite for clears

Development

uv sync                  # installs the dev group
uv run pytest
uv run mypy
uv run ruff check . && uv run ruff format --check .

With Nix: nix develop, or nix run github:biosafetylvl5/gwarchive -- --help to try it. Commits follow Conventional Commits; pre-commit install adds the check. Contributor notes are in AGENTS.md.

Metadata

Release files for gwarchive 1.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gwarchive 1.3.2
File Size Uploaded
gwarchive-1.3.2.tar.gz 234.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gwarchive 1.3.2
File Interpreter ABI Platform
gwarchive-1.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 310.0 kB

Release files / gwarchive-1.3.2.tar.gz

Download URL gwarchive-1.3.2.tar.gz
Size 234.7 kB
Tags Source
SHA-256 checksum
How to use checksums
1692898a98a4372de8b1567e17b3b7de003dc4b6740b4e446d8fdca27c8a98c8
BLAKE2b-256 checksum
How to use checksums
927bc9f2fc53a511ad15e3761e4bf0d29159e145bf4d7b48dec76f8c5c3b5b0a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / gwarchive-1.3.2-py3-none-any.whl

Download URL gwarchive-1.3.2-py3-none-any.whl
Size 75.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9b509a995770b794a0c5ddb4e56dd6db6276f9a5fef1805f1a6e97ea6256c8fd
BLAKE2b-256 checksum
How to use checksums
e57394082869cde16847a28e48b573caef3ad8035e196faf7021afdbe9d6333b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.3.2 This release

2 release files

1.3.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page