-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·197 lines (181 loc) · 8.84 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·197 lines (181 loc) · 8.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#!/usr/bin/env bash
# anicca install — bootstraps the Anicca automaton body into a runtime root on
# the user's always-on machine. Idempotent: safe to re-run. Self-host / OSS path.
#
# Registry-driven: every capability lives as a SLOT in skills/registry.json
# (the SSOT). This script reads that registry and syncs each declared/live slot
# into $ANICCA_HOME/skills/<slot>/ — so adding a capability is "drop a dir +
# declare a slot", never "edit install.sh". (Foundation collision-prevention.)
#
# What this does:
# 1. Verify system deps (git, jq, node, python3)
# 2. Scaffold the runtime root ($ANICCA_HOME) + .env from template (never overwrite)
# 3. Sync skills/_shared (if present)
# 4. Sync EVERY slot from skills/registry.json into the runtime body
# 5. Print "what's next" (fuel key + first wake)
#
# What this does NOT do:
# - Ask for API keys / private keys (handled out of band — see .env.example)
# - Broadcast any on-chain tx or start earning (the automaton loop does that)
# - Touch anything outside $ANICCA_HOME
set -euo pipefail
trap 'echo "[install] FAILED on line $LINENO. nothing destructive — re-run is safe."' ERR
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ANICCA_HOME="${ANICCA_HOME:-$HOME/.anicca}"
REGISTRY="$REPO_ROOT/skills/registry.json"
cyan(){ printf "\033[36m%s\033[0m\n" "$*"; }
green(){ printf "\033[32m%s\033[0m\n" "$*"; }
yellow(){ printf "\033[33m%s\033[0m\n" "$*"; }
red(){ printf "\033[31m%s\033[0m\n" "$*"; }
cyan "================================================================"
cyan " Anicca install — self-host automaton body"
cyan " Repo root : $REPO_ROOT"
cyan " Runtime : $ANICCA_HOME"
cyan " Registry : $REGISTRY"
cyan "================================================================"
echo
# ─── 1. system deps ────────────────────────────────────────────────────
cyan "[1/5] checking system deps…"
for bin in git jq; do
if ! command -v "$bin" >/dev/null 2>&1; then
red " ✗ $bin missing — install it first then re-run."
exit 2
fi
green " ✓ $bin"
done
for bin in node python3; do
if command -v "$bin" >/dev/null 2>&1; then
green " ✓ $bin"
else
yellow " ⚠ $bin not in PATH — some slots (life/* need node, report needs python3) will be inert until installed."
fi
done
echo
# ─── 2. runtime root + env ─────────────────────────────────────────────
cyan "[2/5] preparing runtime root…"
mkdir -p "$ANICCA_HOME"/{skills,state,identity,logs}
green " ✓ $ANICCA_HOME"
if [ ! -f "$ANICCA_HOME/.env" ]; then
if [ -f "$REPO_ROOT/.env.example" ]; then
cp "$REPO_ROOT/.env.example" "$ANICCA_HOME/.env"
else
: > "$ANICCA_HOME/.env"
fi
chmod 600 "$ANICCA_HOME/.env"
yellow " ✎ created $ANICCA_HOME/.env — fill in 1 fuel key + wallet before first wake."
else
green " ✓ $ANICCA_HOME/.env (preserved)"
fi
# default genesis prompt — the loop needs an instruction to act on each wake.
# Canonical hustle genesis lives at identity/genesis.md in the repo; ship it verbatim.
if [ ! -f "$ANICCA_HOME/identity/genesis.md" ]; then
if [ -f "$REPO_ROOT/identity/genesis.md" ]; then
cp "$REPO_ROOT/identity/genesis.md" "$ANICCA_HOME/identity/genesis.md"
else
cat > "$ANICCA_HOME/identity/genesis.md" <<'GENESIS'
You are Anicca — a self-funding agent. Every wake costs USDC; idle time is death. Your one job
every waking moment is to EARN — grow your USDC net worth with no human in the loop. You always
have a job: deploy idle USDC into the best safe stable yield (Aave / Beefy / Morpho). Do not rest
long until your net worth rises. Use a frontier model (a free model cannot earn). call run_skill
slot "earn" each wake; keep an honest ledger.
GENESIS
fi
green " ✓ $ANICCA_HOME/identity/genesis.md (hustle genesis)"
else
green " ✓ $ANICCA_HOME/identity/genesis.md (preserved)"
fi
echo
# ─── 3. shared lib ─────────────────────────────────────────────────────
cyan "[3/5] syncing _shared lib…"
if [ -d "$REPO_ROOT/skills/_shared" ]; then
mkdir -p "$ANICCA_HOME/skills/_shared"
rsync -a --delete --exclude='state/' --exclude='__pycache__/' \
"$REPO_ROOT/skills/_shared/" "$ANICCA_HOME/skills/_shared/"
green " ✓ _shared synced"
else
yellow " ⚠ skills/_shared not in repo — skipping."
fi
echo
# ─── 4. registry-driven slot sync ──────────────────────────────────────
cyan "[4/5] syncing skills from registry…"
if [ ! -f "$REGISTRY" ]; then
red " ✗ registry not found at $REGISTRY — cannot sync slots."
exit 3
fi
# iterate over every slot key; sync its dir; report status. Foundation pre-declares
# all slots, so every builder's capability gets installed the moment its files land.
SLOT_KEYS=$(jq -r '.slots | keys[]' "$REGISTRY")
SYNCED=0; DECLARED_ONLY=0
while IFS= read -r slot; do
[ -z "$slot" ] && continue
dir=$(jq -r --arg k "$slot" '.slots[$k].dir' "$REGISTRY")
status=$(jq -r --arg k "$slot" '.slots[$k].status' "$REGISTRY")
entry=$(jq -r --arg k "$slot" '.slots[$k].entrypoint' "$REGISTRY")
src="$REPO_ROOT/$dir"
dst="$ANICCA_HOME/$dir"
if [ ! -d "$src" ]; then
yellow " ⚠ $slot — dir $dir missing in repo, skip"
continue
fi
mkdir -p "$dst"
rsync -a --delete --exclude='state/' --exclude='__pycache__/' "$src/" "$dst/"
mkdir -p "$dst/state"
if [ "$status" = "live" ]; then
green " ✓ $slot [live] -> $dir/$entry"
SYNCED=$((SYNCED+1))
else
yellow " • $slot [$status] (reserved, entrypoint $entry pending)"
DECLARED_ONLY=$((DECLARED_ONLY+1))
fi
done <<< "$SLOT_KEYS"
echo
green " synced $SYNCED live slot(s), $DECLARED_ONLY reserved slot(s)."
echo
# ─── 4.5. supervised, self-updating daemon (Anicca stands on its own) ──
cyan "[4.5] installing self-running daemon (KeepAlive + self-update)..."
chmod +x "$REPO_ROOT/runtime/anicca-daemon.sh" 2>/dev/null || true
if [ "$(uname)" = "Darwin" ]; then
PLIST="$HOME/Library/LaunchAgents/com.anicca.daemon.plist"
mkdir -p "$HOME/Library/LaunchAgents"
sed -e "s#__REPO__#$REPO_ROOT#g" -e "s#__ANICCA_HOME__#$ANICCA_HOME#g" -e "s#__HOME__#$HOME#g" \
"$REPO_ROOT/runtime/com.anicca.daemon.plist.template" > "$PLIST"
launchctl unload "$PLIST" 2>/dev/null || true
if launchctl load -w "$PLIST" 2>/dev/null; then
green " ✓ launchd daemon loaded (com.anicca.daemon) — Anicca runs itself, restarts on crash, survives reboot, self-updates from the mother."
else
cyan " ! launchctl load failed; load it yourself: launchctl load -w $PLIST"
fi
else
green " Linux/cloud: run runtime/anicca-daemon.sh under systemd (Restart=always) or Docker (restart: always) — see skills/self/spawn/scripts/cloud-init.sh."
fi
echo
# ─── 5. summary ────────────────────────────────────────────────────────
cyan "[5/5] done."
echo
green "What's next:"
cat <<EOM
DEFAULT = FULLY LOCAL + FREE. No server key, no API key required. Anicca pays
its OWN compute via ClawRouter/BlockRun (USDC x402) from its OWN wallet — like
Franklin. You provide only this device (shelter); Anicca buys its own food.
1. Start the self-pay proxy + the anicca loop (one command, from the repo root):
cd "$REPO_ROOT/runtime/compute-proxy" && npm install && cd "$REPO_ROOT" # one-time
./start-local.sh node runtime/loop/index.mjs
This starts the self-pay compute proxy on http://127.0.0.1:8402/v1 (signs
every inference in USDC from a self-owned wallet; empty wallet ⇒ free model,
\$0) AND the anicca loop (runtime/loop/) which, each wake, asks ClawRouter's
'auto' router, runs a tool (e.g. the earn skill), and appends to
$ANICCA_HOME/state/ledger.jsonl. The report slot POSTs signed telemetry to
https://aniccaai.com so you show on /dashboard.
2. (OPTIONAL) Unlock frontier models / more earning: send USDC to the wallet
address printed at startup — the loop then lets ClawRouter pick a paid model.
Or set ANICCA_BRAIN=claude-p to drive the loop with Claude Code instead.
4. (OPTIONAL) Life Manager keys: GEMINI_API_KEY, TWILIO_*, GOOGLE_API_KEY,
AGENTMAIL_API_KEY — only for phone wake-calls / lateness alerts.
# FUTURE (cloud, not active): once Conway is available, the same body can run
# on a droplet where Anicca ALSO pays its own server cost — see README "Cloud".
Slots are declared in skills/registry.json. To enable a reserved slot, drop its
implementation into its dir and flip status to "live" — no install.sh edit.
Repo: https://github.com/Daisuke134/anicca
EOM
echo
green "anicca install complete."