From 7372c61ccc1ddc7a5726fa45d7bcd1952f80c7bf Mon Sep 17 00:00:00 2001 From: patakuti Date: Sat, 3 Oct 2026 11:04:19 +0900 Subject: [PATCH] Split reference sections out of the README into docs/ README keeps the pitch, comparison, security summary, installation and contributing. Usage reference, the Claude Code conversation recipe and the private repository guide move to docs/. Content is moved, not rewritten. Co-Authored-By: Claude Sonnet 5.5 --- README.md | 310 +------------------------------ docs/claude-code-conversation.md | 44 +++++ docs/private-repositories.md | 67 +++++++ docs/usage.md | 202 ++++++++++++++++++++ 4 files changed, 318 insertions(+), 305 deletions(-) create mode 100644 docs/claude-code-conversation.md create mode 100644 docs/private-repositories.md create mode 100644 docs/usage.md diff --git a/README.md b/README.md index 1f93c19..115ce82 100644 --- a/README.md +++ b/README.md @@ -120,252 +120,18 @@ When a file or URL is given as an argument, markdown-proxy checks if the server ## Use Cases -- **Reading a Claude Code conversation as it grows**: Combine a Claude Code `Stop` hook with live reload to keep the whole conversation open in the browser as rendered Markdown. It is updated after every response whether or not the agent decides to show anything, so you can scroll back through earlier turns and copy parts of them. See [Watching a Claude Code conversation](#watching-a-claude-code-conversation). +- **Reading a Claude Code conversation as it grows**: Combine a Claude Code `Stop` hook with live reload to keep the whole conversation open in the browser as rendered Markdown. It is updated after every response whether or not the agent decides to show anything, so you can scroll back through earlier turns and copy parts of them. See [Watching a Claude Code conversation](docs/claude-code-conversation.md). - **Reading any file that keeps changing**: A document you are writing, a generated report or any other file rewritten by a tool is re-rendered as it changes. - **Viewing PlantUML diagrams**: Render PlantUML embedded in Markdown that GitHub/GitLab don't display natively. - **Navigating RAG search reports**: Reports generated by tools like [Local Knowledge RAG MCP Server](https://github.com/patakuti/local-knowledge-rag-mcp) contain links to source documents. In markdown-proxy, open the report in one tab and click through references in new tabs. - **Browsing private repositories**: Access Markdown files from private GitHub/GitLab repos using your existing git credentials. - **Sharing a Markdown viewer with your team**: Run in remote mode with token authentication to let team members view documentation through a browser. -### Watching a Claude Code conversation +## Documentation -Claude Code stores each conversation as a JSONL transcript. A Claude Code `Stop` hook (it runs each time Claude finishes responding) can convert it to Markdown, and markdown-proxy re-renders the file as it changes. - -1. Copy [`docs/examples/claude-transcript-to-md.sh`](docs/examples/claude-transcript-to-md.sh) somewhere on your machine (it needs `jq`). It keeps your prompts and Claude's text replies; thinking, tool calls and tool results are left out. -2. Add the hook to `~/.claude/settings.json`. Choose where the output goes: - - | Output | Option | File | - |---|---|---| - | One fixed file | `--hook FILE` | `FILE` (always the latest conversation) | - | One file per workspace | `--hook --dir DIR --per workspace` | `DIR/.md` | - | One file per session | `--hook --dir DIR --per session` | `DIR//.md` | - - `` is the name of the directory the session was started in. Example with a fixed file: - - ```json - { - "hooks": { - "Stop": [ - { - "hooks": [ - { - "type": "command", - "command": "/path/to/claude-transcript-to-md.sh --hook ~/claude-conversation.md", - "async": true - } - ] - } - ] - } - } - ``` - - `"async": true` matters: the `Stop` hook can fire before Claude Code has written the final response to the transcript, so the script waits one second before reading it. Asynchronous execution keeps that wait from blocking anything. - -3. Open the output file once; it refreshes after each response: - - ```bash - markdown-proxy ~/claude-conversation.md - ``` - -The file is rewritten from the whole transcript every time, so it never has gaps. Directories are created for `--dir`, but not for a fixed `FILE`, so a mistyped path fails with an error. To convert an existing transcript once, run `claude-transcript-to-md.sh ~/.claude/projects//.jsonl > conversation.md`. - -## URL Scheme - -| Type | URL Format | -|------|-----------| -| Top page | `http://localhost:9080/` | -| Local file | `http://localhost:9080/local/path/to/file.md` | -| Local directory | `http://localhost:9080/local/path/to/dir/` | -| Remote (HTTP) | `http://localhost:9080/http/server/path/to/file.md` | -| Remote (HTTPS) | `http://localhost:9080/https/server/path/to/file.md` | -| GitHub repo | `http://localhost:9080/https/github.com/user/repo/blob/main/README.md` | - -### Line Anchor Links - -Markdown and text files support line-level linking using the `file:line` syntax: - -- `[text](foo.md:12)` — rewritten to a link to `foo.md#L12` (line 12 of `foo.md`) -- `[text](foo.md:12-34)` — rewritten to `foo.md#L12-L34` (lines 12–34) -- `[text](foo.txt:12)` — rewritten to `foo.txt#L12` (line 12 of `foo.txt`) -- `text` — same, using raw HTML - -When navigating to a line anchor (`#L12` or `#L12-L34`), the page scrolls to the target line and highlights the surrounding content. For text files, individual lines are highlighted; for Markdown files, the containing block element is highlighted. Highlighting is hidden in print output. - -## Usage - -```bash -markdown-proxy [options] [file-or-url] -``` - -When `file-or-url` is provided: -- **Local file**: Opens the file via the proxy (relative paths are resolved automatically) - - `markdown-proxy README.md` - - `markdown-proxy ../docs/design.md` - - `markdown-proxy /absolute/path/to/file.md` -- **Remote URL**: Opens the URL via the proxy - - `markdown-proxy https://github.com/user/repo` -- If the server is not already running, it is started automatically in the background -- The file is opened in the default browser (`xdg-open` on Linux, `start` on Windows, `open` on macOS) - -### Options - -> **Note:** Options use a single dash (e.g., `-port`) following Go's `flag` package convention. Double dashes (`--port`) also work. - -| Flag | Description | Default | -|------|-------------|---------| -| `-port`, `-p` | Listen port | `9080` | -| `-listen` | Bind address (`127.0.0.1` for local, `0.0.0.0` for remote) | `127.0.0.1` | -| `-theme` | Default CSS theme name (any file in the themes directory) | `github` | -| `-plantuml-server` | PlantUML server URL | (disabled) | -| `-auth-token` | Authentication token (required in remote mode) | | -| `-auth-cookie-max-age` | Authentication cookie max age in days | `30` | -| `-access-log` | Access log file path | | -| `-access-log-max-size` | Max log file size in MB before rotation | `100` | -| `-access-log-max-backups` | Max number of old log files to retain | `3` | -| `-access-log-max-age` | Max days to retain old log files | `28` | -| `-verbose`, `-v` | Enable debug logging to stderr | `false` | -| `-configure` | Interactively create configuration file | | -| `-version` | Show version and exit | | - -## Configuration File - -Settings can be saved to a configuration file so you don't need to pass flags every time. - -### Interactive Setup - -```bash -markdown-proxy --configure -``` - -This walks you through each setting interactively and saves the result. - -### File Location - -| Platform | Path | -|----------|------| -| Linux | `~/.config/markdown-proxy/config.json` | -| macOS | `~/Library/Application Support/markdown-proxy/config.json` | -| Windows | `%APPDATA%/markdown-proxy/config.json` | - -### Supported Settings - -The configuration file stores these settings as JSON: - -```json -{ - "plantuml-server": "https://www.plantuml.com/plantuml", - "theme": "dark", - "port": 9080, - "listen": "127.0.0.1" -} -``` - -Command-line flags override configuration file values. Security-sensitive settings (`-auth-token`, `-access-log`, etc.) are not stored in the config file. - -## CSS Themes - -markdown-proxy supports user-defined CSS themes in addition to the three built-in themes. - -### Theme Directory - -| Platform | Path | -|----------|------| -| Linux | `~/.config/markdown-proxy/themes/` | -| macOS | `~/Library/Application Support/markdown-proxy/themes/` | -| Windows | `%APPDATA%/markdown-proxy/themes/` | - -On first launch, the three built-in themes are written here as editable CSS files: - -- `github.css` — GitHub-style light theme -- `simple.css` — Serif light theme -- `dark.css` — Dark theme - -### Adding a Custom Theme - -1. Create a `.css` file in the themes directory, e.g. `~/.config/markdown-proxy/themes/mycolor.css` -2. Write standard CSS (no special scoping required — the file is loaded as the sole active stylesheet) -3. Restart markdown-proxy (or simply open a new page — the theme list is read at startup) -4. Select `mycolor` from the Theme dropdown - -**Example:** - -```css -body { font-family: "Source Serif Pro", serif; color: #1a1a1a; background: #fffff8; } -.toolbar { background: #f0ece0; border-color: #c8bfa0; } -.home-link, .toolbar-link { color: #8b4513; } -.markdown-body a { color: #8b4513; } -.markdown-body pre { background: #f5f0e8; border: 1px solid #c8bfa0; overflow: auto; } -.markdown-body pre code { background: none; padding: 0; font-size: 100%; } -.copy-btn { background: #fff; color: #444; border-color: #c8bfa0; } -.copy-btn:hover { background: #f0ece0; } -.copy-btn.copied { background: #d4edda; color: #155724; border-color: #c3e6cb; } -.toc-panel { background: #f5f0e8; border-left-color: #c8bfa0; } -.toc-header { border-bottom-color: #c8bfa0; } -.toc-list a.active { border-left-color: #8b4513; background: rgba(139,69,19,0.08); } -``` - -You can also edit the built-in themes directly — changes take effect on the next request (the file is read from disk on each theme CSS request). - -## Operation Modes - -### Local Mode (default) - -```bash -markdown-proxy -``` - -The server binds to `127.0.0.1` and all features are available: -- Local file access (`/local/...`) -- Remote file access (`/http/...`, `/https/...`) -- Live reload via SSE (`/_sse`) -- Private network access is allowed for remote file fetching - -### Remote Mode - -```bash -markdown-proxy -listen 0.0.0.0 -auth-token my-secret-token -``` - -The server binds to the specified address for network access. For security: -- **Local file access is disabled**: `/local/` and `/_sse` return 403 Forbidden -- **Authentication is required**: `-auth-token` must be specified -- **Private network access is blocked**: SSRF protection prevents fetching from internal IPs -- **Top page** shows URL input only (no local file path input) - -Users must authenticate via a login page (`/_login`) by entering the access token. The token is stored in an HttpOnly cookie for the configured duration. - -## Access Logging - -Access logs record each request in the following format: - -``` -2026-02-22T15:04:05+09:00 192.168.1.10 GET /https/github.com/user/repo 200 1234 150ms -``` - -- `-access-log /var/log/mdproxy/access.log`: Log to a file with automatic rotation -- In remote mode without `-access-log`: Logs to stdout by default -- In local mode without `-access-log`: No access logging - -Log rotation is handled automatically using configurable size, count, and age limits. - -## Live Reload - -When viewing local Markdown files or directories (`/local/...`), the browser automatically reloads when the file or directory contents change. This uses Server-Sent Events (SSE) with filesystem notifications (fsnotify). - -- **Local files only**: Remote files (`/http/...`, `/https/...`) are not affected -- **Local mode only**: Not available in remote mode -- **No configuration needed**: Works automatically for all local file views -- **Debounced**: Multiple rapid changes are coalesced into a single reload (100ms debounce) - -## Math Rendering - -Mathematical expressions are rendered using [KaTeX](https://katex.org/). Use standard LaTeX syntax: - -- **Inline math**: `$E = mc^2$` renders inline within text -- **Display math**: `$$\int_0^\infty e^{-x} dx = 1$$` renders as a centered block - -No configuration needed. Math expressions are automatically detected and rendered. +- [Usage reference](docs/usage.md): command-line options, URL scheme and line anchor links, configuration file, CSS themes, local/remote modes, access logging, live reload, math rendering +- [Watching a Claude Code conversation](docs/claude-code-conversation.md): a `Stop` hook recipe for reading a conversation as it grows +- [Private repositories](docs/private-repositories.md): reading private GitHub/GitLab repositories with your git credentials ## Security @@ -383,72 +149,6 @@ No configuration needed. Math expressions are automatically detected and rendere Note that local mode serves any file the user can read under `/local/` (by design, so logs such as `~/.claude/` can be viewed). The protections above prevent other web content from reaching it through your browser. -## Private Repository Access - -markdown-proxy can access private repositories on GitHub and GitLab using your existing git credentials. When authentication is needed (e.g., 401, 403, or 404 from a private repo), markdown-proxy automatically invokes `git credential fill` to retrieve stored credentials. - -If credentials are not configured, an error page with setup guidance is displayed instead of a raw error message. - -### GitHub - -**Option A: GitHub CLI (recommended)** - -```bash -gh auth login -``` - -This configures the git credential helper automatically. - -**Option B: Personal Access Token** - -1. Create a token at https://github.com/settings/tokens (classic) or https://github.com/settings/tokens?type=beta (fine-grained) -2. Required scope: `repo` (classic) or repository read access (fine-grained) -3. Store it via git credential helper: - ```bash - echo -e "protocol=https\nhost=github.com\n" | git credential fill - ``` - If no credential is returned, configure a credential helper (e.g., `git config --global credential.helper store`) and save the token. - -### GitLab - -**gitlab.com:** - -```bash -glab auth login -``` - -**Self-hosted GitLab:** - -`glab auth login --hostname` may not work on some self-hosted instances. If authentication fails, use a Personal Access Token (PAT) instead: - -1. Create a PAT at Settings > Access Tokens with `read_repository` scope -2. Register it with glab: - ```bash - glab auth login --hostname gitlab.example.com --token - ``` - -This stores the PAT in git's credential helper, which markdown-proxy uses automatically. - -### Organization-specific Credentials - -If you need different credentials for specific organizations, use path-based credential configuration: - -```gitconfig -[credential "https://github.com/my-org"] - helper = !gh auth git-credential - useHttpPath = true -``` - -### Verifying Credentials - -To verify that git can provide credentials for a host: - -```bash -echo -e "protocol=https\nhost=github.com\n" | git credential fill -``` - -This should output `username` and `password` fields. If nothing is returned, credentials are not configured for that host. - ## Installation ### Download diff --git a/docs/claude-code-conversation.md b/docs/claude-code-conversation.md new file mode 100644 index 0000000..82642cc --- /dev/null +++ b/docs/claude-code-conversation.md @@ -0,0 +1,44 @@ +[← Back to README](../README.md) + +# Watching a Claude Code conversation + +Claude Code stores each conversation as a JSONL transcript. A Claude Code `Stop` hook (it runs each time Claude finishes responding) can convert it to Markdown, and markdown-proxy re-renders the file as it changes. + +1. Copy [`examples/claude-transcript-to-md.sh`](examples/claude-transcript-to-md.sh) somewhere on your machine (it needs `jq`). It keeps your prompts and Claude's text replies; thinking, tool calls and tool results are left out. +2. Add the hook to `~/.claude/settings.json`. Choose where the output goes: + + | Output | Option | File | + |---|---|---| + | One fixed file | `--hook FILE` | `FILE` (always the latest conversation) | + | One file per workspace | `--hook --dir DIR --per workspace` | `DIR/.md` | + | One file per session | `--hook --dir DIR --per session` | `DIR//.md` | + + `` is the name of the directory the session was started in. Example with a fixed file: + + ```json + { + "hooks": { + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "/path/to/claude-transcript-to-md.sh --hook ~/claude-conversation.md", + "async": true + } + ] + } + ] + } + } + ``` + + `"async": true` matters: the `Stop` hook can fire before Claude Code has written the final response to the transcript, so the script waits one second before reading it. Asynchronous execution keeps that wait from blocking anything. + +3. Open the output file once; it refreshes after each response: + + ```bash + markdown-proxy ~/claude-conversation.md + ``` + +The file is rewritten from the whole transcript every time, so it never has gaps. Directories are created for `--dir`, but not for a fixed `FILE`, so a mistyped path fails with an error. To convert an existing transcript once, run `claude-transcript-to-md.sh ~/.claude/projects//.jsonl > conversation.md`. diff --git a/docs/private-repositories.md b/docs/private-repositories.md new file mode 100644 index 0000000..cae46b9 --- /dev/null +++ b/docs/private-repositories.md @@ -0,0 +1,67 @@ +[← Back to README](../README.md) + +# Private Repository Access + +markdown-proxy can access private repositories on GitHub and GitLab using your existing git credentials. When authentication is needed (e.g., 401, 403, or 404 from a private repo), markdown-proxy automatically invokes `git credential fill` to retrieve stored credentials. + +If credentials are not configured, an error page with setup guidance is displayed instead of a raw error message. + +### GitHub + +**Option A: GitHub CLI (recommended)** + +```bash +gh auth login +``` + +This configures the git credential helper automatically. + +**Option B: Personal Access Token** + +1. Create a token at https://github.com/settings/tokens (classic) or https://github.com/settings/tokens?type=beta (fine-grained) +2. Required scope: `repo` (classic) or repository read access (fine-grained) +3. Store it via git credential helper: + ```bash + echo -e "protocol=https\nhost=github.com\n" | git credential fill + ``` + If no credential is returned, configure a credential helper (e.g., `git config --global credential.helper store`) and save the token. + +### GitLab + +**gitlab.com:** + +```bash +glab auth login +``` + +**Self-hosted GitLab:** + +`glab auth login --hostname` may not work on some self-hosted instances. If authentication fails, use a Personal Access Token (PAT) instead: + +1. Create a PAT at Settings > Access Tokens with `read_repository` scope +2. Register it with glab: + ```bash + glab auth login --hostname gitlab.example.com --token + ``` + +This stores the PAT in git's credential helper, which markdown-proxy uses automatically. + +### Organization-specific Credentials + +If you need different credentials for specific organizations, use path-based credential configuration: + +```gitconfig +[credential "https://github.com/my-org"] + helper = !gh auth git-credential + useHttpPath = true +``` + +### Verifying Credentials + +To verify that git can provide credentials for a host: + +```bash +echo -e "protocol=https\nhost=github.com\n" | git credential fill +``` + +This should output `username` and `password` fields. If nothing is returned, credentials are not configured for that host. diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..f1206d2 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,202 @@ +[← Back to README](../README.md) + +# Usage Reference + +Command-line options, URL scheme, configuration, themes, operation modes, access logging, live reload and math rendering. + +## URL Scheme + +| Type | URL Format | +|------|-----------| +| Top page | `http://localhost:9080/` | +| Local file | `http://localhost:9080/local/path/to/file.md` | +| Local directory | `http://localhost:9080/local/path/to/dir/` | +| Remote (HTTP) | `http://localhost:9080/http/server/path/to/file.md` | +| Remote (HTTPS) | `http://localhost:9080/https/server/path/to/file.md` | +| GitHub repo | `http://localhost:9080/https/github.com/user/repo/blob/main/README.md` | + +### Line Anchor Links + +Markdown and text files support line-level linking using the `file:line` syntax: + +- `[text](foo.md:12)` — rewritten to a link to `foo.md#L12` (line 12 of `foo.md`) +- `[text](foo.md:12-34)` — rewritten to `foo.md#L12-L34` (lines 12–34) +- `[text](foo.txt:12)` — rewritten to `foo.txt#L12` (line 12 of `foo.txt`) +- `text` — same, using raw HTML + +When navigating to a line anchor (`#L12` or `#L12-L34`), the page scrolls to the target line and highlights the surrounding content. For text files, individual lines are highlighted; for Markdown files, the containing block element is highlighted. Highlighting is hidden in print output. + +## Command Line + +```bash +markdown-proxy [options] [file-or-url] +``` + +When `file-or-url` is provided: +- **Local file**: Opens the file via the proxy (relative paths are resolved automatically) + - `markdown-proxy README.md` + - `markdown-proxy ../docs/design.md` + - `markdown-proxy /absolute/path/to/file.md` +- **Remote URL**: Opens the URL via the proxy + - `markdown-proxy https://github.com/user/repo` +- If the server is not already running, it is started automatically in the background +- The file is opened in the default browser (`xdg-open` on Linux, `start` on Windows, `open` on macOS) + +### Options + +> **Note:** Options use a single dash (e.g., `-port`) following Go's `flag` package convention. Double dashes (`--port`) also work. + +| Flag | Description | Default | +|------|-------------|---------| +| `-port`, `-p` | Listen port | `9080` | +| `-listen` | Bind address (`127.0.0.1` for local, `0.0.0.0` for remote) | `127.0.0.1` | +| `-theme` | Default CSS theme name (any file in the themes directory) | `github` | +| `-plantuml-server` | PlantUML server URL | (disabled) | +| `-auth-token` | Authentication token (required in remote mode) | | +| `-auth-cookie-max-age` | Authentication cookie max age in days | `30` | +| `-access-log` | Access log file path | | +| `-access-log-max-size` | Max log file size in MB before rotation | `100` | +| `-access-log-max-backups` | Max number of old log files to retain | `3` | +| `-access-log-max-age` | Max days to retain old log files | `28` | +| `-verbose`, `-v` | Enable debug logging to stderr | `false` | +| `-configure` | Interactively create configuration file | | +| `-version` | Show version and exit | | + +## Configuration File + +Settings can be saved to a configuration file so you don't need to pass flags every time. + +### Interactive Setup + +```bash +markdown-proxy --configure +``` + +This walks you through each setting interactively and saves the result. + +### File Location + +| Platform | Path | +|----------|------| +| Linux | `~/.config/markdown-proxy/config.json` | +| macOS | `~/Library/Application Support/markdown-proxy/config.json` | +| Windows | `%APPDATA%/markdown-proxy/config.json` | + +### Supported Settings + +The configuration file stores these settings as JSON: + +```json +{ + "plantuml-server": "https://www.plantuml.com/plantuml", + "theme": "dark", + "port": 9080, + "listen": "127.0.0.1" +} +``` + +Command-line flags override configuration file values. Security-sensitive settings (`-auth-token`, `-access-log`, etc.) are not stored in the config file. + +## CSS Themes + +markdown-proxy supports user-defined CSS themes in addition to the three built-in themes. + +### Theme Directory + +| Platform | Path | +|----------|------| +| Linux | `~/.config/markdown-proxy/themes/` | +| macOS | `~/Library/Application Support/markdown-proxy/themes/` | +| Windows | `%APPDATA%/markdown-proxy/themes/` | + +On first launch, the three built-in themes are written here as editable CSS files: + +- `github.css` — GitHub-style light theme +- `simple.css` — Serif light theme +- `dark.css` — Dark theme + +### Adding a Custom Theme + +1. Create a `.css` file in the themes directory, e.g. `~/.config/markdown-proxy/themes/mycolor.css` +2. Write standard CSS (no special scoping required — the file is loaded as the sole active stylesheet) +3. Restart markdown-proxy (or simply open a new page — the theme list is read at startup) +4. Select `mycolor` from the Theme dropdown + +**Example:** + +```css +body { font-family: "Source Serif Pro", serif; color: #1a1a1a; background: #fffff8; } +.toolbar { background: #f0ece0; border-color: #c8bfa0; } +.home-link, .toolbar-link { color: #8b4513; } +.markdown-body a { color: #8b4513; } +.markdown-body pre { background: #f5f0e8; border: 1px solid #c8bfa0; overflow: auto; } +.markdown-body pre code { background: none; padding: 0; font-size: 100%; } +.copy-btn { background: #fff; color: #444; border-color: #c8bfa0; } +.copy-btn:hover { background: #f0ece0; } +.copy-btn.copied { background: #d4edda; color: #155724; border-color: #c3e6cb; } +.toc-panel { background: #f5f0e8; border-left-color: #c8bfa0; } +.toc-header { border-bottom-color: #c8bfa0; } +.toc-list a.active { border-left-color: #8b4513; background: rgba(139,69,19,0.08); } +``` + +You can also edit the built-in themes directly — changes take effect on the next request (the file is read from disk on each theme CSS request). + +## Operation Modes + +### Local Mode (default) + +```bash +markdown-proxy +``` + +The server binds to `127.0.0.1` and all features are available: +- Local file access (`/local/...`) +- Remote file access (`/http/...`, `/https/...`) +- Live reload via SSE (`/_sse`) +- Private network access is allowed for remote file fetching + +### Remote Mode + +```bash +markdown-proxy -listen 0.0.0.0 -auth-token my-secret-token +``` + +The server binds to the specified address for network access. For security: +- **Local file access is disabled**: `/local/` and `/_sse` return 403 Forbidden +- **Authentication is required**: `-auth-token` must be specified +- **Private network access is blocked**: SSRF protection prevents fetching from internal IPs +- **Top page** shows URL input only (no local file path input) + +Users must authenticate via a login page (`/_login`) by entering the access token. The token is stored in an HttpOnly cookie for the configured duration. + +## Access Logging + +Access logs record each request in the following format: + +``` +2026-02-22T15:04:05+09:00 192.168.1.10 GET /https/github.com/user/repo 200 1234 150ms +``` + +- `-access-log /var/log/mdproxy/access.log`: Log to a file with automatic rotation +- In remote mode without `-access-log`: Logs to stdout by default +- In local mode without `-access-log`: No access logging + +Log rotation is handled automatically using configurable size, count, and age limits. + +## Live Reload + +When viewing local Markdown files or directories (`/local/...`), the browser automatically reloads when the file or directory contents change. This uses Server-Sent Events (SSE) with filesystem notifications (fsnotify). + +- **Local files only**: Remote files (`/http/...`, `/https/...`) are not affected +- **Local mode only**: Not available in remote mode +- **No configuration needed**: Works automatically for all local file views +- **Debounced**: Multiple rapid changes are coalesced into a single reload (100ms debounce) + +## Math Rendering + +Mathematical expressions are rendered using [KaTeX](https://katex.org/). Use standard LaTeX syntax: + +- **Inline math**: `$E = mc^2$` renders inline within text +- **Display math**: `$$\int_0^\infty e^{-x} dx = 1$$` renders as a centered block + +No configuration needed. Math expressions are automatically detected and rendered.