https://github.com/k1low/mo
mo is a Markdown viewer that opens .md files in a browser.
https://github.com/k1low/mo
markdown markdown-viewer
Last synced: 3 months ago
JSON representation
mo is a Markdown viewer that opens .md files in a browser.
- Host: GitHub
- URL: https://github.com/k1low/mo
- Owner: k1LoW
- License: mit
- Created: 2026-02-27T10:49:43.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-03-04T05:07:00.000Z (4 months ago)
- Last Synced: 2026-03-04T10:31:50.529Z (4 months ago)
- Topics: markdown, markdown-viewer
- Language: TypeScript
- Homepage:
- Size: 2.31 MB
- Stars: 52
- Watchers: 0
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# mo
[](https://github.com/k1LoW/mo/actions/workflows/ci.yml)   
`mo` is a **M**arkdown viewer that **o**pens `.md` files in a browser.
## Features
- GitHub-flavored Markdown (tables, task lists, footnotes, etc.)
- Syntax highlighting ([Shiki](https://shiki.style/))
- [Mermaid](https://mermaid.js.org/) diagram rendering
- LaTeX math rendering ([KaTeX](https://katex.org/))
- [GitHub Alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) (admonitions)
- Fullscreen zoom modal for images and Mermaid diagrams
-
Dark /
light theme
-
File grouping
-
Table of contents panel
-
Flat /
tree sidebar view with drag-and-drop reorder
-
File name /
heading title sidebar display toggle (per-group)
-
Full-text search across file names and content
- YAML frontmatter display (collapsible metadata block)
- MDX file support (renders as Markdown, strips `import`/`export`, escapes JSX tags)
-
Wide /
narrow content width toggle
-
Raw markdown view
-
Copy content (Markdown / Text / HTML)
-
Server restart with session preservation
- Auto session backup and restore
- Drag-and-drop file addition from the OS file manager (content is loaded in-memory; live-reload is not supported for dropped files)
- Live-reload on save (for files opened via CLI)
## Install
**homebrew tap:**
```console
$ brew install k1LoW/tap/mo
```
**manually:**
Download binary from [releases page](https://github.com/k1LoW/mo/releases)
## Usage
``` console
$ mo README.md # Open a single file
$ mo README.md CHANGELOG.md docs/*.md # Open multiple files
$ mo docs/ # Open all .md files in a directory
$ mo spec.md --target design # Open in a named group
```
`mo` opens Markdown files in a browser with live-reload. When you save a file, the browser automatically reflects the changes.
### Single server, multiple files
By default, `mo` runs a single server on port `6275`. If a server is already running on the same port, subsequent `mo` invocations add files to the existing session instead of starting a new one.
``` console
$ mo README.md # Starts a mo server in the background
$ mo CHANGELOG.md # Adds the file to the running mo server
```
To run a completely separate session, use a different port:
``` console
$ mo draft.md -p 6276
```

### Groups
Files can be organized into named groups using the `--target` (`-t`) flag. Each group gets its own URL path and sidebar.
``` console
$ mo spec.md --target design # Opens at http://localhost:6275/design
$ mo api.md --target design # Adds to the "design" group
$ mo notes.md --target notes # Opens at http://localhost:6275/notes
```

### Glob pattern watching
Use `--watch` (`-w`) to specify glob patterns. Matching files are opened automatically, and watched directories are monitored for new files.
``` console
$ mo --watch '**/*.md' # Watch and open all .md files recursively
$ mo --watch 'docs/**/*.md' --target docs # Watch docs/ tree in "docs" group
$ mo --watch '*.md' --watch 'docs/**/*.md' # Multiple patterns
```
When a directory is passed with `--watch`, it is automatically converted to a `dir/*.md` watch pattern:
``` console
$ mo --watch docs/ # Equivalent to mo --watch 'docs/*.md'
```
`--watch` cannot be combined with file arguments. The `**` pattern matches directories recursively.
#### Removing watch patterns
Use `--unwatch` to stop watching a previously registered pattern. Files already added remain in the sidebar.
``` console
$ mo --unwatch '**/*.md' # Stop watching a pattern (default group)
$ mo --unwatch 'docs/**/*.md' --target docs # Stop watching in a specific group
$ mo --unwatch '/Users/you/project/**/*.md' # Stop watching by absolute path
```
Patterns are resolved to absolute paths before matching, so you can specify either a relative glob or the full path shown by `--status`.
### Sidebar view modes
The sidebar supports flat and tree view modes. Flat view shows file names only, while tree view displays the directory hierarchy.
|
Flat |
Tree |
|------|------|
|  |  |
### Starting and stopping
`mo` runs in the background by default — the command returns immediately, leaving the shell free for other work. This makes it easy to incorporate into scripts, tool chains, or LLM-driven workflows.
``` console
$ mo README.md
mo: serving at http://localhost:6275 (pid 12345)
$ # shell is available immediately
```
Use `--status` to check all running mo servers, and `--shutdown` to stop one:
``` console
$ mo --status # Show all running mo servers
http://localhost:6275 (pid 12345, v0.12.0)
default: 5 file(s)
watching: /Users/you/project/src/**/*.md, /Users/you/project/*.md
docs: 2 file(s)
watching: /Users/you/project/docs/**/*.md
$ mo --shutdown # Shut down the mo server on the default port
$ mo --shutdown -p 6276 # Shut down the mo server on a specific port
$ mo --restart # Restart the mo server on the default port
```
If you need the mo server to run in the foreground (e.g. for debugging), use `--foreground`:
``` console
$ mo --foreground README.md
```
### Server restart
Click the
restart button (bottom-right corner) or run `mo --restart` to restart the `mo` server process. The current session — all open files and groups — is preserved across the restart. This is useful when you have updated the `mo` binary and want to pick up the new version without re-opening your files.
### Session backup and restore
`mo` automatically saves session state (open files and watch patterns per group) when files are added or removed. When starting a new server, the previous session is automatically restored and merged with any files specified on the command line. Restored session entries appear first, followed by newly specified files.
``` console
$ mo README.md CHANGELOG.md # Start with two files
$ mo --shutdown # Shut down the server
$ mo # Restores README.md and CHANGELOG.md
$ mo TODO.md # Restores previous session + adds TODO.md
```
Use `--close` to remove specific files from the running server:
``` console
$ mo --close README.md # Close a file from the default group
$ mo --close docs/*.md -t docs # Close files from the "docs" group
```
Use `--clear` to remove a saved session. If a server is running, it is automatically restarted with an empty state:
``` console
$ mo --clear # Clear saved session for the default port
$ mo --clear -p 6276 # Clear saved session for a specific port
```
### JSON output
Use `--json` to get structured JSON output on stdout, useful for scripting and integration with other tools.
``` console
$ mo --json README.md
{
"url": "http://localhost:6275",
"files": [
{
"url": "http://localhost:6275/?file=a1b2c3d4",
"name": "README.md",
"path": "/Users/you/project/README.md"
}
]
}
```
`--status` also supports `--json`:
``` console
$ mo --status --json
[
{
"url": "http://localhost:6275",
"status": "running",
"pid": 12345,
"version": "0.15.0",
"revision": "abc1234",
"groups": [
{
"name": "default",
"files": 3,
"patterns": ["**/*.md"]
}
]
}
]
```
### Flags
| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--target` | `-t` | `default` | Group name |
| `--port` | `-p` | `6275` | Server port |
| `--bind` | `-b` | `localhost` | Bind address (e.g. `0.0.0.0`) |
| `--open` | | | Always open browser |
| `--no-open` | | | Never open browser |
| `--status` | | | Show all running mo servers |
| `--watch` | `-w` | | Glob pattern to watch for matching files (repeatable) |
| `--unwatch` | | | Remove a watched glob pattern (repeatable) |
| `--close` | | | Close files instead of opening them |
| `--shutdown` | | | Shut down the running mo server |
| `--restart` | | | Restart the running mo server |
| `--clear` | | | Clear saved session (restarts server if running) |
| `--foreground` | | | Run mo server in foreground |
| `--json` | | | Output structured data as JSON to stdout |
| `--dangerously-allow-remote-access` | | | Allow remote access without authentication (trusted networks only) |
> [!WARNING]
> Binding to a non-localhost address exposes mo to the network **without any authentication**. Remote clients can read any file accessible by the user, browse the filesystem via glob patterns, and shut down the server. A confirmation prompt is shown when `--bind` is set to a non-loopback address.
## Build
Requires Go and [pnpm](https://pnpm.io/).
``` console
$ make build
```
## References
- [yusukebe/gh-markdown-preview](https://github.com/yusukebe/gh-markdown-preview): GitHub CLI extension to preview Markdown looks like GitHub.
## License
- [MIT License](LICENSE)
- Include logo as well as source code.
- Only logo license can be selected [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
- Also, if there is no alteration to the logo and it is used for technical information about mo, I would not say anything if the copyright notice is omitted.