{"id":45879638,"url":"https://github.com/k1low/mo","last_synced_at":"2026-04-10T01:23:20.840Z","repository":{"id":340978189,"uuid":"1168402468","full_name":"k1LoW/mo","owner":"k1LoW","description":"mo is a Markdown viewer that opens .md files in a browser.","archived":false,"fork":false,"pushed_at":"2026-03-04T05:07:00.000Z","size":2426,"stargazers_count":52,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-04T10:31:50.529Z","etag":null,"topics":["markdown","markdown-viewer"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/k1LoW.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"k1LoW","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2026-02-27T10:49:43.000Z","updated_at":"2026-03-04T09:38:38.000Z","dependencies_parsed_at":"2026-03-04T07:10:34.026Z","dependency_job_id":null,"html_url":"https://github.com/k1LoW/mo","commit_stats":null,"previous_names":["k1low/mo"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/k1LoW/mo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1LoW%2Fmo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1LoW%2Fmo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1LoW%2Fmo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1LoW%2Fmo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/k1LoW","download_url":"https://codeload.github.com/k1LoW/mo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k1LoW%2Fmo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30115662,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T03:40:26.266Z","status":"ssl_error","status_checked_at":"2026-03-05T03:39:15.902Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["markdown","markdown-viewer"],"created_at":"2026-02-27T13:30:20.589Z","updated_at":"2026-04-10T01:23:20.832Z","avatar_url":"https://github.com/k1LoW.png","language":"TypeScript","funding_links":["https://github.com/sponsors/k1LoW"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\n\u003cimg src=\"https://github.com/k1LoW/mo/raw/main/images/logo.svg\" width=\"120\" alt=\"mo\"\u003e\n\u003cbr\u003e\u003cbr\u003e\u003cbr\u003e\n\u003c/p\u003e\n\n# mo\n\n[![build](https://github.com/k1LoW/mo/actions/workflows/ci.yml/badge.svg)](https://github.com/k1LoW/mo/actions/workflows/ci.yml) ![Coverage](https://raw.githubusercontent.com/k1LoW/octocovs/main/badges/k1LoW/mo/coverage.svg) ![Code to Test Ratio](https://raw.githubusercontent.com/k1LoW/octocovs/main/badges/k1LoW/mo/ratio.svg) ![Test Execution Time](https://raw.githubusercontent.com/k1LoW/octocovs/main/badges/k1LoW/mo/time.svg)\n\n`mo` is a **M**arkdown viewer that **o**pens `.md` files in a browser.\n\n## Features\n\n- GitHub-flavored Markdown (tables, task lists, footnotes, etc.)\n- Syntax highlighting ([Shiki](https://shiki.style/))\n- [Mermaid](https://mermaid.js.org/) diagram rendering\n- LaTeX math rendering ([KaTeX](https://katex.org/))\n- [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)\n- Fullscreen zoom modal for images and Mermaid diagrams\n- \u003cimg src=\"images/icons/theme-light.svg\" width=\"16\" height=\"16\" alt=\"dark theme\"\u003e Dark / \u003cimg src=\"images/icons/theme-dark.svg\" width=\"16\" height=\"16\" alt=\"light theme\"\u003e light theme\n- \u003cimg src=\"images/icons/group.svg\" width=\"16\" height=\"16\" alt=\"group\"\u003e File grouping\n- \u003cimg src=\"images/icons/toc.svg\" width=\"16\" height=\"16\" alt=\"toc\"\u003e Table of contents panel\n- \u003cimg src=\"images/icons/view-flat.svg\" width=\"16\" height=\"16\" alt=\"flat view\"\u003e Flat / \u003cimg src=\"images/icons/view-tree.svg\" width=\"16\" height=\"16\" alt=\"tree view\"\u003e tree sidebar view with drag-and-drop reorder\n- \u003cimg src=\"images/icons/title-filename.svg\" width=\"16\" height=\"16\" alt=\"file name\"\u003e File name / \u003cimg src=\"images/icons/title-heading.svg\" width=\"16\" height=\"16\" alt=\"heading title\"\u003e heading title sidebar display toggle (per-group)\n- \u003cimg src=\"images/icons/search.svg\" width=\"16\" height=\"16\" alt=\"search\"\u003e Full-text search across file names and content\n- YAML frontmatter display (collapsible metadata block)\n- MDX file support (renders as Markdown, strips `import`/`export`, escapes JSX tags)\n- \u003cimg src=\"images/icons/width-expand.svg\" width=\"16\" height=\"16\" alt=\"wide view\"\u003e Wide / \u003cimg src=\"images/icons/width-compress.svg\" width=\"16\" height=\"16\" alt=\"narrow view\"\u003e narrow content width toggle\n- \u003cimg src=\"images/icons/raw.svg\" width=\"16\" height=\"16\" alt=\"raw\"\u003e Raw markdown view\n- \u003cimg src=\"images/icons/copy.svg\" width=\"16\" height=\"16\" alt=\"copy\"\u003e Copy content (Markdown / Text / HTML)\n- \u003cimg src=\"images/icons/restart.svg\" width=\"16\" height=\"16\" alt=\"restart\"\u003e Server restart with session preservation\n- Auto session backup and restore\n- Drag-and-drop file addition from the OS file manager (content is loaded in-memory; live-reload is not supported for dropped files)\n- Live-reload on save (for files opened via CLI)\n\n## Install\n\n**homebrew tap:**\n\n```console\n$ brew install k1LoW/tap/mo\n```\n\n**manually:**\n\nDownload binary from [releases page](https://github.com/k1LoW/mo/releases)\n\n## Usage\n\n``` console\n$ mo README.md                          # Open a single file\n$ mo README.md CHANGELOG.md docs/*.md   # Open multiple files\n$ mo docs/                              # Open all .md files in a directory\n$ mo spec.md --target design            # Open in a named group\n```\n\n`mo` opens Markdown files in a browser with live-reload. When you save a file, the browser automatically reflects the changes.\n\n### Single server, multiple files\n\nBy 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.\n\n``` console\n$ mo README.md          # Starts a mo server in the background\n$ mo CHANGELOG.md       # Adds the file to the running mo server\n```\n\nTo run a completely separate session, use a different port:\n\n``` console\n$ mo draft.md -p 6276\n```\n\n![Multiple files with sidebar](images/multiple-files.png)\n\n### Groups\n\nFiles can be organized into named groups using the `--target` (`-t`) flag. Each group gets its own URL path and sidebar.\n\n``` console\n$ mo spec.md --target design      # Opens at http://localhost:6275/design\n$ mo api.md --target design       # Adds to the \"design\" group\n$ mo notes.md --target notes      # Opens at http://localhost:6275/notes\n```\n\n![Group view](images/groups.png)\n\n### Glob pattern watching\n\nUse `--watch` (`-w`) to specify glob patterns. Matching files are opened automatically, and watched directories are monitored for new files.\n\n``` console\n$ mo --watch '**/*.md'                          # Watch and open all .md files recursively\n$ mo --watch 'docs/**/*.md' --target docs       # Watch docs/ tree in \"docs\" group\n$ mo --watch '*.md' --watch 'docs/**/*.md'      # Multiple patterns\n```\n\nWhen a directory is passed with `--watch`, it is automatically converted to a `dir/*.md` watch pattern:\n\n``` console\n$ mo --watch docs/                             # Equivalent to mo --watch 'docs/*.md'\n```\n\n`--watch` cannot be combined with file arguments. The `**` pattern matches directories recursively.\n\n#### Removing watch patterns\n\nUse `--unwatch` to stop watching a previously registered pattern. Files already added remain in the sidebar.\n\n``` console\n$ mo --unwatch '**/*.md'                              # Stop watching a pattern (default group)\n$ mo --unwatch 'docs/**/*.md' --target docs            # Stop watching in a specific group\n$ mo --unwatch '/Users/you/project/**/*.md'            # Stop watching by absolute path\n```\n\nPatterns are resolved to absolute paths before matching, so you can specify either a relative glob or the full path shown by `--status`.\n\n### Sidebar view modes\n\nThe sidebar supports flat and tree view modes. Flat view shows file names only, while tree view displays the directory hierarchy.\n\n| \u003cimg src=\"images/icons/view-flat.svg\" height=\"16\"\u003e Flat | \u003cimg src=\"images/icons/view-tree.svg\" height=\"16\"\u003e Tree |\n|------|------|\n| ![Flat view](images/sidebar-flat.png) | ![Tree view](images/sidebar-tree.png) |\n\n### Starting and stopping\n\n`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.\n\n``` console\n$ mo README.md\nmo: serving at http://localhost:6275 (pid 12345)\n$ # shell is available immediately\n```\n\nUse `--status` to check all running mo servers, and `--shutdown` to stop one:\n\n``` console\n$ mo --status              # Show all running mo servers\nhttp://localhost:6275 (pid 12345, v0.12.0)\n  default: 5 file(s)\n    watching: /Users/you/project/src/**/*.md, /Users/you/project/*.md\n  docs: 2 file(s)\n    watching: /Users/you/project/docs/**/*.md\n\n$ mo --shutdown            # Shut down the mo server on the default port\n$ mo --shutdown -p 6276    # Shut down the mo server on a specific port\n$ mo --restart             # Restart the mo server on the default port\n```\n\nIf you need the mo server to run in the foreground (e.g. for debugging), use `--foreground`:\n\n``` console\n$ mo --foreground README.md\n```\n\n### Server restart\n\nClick the \u003cimg src=\"images/icons/restart.svg\" width=\"16\" height=\"16\" alt=\"restart\"\u003e 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.\n\n### Session backup and restore\n\n`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.\n\n``` console\n$ mo README.md CHANGELOG.md       # Start with two files\n$ mo --shutdown                   # Shut down the server\n$ mo                              # Restores README.md and CHANGELOG.md\n$ mo TODO.md                      # Restores previous session + adds TODO.md\n```\n\nUse `--close` to remove specific files from the running server:\n\n``` console\n$ mo --close README.md            # Close a file from the default group\n$ mo --close docs/*.md -t docs    # Close files from the \"docs\" group\n```\n\nUse `--clear` to remove a saved session. If a server is running, it is automatically restarted with an empty state:\n\n``` console\n$ mo --clear                      # Clear saved session for the default port\n$ mo --clear -p 6276              # Clear saved session for a specific port\n```\n\n### JSON output\n\nUse `--json` to get structured JSON output on stdout, useful for scripting and integration with other tools.\n\n``` console\n$ mo --json README.md\n{\n  \"url\": \"http://localhost:6275\",\n  \"files\": [\n    {\n      \"url\": \"http://localhost:6275/?file=a1b2c3d4\",\n      \"name\": \"README.md\",\n      \"path\": \"/Users/you/project/README.md\"\n    }\n  ]\n}\n```\n\n`--status` also supports `--json`:\n\n``` console\n$ mo --status --json\n[\n  {\n    \"url\": \"http://localhost:6275\",\n    \"status\": \"running\",\n    \"pid\": 12345,\n    \"version\": \"0.15.0\",\n    \"revision\": \"abc1234\",\n    \"groups\": [\n      {\n        \"name\": \"default\",\n        \"files\": 3,\n        \"patterns\": [\"**/*.md\"]\n      }\n    ]\n  }\n]\n```\n\n### Flags\n\n| Flag | Short | Default | Description |\n|------|-------|---------|-------------|\n| `--target` | `-t` | `default` | Group name |\n| `--port` | `-p` | `6275` | Server port |\n| `--bind` | `-b` | `localhost` | Bind address (e.g. `0.0.0.0`) |\n| `--open` | | | Always open browser |\n| `--no-open` | | | Never open browser |\n| `--status` | | | Show all running mo servers |\n| `--watch` | `-w` | | Glob pattern to watch for matching files (repeatable) |\n| `--unwatch` | | | Remove a watched glob pattern (repeatable) |\n| `--close` | | | Close files instead of opening them |\n| `--shutdown` | | | Shut down the running mo server |\n| `--restart` | | | Restart the running mo server |\n| `--clear` | | | Clear saved session (restarts server if running) |\n| `--foreground` | | | Run mo server in foreground |\n| `--json` | | | Output structured data as JSON to stdout |\n| `--dangerously-allow-remote-access` | | | Allow remote access without authentication (trusted networks only) |\n\n\u003e [!WARNING]\n\u003e 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.\n\n## Build\n\nRequires Go and [pnpm](https://pnpm.io/).\n\n``` console\n$ make build\n```\n\n## References\n\n- [yusukebe/gh-markdown-preview](https://github.com/yusukebe/gh-markdown-preview): GitHub CLI extension to preview Markdown looks like GitHub.\n\n## License\n\n- [MIT License](LICENSE)\n    - Include logo as well as source code.\n    - Only logo license can be selected [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).\n    - 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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk1low%2Fmo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fk1low%2Fmo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk1low%2Fmo/lists"}