Skip to content
Merged
Show file tree
Hide file tree
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
295 changes: 271 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ bun run compile

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

## Configuration
## Quick start

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

Expand All @@ -56,33 +56,280 @@ codimd-cli whoami
codimd-cli list
```

You can also pass the server 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.

## Configuration

Settings are merged from `~/.codimd/config.json`, environment variables, and CLI flags (highest priority).

| Variable | Description |
|----------|-------------|
| `CMD_CLI_SERVER_URL` | CodiMD server URL |
| `CMD_CLI_CONFIG_DIR` | Config directory (default `~/.codimd`) |
| `CMD_CLI_COOKIE_PATH` | Cookie file path |
| `CMD_CLI_ID` / `CMD_CLI_PASSWORD` | Non-interactive login |

## Commands

| Command | Description |
|---------|-------------|
| `login` | Sign in with email/password or `--ldap` |
| `logout` | Clear session |
| `whoami` | Current user info (`GET /me`) |
| `config set/show` | Manage local config |
| `list` | List owned notes (`GET /api/notes/myNotes`) |
| `show <noteId>` | Print note markdown (`GET /:id/download`) |
| `info <noteId>` | Note metadata JSON (`GET /:id/info`) |
| `create [file]` | Create note from file or stdin (`POST /new`) |
| `import [file]` | Alias of `create` |
| `update <noteId> [file]` | Update note content (`PUT /api/notes/:id`) |
| `delete <noteId>` | Delete owned note (`DELETE /api/notes/:id`) |
| `export <noteId> [file]` | Export note (`--md`, `--html`, `--pdf`) |
| `history` | Browsing history (`GET /history`, `--pin` / `--unpin`) |
| `open <noteId>` | Open note URL in the default browser |
| `tui` | Interactive note browser (OpenTUI) |
| *(stdin pipe)* | `cat doc.md \| codimd-cli` creates a note |
| `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 |

### Global options

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`) |
| `-V, --version` | Print version |

## Command reference

### Authentication

#### `login`

Sign in with email/password or LDAP. Prompts interactively when credentials are not provided.

```bash
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 come from `CMD_CLI_ID` / `CMD_CLI_PASSWORD` or saved config.

#### `logout`

Clear the session cookie and call the server logout endpoint.

```bash
codimd-cli logout
```

#### `whoami`

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

```bash
codimd-cli whoami
```

### Configuration

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

Persist a config value to `~/.codimd/config.json`.

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

Supported keys: `serverUrl`.

#### `config show`

Print the effective merged configuration as JSON.

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

#### `list`

List notes you own (`GET /api/notes/myNotes`).

```bash
codimd-cli list
codimd-cli list --json
```

| Option | Description |
|--------|-------------|
| `--json` | Output raw JSON instead of a table |

#### `show <noteId>`

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

```bash
codimd-cli show abc123
codimd-cli show abc123 > note.md
```

#### `info <noteId>`

Print note metadata as JSON (`GET /:noteId/info`).

```bash
codimd-cli info abc123
```

#### `create [file]` / `import [file]`

Create a note from a file or stdin (`POST /new`). `import` is an alias of `create`.

```bash
codimd-cli create draft.md
echo "# Hello" | codimd-cli create
cat draft.md | codimd-cli import
```

On success, prints the new note URL to stdout.

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

Replace note content from a file or stdin (`PUT /api/notes/:noteId`).

```bash
codimd-cli update abc123 revised.md
cat revised.md | codimd-cli update abc123
```

#### `delete <noteId>`

Delete a note you own (`DELETE /api/notes/:noteId`). Prompts for confirmation unless `--yes` is passed.

```bash
codimd-cli delete abc123
codimd-cli delete abc123 --yes
```

| Option | Description |
|--------|-------------|
| `-y, --yes` | Skip confirmation prompt |

#### `export <noteId> [output]`

Export a note to stdout or a file.

```bash
codimd-cli export abc123 # markdown to stdout
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, text formats go to stdout; PDF is written as binary to stdout.

#### `open <noteId>`

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

```bash
codimd-cli open abc123
```

### History

#### `history`

Show browsing history (`GET /history`), or pin/unpin entries.

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

### Interactive

#### `tui`

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

```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`):

```bash
cat doc.md | codimd-cli
pbpaste | codimd-cli -s https://your-codimd.example.com
```

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.

Generate and enable completions for your shell:

### Bash

Add to `~/.bashrc`:

```bash
source <(codimd-cli completions bash)
```

### Zsh

Add to `~/.zshrc`:

```bash
source <(codimd-cli completions zsh)
```

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

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

### Fish

Either load in the current session:

```fish
codimd-cli completions fish | source
```

Or install persistently:

```fish
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`.

To inspect the generated script without enabling it:

```bash
codimd-cli completions bash
codimd-cli completions zsh
codimd-cli completions fish
```

## CodiMD API mapping

Expand Down
4 changes: 3 additions & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env bun

import { Command } from "@cliffy/command";
import { CompletionsCommand } from "@cliffy/command/completions";
import pkg from "../package.json" with { type: "json" };

import { config } from "./config";
Expand Down Expand Up @@ -63,7 +64,8 @@ const cli = new Command()
.command("history", historyCommand)
.command("tui", tuiCommand)
.command("delete", deleteNoteCommand)
.command("open", openCommand);
.command("open", openCommand)
.command("completions", new CompletionsCommand());

if (import.meta.main) {
await cli.parse(getCliArgs());
Expand Down
Loading