lazynote is a local, terminal-first notes app for developer workflows.
Take notes instantly from the CLI, browse them in a small TUI, and expose the same notes to shell scripts, terminal tools, and coding agents. It is built for quick context capture without an account, server, database, or sync service.
Notes are stored locally as JSON. The released binary does not require a Go toolchain.
- Why lazynote?
- Quick Example
- Install and Update
- CLI Workflows
- Agent Plugins
- TUI
- Storage
- Development
- Roadmap
- Releases
- Acknowledgements
- License
- Capture notes from arguments, stdin, and shell pipelines.
- Retrieve context with plain commands such as
list,show,search, andexport. - Share one local notes file between humans, scripts, and coding agents.
- Browse notes in a fast terminal UI when you want a human view.
# take simple note: $ lazynote <title> <body>
lazynote showerthought 'Running from the cops is the ultimate double or nothing.'
# tag a note while capturing it
lazynote --tag work idea 'Use a single notes file so agents and humans share context.'
# piped body with an inferred title
printf '## Session abc123\n- fixed flaky test\n' | lazynote
# retrieve context
lazynote list
lazynote search flaky
lazynote search '#work'
lazynote export jsonRecommended for installing or updating to the latest release on Linux and macOS:
curl -fsSL https://raw.githubusercontent.com/rschoch/lazynote/main/install.sh | shThe same command handles both installation and updates. It downloads the latest
release, verifies checksums when possible, and installs or replaces lazynote
in ~/.local/bin.
Confirm the installed version afterward:
lazynote --versionIf your shell cannot find it:
export PATH="$HOME/.local/bin:$PATH"Inspect the installer first:
curl -fsSLO https://raw.githubusercontent.com/rschoch/lazynote/main/install.sh
sh install.shInstaller options:
sh install.sh --dir /usr/local/bin
sh install.sh --version vX.Y.ZUninstall a script-installed binary:
rm -f ~/.local/bin/lazynotePrebuilt archives and Linux .deb, .rpm, and .apk packages are available on
the GitHub Releases page. Direct
downloads do not add an apt/yum/apk repository, so package-manager auto-updates
are not configured yet.
From source:
go install github.com/rschoch/lazynote/cmd/lazynote@latestFrom a checkout:
make build
make installmake install uses /usr/local by default. Use PREFIX for another root:
make install PREFIX="$HOME/.local"Capture a note:
lazynote idea 'Use a single notes file so agents and humans share context.'
lazynote --tag work --tag idea idea 'Keep note metadata small and useful.'Capture from stdin:
echo 'Refactor release notes before tagging the next release.' | lazynote release
cat summary.md | lazynote 'session summary'
lazynote 'session summary' - < summary.mdIf stdin is piped without a title, the first non-empty line becomes the title:
printf '## Session abc123\n- shipped release prep\n' | lazynoteSuppress success output for scripts and agents:
some-command | lazynote --quiet 'session summary'
lazynote --quiet release 'Tag after CI passes.'Retrieve context:
lazynote list
lazynote show <id>
lazynote show --body <id>
lazynote search packaging
lazynote search '#work'
lazynote backup
lazynote export markdown
lazynote export json
lazynote pathlist prints tab-separated id, created_at, and title fields, plus a
metadata field when a note is pinned or tagged. show accepts a full ID or a
unique ID prefix.
Manage existing notes:
lazynote edit <id>
lazynote edit <id> 'new title' 'new body'
lazynote edit <id> 'new title' - < body.md
lazynote delete <id>
lazynote pin <id>
lazynote unpin <id>
lazynote tag <id> work idea
lazynote untag <id> work
lazynote tags <id>edit <id> opens $VISUAL, $EDITOR, or vi. Direct edit commands replace
the title and body without opening an editor. tag normalizes tags to
lower-case names and accepts optional leading #.
backup prints the backup file path. With no path it writes a timestamped JSON
copy under a backups directory next to the notes file. Pass a file path to
choose the exact destination, or an existing directory for a timestamped backup
inside that directory.
Command words such as list, show, search, edit, delete, pin,
unpin, tag, untag, tags, path, backup, and export are reserved
when they are the first argument. Use -- to use one as a title:
lazynote -- search 'a note whose title is search'Use single quotes for literal shell text, especially if the note contains
characters like !, $, or backticks.
Agent plugins are optional. The lazynote CLI works on its own; plugins only
teach tools like Codex or Claude Code how to save and retrieve notes through the
CLI. Install the lazynote binary first, then install the plugin for your
agent.
Add the GitHub marketplace source. This does not require cloning lazynote
first:
codex plugin marketplace add rschoch/lazynoteThen open /plugins in Codex and install lazynote.
To pick up newer plugin instructions later, upgrade the marketplace source and
update the installed plugin from /plugins:
codex plugin marketplace upgrade lazynoteAsk Codex to use lazynote when you want it to persist or retrieve project
context:
"Use lazynote to save the proposed implementation plan."
"Search lazynote for notes about release packaging."
"Save a summary of this debugging session to lazynote."
Add the GitHub marketplace source, install the plugin, and reload plugins. This
does not require cloning lazynote first:
/plugin marketplace add rschoch/lazynote
/plugin install lazynote@lazynote
/reload-plugins
To pick up newer plugin instructions later, reinstall the plugin and reload:
/plugin install lazynote@lazynote
/reload-plugins
Invoke the Claude Code skill with /lazynote:
/lazynote Save the proposed implementation plan.
/lazynote Search for notes about release packaging.
/lazynote Save a summary of this debugging session.
Open the terminal UI:
lazynoteThe TUI shows note titles on the left and the selected note body on the right. It automatically reloads when the notes file changes, so notes added from another terminal tab, script, or coding agent appear while the TUI stays open. The bottom status line shows context-specific key hints.
Keys:
- left: focus note list
- right: focus note body
- down: move or scroll down in the active pane
- up: move or scroll up in the active pane
- PageDown: scroll note body down
- PageUp: scroll note body up
/: filter notes by title, body, or#tag; Enter applies, Esc cancelsr: reload notes from disk nown: create a note in$VISUAL,$EDITOR, orvie: edit the selected note in$VISUAL,$EDITOR, orvip: pin or unpin the selected note?: show or hide the help overlayc: copy the selected title or note bodyd/ delete: arm deletion; pressdagain to confirm- Esc: clear the active filter
q/ Ctrl-C: quit
Copy uses terminal clipboard support. Creating and editing open a temporary
file whose first line is the note title and whose remaining content is the note
body. The note body pane shows tags and edited timestamps when present. Pinned
notes stay at the top of the list and use ▴ in the list gutter. Notes that
arrive from another process while the TUI is open use ● until selected.
Fonts, glyph rendering, and colors depend on your terminal emulator.
Set your preferred external editor before launching lazynote:
export VISUAL="nvim"
export EDITOR="nano"VISUAL is preferred over EDITOR; if neither is set, lazynote falls back to
vi. GUI editors should wait for the file to close, for example
VISUAL="code --wait".
TUI behavior is configured in ~/.config/lazynote/config.json:
{
"tui": {
"refreshIntervalSeconds": 1,
"noteOrder": "oldest-first",
"autoSelectNewNotes": false
}
}Supported values:
refreshIntervalSeconds: how often the open TUI checks for external changesnoteOrder:oldest-firstornewest-firstautoSelectNewNotes: jump to newly arrived notes after auto-refresh
The TUI includes adaptive default, mono, and high-contrast themes, plus
fixed dark and light themes. The default inherits your terminal's foreground
and background colors, so it remains readable with either a light or dark
terminal profile.
LAZYNOTE_THEME=light lazynoteCustom theme overrides are configured in ~/.config/lazynote/config.json.
See THEMING.md for the full format and examples.
Default notes file:
~/.local/share/lazynote/notes.json
Print the active path:
lazynote pathUse a different notes file:
LAZYNOTE_PATH=/tmp/lazynote-dev.json lazynote listBack up your notes:
lazynote backup
lazynote backup ~/backup/lazynote
lazynote backup ~/backup/lazynote/notes.jsonBecause storage is one JSON file, it can be synced with tools like Syncthing,
Dropbox, iCloud Drive, or a private dotfiles repository. The TUI reloads when
the file changes, including atomic replacements. Writes use a small lock file
next to the notes file so concurrent CLI, TUI, script, and agent writes do not
silently overwrite each other. Newer versions may write optional tags,
updated_at, and pinned fields; older notes without these fields continue to
load normally.
Run tests and build a dev binary:
make test
make build
bin/lazynote --versionTry the dev binary without touching your real notes:
LAZYNOTE_PATH=/tmp/lazynote-dev.json bin/lazynote 'dev smoke' 'hello from local build'
LAZYNOTE_PATH=/tmp/lazynote-dev.json bin/lazynote list
LAZYNOTE_PATH=/tmp/lazynote-dev.json bin/lazynote export markdown
LAZYNOTE_PATH=/tmp/lazynote-dev.json bin/lazynoteIf go is installed but not on PATH:
make GO=/usr/local/go/bin/go test
make GO=/usr/local/go/bin/go buildCheck the installer script:
sh -n install.sh
sh install.sh --helpUseful targets:
make build: buildbin/lazynotemake test: rungo test ./...make install: install under$(PREFIX)/binmake uninstall: remove from$(PREFIX)/binmake clean: remove local build and release artifactsmake release-snapshot: build local GoReleaser artifacts
See ROADMAP.md for lightweight future candidates and deliberately deferred ideas.
GoReleaser configuration lives in .goreleaser.yaml. Tagged releases build
Linux, macOS, and Windows binaries for amd64 and arm64, plus checksums,
archives, and Linux packages.
Create a local snapshot:
make release-snapshotPublish a tagged release:
git tag vX.Y.Z
git push origin vX.Y.ZGitHub Actions runs tests and publishes release artifacts. Publishing apt/yum/apk repositories or Homebrew taps is a separate distribution step.
lazynote takes a lot of inspiration from
LazyGit, especially around keeping a
terminal UI fast, keyboard-driven, and practical without making it feel heavy.
MIT
