CLI for Grug Notes API
Project description
grugnotes-cli
Command-line client for the Grug Notes /api/v1/ API.
Setup
pip install grugnotes-cli
grugnotes auth # opens settings page, paste your API key
grugnotes status # verify connection
API keys are fixed to one space. A key may be broad within that space or limited to a selected prompt allowlist. Permissions are set at creation; create a new key if you need different access.
Security defaults
grugnotes authstores the API key in plain text at~/.grugnotes. The CLI sets that file to owner-only permissions (0600) and refuses symlinked config paths.sync init --save-keyandsync reset --save-keysave the active API key into.grugnotes.jsonso each sync directory remembers its own key. This is useful when you have multiple API keys for different spaces. Keys from--api-keyorGRUGNOTES_API_KEYare ephemeral by default and require--save-keyto persist. Keys from~/.grugnotes(global config) are always saved automatically. Precedence:--api-key>GRUGNOTES_API_KEY>.grugnotes.json(local) >~/.grugnotes(global).- For CI, shared machines, or ephemeral shells, prefer
GRUGNOTES_API_KEYinstead of saving a key locally. - The CLI refuses plain
http://base URLs unless the host is loopback (localhost,127.0.0.1, or::1). To deliberately use insecure HTTP against a non-localhost host, pass--allow-insecure-httpor setGRUGNOTES_ALLOW_INSECURE_HTTP=1. - Avoid
--api-keywhen possible; shell history and process lists can leak it. Prefergrugnotes authorGRUGNOTES_API_KEY. - Saved API keys are bound to the base URL they were stored with. If you switch
--base-urlorGRUGNOTES_BASE_URL, the CLI refuses to reuse the saved key unless you provide an explicit key for that host. - Sync commands refuse to operate on symlinked sync directories or directories that contain symlinked sync paths or prompt metadata directories.
sync initandsync resetwrite a local.gitignorecovering.grugnotes/,.grugnotes.json,.prompt.json, and*.conflict.md.
Commands
notes — list notes
grugnotes notes # all notes
grugnotes notes daily-notes # filter by prompt
grugnotes notes --from 2026-03-01 --to 2026-03-03
grugnotes notes --page 2 --limit 50 # pagination
read — read a note
grugnotes read 42 # by id
grugnotes read 2026-03-03 # list notes from a date
grugnotes read daily-notes # list notes from a prompt
grugnotes read daily-notes/2026-03-03 # single note (prompt + date)
create — create a note
grugnotes create daily-notes "Hello world"
grugnotes create daily-notes "More text" --date 2026-03-03
grugnotes create daily-notes "Append this" --append
edit — edit a note
grugnotes edit 42 --notes "Full replacement"
grugnotes edit 42 --old "typo" --new "fixed"
prompts / prompt — list or show prompts
grugnotes prompts # list all
grugnotes prompts --page 2 --limit 50 # pagination
grugnotes prompt daily-notes # show one prompt
prompts-search — offline prompt search
Searches synced prompt metadata locally (no API call). Matches by exact name, then startswith, then contains.
grugnotes prompts-search daily
sync — initialize, inspect, and reconcile
grugnotes sync init
grugnotes sync init --prompt daily-notes
grugnotes sync init --from 2026-03-01 --to 2026-03-03
grugnotes sync init --save-key # persist API key in this directory
grugnotes sync status
grugnotes sync pull
grugnotes sync push
grugnotes sync reset
grugnotes sync reset --save-key # persist API key on reset
grugnotes sync watch # continuous sync
grugnotes sync watch --interval 60 # poll every 60s (default 30)
All sync subcommands except watch support --dry-run to preview changes
without writing files. Sync commands exit with code 2 on unresolved conflicts.
sync watch polls at the configured interval while there is recent sync activity,
then slows remote checks to 60s after 5 minutes of quiet time. If the remote hash
signal is temporarily unavailable, watch mode tolerates 3 unavailable poll cycles
before falling back to a direct pull.
Poll sleeps add up to 25% jitter to avoid synchronized bursts across many clients.
How sync works
The CLI tracks three versions of each note: the remote copy on the server,
the local .md file, and a shadow (the last content both sides agreed on,
stored in .grugnotes/shadows/).
On pull, the CLI fetches notes changed since the last sync. If only the remote
changed, the local file is updated. If both sides changed the same note, a
.conflict.md file is written and further syncs are blocked until you resolve it
by deleting the conflict file.
On push, the CLI diffs local files against their shadows and sends a 3-way merge patch to the server. The server rejects the push if someone else saved in between (you'll need to pull first).
watch runs both continuously: a file watcher pushes local edits (debounced 3s), while a lightweight poll checks for remote changes every 30–60s.
Scripting pattern: pull → edit → push
When a script modifies synced files (e.g. appending changelog entries), always pull before editing to avoid overwriting changes made on the server:
grugnotes sync pull "$DIR" # get latest from server
echo "new content" >> "$DIR/file.md" # edit local files
grugnotes sync push "$DIR" # push changes back
Pulls are incremental — only notes modified since the last sync are fetched.
JSON output
Most commands accept --json to output machine-readable data instead of
human-formatted text. sync watch is the main exception because it is a
long-running log stream. Useful for scripting:
grugnotes read daily-notes --json | jq '.data[].date'
grugnotes notes --json | jq '.data | length'
Global flags
grugnotes --base-url https://grugnotes.com status
Or use env vars:
export GRUGNOTES_API_KEY="gn_..."
export GRUGNOTES_BASE_URL="https://grugnotes.com"
AI agent integration
The package includes an AGENTS.md skill file with structured instructions
for AI coding agents. After install, find it with:
python -c "import importlib.resources; print(importlib.resources.files('grugnotes_cli').parent / 'AGENTS.md')"
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file grugnotes_cli-0.1.0.tar.gz.
File metadata
- Download URL: grugnotes_cli-0.1.0.tar.gz
- Upload date:
- Size: 37.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cecc74b9a0412052bf5cd5258e9aa9ff825022c93b28c9a31dbdc4526f4cfd86
|
|
| MD5 |
ab8bba67bc07506a7fd23ed202d2d567
|
|
| BLAKE2b-256 |
5e56ce2a54bb80d2e8f1dbd1702eaaca94f051bd4fdbdf4a3e9944a28788c705
|
Provenance
The following attestation bundles were made for grugnotes_cli-0.1.0.tar.gz:
Publisher:
publish.yml on keizo/grugnotes-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
grugnotes_cli-0.1.0.tar.gz -
Subject digest:
cecc74b9a0412052bf5cd5258e9aa9ff825022c93b28c9a31dbdc4526f4cfd86 - Sigstore transparency entry: 1244770778
- Sigstore integration time:
-
Permalink:
keizo/grugnotes-cli@67913f9fdf171379b3dd1eb0a7278217b2258929 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/keizo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@67913f9fdf171379b3dd1eb0a7278217b2258929 -
Trigger Event:
release
-
Statement type:
File details
Details for the file grugnotes_cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: grugnotes_cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 40.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28acf3bad0e56291637958f664d96b07ed84325e92c1c7005de7116135ec86cf
|
|
| MD5 |
9a50cf35fea4f0720f82fc989c78c398
|
|
| BLAKE2b-256 |
32a7058766e51257c5ab2bf620a9eb2cfdb1072e20ed54efe80b4113c3f76eb3
|
Provenance
The following attestation bundles were made for grugnotes_cli-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on keizo/grugnotes-cli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
grugnotes_cli-0.1.0-py3-none-any.whl -
Subject digest:
28acf3bad0e56291637958f664d96b07ed84325e92c1c7005de7116135ec86cf - Sigstore transparency entry: 1244770790
- Sigstore integration time:
-
Permalink:
keizo/grugnotes-cli@67913f9fdf171379b3dd1eb0a7278217b2258929 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/keizo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@67913f9fdf171379b3dd1eb0a7278217b2258929 -
Trigger Event:
release
-
Statement type: