Command-line tool for self-hosted CodiMD instances.
Built with Bun, Cliffy for the traditional CLI, and OpenTUI for interactive mode.
Features:
- Create, read, update, delete, and export notes (Markdown, HTML, PDF)
- Full-featured terminal UI with a note browser and live preview
- Shell completions for Bash, Zsh, and Fish
- Pipe-friendly stdin shortcut for quick note creation
For hackmd.io or on-premise HackMD Enterprise, use hackmd-cli instead.
curl -fsSL https://raw.githubusercontent.com/hackmdio/codimd-cli/main/scripts/install.sh | bashInstall a specific version or to a custom directory:
curl -fsSL https://raw.githubusercontent.com/hackmdio/codimd-cli/main/scripts/install.sh | bash -s -- --version 0.2.3
CODIMD_CLI_INSTALL_DIR=/usr/local/bin curl -fsSL https://raw.githubusercontent.com/hackmdio/codimd-cli/main/scripts/install.sh | bashRe-run the same command to update to the latest release. The installer downloads standalone binaries from GitHub Releases — no Bun or Zig required.
| Artifact | Platform |
|---|---|
codimd-cli-linux-x64 |
Linux x64 |
codimd-cli-linux-arm64 |
Linux arm64 |
codimd-cli-darwin-arm64 |
macOS Apple Silicon |
codimd-cli-windows-x64.exe |
Windows x64 |
Intel macOS (
darwin-x64) is not published yet; build from source on those machines.
git clone https://github.com/hackmdio/codimd-cli.git
cd codimd-cli
bun install
bun run compile
./dist/codimd-cli --helpRequires Bun >= 1.2 and Zig (for OpenTUI native bindings).
Config and cookies are stored in ~/.codimd/ by default.
export CMD_CLI_SERVER_URL=https://your-codimd.example.com
codimd-cli login
codimd-cli whoami
codimd-cli listYou can also set the server URL persistently in the config file:
codimd-cli config set serverUrl https://your-codimd.example.comOr pass it per invocation:
codimd-cli -s https://your-codimd.example.com listRun codimd-cli --help or codimd-cli <command> --help for full usage.
Settings are merged from ~/.codimd/config.json, environment variables, and CLI flags (highest priority wins).
| Variable | Description |
|---|---|
CMD_CLI_SERVER_URL |
CodiMD server URL |
CMD_CLI_CONFIG_DIR |
Config directory (default: ~/.codimd) |
CMD_CLI_COOKIE_PATH |
Cookie file path (default: ~/.codimd/cookies.json) |
CMD_CLI_ID |
Email or username for non-interactive login |
CMD_CLI_PASSWORD |
Password for non-interactive login |
Available on every command:
| Option | Description |
|---|---|
-s, --server <url> |
Override the configured CodiMD server URL |
-h, --help |
Show help (-h for short descriptions, --help for full) |
-V, --version |
Print version |
Sign in with email/password or LDAP. Prompts interactively when credentials are not provided.
codimd-cli login
codimd-cli login -u you@example.com
codimd-cli login --ldap -u ldap-user| Option | Description |
|---|---|
-u, --id <id> |
Email or username |
--ldap |
Use LDAP authentication (POST /auth/ldap) |
Credentials can also be provided via CMD_CLI_ID / CMD_CLI_PASSWORD environment variables or saved config.
End the current session and clear the stored cookie.
codimd-cli logoutPrint the currently authenticated user as JSON (GET /me).
codimd-cli whoamicodimd-cli uses cookie-session authentication (adapted from hackmd-cli v1):
- POST credentials to
/login - Persist the session cookie to disk (
~/.codimd/cookies.json) - Reuse the cookie on all subsequent requests
Persist a config value to ~/.codimd/config.json.
codimd-cli config set serverUrl https://your-codimd.example.comSupported keys: serverUrl.
Print the effective merged configuration as JSON.
codimd-cli config showNote IDs are the short alphanumeric strings in CodiMD URLs — for example, abc123 from https://your-codimd.example.com/abc123.
List notes you own (GET /api/notes/myNotes).
codimd-cli list
codimd-cli list --json| Option | Description |
|---|---|
--json |
Output raw JSON instead of a table |
Print note Markdown to stdout (GET /:noteId/download).
codimd-cli show abc123
codimd-cli show abc123 > note.mdPrint note metadata as JSON (GET /:noteId/info).
codimd-cli info abc123Create a note from a file or stdin (POST /new). import is an alias of create.
codimd-cli create draft.md
echo "# Hello" | codimd-cli create
cat draft.md | codimd-cli importPrints the new note URL to stdout on success.
Replace note content from a file or stdin (PUT /api/notes/:noteId).
codimd-cli update abc123 revised.md
cat revised.md | codimd-cli update abc123Delete a note you own (DELETE /api/notes/:noteId). Prompts for confirmation unless --yes is passed.
codimd-cli delete abc123
codimd-cli delete abc123 --yes| Option | Description |
|---|---|
-y, --yes |
Skip confirmation prompt |
Export a note to stdout or a file.
codimd-cli export abc123 # Markdown to stdout (default)
codimd-cli export abc123 --html # HTML to stdout
codimd-cli export abc123 --pdf out.pdf # PDF to file
codimd-cli export abc123 --md backup.md # Markdown to file| Option | Description |
|---|---|
--md |
Export as Markdown (default) |
--html |
Export as HTML |
--pdf |
Export as PDF |
When no output path is given, Markdown and HTML are written to stdout. PDF is written as binary — pipe to a file or specify an output path.
Open the note in your default browser and print its URL.
codimd-cli open abc123Show browsing history (GET /history), or pin/unpin entries.
codimd-cli history
codimd-cli history --json
codimd-cli history --pin abc123
codimd-cli history --unpin abc123| Option | Description |
|---|---|
--json |
Output raw JSON |
--pin <noteId> |
Pin a history entry |
--unpin <noteId> |
Unpin a history entry |
Launch the OpenTUI note browser. See keyboard shortcuts below.
codimd-cli tuiWhen no subcommand is given and stdin is not a TTY, codimd-cli reads from stdin and creates a note — the same as running create:
cat doc.md | codimd-cli
pbpaste | codimd-cli -s https://your-codimd.example.comPrints the new note URL to stdout.
Tab completion for commands and flags is built in via Cliffy's CompletionsCommand. No extra packages are required.
Generate and enable completions for your shell:
Add to ~/.bashrc:
source <(codimd-cli completions bash)Add to ~/.zshrc:
source <(codimd-cli completions zsh)If you use Oh My Zsh, save the script once instead:
codimd-cli completions zsh > "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/_codimd-cli"Load in the current session:
codimd-cli completions fish | sourceOr install persistently:
mkdir -p ~/.config/fish/completions
codimd-cli completions fish > ~/.config/fish/completions/codimd-cli.fishRestart your shell or source the updated config file. Completions cover subcommands (list, show, …) and global flags like --server.
To inspect the generated script without enabling it:
codimd-cli completions bash
codimd-cli completions zsh
codimd-cli completions fish| Operation | CodiMD endpoint |
|---|---|
| Login | POST /login (form: email, password) |
| LDAP login | POST /auth/ldap |
| Logout | GET /logout |
| List notes | GET /api/notes/myNotes |
| Read content | GET /:noteId/download |
| Update | PUT /api/notes/:noteId { "content": "..." } |
| Delete | DELETE /api/notes/:noteId |
| Create | POST /new (raw Markdown body) |
| History pin | POST /history/:noteId (form: pinned=true/false) |
| Key | Action |
|---|---|
Tab / Shift+Tab |
Move focus between list and preview |
h / l |
Jump to list / preview (h also exits maximized preview) |
m |
Maximize / restore the preview panel |
{ / } |
Shrink / widen the list panel |
| Drag split line | Resize list / preview split |
[ / ] |
Switch between Notes and History tabs |
↑ / ↓ |
Navigate list |
Enter |
Preview selected note |
/ |
Open floating filter (empty + Enter clears filter) |
n |
Full-screen compose |
Meta+Enter |
Publish note (while composing) |
o |
Copy note URL (or open in browser) |
p |
Pin/unpin history entry |
r |
Reload list (when list is focused) |
d d |
Delete selected note (double-tap to confirm) |
? |
Shortcut help modal (j/k to scroll) |
Ctrl+P |
Command palette |
Esc |
Close filter / help / palette / compose |
Ctrl+C |
Quit |
The status bar always shows Notes and History counts; the active tab is wrapped in [brackets].
bun run dev -- --help
bun test
bun run typecheck
bun run compileCliffy packages are installed from JSR via .npmrc. To add more Cliffy modules:
bunx jsr add @cliffy/<package>Push a semver tag to trigger the release workflow:
git tag v0.1.0
git push origin v0.1.0Pre-releases use tags containing -alpha, -beta, -rc, or -pre. (for example v0.2.0-beta.1).
Release artifacts match the install script matrix above.
MIT