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
6415 skills3 agents1 MCP
Install
$ npx -y skills add 7xuanlu/wenlan --skill run-wenlan --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/run-wenlan

Context preview

The summary Claude sees to decide when to auto-load this skill.

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.

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. Isolating the port and `WENLAN_DATA_DIR` is not enough: the default pages folder is `.wenlan/pages` under the OS user-home, NOT under `WENLAN_DATA_DIR`, so a capture will write into the user's real notes unless `knowledge_path` is set explicitly. Write the scratch `config.json` BEFORE the daemon starts, then read the live value back from `/api/knowledge/path` — the daemon reloads config per request, so a value written afterwards proves nothing about what was already ingested.

`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 cannot read instead of reporting the process absent. All of it lives in `ps_w_row_for`, the single validated `ps -W` parse in the repository:

. scripts/lib/host-process.sh

rc=0
row="$(ps_w_row_for PID "$JOB_PID")" || rc=$?
case "$rc" in
Read more
Ships withwenlan

Wenlan is a knowledge base for the AI-native age. Your AI agents capture what they learn, Wenlan keeps it current and distills it into source-cited wiki pages you can trust

Get the whole plugin

Other skills on wenlan.

prove
Skill

prove

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

@7xuanlu@7xuanluView Skill
verify
Skill

verify

Drive/evidence recipe for verifying wenlan changes at their real surfaces (daemon HTTP, CLI, MCP stdio). The handle file the built-in verify protocol expects;…

@7xuanlu@7xuanluView Skill
brief
Skill

brief

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

@7xuanlu@7xuanluView Skill
capture
Skill

capture

Save a durable memory to Wenlan from Codex. Use proactively when the user states a preference, makes a decision, corrects you, or shares a durable fact.…

@7xuanlu@7xuanluView Skill
curate
Skill

curate

Review pending Wenlan captures, revisions, or daemon refinements from Codex. Use for explicit audit walks after /brief or /handoff surfaces pending work.…

@7xuanlu@7xuanluView Skill