Skip to main content

sillytavern-honcho-setup

Install the Honcho Memory extension + plugin into a SillyTavern checkout. Use when installing, re-installing, or troubleshooting the integration — including on a fresh SillyTavern checkout. Safe to re-run; every patch step is idempotent.

Source facts

Repository
plastic-labs/sillytavern-honcho
Last source activity
April 21, 2026 at 21:24
Detected SKILL.md language
English
Stars
8
Forks
2

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
sillytavern-honcho-setup
description
Install the Honcho Memory extension + plugin into a SillyTavern checkout. Use when installing, re-installing, or troubleshooting the integration — including on a fresh SillyTavern checkout. Safe to re-run; every patch step is idempotent.
allowed-tools
Read, Glob, Grep, Bash(npm:*), Bash(node:*), Bash(ln:*), Bash(ls:*), Bash(cd:*), Bash(cat:*), Bash(mkdir:*), Bash(cp:*), Bash(rm:*), Bash(git:*), Bash(curl:*), Bash(lsof:*), Bash(pgrep:*), Bash(kill:*), Bash(sleep:*), Edit, Write, AskUserQuestion
user-invocable
true
# Install the Honcho Memory extension into SillyTavern - Follow each phase in order. Do not skip preflight. - Verify every patch is idempotent with `grep -q` before running the Edit. - If any phase fails, stop and surface the failure — do not route around it. ## When to use / can be skipped Use when: setting up the integration on a new SillyTavern checkout, re-installing after a failed attempt, or diagnosing a broken install. Skip when: the install is already verified working (Phase 4 smoke test passes) and you don't need to change configuration. ## Skill discoverability (read this before invoking) This skill lives inside the `sillytavern-honcho` repo at `skills/setup/SKILL.md`. Claude Code does not auto-discover it. To invoke as `/sillytavern-honcho-setup` in a new session, either: 1. **Symlink into the project's `.claude/skills/` directory**, then restart the Claude Code session: ```bash mkdir -p <cwd>/.claude/skills/sillytavern-honcho-setup ln -sf <repo>/skills/setup/SKILL.md \ <cwd>/.claude/skills/sillytavern-honcho-setup/SKILL.md ``` 2. **Or read the file directly** and execute each phase as a checklist (what Path B's executor fell back to). The repo's README should document option 1 as the supported path. ## Phase 0 — Preflight Run these checks in parallel. If any fails, stop and report — do not proceed. ```bash PORT="${ST_PORT:-8000}" node --version # require >= 18 git --version # required [[ -d "$ST_DIR" ]] && git -C "$ST_DIR" status --short # expect clean tree [[ -d "$SH_DIR" ]] && git -C "$SH_DIR" branch --show-current # capture branch for logs lsof -i ":$PORT" -P 2>/dev/null | grep LISTEN # detect pre-existing SillyTavern on target port [[ -f ~/.honcho/config.json ]] && echo "global config present" ``` Where: - `$ST_DIR` = SillyTavern checkout. Ask the user if not set. - `$SH_DIR` = `sillytavern-honcho` checkout. Ask the user if not set. - `$ST_PORT` = SillyTavern's listen port. Defaults to 8000. Override (e.g. `ST_PORT=8099`) to run alongside an existing SillyTavern on 8000 without collision. ### Gate: pre-existing SillyTavern on the target port If `$PORT` is already listening, ask the user before proceeding. Running this skill will start a new server on the same port and can clobber their live session. Use **AskUserQuestion**: "A SillyTavern instance is already running on port `$PORT` (PID `<pid>`). I'll need to stop it to complete this install. Stop it? [yes / no — I'll pick a different port]". If the user picks a different port, re-run with `ST_PORT=<new-port>` exported — every `npm start` / `node server.js` / `curl` call below already honors `$ST_PORT`. ### Gate: existing vs cold-start user Use **AskUserQuestion** with two options: - **Existing Honcho user** — "I already use Honcho in another tool (Claude Code, Cursor, Hermes). I have `~/.honcho/config.json` with a real API key and workspace." → Phase 5 Branch A. - **Cold-start user** — "First time using Honcho. I'll need to enter an API key and workspace ID by hand." → Phase 5 Branch B. If `~/.honcho/config.json` is absent OR present but `hosts.sillytavern = {}` AND no root-level `apiKey`, treat the user as cold-start regardless of answer — the file won't help the plugin resolve a key. ## Phase 1 — SillyTavern baseline and `config.yaml` ### 1.1 Install dependencies ```bash cd "$ST_DIR" && npm install ``` Expect `npm warn` lines and a vulnerability count. Skill does not fix these; they're upstream. Note: v1 claimed a `postinstall` script copies `default/config.yaml` → `config.yaml`. That is not true on current SillyTavern. See 1.2. ### 1.2 Generate `config.yaml` `config.yaml` is created by SillyTavern's server on first launch, not by `npm install`. Start the server once to generate it, then stop. ```bash PORT="${ST_PORT:-8000}" BOOT_LOG=$(mktemp -t silly-first-launch.XXXXXX.log) # exec npm so $! captures the node process directly (not the subshell), # making `kill "$ST_PID"` reach node without the broad `pkill -f # "node.*server.js"` footgun that would nuke unrelated ST instances. ( cd "$ST_DIR" && exec npm start -- --port "$PORT" > "$BOOT_LOG" 2>&1 ) & ST_PID=$! # Wait for config.yaml to appear, up to 90s (tight on slow hardware) for _ in $(seq 1 90); do [[ -f "$ST_DIR/config.yaml" ]] && break; sleep 1; done { kill "$ST_PID" 2>/dev/null; wait "$ST_PID" 2>/dev/null; } || true [[ -f "$ST_DIR/config.yaml" ]] || { echo "config.yaml did not appear — inspect $BOOT_LOG"; exit 1; } ``` ### 1.3 Enable server plugins; disable auto-update Two edits in `config.yaml`. Both are idempotent (precheck before editing). ```bash cd "$ST_DIR" # sed -i.bak + rm is the portable form; `sed -i ''` is BSD-only and # breaks on GNU sed (Linux). The .bak suffix is accepted by both. grep -q '^enableServerPlugins: true' config.yaml || { sed -i.bak 's/^enableServerPlugins: false/enableServerPlugins: true/' config.yaml rm -f config.yaml.bak } grep -q '^enableServerPluginsAutoUpdate: false' config.yaml || { sed -i.bak 's/^enableServerPluginsAutoUpdate: true/enableServerPluginsAutoUpdate: false/' config.yaml rm -f config.yaml.bak } ``` Why disable auto-update: this install symlinks a local dev checkout of `sillytavern-honcho`. If auto-update is on, SillyTavern tries to `git pull` that checkout on every boot, which surprises anyone actively editing the repo. Re-enable after shipping. Verify: ```bash grep -E '^enableServerPlugins(AutoUpdate)?:' config.yaml # expect: enableServerPlugins: true # enableServerPluginsAutoUpdate: false # Note: empty alternation like ^foo(|Bar): fails on BSD grep (macOS default). # The (AutoUpdate)? form is portable across both GNU and BSD grep. ``` ## Phase 2 — Apply core patches (idempotent) These add a `HONCHO` entry to SillyTavern's `SECRET_KEYS` object in two files, plus a `FRIENDLY_NAMES` entry on the client side. They're required for the Extensions-panel API-key input (SillyTavern secret manager) to persist a key. Not required for the plugin to load, and not required for the `~/.honcho/config.json` config path. ### 2.1 Server-side `SECRET_KEYS` ```bash cd "$ST_DIR" if ! grep -q "HONCHO: 'api_key_honcho'" src/endpoints/secrets.js; then # Insert before the closing `};` of the SECRET_KEYS object (the first `};` in the file) # v1 pinned this to a specific neighbor key (VOLCENGINE_ACCESS_KEY). Current staging # has WORKERS_AI last — the neighbor drifts. Patch by structure, not neighbor name. awk ' /^export const SECRET_KEYS = \{/ { in_sk=1 } in_sk && /^\};/ && !done { print " HONCHO: '\''api_key_honcho'\'',"; in_sk=0; done=1 } { print } ' src/endpoints/secrets.js > src/endpoints/secrets.js.new && mv src/endpoints/secrets.js.new src/endpoints/secrets.js fi grep -q "HONCHO: 'api_key_honcho'" src/endpoints/secrets.js # verify ``` ### 2.2 Client-side `SECRET_KEYS` and `FRIENDLY_NAMES` Two inserts in `public/scripts/secrets.js`. Same idempotency pattern. ```bash cd "$ST_DIR" # SECRET_KEYS insert — first `};` after the SECRET_KEYS open if ! grep -q "HONCHO: 'api_key_honcho'" public/scripts/secrets.js; then awk ' /^export const SECRET_KEYS = \{/ { in_sk=1 } in_sk && /^\};/ && !sk_done { print " HONCHO: '\''api_key_honcho'\'',"; in_sk=0; sk_done=1 } { print } ' public/scripts/secrets.js > public/scripts/secrets.js.new && mv public/scripts/secrets.js.new public/scripts/secrets.js fi # FRIENDLY_NAMES insert — second `};`, scoped to the FRIENDLY_NAMES block if ! grep -q "\[SECRET_KEYS.HONCHO\]: 'Honcho AI'" public/scripts/secrets.js; then awk ' /^const FRIENDLY_NAMES = \{/ { in_fn=1 } in_fn && /^\};/ && !fn_done { print " [SECRET_KEYS.HONCHO]: '\''Honcho AI'\'',"; in_fn=0; fn_done=1 } { print } ' public/scripts/secrets.js > public/scripts/secrets.js.new && mv public/scripts/secrets.js.new public/scripts/secrets.js fi grep -c 'HONCHO' public/scripts/secrets.js # expect >= 2 ``` ## Phase 3 — Install extension and plugin ### 3.1 Symlink extension ```bash cd "$ST_DIR" EXT_DIR="public/scripts/extensions/third-party/sillytavern-honcho" if [[ ! -e "$EXT_DIR" ]]; then mkdir -p "$(dirname "$EXT_DIR")" ln -s "$SH_DIR" "$EXT_DIR" fi [[ -f "$EXT_DIR/manifest.json" ]] || { echo "manifest.json unreachable — abort"; exit 1; } ``` ### 3.2 Symlink plugin + install SDK ```bash cd "$ST_DIR" if [[ ! -e "plugins/honcho-proxy" ]]; then ln -s "$SH_DIR/plugin" "plugins/honcho-proxy" fi [[ -f "plugins/honcho-proxy/index.js" ]] || { echo "plugin index.js unreachable — abort"; exit 1; } # Install once; npm install is idempotent ( cd "plugins/honcho-proxy" && npm install ) [[ -f "plugins/honcho-proxy/node_modules/@honcho-ai/sdk/package.json" ]] || { echo "SDK install failed"; exit 1; } ``` ## Phase 4 — Start and verify (programmatic, no browser) ### 4.1 Start the server ```bash PORT="${ST_PORT:-8000}" cd "$ST_DIR" rm -f /tmp/silly-server.log npm start -- --port "$PORT" > /tmp/silly-server.log 2>&1 & ST_PID=$! # Wait for "listening" line, up to 30s for _ in $(seq 1 30); do grep -q "is listening on" /tmp/silly-server.log && break; sleep 1; done ``` ### 4.2 Verify plugin loaded (substring match only) v1 grepped for `"Honcho SDK loaded successfully"` and `"Plugin initialized with 5 routes"`. Both are brittle. Check substrings instead. ```bash grep -q "\[honcho-proxy\] Honcho SDK loaded" /tmp/silly-server.log || { echo "plugin did not load"; exit 1; } grep -q "\[honcho-proxy\] Plugin initialized" /tmp/silly-server.log || { echo "plugin failed to init"; exit 1; } grep "\[honcho-proxy\]" /tmp/silly-server.log # surface any other messages for the user ``` ### 4.3 Verify extension served ```bash PORT="${ST_PORT:-8000}" for f in manifest.json settings.html index.js style.css; do code=$(curl -s -o /dev/null -w "%{http_code}" \ "http://127.0.0.1:$PORT/scripts/extensions/third-party/sillytavern-honcho/$f") [[ "$code" == "200" ]] || { echo "$f returned $code — abort"; exit 1; } done ``` ### 4.4 Verify plugin route is mounted A POST with a bogus workspaceId should return 403/400/500, not 404. A 404 means the route isn't mounted. ```bash code=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ -H "Content-Type: application/json" \ -d '{"workspaceId":"smoke","peerId":"smoke"}' \ "http://127.0.0.1:$PORT/api/plugins/honcho-proxy/peer") [[ "$code" != "404" ]] || { echo "plugin route not mounted — abort"; exit 1; } echo "plugin route mounted (HTTP $code — expected 400/403/500 without CSRF+key)" ``` ## Phase 5 — Configuration (branch on user type) ### Branch A — Existing Honcho user The plugin reads `~/.honcho/config.json` at startup. Confirm the keys it actually uses are resolvable: ```bash # python3 is preferred over jq because it's a hard dep on macOS + most # Linux dev envs. If it's still missing (minimal Alpine / Debian-slim), # skip the probe and fall through to Branch B rather than crashing. if ! command -v python3 >/dev/null 2>&1; then echo "python3 not available — skipping apiKey probe; treat as cold-start" >&2 # Branch B else # Config path passed via argv (not heredoc interpolation) so a # pathological path can't inject Python code. python3 - "$HOME/.honcho/config.json" <<'PY' 2>/dev/null import json, sys try: d = json.load(open(sys.argv[1])) h = d.get("hosts", {}).get("sillytavern", {}) ok = bool(h.get("apiKey") or d.get("apiKey")) print("resolvable" if ok else "EMPTY — treat as cold-start", file=sys.stderr) sys.exit(0 if ok else 1) except Exception: print("EMPTY — treat as cold-start", file=sys.stderr) sys.exit(1) PY fi ``` If the check prints `EMPTY — treat as cold-start` (or `python3 not available`), jump to Branch B. "Auto-populated" is a false promise when `hosts.sillytavern = {}` with no root-level fallback.
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub