claw-mo-open
Add a specific file, directory, or piped markdown content to the running mo server and open the browser directly on that file.
For config schema, HTTP API, deep-linking, and browser opening: read ${CLAUDE_PLUGIN_ROOT}/references/shared.md
Arguments
$ARGUMENTS— one of:- File path:
docs/spec.md - Directory:
docs/(added as a watch pattern) -or--stdin: read markdown from stdin (e.g.,cat notes.md | /claw-mo-open -)- Optional
--group <name>to pin the target group (otherwise auto-detected)
- File path:
- Examples:
/claw-mo-open docs/spec.md/claw-mo-open plans/ --group planssome-tool | /claw-mo-open - --group scratch
Steps
Parse
$ARGUMENTS:- Detect
--stdinor a bare-→ stdin mode - Otherwise resolve file/dir path with
realpath - Extract
--group; if absent, auto-detect from config (match the file path against each group's patterns, fall back todefault)
- Detect
Prerequisites:
command -v mo >/dev/null 2>&1.Project key:
git rev-parse --show-toplevel(fallback:$PWD).Read config from
${CLAUDE_PLUGIN_DATA}/config.json.Check running server:
mo --status --json→ is a server on$PORT?If server is running AND config exists — verify sync before mutating:
- Compare live group→patterns to saved config (see
shared.md) - If drifted: tell the user that
/claw-mo-upwould clear+rebuild this runtime; ask whether to resync first or add into the drifted runtime - If they resync: clear, restart from config, then continue
- If they decline: continue but warn the change won't survive the next
/claw-mo-upunless config is updated
- Compare live group→patterns to saved config (see
Add the content based on mode:
(a) File path, server running:
curl -s -X POST "http://localhost:$PORT/_/api/groups/$GROUP/files" \ -H 'Content-Type: application/json' \ -d "{\"path\": \"$(realpath file.md)\"}"(b) Directory, server running:
curl -s -X POST "http://localhost:$PORT/_/api/patterns" \ -H 'Content-Type: application/json' \ -d "{\"pattern\": \"$(realpath dir)/**/*.md\", \"group\": \"$GROUP\"}"(c) Stdin, server running: mo's single-instance detection pushes stdin content to the running server automatically:
cat | mo --no-open -p $PORT -t "$GROUP"(d) Server NOT running:
- Has config → perform
/claw-mo-upbehavior first (restart if server reappears mid-flight), then retry step 7 - No config → quick-open with auto-config:
- Auto-assign port:
echo $((6300 + $(echo "$PROJECT_ROOT" | cksum | cut -d' ' -f1) % 100)) - Start mo:
- File:
mo --no-open -p $PORT "$(realpath file.md)" - Dir:
mo --no-open -p $PORT "$(realpath dir)"(mo converts dir →dir/*.mdwatch) - Stdin:
cat | mo --no-open -p $PORT
- File:
- Save minimal config to
${CLAUDE_PLUGIN_DATA}/config.json:{ "PROJECT_ROOT": { "port": PORT, "groups": { "default": ["*.md"] } } } - Tell the user: "Saved a minimal config. Run
/claw-mo-setupto customize watch groups."
- Auto-assign port:
- Has config → perform
Resolve deep-link URL — try to open directly on the added file, not just the group:
File mode:
FILE_ID=$(curl -s "http://localhost:$PORT/_/api/groups" | python3 -c " import sys, json, os target = '$(realpath file.md)' for g in json.load(sys.stdin): for f in g.get('files', []): if f.get('path') == target: print(f['id']); break ") URL="http://localhost:$PORT/$GROUP" [ -n "$FILE_ID" ] && URL="$URL?file=$FILE_ID"Stdin mode: mo generates
stdin-<hash>.md. Look up its ID the same way, matching by name prefixstdin-.Directory mode: no single file to link to; use
http://localhost:$PORT/$GROUP.Open browser using the cmux-preferred logic from
shared.md(reuse existing surface if one targets this port).Report — what was added (path or
stdin-<hash>.md), which group, whether the session was reused/resynced, the resolved URL.
Gotchas
- HTTP API needs absolute paths — always
realpathbefore sending. - Compare live to config before reusing a running session — matching port or group names alone doesn't prove correctness.
- Drift warning is a feature, not a chore: runtime-only additions get wiped by the next
/claw-mo-upunless persisted through/claw-mo-setupor/claw-mo-manage. - Directory args ≠ watch patterns at the API layer: the HTTP API requires you to form the glob (
dir/**/*.md) explicitly. mo's CLI does that conversion for free when you pass a dir as a positional arg — that's why quick-open uses the CLI form. - Deep-linking falls back gracefully: if the file ID lookup fails (file just added, async), opening
/GROUPstill works and the new file will appear in the sidebar via SSE. - Stdin content dedupes by hash: piping the same content twice reuses the existing entry (
stdin-<hash>.md). cat | morequires stdin to not be a TTY. Fine when a pipe is present; fails silently if Claude somehow passes an interactive stdin. The shell pipecat | moforces non-TTY.- Quick-open saves a minimal config so
/claw-mo-up,/claw-mo-down, and/claw-mo-managecan find the session. - If the group doesn't exist in mo yet, the API creates it. The group name becomes a URL path segment — keep it simple lowercase.
- Adding a file already in mo is safe — dedup by path.