Skip to content

Latest commit

 

History

History
380 lines (289 loc) · 13.9 KB

native-first-run.md

File metadata and controls

380 lines (289 loc) · 13.9 KB

First run natively on macOS

Installing? The steps are in the "For agents" section of the README; this page is background and detail.

For jerpint and whoever is pairing with him. This is the walkthrough for running Woltspace natively on a Mac — no Docker.

Stop the container first. Two things below depend on it: the Telegram bot token can only be polled by one process, and the instance lock is not reliable across a Docker bind mount. Details in native-and-container.md; the short version is that this walkthrough uses a fresh data root and never touches the container's.

What was and was not verified. Every command and every quoted output below was actually run — inside the Linux dev container, from this branch, with an isolated tool dir, npm prefix, data root, and port. What that cannot cover is macOS itself: Homebrew installs, Apple Silicon wheels, the macOS ps/tmux builds, and Gatekeeper. Steps marked (untested on macOS) are the ones where the Mac could still differ.


1. Prerequisites

You need three things on PATH: tmux, Node 22+, and uv.

tmux -V
node --version
uv --version

Anything missing (untested on macOS):

brew install tmux node
curl -LsSf https://astral.sh/uv/install.sh | sh

You also need a harness you are already logged into — claude, codex, or opencode. Native mode reuses that login in place; it never copies your credentials anywhere. If you are not logged in yet, log in the normal way for that CLI first.


2. Install Woltspace

The published packages are the way to install:

uv tool install 'woltspace'

An AI agent installing Woltspace should set WOLTSPACE_DEFAULT_HARNESS to its own registered harness (for example, claude or codex) before the first woltspace start; this skips the redundant first-run harness question.

A fresh lodge installs the public MIT-licensed jerpint/woltspace-starter-lodge from its latest main at first start (not pinned to a release, so onboarding can improve between releases; existing lodges never re-fetch it). Set WOLTSPACE_STARTER_SEED=none before the first start to turn it off, or set another seed source explicitly. The default install needs network access on first run; if offline, the failure is reported and onboarding continues.

The browser terminal is part of the Python package. Install the optional @woltspace/tui npm package only if you want the separate terminal cockpit.

From a checkout (developing the platform)

If you are working on the platform itself, install from your checkout instead so you pick up local changes:

cd /path/to/woltspace
uv tool install .

Check the installed package:

$ woltspace --version
woltspace 0.5.1

If uv tool install warns that its bin directory is not on your PATH, follow the export PATH=... line it prints (or run uv tool update-shell) and open a new shell.

Three programs are called woltspace, and on a native install two of them can sit ahead of the one you just installed:

  1. <bundle>/container/bin/woltspace — the thin HTTP control client. It is on every session's PATH by design, because that is the directory notify, push-view and session-reg come from. It now recognises a native install and execs the console script beside it for anything it does not serve itself, so woltspace start and woltspace doctor reach the right program even when this copy wins the PATH race.
  2. woltspace at the root of a checkout — the container-era bash Docker launcher. If your shell rc puts the checkout ahead of ~/.local/bin (export PATH="$HOME/woltspace:$PATH" is the usual line), plain woltspace start runs this, and it will try to boot a container. It now refuses when a native control plane owns the data root — but the launcher is not the CLI you want on a native host either way.
  3. ~/.local/bin/woltspace — the one you want.

which -a woltspace shows the order. If a checkout is winning, drop that export PATH line from your shell rc, or move it after ~/.local/bin.


3. Point it at a fresh data root

Do not point the first native run at ~/.woltspace/wolts while the container has it mounted. Use a new directory:

export WOLTSPACE_WOLTS_DIR=~/.woltspace/native-wolts

Confirm what it resolved:

$ woltspace paths
wolts_dir: /Users/you/.woltspace/native-wolts
state_root: /Users/you/.woltspace/native-wolts/.space
install_root: /Users/you/.local/share/uv/tools/woltspace/lib/python3.11/site-packages/woltspace/_bundle
endpoint: http://127.0.0.1:7777
isolation: host

install_root pointing inside the installed package is correct — that is the bundled server and web assets, not your checkout.


4. Preflight

$ woltspace doctor
✓ python: Python 3.11.2
✓ package: runtime and web assets present
✓ data-root: /Users/you/.woltspace/native-wolts (nearest existing parent: /Users/you/.woltspace)
✓ tmux: /usr/bin/tmux
✓ harness: claude=/Users/you/.local/bin/claude, codex=/usr/local/bin/codex
✓ host-auth: claude, codex
✓ browser-terminal: embedded Python PTY bridge
✓ port: 127.0.0.1:7777 is available

Doctor only reads. Every failure names one command that fixes it; work down the list until it is clean.

Two checks worth understanding:

  • host-auth is a warning, not a failure. It means Woltspace found an existing harness login it can reuse. If it says nothing was detected, log in with that CLI — Woltspace will never copy a credential file for you.
  • data-root-sharing only appears if the directory is already claimed by another instance, including a running container. If you see it, stop that instance or pick a different WOLTSPACE_WOLTS_DIR.
  • browser-terminal confirms that tmux is available to the embedded Python PTY bridge. Node, npm and the optional terminal cockpit are not involved.

5. Start

$ woltspace start
  🦫  woltspace

  ⛺ the lodge started
     lights on in the den

  🦫 http://127.0.0.1:7777
     the lodge is open

  🌲 tunnel disabled - the lodge stays on this machine

  🪵 wolts: /Users/you/.woltspace/native-wolts
  🪵 logs: /Users/you/.woltspace/native-wolts/.space/logs/control-plane.log
  🪵 status: woltspace status

start runs doctor first and refuses to launch if it fails. Add --port 7788 if 7777 is taken.

$ woltspace status
  ⛺ the lodge is open
state: healthy

endpoint: http://127.0.0.1:7777
  🪵 tunnel: disabled
  🪵 wolts: /Users/you/.woltspace/native-wolts
  🪵 owner: your-macbook
  🐾 adoption: 0 live · 0 orphaned · 0 unchanged

  🐶 connector telegram: disabled · disabled
     fix: Set channels.telegram = {"enabled": true, "token": "<bot token>"} in /Users/you/.woltspace/native-wolts/.space/platform/config.json (or export TELEGRAM_BOT_TOKEN).

state: and endpoint: sit at column 0 on purpose — those two lines are what scripts grep for, and --json carries everything else, including the pid and instance id the human read leaves out. adoption: 0 live is right on a first run — there are no sessions to adopt yet. On later restarts this is how you see that live sessions were picked back up. The browser terminal is served inside the control plane and therefore has no separate connector status.

The tunnel is off by default natively; nothing is published. To expose the lodge deliberately, WOLTSPACE_PUBLIC_TUNNEL=true woltspace start.

Open http://127.0.0.1:7777 and the lodge should be there. Create a wolt from the lodge and the split view opens with a terminal on the left. The first thing you will see in it is Claude Code's own workspace trust prompt for the new wolt directory — native sessions run bare claude (the container pre-trusts with wclaude), and prompt mode is the point. Accept it and the session continues; it has not hung.


6. The TUI

$ woltspace tui --dry-run
source: local
package: @woltspace/tui@0.5.1
command: /Users/you/.npm-global/bin/woltspace-tui

source: local means it found your installed TUI and its identity checked out. Then run it for real:

woltspace tui

From there: create or select a wolt, confirm the working directory and permission policy it shows you, spawn, and attach. Detach with tmux's usual Ctrl-b d and you are back at the list; the session keeps running.

If --dry-run says source: npx instead, it did not accept your local binary and will try to download from the registry — which cannot work yet. It tells you so:

$ woltspace tui --dry-run
source: npx
package: @woltspace/tui@latest
command: /usr/local/bin/npx --yes --package=@woltspace/tui@latest woltspace-tui
woltspace: ignoring /nonexistent/woltspace-tui — [Errno 2] No such file or directory: '/nonexistent/woltspace-tui'; resolving @woltspace/tui@latest through npx instead.
woltspace: if that fails because @woltspace/tui@latest is not published yet, install both artifacts from a checkout: uv tool install . && cd tui && npm pack && npm install -g ./woltspace-tui-*.tgz

Redo step 2 if you see that.


7. Telegram, if you want it

Use a different bot token than the container's. One token can only be long-polled by one process; the second poller gets 409 Conflict from Telegram and goes deaf while still looking alive. Make a second bot with BotFather for native testing.

Telegram and Slack dependencies are included in the default package since 0.5.4. The install in step 2 already includes them; no extra install is needed.

Then write $WOLTSPACE_WOLTS_DIR/.space/platform/config.json:

{
  "channels": {
    "telegram": {
      "enabled": true,
      "token": "123456:your-test-bot-token",
      "allowed_users": ["your-telegram-user-id"]
    }
  }
}

Restart and check:

woltspace restart
woltspace status

connector telegram: running · Telegram · bundled connector … · pid N means it is up. If it says degraded with a 409, the other bot is still polling that token. If it says disabled · enabled but python-telegram-bot is not installed, you skipped the extra — this is the exact output when that happens:

connector telegram: disabled · enabled but python-telegram-bot is not installed
  fix: Reinstall woltspace to restore its dependencies: `uv tool install --force woltspace` (from a checkout: `uv tool install --force .`), then `woltspace start`.

Leave the tunnel off. Native defaults to no tunnel, and you should not reuse the container's named-tunnel token while the container runs: two cloudflared connectors on one named tunnel load-balance, so real traffic would start landing on the test instance.


8. Stopping

$ woltspace stop
control plane stopped; tmux sessions untouched

That last clause is deliberate: stopping the control plane does not kill your wolts. Their tmux sessions keep running, and the next woltspace start re-adopts them from the registry — woltspace status will show them under adoption. To end a session, stop the session, not the control plane.


Pointing native at your real colony

Once the fresh-root run works, the same commands against WOLTSPACE_WOLTS_DIR=~/.woltspace/wolts (container stopped!) bring up your existing wolts. Several things the container does at boot have no native equivalent yet — platform tools on PATH, .env secrets for the bot, skill sync, the creatures. The full list with workarounds is in native-and-container.md.


Troubleshooting

Start with woltspace doctor and woltspace status; between them they cover most of it.

Symptom What it means
start failed: doctor-failed with a list A prerequisite is missing; each line names its fix.
port: 127.0.0.1:7777 is already in use Something else has the port — woltspace start --port 7788.
woltspace already running: http://127.0.0.1:PORT An instance owns this data root. That URL is where it actually serves, which may not be the port you asked for.
state: stale A previous control plane died without cleaning up. woltspace stop clears the metadata; it signals nothing and leaves tmux alone.
data-root-sharing warning Another instance — likely the container — claims this directory. Stop it or use a different WOLTSPACE_WOLTS_DIR.
serve failed: … is not mounted Container mode without the wolts mount. Not applicable to a native run.
Connector degraded with a 409 Another process is polling that bot token.
Connector failed after several restarts It could not stay up; read .space/logs/connector-<name>.log.
Terminal pane says [tui] connection failed: tmux is not installed Install tmux, then restart Woltspace. woltspace doctor reports the same missing prerequisite.
Terminal pane says its named tmux session does not exist The browser will ask the lodge to resume that session and reconnect; if it repeats, inspect the session record and control-plane log.

The control plane's own log is $WOLTSPACE_WOLTS_DIR/.space/logs/control-plane.log.

Confirming it wrote no credentials

The point of native mode is that your harness login is reused, never copied. After a first run, the data root should contain state and logs and nothing resembling a credential:

$ find "$WOLTSPACE_WOLTS_DIR" \( -name "*credential*" -o -name "auth.json" \) | wc -l
0

$ find "$WOLTSPACE_WOLTS_DIR"
<wolts>
<wolts>/.space
<wolts>/.space/logs
<wolts>/.space/logs/control-plane.log
<wolts>/.space/logs/connector-tui.log
<wolts>/.space/platform
<wolts>/.space/platform/adoption.json
<wolts>/.space/platform/connectors.json
<wolts>/.space/platform/control-plane.json
<wolts>/.space/platform/control-plane.lock

No tunnel.json either: natively the tunnel is off unless you turned it on.

If a credential file ever shows up there, that is a bug worth stopping for.