Skip to content
Documentation
Skill

/run-wenlan

Build, launch, and stop the wenlan daemon (wenlan-server) for local dev and verification. Use when asked to run or restart the daemon, or before driving any surface (HTTP, CLI, MCP) against a live instance.

From plugin
wenlan
8921 skills3 agents1 MCP

Claude Code

$ npx -y skills add wenlan-app/wenlan --skill run-wenlan --agent claude-code

SKILL.md

run-wenlan.SKILL.md
name: run-wenlan
description: Build, launch, and stop the wenlan daemon (wenlan-server) for local dev and verification. Use when asked to run or restart the daemon, or before driving any surface (HTTP, CLI, MCP) against a live instance.

Run wenlan-server (dev)

Build: `cargo build -p wenlan-server -p wenlan` (add `-p wenlan-mcp` for the MCP bridge).

Ports — one allocation, no guessing

Three ports exist and they are not interchangeable. Stopping "the isolated daemon" on the wrong one leaves a live daemon behind and reports success.

| Port | Owner | Notes | |---|---|---| | 7878 | the user's real daemon | never kill casually, never verify against | | 17878 | manual isolated instance (this skill) | the recipes below | | 17881 | `scripts/smoke-cli.sh` | `PORT=` overrides | | 17882 | `scripts/smoke-mcp.sh` | `PORT=` overrides; runs alongside the CLI smoke |

The smokes own their own ports so both can run at once. Do not repoint them at 17878 — a manual daemon and a smoke would then fight over one listener, and the smoke's ownership assertion would fail on a daemon it did not start.

Isolated instance (default for verification)

Never verify against the shared prod daemon on :7878 — dev and prod share the platform data dir by default. When `WENLAN_DATA_DIR` names any root other than the installed app's own, the default pages folder is `$WENLAN_DATA_DIR/pages`, and the daemon refuses to start if a `knowledge_path` points into the real `~/.wenlan/pages` (or a custom pages folder in the real config). Builds older than that fix used the real `~/.wenlan/pages` by default, so the recipe below still writes `knowledge_path` explicitly BEFORE the daemon starts. Then read the live value back from `/api/knowledge/path` and the `Wenlan pages folder:` startup log line. Use one absolute data dir for every command: on macOS the sandboxed and unsandboxed shells see different `TMPDIR`s, so a path derived from `TMPDIR` in one shell is a different folder in the other.

`WENLAN_NO_AUTOSTART=1` belongs on every harness command: without it a failed connect starts the user's registered background service.

DATA_DIR="$(mktemp -d "${TMPDIR:-/tmp}/run.XXXXXX")"
mkdir -p "$DATA_DIR/pages"
printf '{"knowledge_path":"%s"}' "$DATA_DIR/pages" >"$DATA_DIR/config.json.tmp"
mv "$DATA_DIR/config.json.tmp" "$DATA_DIR/config.json"   # atomic, before spawn
WENLAN_NO_AUTOSTART=1 WENLAN_PORT=17878 WENLAN_DATA_DIR="$DATA_DIR" \
  ./target/debug/wenlan-server &
# ready:  curl -sf --max-time 2 http://127.0.0.1:17878/api/health  (poll up to ~120s)
# check:  curl -sf http://127.0.0.1:17878/api/knowledge/path   → must be $DATA_DIR/pages
# stop:   lsof -ti :17878 | xargs kill -9

Sandbox gotcha: always give mktemp a template (`"${TMPDIR:-/tmp}/x.XXXXXX"`); bare `mktemp -d` lands in a denied dir on macOS.

Windows (Git Bash) — the same instance, four differences

`TMPDIR` is unset, `lsof` is absent, `$!` is not the pid the OS knows the daemon by, and an MSYS path is not a path the native daemon can open. Each one fails quietly in a different way, so none of them is optional.

# 1. mktemp has no TMPDIR to fall back on: give it an explicit template.
DATA_DIR="$(mktemp -d "${TMPDIR:-/tmp}/run.XXXXXX")"
mkdir -p "$DATA_DIR/pages"

# 2. TWO variables, not one rewritten one. The shell keeps the MSYS spelling for
#    its own `rm -rf`; the daemon is handed the native spelling. `cygpath -m`
#    converts at the daemon boundary ONLY: /tmp/run.EiVYlp →
#    C:/Users/<you>/AppData/Local/Temp/run.EiVYlp
NATIVE_DATA_DIR="$(cygpath -m "$DATA_DIR")"
NATIVE_PAGES_DIR="$(cygpath -m "$DATA_DIR/pages")"
printf '{"knowledge_path":"%s"}' "$NATIVE_PAGES_DIR" >"$DATA_DIR/config.json.tmp"
mv "$DATA_DIR/config.json.tmp" "$DATA_DIR/config.json"

WENLAN_NO_AUTOSTART=1 WENLAN_PORT=17878 WENLAN_DATA_DIR="$NATIVE_DATA_DIR" \
  /c/wl-target/debug/wenlan-server.exe &
JOB_PID=$!   # an MSYS job pid — NOT the pid netstat and tasklist report

**Listener check — source the library; do not hand-roll `netstat`.** There is no `lsof`, and the obvious `netstat -ano | awk ... $4=="LISTENING"` one-liner is NOT a substitute. It has two states where the question has three, and the state it cannot express is the dangerous one:

  • `netstat` missing, killed, or exiting non-zero → no matching row → reads as

**free**.

  • a non-English Windows → the State column says `ABHOEREN`, not `LISTENING` →

no matching row → reads as **free**, with the port genuinely busy.

  • an unexpected or truncated table → no matching row → reads as **free**.

Starting a second daemon on a port nobody measured is how two daemons end up sharing one data directory. `scripts/lib/host-process.sh` already answers this in three states, keys on the structural shape of a listening row rather than on the localised word, and validates that what it parsed really is the table. Use it, on Windows and POSIX alike:

. scripts/lib/host-process.sh

probe_listener_port 17878
case "$LISTENER_PROBE_STATE" in
  found)      echo "busy: pid $LISTENER_PROBE_PID"; exit 1 ;;
  none)       echo "measured free" ;;
  unmeasured) echo "COULD NOT MEASURE port 17878 — refusing to start"; exit 2 ;;
esac

Underneath is `listener_pid_for_port` (0 = found, 1 = measured free, 2 = could not measure); `probe_listener_port` is the wrapper that turns those into `LISTENER_PROBE_STATE`, because `out="$(f)"; rc=$?` aborts under `set -e` and `if out="$(f)"; then …; fi; rc=$?` reads the compound's status, which is 0. Branch on all three states every time. There is no fourth branch to add and no default that is safe to leave off.

**Resolve the real pid before killing anything.** `$!` is the MSYS job pid; the Windows pid is the `WINPID` column of `ps -W`, and the image is the `COMMAND` column read from the header's own offset — `STIME` is one token (`10:23:45`) or two (`Aug 27`), so a field-index parse shifts on every row for a process that outlived midnight. That parse also has to reject a table it c

Read more
@7xuanlu
Ships withwenlan

A living wiki your AI writes from your notes, code, AI chats (memories), and docs, checked against sources. It flags what it can’t back up and updates pages when sources change. Supports Claude, Codex, Obsidian...

8921 skills3 agents1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
89
Star history of 7xuanlu/wenlan on GitHub, a chart by star-history.com

Other skills on wenlan.

prove

prove

Per-surface verification loops for wenlan — daemon, cli, mcp, plugin, suite strength (mutation), behavior trace, weekly sweep.…

@7xuanlu@7xuanluInstall Skill
run-wenlan-app

run-wenlan-app

Build, launch, screenshot, and drive the wenlan-app Tauri desktop app in dev mode on macOS (WKWebView) or Windows (WebView2). Use…

@7xuanlu@7xuanluInstall Skill
verify

verify

Drive/evidence recipe for verifying wenlan changes at their real surfaces (daemon HTTP, CLI, MCP stdio). The handle file the…

@7xuanlu@7xuanluInstall Skill
wenlan-brief

wenlan-brief

Read the current Space-owned project Brief from Wenlan. With an optional topic, appends separately labeled related context from…

@7xuanlu@7xuanluInstall Skill
wenlan-capture

wenlan-capture

Save a memory to Wenlan in flow, or save something from this conversation as one note when the user asks for a note. Use…

@7xuanlu@7xuanluInstall Skill
wenlan-handoff

wenlan-handoff

End a work session. Stores durable captures, writes a narrative session log, and automatically applies typed item-level deltas to…

@7xuanlu@7xuanluInstall Skill

More skills from other plugins.

context7-cli

context7-cli

Use the ctx7 CLI to fetch library documentation and configure Context7 MCP. Activate when the user mentions "ctx7" or "context7",…

context711d64k
@upstash@upstashInstall Skill
docs-components

docs-components

Comprehensive MDX component patterns (Note, Pitfall, DeepDive, Recipes, etc.) for all documentation types. Authoritative source…

@reactjs@reactjsInstall Skill
codebase-wiki

codebase-wiki

How to work in a Codebase Wiki project (the `codebase-wiki` starter pack): an agent-authored, source-grounded wiki of the…

@inkeep@inkeepInstall Skill

Questions about run-wenlan.

Which coding agents can use run-wenlan?
run-wenlan installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.