The mdnest CLI lets you read, write, search, and organize notes from any terminal. Supports multiple servers with @alias paths.
One command, works on macOS and Linux:
curl -fsSL https://raw.githubusercontent.com/mahsanamin/mdnest/main/install-cli.sh | bashNo dependencies — just bash and curl. python3/jq are used when present (for prettier JSON), but the CLI falls back to pure-bash/awk so every command works without them. The installer downloads to a temp file and installs atomically (using sudo only if /usr/local/bin isn't writable, and falling back to ~/.local/bin with a PATH hint if it can't) — so it never leaves a half-written binary or aborts mid-download on a fresh machine.
To try an unreleased build, point at that branch's installer and set MDNEST_BRANCH:
curl -fsSL https://raw.githubusercontent.com/mahsanamin/mdnest/develop/install-cli.sh | MDNEST_BRANCH=develop bashmdnest update honours the same MDNEST_BRANCH (default main), so you can stay on a branch:
MDNEST_BRANCH=develop mdnest update --forceEvery server you log into gets a short alias (@work, @home, etc). The alias appears in your paths (@work/engineering/README.md) and in copy-path URIs from the web UI.
mdnest login @work https://work-server:3236 <token>
mdnest login @personal https://home-server:3236 <token>If the server has SERVER_ALIAS=work set in its mdnest.conf, the CLI can pick that up automatically:
mdnest login https://work-server:3236 <token>
# → Logged in to @work (https://work-server:3236) (SERVER_ALIAS from /api/config)If the server doesn't advertise a SERVER_ALIAS, the CLI refuses — you'll be told to either pass @alias explicitly or configure SERVER_ALIAS on the server. (There is no more silent @default — that hid which server was which.)
If you have an older @default alias from a previous CLI version, rename it:
mdnest rename @default @workCreate API tokens in the web UI: Settings → API Tokens. Tokens work regardless of how the server authenticates users (local password, SSO, Firebase) — the token authenticates you directly, no IdP round-trip.
API tokens inherit your current access at request time (v3.5.0+). If you're a SuperAdmin, your token has SuperAdmin scope. If you're a namespace admin of growth, your token can read/write within growth only. If your access is revoked or your namespace-admin row is removed, your token loses that access immediately on the next request.
Every command uses a unified path:
@server/namespace/path/to/file.md
- @server — server alias (optional if only one server configured)
- namespace — workspace name on that server
- path — file or folder path within the namespace
The same format is used when you right-click → Copy Path in the web UI.
mdnest list # namespaces on default server
mdnest list @work # namespaces on @work
mdnest list @work/engineering # files in namespacemdnest read @work/engineering/Architecture/system-overview.md
mdnest read engineering/docs/api.md # single server (no @)mdnest write @work/engineering/log.md "New content"
mdnest write @work/engineering/draft.md - # read from stdin
echo "piped" | mdnest write engineering/draft.md -mdnest create @work/engineering/new-doc.md "# Title"
echo "# Title" | mdnest create @work/engineering/new-doc.md - # read from stdincreate takes content the same way as write/append: an inline string, or
- to read from stdin. It exits non-zero if no content is supplied (rather than
silently creating an empty file), and fails if the note already exists — use
write to overwrite an existing note.
mdnest append @work/engineering/log.md "## $(date) - Meeting notes"
mdnest prepend @work/engineering/log.md "Important update"
echo "from pipe" | mdnest append engineering/log.md -mdnest delete @work/engineering/old-doc.mdmdnest move @work/engineering/old-name.md new-name.mdmdnest search @work/engineering "database"
mdnest search engineering "meeting"mdnest servers # list servers + version (and build commit, e.g. 3.11.0 (a1b2c3d))
mdnest servers -v # also list namespaces per server
mdnest whoami # CLI version + all servers
mdnest logout @work # remove one server
mdnest logout # remove all
mdnest rename @old @new # rename a server alias (updates the default pointer too)The old mdnest note <action> <namespace> <path> format still works:
mdnest note list
mdnest note read engineering Architecture/system-overview.md
mdnest note append engineering log.md "text"Server configs are stored in ~/.config/mdnest/servers/. Each server has its own file.
To set the server alias that appears in Copy Path from the web UI, add to mdnest.conf:
SERVER_ALIAS=work
This makes Copy Path produce @work/namespace/path which the CLI can use directly.
The CLI checks the server version on login. If major versions don't match, you'll see a warning. Update with:
curl -fsSL https://raw.githubusercontent.com/mahsanamin/mdnest/main/install-cli.sh | bash