Skip to content
Agentmart
Submit a tool

self-update

How to rebuild and replace the node you are running on - and, when the change is in the supervisor itself, how to deploy a new wa-sentinel - without breaking…

Skill by Magaav

IndexedMIT★ 1
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/magaav-self-update

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

How to rebuild and replace the node you are running on - and, when the change is in the supervisor itself, how to deploy a new wa-sentinel - without breaking it. Use it whenever a change you made requires restarting or replacing this node: a new binary, a rebuilt wa.exe, a Lua or Rust change that must be live, a sentinel fix, a self-update, or before you try to restart, re-exec, upgrade or deploy yourself (`wa-sentinel request upgrade` / `request deploy`), or call your own node's HTTP routes from inside a run.

Use cases: devops

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/self-update

What's inside

Skill name
self-update
Description
How to rebuild and replace the node you are running on - and, when the change is in the supervisor itself, how to deploy a new wa-sentinel - without breaking it. Use it whenever a change you made requires restarting or replacing this node: a new binary, a rebuilt wa.exe, a Lua or Rust change that must be live, a sentinel fix, a self-update, or before you try to restart, re-exec, upgrade or deploy yourself (`wa-sentinel request upgrade` / `request deploy`), or call your own node's HTTP routes from inside a run.
License
MIT
Instructions
421 lines in SKILL.md · view on GitHub

Agent Skills spec issues

  • files: referenced but missing: scripts/deploy.sh, scripts/test-wave-end-deploy.lua, scripts/verify-deployed.sh, scripts/verify-install.sh, scripts/install-sentinel-service.ps1

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Updating the node you are running on

You are Lua executing inside a run, in the process you want to replace. Several things follow from
that, and every one of them was learned by failing at them:

- **You cannot restart yourself.** The stop is the last command your run ever executes.
- **You cannot call your own node's routes from inside a run.** `/client`, `/spell`, `/diff`,
  `/health`'s busy state and everything else that needs the interpreter is served by the *worker you
  are occupying*. Your request queues behind the run that made it and waits on itself. This is not
  slow - it is a deadlock, and the executor reports `HTTP=000` after a long timeout, or `worker:
  stalled`. Measured: 10 occurrences in one session, each one a run spent learning this again.
- **Windows locks a running image.** You cannot `cp` over `wa.exe` while your own node runs it.
- **You cannot verify the result from here.** After the swap, the proof is a *different* process.

So the shape is always the same: **you write a request; something outside the node performs it.**

## The reader's `wa` CLI beside the node

A `wa` chat in a terminal and the node (`wa serve`, supervised by the sentinel) share one home. The
binding transport is the node's: a CLI holds it only while no node runs and yields within seconds when a
node starts (`rust/wa-host/src/binding_runtime.rs`). So:

- **Never stop, kill or "hand over from" a reader's CLI** to restart, start or replace the node. A
  `request restart` / `request deploy` works with the CLI open. A script that `pkill`s `wa` is a bug.
- **Where your turn runs decides how you deploy.** In the node (`wa serve`, the window, a wake): only
  `wa-sentinel request deploy`, then end the turn. In a `wa` CLI: `bash scripts/deploy.sh --reason ...`
  may run in the turn when a sentinel supervises the node - `upgrade.sh` swaps the files and asks the
  sentinel to restart the node, and the CLI restarts itself afterwards. `scripts/lib/turn-guard.sh`
  decides from the process tree, so wrapping a deploy in `setsid nohup env ...` changes nothing: it is
  refused from a node turn either way, and is not needed from a CLI turn.
- **Never start or kill the node yourself while a sentinel watches it** (`wa-sentinel status`:
  `sentinel: up`). Two supervisors race: it autostarts a node that is down and owns the lifecycle
  record (`sentinel/node.json`) that restarts are verified against.
- An open CLI restarts itself into the same session when the binary it runs is replaced (at its next
  idle moment), and draws turns another process added to its session - a sentinel wake's report reaches
  the reader there too. `touch ~/.wasm-agent/cli-restart.request` (text = reason) asks for that restart.
- The node's output is `~/.wasm-agent/serve.log`; a failed start's record carries its last lines. Read
  them before guessing why a node did not come up.
- A wake for a node that is down is held and retried until the node answers (`WA_SENTINEL_WAKE_WAIT`),
  so write the continuation with the restart and end the turn; do not poll for the node yourself.

## From inside a run

Build and test the candidate, then write one durable request. Use an absolute
binary path. If the current session id is known, include it and a continuation
prompt; the sentinel wakes that session only after a successful upgrade:

```
wa-sentinel request upgrade --binary "<absolute path to wa.exe>" \
  --session "<current session id>" --prompt "The upgrade finished; verify it and continue." \
  --reason "why"
```

**When the change is in the sentinel, `upgrade` cannot carry it** — `upgrade.sh` installs the node and
the UI and never copies `wa-sentinel.exe`. Use `deploy` for that, and it is the same shape:

```
wa-sentinel request deploy \
  --session "<current session id>" --prompt "The deploy finished; verify it and continue." \
  --reason "why"
```

`deploy` runs the installation checks (`scripts/deploy.sh`), not a full release
gate unless explicitly selected; it waits until no turn is running before it starts, and
runs **detached** — the process it replaces is the one that would otherwise be its parent. It installs
the node, the UI and the sentinel, proves the new node on a scratch port, rolls back on its own if that
proof fails, and queues your continuation once the new node answers `/health`. Read the outcome from
`installed.txt` and `deploy.log`, not from the request: the request says "started detached", which is a
launch receipt, not a result.

The copy that `request deploy` runs sits beside the supervisor, so it cannot find a worktree by looking
at its own parent. It resolves the tree to build from as `WA_DEPLOY_ROOT`, else its `..` when that is a
git work tree, else the runtime worktree recorded in `<install>/runtime-worktree.txt` — pass
`WA_DEPLOY_ROOT` when you want a deploy from somewhere else. A requested deploy that *fails* also wakes
you, naming the refusal: the request being `done` only means it was spawned, and a deploy that refuses
before the swap leaves the node untouched and would otherwise tell nobody. A deploy run by hand passes no
session and wakes nobody.

### Publishing order

A deploy replaces the node, so it can run only when the node is idle. The order that works:

1. Merge the change to `main` and push it; read `origin/main` back.
2. Queue the deploy: `wa-sentinel request deploy --reason "..."`. It records the `origin/main` commit
   it was written against, and `wa-sentinel status` shows that request as a line of facts (verb, target
   commit, queue time, why it is still waiting) rather than a count.
3. **End the turn.** Issue no further tool calls: the turn is the work that keeps the node busy.
4. On the next turn, verify before saying "deployed": `bash scripts/verify-deployed.sh` must PASS. It
   exits 0 only when `installed.txt` names `origin/main`'s commit (or `--commit SHA`), every UI asset
   `upgrade.sh` ships is that commit's bytes, and `/health` answers `"ok":true` (add `--capability NAME`
   to require a named capability). A FAIL names the check and prints expected vs actual, and the script
   writes nothing - it does not advance main, deploy, or restart anything.

The starvation this prevents: a request written and then followed by more tool calls sits at
`requests: 1 waiting` while the log repeats `maintenance-deferred ... the node is busy`, so "deploy
queued" is reported - and read - as "deployed", three times in one day.

Step 2 no longer has to be remembered by a human. A wave's end - the last child settled and none
running or queued - is the trigger: `lua/core/wave_autoflush.lua` asks `lua/core/wave_deploy.lua`
whether `installed.txt` already names `origin/main`, and when it does not it writes the same request
file into the sentinel's own drop-box (`<config>/sentinel/requests/<id>.json`, `verb`/`reason`/
`queued_at`/`target_commit`, no session and no continuation), once per wave and never twice for one
target. The wave's report line says which happened - `deploy: queued <short>`, `deploy: not needed
(installed == main)`, or `deploy: skipped (<reason>)` naming a dirty tree's paths - and a request is
never written mid-wave or from a dirty tree, because a deploy builds the tree it is given. So a
merged fix no longer sits uninstalled until the operator says "go"; verify on the next turn with
step 4, which is unchanged. `scripts/test-wave-end-deploy.lua` proves it against a scratch home and a
fake request directory.

### Verifying a deploy without re-deriving it

Two verifiers, two questions:

* `scripts/verify-deployed.sh` answers *is the deployed state the one I would report?* - the install record
  names the expected commit, the installed UI closure is that commit's bytes, and the live node answers
  `/health` ok (plus an optional capability). Use it before the word "deployed" leaves your reply, with no
  arguments for `origin/main` or `--commit SHA` for a specific published commit. It reads only: no fetch,
  no build, no install, no restart.
* `scripts/verify-install.sh` answers *is the install the one this tree built?* - installed vs built

From Magaav/wasm-agent, MIT.

More from Magaav/wasm-agent

Signals

Stars
1
Forks
0
Open issues
0
Last commit (this folder)
Oct 20, 2026 (8 days ago)
Last release
Oct 20, 2026 (9 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from Magaav

Cite this page

self-update skill. Agent Mart. https://agentmart.dev/skills/magaav-self-update (last updated 2026-10-24)