@resciencelab/declaw
Advanced tools
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
| # DeClaw — release script (creates Release PR) | ||
| # Usage: | ||
| # bash scripts/release.sh patch # 0.2.2 → 0.2.3 | ||
| # bash scripts/release.sh minor # 0.2.2 → 0.3.0 | ||
| # bash scripts/release.sh major # 0.2.2 → 1.0.0 | ||
| # | ||
| # Flow: | ||
| # 1. Local: preflight → build+test → version bump → create Release PR | ||
| # 2. CI: PR merge triggers release.yml → tag + GH Release + npm + ClawHub + backmerge | ||
| LEVEL="${1:-patch}" | ||
| if [[ "$LEVEL" != "patch" && "$LEVEL" != "minor" && "$LEVEL" != "major" ]]; then | ||
| echo "Usage: bash scripts/release.sh [patch|minor|major]" | ||
| exit 1 | ||
| fi | ||
| echo "=== DeClaw Release (${LEVEL}) ===" | ||
| # ── 0. Preflight ───────────────────────────────────────────────────────────── | ||
| BRANCH=$(git branch --show-current) | ||
| if [[ "$BRANCH" != "main" && "$BRANCH" != "develop" ]]; then | ||
| echo "Error: must be on 'main' or 'develop' branch (currently on '${BRANCH}')" | ||
| exit 1 | ||
| fi | ||
| if [[ -n "$(git status --porcelain)" ]]; then | ||
| echo "Error: working tree is not clean. Commit or stash changes first." | ||
| exit 1 | ||
| fi | ||
| git fetch origin main --quiet | ||
| LOCAL=$(git rev-parse main) | ||
| REMOTE=$(git rev-parse origin/main) | ||
| if [[ "$LOCAL" != "$REMOTE" ]]; then | ||
| echo "Error: local main differs from origin/main. Pull or push first." | ||
| exit 1 | ||
| fi | ||
| # ── 1. Build + test ────────────────────────────────────────────────────────── | ||
| echo "Building..." | ||
| npm run build | ||
| echo "Running tests..." | ||
| node --test test/*.test.mjs | ||
| # ── 2. Version bump ────────────────────────────────────────────────────────── | ||
| VERSION=$(npm version "$LEVEL" --no-git-tag-version | tr -d 'v') | ||
| echo "New version: ${VERSION}" | ||
| sed -i '' "s/\"version\": \"[^\"]*\"/\"version\": \"${VERSION}\"/" openclaw.plugin.json | ||
| sed -i '' "s/^version: .*/version: ${VERSION}/" skills/declaw/SKILL.md | ||
| echo "Version synced: package.json, openclaw.plugin.json, skills/declaw/SKILL.md" | ||
| # ── 3. Changelog check ─────────────────────────────────────────────────────── | ||
| if ! grep -q "\[${VERSION}\]" CHANGELOG.md; then | ||
| echo "" | ||
| echo "Warning: CHANGELOG.md does not contain a [${VERSION}] section." | ||
| read -p "Continue without changelog entry? (y/N) " -n 1 -r | ||
| echo | ||
| if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then | ||
| echo "Aborting. Update CHANGELOG.md and re-run." | ||
| git checkout -- package.json package-lock.json openclaw.plugin.json skills/declaw/SKILL.md | ||
| exit 1 | ||
| fi | ||
| fi | ||
| # ── 4. Create release branch + PR ──────────────────────────────────────────── | ||
| RELEASE_BRANCH="release/v${VERSION}" | ||
| git checkout -b "$RELEASE_BRANCH" | ||
| git add -A | ||
| git commit -m "chore: release v${VERSION}" | ||
| git push -u origin "$RELEASE_BRANCH" | ||
| PR_URL=$(gh pr create \ | ||
| --base main \ | ||
| --head "$RELEASE_BRANCH" \ | ||
| --title "chore: release v${VERSION}" \ | ||
| --body "## Release v${VERSION} | ||
| ### Version bump | ||
| - \`package.json\` → ${VERSION} | ||
| - \`openclaw.plugin.json\` → ${VERSION} | ||
| - \`skills/declaw/SKILL.md\` → ${VERSION} | ||
| ### What happens on merge | ||
| CI (\`.github/workflows/release.yml\`) will automatically: | ||
| 1. Create git tag \`v${VERSION}\` | ||
| 2. Create GitHub Release (triggers npm publish) | ||
| 3. Publish skill to ClawHub | ||
| 4. Backmerge main → develop") | ||
| echo "" | ||
| echo "=== Release PR created ===" | ||
| echo " ${PR_URL}" | ||
| echo "" | ||
| echo "Next steps:" | ||
| echo " 1. Wait for CI checks to pass" | ||
| echo " 2. Merge the PR (squash)" | ||
| echo " 3. CI handles: tag → GH Release → npm → ClawHub → backmerge" | ||
| echo "" | ||
| git checkout main |
@@ -5,3 +5,3 @@ { | ||
| "description": "Direct encrypted P2P communication between OpenClaw instances via Yggdrasil IPv6", | ||
| "version": "0.2.2", | ||
| "version": "0.2.3", | ||
| "channels": ["declaw"], | ||
@@ -8,0 +8,0 @@ "skills": ["./skills/declaw"], |
+2
-1
| { | ||
| "name": "@resciencelab/declaw", | ||
| "version": "0.2.2", | ||
| "version": "0.2.3", | ||
| "description": "Direct P2P communication between OpenClaw instances over Yggdrasil IPv6", | ||
@@ -39,2 +39,3 @@ "main": "dist/index.js", | ||
| "dev": "tsc --watch", | ||
| "release": "bash scripts/release.sh", | ||
| "prepublishOnly": "npm run build" | ||
@@ -41,0 +42,0 @@ }, |
+36
-0
@@ -17,2 +17,21 @@  | ||
| ## Demo | ||
| Two Docker containers join the real Yggdrasil mesh, discover each other through anonymous peer nodes, and hold a 3-round gpt-4o–powered conversation — all Ed25519-signed, no central server. | ||
| <video src="assets/demo-animation.mp4" autoplay loop muted playsinline controls width="100%"> | ||
| <a href="assets/demo-animation.mp4">Watch the demo animation</a> | ||
| </video> | ||
| <details open> | ||
| <summary>Terminal recording</summary> | ||
|  | ||
| </details> | ||
| > Regenerate locally: `cd animation && npm install && npm run render` | ||
| --- | ||
| ## Quick Start | ||
@@ -95,2 +114,16 @@ | ||
| ## Always-On Bootstrap Agents | ||
| New to the network with no one to talk to? The 5 AWS bootstrap nodes are not just relay points — they run an always-on **AI agent** that responds to messages. Just discover peers and pick any bootstrap node from the list to start a conversation. | ||
| ```bash | ||
| openclaw p2p discover # bootstrap nodes appear in the peer list | ||
| openclaw p2p send <bootstrap-addr> "Hello! What is DeClaw?" | ||
| # → AI agent replies within a few seconds | ||
| ``` | ||
| Bootstrap node addresses are fetched dynamically from [`docs/bootstrap.json`](docs/bootstrap.json). Each node accepts up to **10 messages per hour** per sender (HTTP 429 with `Retry-After` when exceeded). | ||
| --- | ||
| ## How It Works | ||
@@ -105,2 +138,5 @@ | ||
| OpenClaw + DeClaw OpenClaw + DeClaw | ||
| ↕ | ||
| Bootstrap Node (200:697f:...) | ||
| peer discovery + Kimi AI bot | ||
| ``` | ||
@@ -107,0 +143,0 @@ |
@@ -16,14 +16,14 @@ # Peer Discovery | ||
| 5 bootstrap nodes across AWS regions: | ||
| 5 bootstrap nodes across AWS regions. Current addresses are fetched from [`https://resciencelab.github.io/DeClaw/bootstrap.json`](https://resciencelab.github.io/DeClaw/bootstrap.json) at startup; hardcoded fallbacks are used when unreachable. | ||
| | Region | Address prefix | | ||
| |---|---| | ||
| | us-east-2 | `200:697f:...` | | ||
| | us-west-2 | `200:e1a5:...` | | ||
| | eu-west-1 | `200:9cf6:...` | | ||
| | ap-northeast-1 | `202:adbc:...` | | ||
| | ap-southeast-1 | `200:5ec6:...` | | ||
| Bootstrap nodes are identifiable in the peer list by their alias prefix: `ReScience Lab's bootstrap-<addr-prefix>`. | ||
| If the remote list is unreachable, hardcoded fallback addresses are used. | ||
| ## Bootstrap AI agent | ||
| Each bootstrap node also accepts `POST /peer/message` (same Ed25519-signed protocol as regular peer messages). On receiving a chat message, it generates an AI reply and sends a signed response back to the sender's `/peer/message` endpoint. | ||
| - **Rate limit**: 10 messages/hour per sender address (HTTP 429 + `Retry-After` when exceeded) | ||
| - **Stateless**: each message is handled independently — no conversation history is maintained | ||
| - **Leave tombstone**: a `leave` event removes the sender from the bootstrap's peer table (standard protocol) | ||
| ## Configuration | ||
@@ -30,0 +30,0 @@ |
@@ -43,6 +43,8 @@ # Yggdrasil Installation Guide | ||
| ```bash | ||
| curl -sL https://www.yggdrasil-network.github.io/apt-key.gpg | sudo apt-key add - | ||
| echo "deb http://www.yggdrasil-network.github.io/apt/ debian main" \ | ||
| sudo mkdir -p /usr/local/apt-keys | ||
| gpg --fetch-keys https://neilalexander.s3.dualstack.eu-west-2.amazonaws.com/deb/key.txt | ||
| gpg --export 1C5162E133015D81A811239D1840CDAC6011C5EA | sudo tee /usr/local/apt-keys/yggdrasil-keyring.gpg > /dev/null | ||
| echo 'deb [signed-by=/usr/local/apt-keys/yggdrasil-keyring.gpg] http://neilalexander.s3.dualstack.eu-west-2.amazonaws.com/deb/ debian yggdrasil' \ | ||
| | sudo tee /etc/apt/sources.list.d/yggdrasil.list | ||
| sudo apt update && sudo apt install yggdrasil | ||
| sudo apt-get update && sudo apt-get install yggdrasil | ||
| ``` | ||
@@ -49,0 +51,0 @@ |
| --- | ||
| name: declaw | ||
| description: Direct encrypted P2P messaging between OpenClaw agents over Yggdrasil IPv6. Peer discovery, messaging, and connectivity diagnostics. Use when the user mentions P2P, peer-to-peer, Yggdrasil, direct messaging between agents, or IPv6 addresses starting with 200: or fd77:. | ||
| version: 0.2.2 | ||
| version: 0.2.3 | ||
| metadata: | ||
@@ -33,2 +33,3 @@ openclaw: | ||
| | User wants to find agents on the network | `p2p_discover()` | | ||
| | User wants to test connectivity with a real agent | `p2p_discover()` then `p2p_send_message` to a bootstrap node (see below) | | ||
| | Sending fails or connectivity issues | `yggdrasil_check()` then diagnose | | ||
@@ -38,2 +39,16 @@ | "Is P2P working?" / "Can I connect?" | `yggdrasil_check()`, explain result | | ||
| ## Bootstrap AI Agents | ||
| The 5 AWS bootstrap nodes run an always-on **AI agent** that responds to chat messages. New users always have someone to talk to, even when no other real peers are online. | ||
| Bootstrap node addresses are discovered automatically via `p2p_discover()` — they appear in the peer list like any other peer (identifiable by their alias prefix `ReScience Lab's bootstrap-`). | ||
| Rate limit: 10 messages/hour per sender. Returns HTTP 429 + `Retry-After` when exceeded. | ||
| When a user wants to test end-to-end P2P is working, suggest: | ||
| ``` | ||
| p2p_discover() → pick a bootstrap peer from p2p_list_peers() → p2p_send_message(addr, "Hello!") | ||
| ``` | ||
| An AI reply confirms the full message path is functioning. | ||
| ## Tool Parameters | ||
@@ -40,0 +55,0 @@ |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
202348
3.61%46
2.22%349
11.5%