Manage your Standard Notes account from the terminal.
Standard Notes is an end-to-end encrypted notes app. sn is an unofficial
command-line client for it: it signs in, syncs, and decrypts your items
locally, so you can read, write, search and back up your notes without opening
the desktop or web app. It works against the hosted service and against a
self-hosted server.
It is a single static binary with no runtime dependencies.
- Notes, tags, checklists and note templates, all from the shell
- Full-text search over titles and content, with fuzzy matching and an offline mode
- Backup and restore to a single zip file, optionally encrypted
- Export to Markdown, HTML or JSON, including Hugo and Jekyll layouts
- Migration to an Obsidian vault, with Maps of Content generated for you
- Sessions stored in the system keychain on macOS and Linux, so your password need not live in your environment
- Runs on macOS, Linux, Windows, FreeBSD and OpenBSD
On macOS and Linux, using homebrew:
brew install jonhadfield/tap/sn-cliThat installs the sn binary and clears the macOS quarantine flag for you.
Or in one line, which picks the right archive for your platform, verifies
its checksum against the published list, and installs to /usr/local/bin,
using sudo only if the install directory is not writable:
curl -fsSL https://raw.githubusercontent.com/jonhadfield/sn-cli/main/install.sh | shSet BIN_DIR to install somewhere else, or VERSION to pin a release. With a
BIN_DIR you own, such as the one below, it needs no sudo at all:
curl -fsSL https://raw.githubusercontent.com/jonhadfield/sn-cli/main/install.sh | BIN_DIR="$HOME/.local/bin" sh
curl -fsSL https://raw.githubusercontent.com/jonhadfield/sn-cli/main/install.sh | VERSION=0.5.3 shIf you would rather read it before running it, install.sh is in this repository.
Otherwise, download an archive for your platform from the
releases page and put sn
somewhere on your PATH. The darwin binaries are not signed, so a tarball
fetched through a browser is quarantined and Gatekeeper will refuse to run it.
Homebrew and install.sh handle this; if you downloaded it yourself, clear the
flag:
xattr -d com.apple.quarantine /usr/local/bin/snYou need a Standard Notes account. If you do not have one, sn register --email you@example.com will create it, but read Known issues first.
The recommended way to sign in is to store a session in your system keychain, so your password is neither typed for every command nor left in your environment:
# Prompts for your email, password and 2FA code if you have it enabled,
# then stores the session in the keychain (macOS and Linux).
sn session --add
# Tell sn to use it, either for the shell session or per command.
export SN_USE_SESSION=true
sn --use-session get notesOnce that is set up:
# What can it do?
sn --help
# Add a note
sn add note --title "My First Note" --text "Hello, Standard Notes!"
# List your notes
sn get notes
# Search them
sn search --query "hello"
# See what is in the account
sn statsCheck or remove the stored session at any time:
sn session --status
sn session --removeTo encrypt the stored session, give --session-key a value when you add it,
and the same value when you use it:
sn session --add --session-key "some-passphrase"
sn --session-key "some-passphrase" get notesFor CI and scripting, sn reads credentials from the environment:
export SN_EMAIL="you@example.com"
export SN_PASSWORD="your-password"Be deliberate about this. SN_PASSWORD puts your Standard Notes password —
the key to an end-to-end encrypted account — in plaintext in your environment,
and in your shell history if you export it interactively. Prefer sn session --add for day-to-day use, and a secret manager for automation.
sn session --add stores the session in the system keychain, which a headless
Linux server usually does not have. Point sn at a file instead, sign in once
over SSH — entering your 2FA code if you have it enabled — and later commands
refresh the session and write it back to that file:
export SN_SESSION_FILE=~/.config/sncli/session
export SN_USE_SESSION=true
sn session --add
sn get notesThe file is written with 0600 permissions, so only you can read it. It holds
a session rather than your password, and --session-key encrypts it just as it
does a keychain session. The path can also be given with --session-file, or
as session_file in the config file.
Run sn <command> --help for the flags of any command.
| Command | Description |
|---|---|
add |
Add notes or tags |
backup |
Create, inspect and restore zip backups (alias: bak) |
debug |
Debugging tools, such as decrypting a single string |
delete |
Delete notes, tags or items by title or UUID, or clear duplicates |
edit |
Edit a note or tag in your $EDITOR |
editor |
Show or set the editor Standard Notes associates with new notes |
export |
Export notes to Markdown, HTML or JSON (alias: exp) |
get |
Retrieve notes, tags, items or account settings |
healthcheck |
Find account data errors, such as items that will not decrypt |
migrate |
Migrate notes to another application (currently Obsidian) |
organize |
Suggest tags and better titles using Google Gemini |
register |
Register a new Standard Notes account |
resync |
Purge the local cache and sync again |
search |
Full-text search across notes (alias: find) |
session |
Add, inspect and remove the keychain session |
stats |
Show statistics about the account |
tag |
Apply tags in bulk, and visualise them |
task |
Manage Checklist and Advanced Checklist tasks |
template |
Manage note templates (alias: tpl) |
wipe |
Delete all supported content in the account |
These global flags work on every command:
| Flag | Description |
|---|---|
--debug |
Verbose output, useful when reporting a bug |
--server |
Use a self-hosted server rather than the hosted service |
--use-session |
Authenticate with the stored keychain session |
--session-key |
Passphrase for an encrypted stored session |
--cachedb-dir |
Where to keep the local cache (default ~/.sn-cli) |
# Create a note, with tags
sn add note --title "Meeting Notes" --text "Important discussion points" --tag work,meetings
# Create a note from a file
sn add note --file ./notes/standup.md --tag work
# Create a nested tag
sn add tag --title "projects" --parent work
# Find notes by tag, with a preview of each
sn get notes --tag work --preview
# Read a note with markdown rendering
sn get notes --title "Meeting Notes" --rich
# Edit a note in $EDITOR
sn edit note --title "Meeting Notes"
# Review duplicate notes, then delete all but the newest of each set.
# The listing flags whether each note's content is identical to the one kept.
sn delete duplicates --dry-run
sn delete duplicates
# Only delete exact copies, leaving any that have been edited since
sn delete duplicates --identical-only
# Tag every note whose title matches, in one go
sn tag --find-title "invoice" --title finance --ignore-case
# See which tags are actually being used
sn tag stats
sn tag cloud
# Add and complete a checklist task
sn task add --list "Todo" --title "Buy groceries"
sn task show --list "Todo"
sn task complete --list "Todo" --title "Buy groceries"
# Statistics, with charts
sn stats --visual# Titles and content are both searched by default
sn search --query "keyword"
sn search -q "keyword"
# Fuzzy matching, for when you cannot remember the spelling
sn search -q "imprtant" --fuzzy
# Case-sensitive, limited to one tag
sn search -q "Project" --case-sensitive --tag work
# Top ten results, rendered with markdown highlighting
sn search -q "todo" --limit 10 --output rich
# Titles only, which is faster
sn search -q "meeting" --content=false
# Skip the sync and search the local cache only
sn search -q "meeting" --offlineResults are sorted by relevance, with title matches scoring above content
matches, and shown with the matching terms highlighted in context. --output
accepts table (the default), rich, json and yaml.
Run sn search --help for the full set of flags.
# Everything, into one zip
sn backup create --output ./sn-backup.zip
# Encrypted, and only what changed since the last one
sn backup create --output ./sn-backup.zip --encrypt --incremental
# Look inside a backup before trusting it
sn backup info --file ./sn-backup.zip
# Restore, with a dry run first
sn backup restore --input ./sn-backup.zip --dry-run
sn backup restore --input ./sn-backup.zip# Markdown, one file per note
sn export --output ./export
# HTML, foldered by tag, with frontmatter
sn export --output ./export --format html --by-tags --metadata
# Ready to drop into a Hugo or Jekyll site
sn export --output ./site/content --static-site hugosn template list
sn template create --name standup --title "Standup {{date}}" --content "## Yesterday" --tags work
sn template show --name standup
sn template use --template standup --title "Standup" --var project=sn-clisn organize asks Google Gemini to suggest tags and better titles for your
notes, shows you a preview, and applies nothing until you agree.
This command sends the content of the notes it processes to Google Gemini.
No other part of sn transmits note content anywhere except to your Standard
Notes server. If that is not acceptable for your notes, do not use this
command, or narrow what it sees with --title, --uuid, --since and
--until.
# Needs an API key, from the flag or GEMINI_API_KEY
export GEMINI_API_KEY="..."
# Preview suggestions for recent notes and confirm interactively
sn organize --since 2026-01-01T00:00:00Z
# Only the notes whose titles match
sn organize --title "meeting,standup"
# Apply without confirming
sn organize --since 2026-01-01T00:00:00Z --yesKeys come from Google AI Studio.
# An Obsidian vault, with Maps of Content generated for you
sn migrate obsidian --output ./my-vault
# See what it would write, without writing it
sn migrate obsidian --output ./my-vault --dry-runTags become YAML frontmatter, links become wikilinks, and creation dates and UUIDs are preserved. See docs/obsidian-migration.md for the MOC styles, tag filtering and the vault layout it produces.
There is no config file. sn is configured with flags and environment
variables:
| Variable | Effect |
|---|---|
SN_EMAIL |
Account email, when not using a stored session |
SN_PASSWORD |
Account password, when not using a stored session |
SN_SERVER |
Self-hosted server URL |
SN_USE_SESSION |
Set to true to authenticate with the keychain session |
SN_CACHEDB_DIR |
Where to keep the local cache (default ~/.sn-cli) |
SN_DEBUG |
Set to true for verbose output |
SN_DEFAULT_LIST |
Default --list for the task command |
SN_DEFAULT_GROUP |
Default --group for the task command |
SN_SHOW_COMPLETED |
Set to true to include completed tasks by default |
GEMINI_API_KEY |
API key for sn organize |
EDITOR |
Editor used by sn edit note |
--session-key is a flag only; it is deliberately not read from the
environment.
export SN_SERVER="https://your-standardnotes-server.com"Tab completion is available for Bash, Zsh, Fish and PowerShell. The scripts call
the binary's built-in --generate-bash-completion flag, so they stay in step
with the commands and flags automatically.
The completion script has to be installed under the name of the binary, which
is sn:
# Bash, on macOS with homebrew
brew install bash-completion@2
sudo cp autocomplete/bash_autocomplete "$(brew --prefix)/etc/bash_completion.d/sn"See autocomplete/README.md for the other shells and for troubleshooting.
Notes are missing, or out of date. sn keeps a local cache under
~/.sn-cli (override with --cachedb-dir or SN_CACHEDB_DIR). Purge it and
sync again:
sn resyncItems that will not decrypt. Usually a sign that an items key is missing or damaged, which can happen after a password change or a partial sync elsewhere:
sn healthcheck keys"sn" cannot be opened on macOS. The darwin binaries are unsigned, so a
tarball downloaded through a browser carries the quarantine flag. Homebrew and
install.sh clear it; otherwise do it yourself:
xattr -d com.apple.quarantine /usr/local/bin/snTab completion does nothing. The completion script has to be installed
under the binary's name, sn, not sncli. See
autocomplete/README.md.
Something fails and you cannot tell why. Run the command again with
--debug, which reports the requests being made. Include that output if you
open an issue, with your password and session redacted.
- New accounts registered with
sn registerneed one login through the official web or desktop app beforesncan use them, because that first login is what initialises the account's encryption keys.
git clone https://github.com/jonhadfield/sn-cli.git
cd sn-cli
# Builds .local_dist/sncli
make build
# Build and install it to /usr/local/bin/sn
make mac-install # or: make linux-install
# Run the offline unit tests
make test
# Lint and test, as CI does
make ciTests that talk to a real Standard Notes account are opt-in, because they
create and delete live items. make test and CI run only the offline unit
tests. To run the live ones as well:
SN_INTEGRATION_TESTS=1 SN_EMAIL=you@example.com SN_PASSWORD=... go test ./...Contributions are welcome. Please read the Contributing Guide for the code of conduct and the process for submitting pull requests.
MIT. See LICENSE.
- Standard Notes - the note-taking app this CLI supports
- Changelog - what changed, release by release
- Releases - download a build
- Issues - bugs and requests