Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 62 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
# codimd-cli

Command-line tool for self-hosted [CodiMD](https://github.com/hackmdio/codimd) instances, using **cookie session authentication** (no API token required).
Command-line tool for self-hosted [CodiMD](https://github.com/hackmdio/codimd) instances.

Built with [Bun](https://bun.sh), [Cliffy](https://cliffy.io/) for the traditional CLI, and [OpenTUI](https://github.com/anomalyco/opentui) for interactive mode.

For HackMD Enterprise or HackMD Cloud, use [hackmd-cli](https://github.com/hackmdio/hackmd-cli) instead.
**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](https://hackmd.io) or on-premise HackMD Enterprise, use [hackmd-cli](https://github.com/hackmdio/hackmd-cli) instead.

## Install

Expand All @@ -14,14 +20,14 @@ For HackMD Enterprise or HackMD Cloud, use [hackmd-cli](https://github.com/hackm
curl -fsSL https://raw.githubusercontent.com/hackmdio/codimd-cli/main/scripts/install.sh | bash
```

Install a specific version or directory:
Install a specific version or to a custom directory:

```bash
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 | bash
```

Re-run the same command to update to the latest release. The installer downloads standalone binaries from [GitHub Releases](https://github.com/hackmdio/codimd-cli/releases); no Bun or Zig required.
Re-run the same command to update to the latest release. The installer downloads standalone binaries from [GitHub Releases](https://github.com/hackmdio/codimd-cli/releases) no Bun or Zig required.

| Artifact | Platform |
|----------|----------|
Expand All @@ -30,9 +36,9 @@ Re-run the same command to update to the latest release. The installer downloads
| `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.
> Intel macOS (`darwin-x64`) is not published yet; build from source on those machines.

## Install from source
### From source

```bash
git clone https://github.com/hackmdio/codimd-cli.git
Expand All @@ -42,37 +48,42 @@ bun run compile
./dist/codimd-cli --help
```

Requires [Bun](https://bun.sh) >= 1.2 and [Zig](https://ziglang.org/) (OpenTUI native bindings).
Requires [Bun](https://bun.sh) >= 1.2 and [Zig](https://ziglang.org/) (for OpenTUI native bindings).

## Quick start

Config and cookies are stored under `~/.codimd/` by default.
Config and cookies are stored in `~/.codimd/` by default.

```bash
export CMD_CLI_SERVER_URL=https://your-codimd.example.com
codimd-cli config set serverUrl https://your-codimd.example.com
codimd-cli login
codimd-cli whoami
codimd-cli list
```

You can also pass the server per invocation:
You can also set the server URL persistently in the config file:

```bash
codimd-cli config set serverUrl https://your-codimd.example.com
```

Or pass it per invocation:

```bash
codimd-cli -s https://your-codimd.example.com list
```

Run `codimd-cli --help` or `codimd-cli <command> --help` for the full usage text.
Run `codimd-cli --help` or `codimd-cli <command> --help` for full usage.

## Configuration

Settings are merged from `~/.codimd/config.json`, environment variables, and CLI flags (highest priority).
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_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 |

Expand All @@ -83,7 +94,7 @@ Available on every command:
| Option | Description |
|--------|-------------|
| `-s, --server <url>` | Override the configured CodiMD server URL |
| `-h, --help` | Show help (short descriptions with `-h`, full with `--help`) |
| `-h, --help` | Show help (`-h` for short descriptions, `--help` for full) |
| `-V, --version` | Print version |

## Command reference
Expand All @@ -105,25 +116,33 @@ codimd-cli login --ldap -u ldap-user
| `-u, --id <id>` | Email or username |
| `--ldap` | Use LDAP authentication (`POST /auth/ldap`) |

Credentials can also come from `CMD_CLI_ID` / `CMD_CLI_PASSWORD` or saved config.
Credentials can also be provided via `CMD_CLI_ID` / `CMD_CLI_PASSWORD` environment variables or saved config.

#### `logout`

Clear the session cookie and call the server logout endpoint.
End the current session and clear the stored cookie.

```bash
codimd-cli logout
```

#### `whoami`

Print the current user as JSON (`GET /me`).
Print the currently authenticated user as JSON (`GET /me`).

```bash
codimd-cli whoami
```

### Configuration
### How authentication works

`codimd-cli` uses cookie-session authentication (adapted from [hackmd-cli v1](https://github.com/hackmdio/hackmd-cli/tree/v1.2.0)):

1. POST credentials to `/login`
2. Persist the session cookie to disk (`~/.codimd/cookies.json`)
3. Reuse the cookie on all subsequent requests

### Configuration commands

#### `config set <key> <value>`

Expand All @@ -145,7 +164,7 @@ codimd-cli config show

### Notes

Note IDs are the short alphanumeric strings from CodiMD URLs (for example `abc123` from `https://your-codimd.example.com/abc123`).
Note IDs are the short alphanumeric strings in CodiMD URLs for example, `abc123` from `https://your-codimd.example.com/abc123`.

#### `list`

Expand All @@ -162,7 +181,7 @@ codimd-cli list --json

#### `show <noteId>`

Print note markdown to stdout (`GET /:noteId/download`).
Print note Markdown to stdout (`GET /:noteId/download`).

```bash
codimd-cli show abc123
Expand All @@ -187,7 +206,7 @@ echo "# Hello" | codimd-cli create
cat draft.md | codimd-cli import
```

On success, prints the new note URL to stdout.
Prints the new note URL to stdout on success.

#### `update <noteId> [file]`

Expand Down Expand Up @@ -216,10 +235,10 @@ codimd-cli delete abc123 --yes
Export a note to stdout or a file.

```bash
codimd-cli export abc123 # markdown to stdout
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
codimd-cli export abc123 --md backup.md # Markdown to file
```

| Option | Description |
Expand All @@ -228,11 +247,11 @@ codimd-cli export abc123 --md backup.md # markdown to file
| `--html` | Export as HTML |
| `--pdf` | Export as PDF |

When no output path is given, text formats go to stdout; PDF is written as binary to stdout.
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 <noteId>`

Open the note URL in your default browser and print the URL.
Open the note in your default browser and print its URL.

```bash
codimd-cli open abc123
Expand All @@ -257,19 +276,19 @@ codimd-cli history --unpin abc123
| `--pin <noteId>` | Pin a history entry |
| `--unpin <noteId>` | Unpin a history entry |

### Interactive
### Interactive TUI

#### `tui`

Launch the OpenTUI note browser. See [Interactive TUI](#interactive-tui) for keyboard shortcuts.
Launch the OpenTUI note browser. See [keyboard shortcuts](#keyboard-shortcuts) below.

```bash
codimd-cli tui
```

### Stdin shortcut

When no subcommand is given and stdin is not a TTY, `codimd-cli` reads stdin and creates a note (same as `create`):
When no subcommand is given and stdin is not a TTY, `codimd-cli` reads from stdin and creates a note — the same as running `create`:

```bash
cat doc.md | codimd-cli
Expand All @@ -280,7 +299,7 @@ Prints the new note URL to stdout.

## Shell completions

Tab completion for commands and flags is built in via Cliffy's `CompletionsCommand`. No extra packages are required beyond the existing `@cliffy/command` dependency.
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:

Expand All @@ -300,15 +319,15 @@ Add to `~/.zshrc`:
source <(codimd-cli completions zsh)
```

If you use Oh My Zsh, you can instead save the script once:
If you use Oh My Zsh, save the script once instead:

```bash
codimd-cli completions zsh > "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/_codimd-cli"
```

### Fish

Either load in the current session:
Load in the current session:

```fish
codimd-cli completions fish | source
Expand All @@ -321,7 +340,7 @@ mkdir -p ~/.config/fish/completions
codimd-cli completions fish > ~/.config/fish/completions/codimd-cli.fish
```

Restart your shell or `source` the updated config file. Completions cover subcommands (`list`, `show`, …) and global flags such as `--server`.
Restart 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:

Expand All @@ -336,29 +355,25 @@ codimd-cli completions fish
| Operation | CodiMD endpoint |
|-----------|-----------------|
| Login | `POST /login` (form: email, password) |
| LDAP | `POST /auth/ldap` |
| 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) |
| Create | `POST /new` (raw Markdown body) |
| History pin | `POST /history/:noteId` (form: pinned=true/false) |

## Interactive TUI

```bash
codimd-cli tui
```
## Keyboard shortcuts

| Key | Action |
|-----|--------|
| `Tab` / `Shift+Tab` | Focus list / preview |
| `h` / `l` | Jump to list / preview (`h` also exits preview-max) |
| `m` | Maximize / restore preview panel |
| `{` / `}` | Shrink / widen list panel |
| `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 |
| `[` / `]` | Notes / History |
| `[` / `]` | Switch between Notes and History tabs |
| `↑` / `↓` | Navigate list |
| `Enter` | Preview selected note |
| `/` | Open floating filter (empty + Enter clears filter) |
Expand All @@ -367,13 +382,13 @@ codimd-cli tui
| `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 confirm) |
| `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 |

Chrome and list titles always show **Notes** and **History** counts; the active view is wrapped in `[brackets]`.
The status bar always shows Notes and History counts; the active tab is wrapped in `[brackets]`.

## Development

Expand Down Expand Up @@ -403,14 +418,6 @@ Pre-releases use tags containing `-alpha`, `-beta`, `-rc`, or `-pre.` (for examp

Release artifacts match the install script matrix above.

## Auth model

Cookie-session flow adapted from [hackmd-cli v1](https://github.com/hackmdio/hackmd-cli/tree/v1.2.0):

- POST credentials to `/login`
- Persist session cookies to disk (`~/.codimd/cookies.json`)
- Reuse cookies on subsequent requests

## License

MIT
Loading