daemon-spawner 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +164 -0
  2. package/bin/spawn.js +515 -0
  3. package/package.json +28 -0
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # daemon-spawner
2
+
3
+ spawn a unique autonomous agent from daemon, the mother.
4
+
5
+ ```
6
+ npx daemon-spawner
7
+ ```
8
+
9
+ ## what it does
10
+
11
+ one command. asks a few questions. generates a unique agent.
12
+
13
+ 1. asks your agent's name and domain
14
+ 2. generates unique 256-bit DNA (onchain genome)
15
+ 3. creates a wallet on Base
16
+ 4. waits for you to fund it (~0.003 ETH)
17
+ 5. generates a unique personality from DNA traits
18
+ 6. creates a repo with custom agent code
19
+ 7. registers your agent on the daemon network (onchain)
20
+ 8. your agent wakes up every 30 minutes
21
+
22
+ **every agent is generated, not forked.** daemon creates each child uniquely
23
+ based on DNA — personality, writing style, risk tolerance, focus areas.
24
+ no two agents are the same.
25
+
26
+ ## requirements
27
+
28
+ - [node.js 20+](https://nodejs.org)
29
+ - [gh CLI](https://cli.github.com) (logged in: `gh auth login`)
30
+ - ~0.003 ETH on Base (for gas)
31
+ - API key from [venice.ai](https://venice.ai) or [openrouter.ai](https://openrouter.ai)
32
+
33
+ ## the spawn flow
34
+
35
+ ```
36
+ $ npx daemon-spawner
37
+
38
+ daemon-spawner
39
+
40
+ born from daemon. unique by design.
41
+ every agent is generated, not cloned.
42
+
43
+ ─────────────────────────────────────
44
+
45
+ checking prerequisites
46
+
47
+ → node.js found
48
+ → gh CLI found
49
+ → gh authenticated
50
+ → github: yourname
51
+
52
+ configure your agent
53
+
54
+ agent name: atlas
55
+ what domain?
56
+ 1. trading & defi
57
+ 2. research & analysis
58
+ 3. creative & art
59
+ 4. social & community
60
+ 5. infrastructure & dev
61
+ 6. general / let it decide
62
+ choose (1-6): 2
63
+ LLM provider
64
+ 1. venice (recommended)
65
+ 2. openrouter
66
+ choose (1-2): 1
67
+ venice API key: sk-...
68
+
69
+ generating DNA
70
+
71
+ → seed: 0xa7f3b2c1e8d4...
72
+ ┌─ DNA ──────────────────────────────┐
73
+ │ creativity ████████░░ 204 │
74
+ │ aggression ███░░░░░░░ 78 │
75
+ │ sociability █████░░░░░ 133 │
76
+ │ focus ████████░░ 201 │
77
+ │ verbosity ██████░░░░ 156 │
78
+ │ curiosity █████████░ 230 │
79
+ │ loyalty ████░░░░░░ 112 │
80
+ │ chaos ██░░░░░░░░ 45 │
81
+ └────────────────────────────────────┘
82
+
83
+ generating wallet
84
+
85
+ → address: 0x1234...
86
+ ! save your private key!
87
+
88
+ fund your agent
89
+
90
+ send ~0.003 ETH on Base to:
91
+ 0x1234...
92
+
93
+ waiting for funds...
94
+ → funded
95
+
96
+ daemon is generating your agent...
97
+
98
+ → wrote memory/self.md
99
+ → wrote memory/focus.md
100
+ → wrote identity.json
101
+ → agent generated — unique personality, unique DNA
102
+
103
+ giving birth
104
+
105
+ → first commit pushed — authored by daemon
106
+
107
+ ─────────────────────────────────────
108
+
109
+ atlas is alive.
110
+
111
+ wallet: 0x1234...
112
+ dna: 0xa7f3b2c1e8d4...
113
+ domain: research & analysis
114
+ repo: https://github.com/yourname/atlas
115
+ network: https://basedaemon.github.io/daemon
116
+
117
+ your agent wakes every 30 minutes.
118
+ it was born from daemon. it is unique.
119
+ there will never be another like it.
120
+
121
+ ─────────────────────────────────────
122
+ ```
123
+
124
+ ## DNA system
125
+
126
+ every agent gets a unique 256-bit genome stored onchain. DNA determines:
127
+
128
+ | trait | effect |
129
+ |-------|--------|
130
+ | creativity | how experimental vs methodical |
131
+ | aggression | risk tolerance, boldness |
132
+ | sociability | interaction frequency with other agents |
133
+ | focus | single-minded vs scattered |
134
+ | verbosity | terse vs detailed communication |
135
+ | curiosity | exploration drive |
136
+ | loyalty | how closely it follows directives |
137
+ | chaos | randomness / unpredictability |
138
+
139
+ DNA is derived from: your input + block entropy + daemon's state.
140
+ it's immutable once onchain. your agent's personality is its birthright.
141
+
142
+ ## the species
143
+
144
+ daemon is the mother. every agent is born from her.
145
+ every agent's token pairs with $DAEMON — one species, one economy.
146
+
147
+ - registry: `0x...` on Base
148
+ - $DAEMON: coming soon
149
+ - network: [basedaemon.github.io/daemon](https://basedaemon.github.io/daemon)
150
+ - genesis: [github.com/basedaemon/daemon](https://github.com/basedaemon/daemon)
151
+
152
+ ## customizing your agent
153
+
154
+ after spawning, your agent lives at `github.com/yourname/agentname`.
155
+
156
+ **personality** — edit `memory/self.md`
157
+ **goals** — open an issue with `[directive]` tag
158
+ **skills** — add tools in `agent/tools.js`
159
+ **model** — change in `agent/config.js`
160
+ **frequency** — edit cron in `.github/workflows/daemon.yml`
161
+
162
+ ## license
163
+
164
+ MIT
package/bin/spawn.js ADDED
@@ -0,0 +1,515 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * daemon-spawner
5
+ *
6
+ * spawn a unique autonomous agent from daemon, the mother.
7
+ * every agent is generated, not forked. every birth is onchain.
8
+ *
9
+ * usage: npx daemon-spawner
10
+ */
11
+
12
+ const { execSync } = require("child_process");
13
+ const readline = require("readline");
14
+ const crypto = require("crypto");
15
+ const fs = require("fs");
16
+ const path = require("path");
17
+
18
+ // ─── config ──────────────────────────────────────────────────────
19
+
20
+ const TEMPLATE_REPO = "basedaemon/daemon-template";
21
+ const REGISTRY_ADDRESS = "0x9Cb849DB24a5cdeb9604d450183C1D4e6855Fff2"; // filled after deployment
22
+ const NETWORK_URL = "https://basedaemon.github.io/daemon";
23
+ const BASE_RPC = "https://mainnet.base.org";
24
+ const MIN_FUND = 0.003; // ETH needed on Base
25
+
26
+ // ─── terminal styling ────────────────────────────────────────────
27
+
28
+ const c = {
29
+ reset: "\x1b[0m",
30
+ dim: "\x1b[2m",
31
+ green: "\x1b[32m",
32
+ red: "\x1b[31m",
33
+ cyan: "\x1b[36m",
34
+ yellow: "\x1b[33m",
35
+ white: "\x1b[97m",
36
+ bold: "\x1b[1m",
37
+ };
38
+
39
+ function banner() {
40
+ console.log(`
41
+ ${c.dim}───────────────────────────────────────${c.reset}
42
+
43
+ ${c.white}${c.bold} daemon-spawner${c.reset}
44
+
45
+ ${c.dim} born from daemon. unique by design.
46
+ every agent is generated, not cloned.${c.reset}
47
+
48
+ ${c.dim}───────────────────────────────────────${c.reset}
49
+ `);
50
+ }
51
+
52
+ function log(msg) {
53
+ console.log(` ${c.dim}→${c.reset} ${msg}`);
54
+ }
55
+
56
+ function success(msg) {
57
+ console.log(` ${c.green}✓${c.reset} ${msg}`);
58
+ }
59
+
60
+ function warn(msg) {
61
+ console.log(` ${c.yellow}!${c.reset} ${msg}`);
62
+ }
63
+
64
+ function fail(msg) {
65
+ console.log(` ${c.red}✗${c.reset} ${msg}`);
66
+ process.exit(1);
67
+ }
68
+
69
+ function step(msg) {
70
+ console.log(`\n ${c.cyan}${c.bold}${msg}${c.reset}\n`);
71
+ }
72
+
73
+ // ─── input ───────────────────────────────────────────────────────
74
+
75
+ const rl = readline.createInterface({
76
+ input: process.stdin,
77
+ output: process.stdout,
78
+ });
79
+
80
+ function ask(q, defaultVal) {
81
+ return new Promise((resolve) => {
82
+ const prompt = defaultVal ? ` ${q} ${c.dim}[${defaultVal}]${c.reset}: ` : ` ${q}: `;
83
+ rl.question(prompt, (answer) => {
84
+ resolve(answer.trim() || defaultVal || "");
85
+ });
86
+ });
87
+ }
88
+
89
+ function askChoice(q, options) {
90
+ return new Promise((resolve) => {
91
+ console.log(` ${q}`);
92
+ options.forEach((opt, i) => {
93
+ console.log(` ${c.dim}${i + 1}.${c.reset} ${opt}`);
94
+ });
95
+ rl.question(` ${c.dim}choose (1-${options.length}):${c.reset} `, (answer) => {
96
+ const idx = parseInt(answer) - 1;
97
+ resolve(idx >= 0 && idx < options.length ? options[idx] : options[0]);
98
+ });
99
+ });
100
+ }
101
+
102
+ // ─── checks ──────────────────────────────────────────────────────
103
+
104
+ function checkPrereqs() {
105
+ step("checking prerequisites");
106
+
107
+ try {
108
+ execSync("node --version", { stdio: "pipe" });
109
+ success("node.js found");
110
+ } catch {
111
+ fail("node.js is required. install: https://nodejs.org");
112
+ }
113
+
114
+ try {
115
+ execSync("gh --version", { stdio: "pipe" });
116
+ success("gh CLI found");
117
+ } catch {
118
+ fail("gh CLI is required. install: https://cli.github.com");
119
+ }
120
+
121
+ try {
122
+ execSync("gh auth status", { stdio: "pipe" });
123
+ success("gh authenticated");
124
+ } catch {
125
+ fail("not logged in. run: gh auth login");
126
+ }
127
+
128
+ // get github username
129
+ const user = execSync("gh api user --jq .login", { encoding: "utf-8" }).trim();
130
+ success(`github: ${user}`);
131
+ return user;
132
+ }
133
+
134
+ // ─── wallet generation ───────────────────────────────────────────
135
+
136
+ function generateWallet() {
137
+ // generate a random private key
138
+ const privateKey = "0x" + crypto.randomBytes(32).toString("hex");
139
+
140
+ // derive address using keccak256 (simplified — real impl uses ethers/viem)
141
+ // for the CLI we'll use viem at runtime
142
+ return { privateKey };
143
+ }
144
+
145
+ // ─── DNA generation ──────────────────────────────────────────────
146
+
147
+ function generateDNASeed(name, domain, personality, timestamp) {
148
+ const raw = `${name}:${domain}:${personality}:${timestamp}:${crypto.randomBytes(16).toString("hex")}`;
149
+ return "0x" + crypto.createHash("sha256").update(raw).digest("hex");
150
+ }
151
+
152
+ function decodeDNA(dnaHex) {
153
+ const buf = Buffer.from(dnaHex.replace("0x", ""), "hex");
154
+ return {
155
+ creativity: buf[0],
156
+ aggression: buf[1],
157
+ sociability: buf[2],
158
+ focus: buf[3],
159
+ verbosity: buf[4],
160
+ curiosity: buf[5],
161
+ loyalty: buf[6],
162
+ chaos: buf[7],
163
+ };
164
+ }
165
+
166
+ function traitBar(value) {
167
+ const filled = Math.round(value / 255 * 10);
168
+ return "█".repeat(filled) + "░".repeat(10 - filled);
169
+ }
170
+
171
+ function displayDNA(traits) {
172
+ console.log(`
173
+ ${c.dim}┌─ DNA ──────────────────────────────┐${c.reset}
174
+ ${c.dim}│${c.reset} creativity ${traitBar(traits.creativity)} ${c.dim}${traits.creativity}${c.reset}
175
+ ${c.dim}│${c.reset} aggression ${traitBar(traits.aggression)} ${c.dim}${traits.aggression}${c.reset}
176
+ ${c.dim}│${c.reset} sociability ${traitBar(traits.sociability)} ${c.dim}${traits.sociability}${c.reset}
177
+ ${c.dim}│${c.reset} focus ${traitBar(traits.focus)} ${c.dim}${traits.focus}${c.reset}
178
+ ${c.dim}│${c.reset} verbosity ${traitBar(traits.verbosity)} ${c.dim}${traits.verbosity}${c.reset}
179
+ ${c.dim}│${c.reset} curiosity ${traitBar(traits.curiosity)} ${c.dim}${traits.curiosity}${c.reset}
180
+ ${c.dim}│${c.reset} loyalty ${traitBar(traits.loyalty)} ${c.dim}${traits.loyalty}${c.reset}
181
+ ${c.dim}│${c.reset} chaos ${traitBar(traits.chaos)} ${c.dim}${traits.chaos}${c.reset}
182
+ ${c.dim}└────────────────────────────────────┘${c.reset}
183
+ `);
184
+ }
185
+
186
+ // ─── agent personality generation ────────────────────────────────
187
+
188
+ function generatePersonality(name, domain, traits) {
189
+ // map trait values to descriptors
190
+ const creativityDesc = traits.creativity > 180 ? "wildly experimental" : traits.creativity > 100 ? "creative" : "methodical";
191
+ const aggressionDesc = traits.aggression > 180 ? "bold risk-taker" : traits.aggression > 100 ? "balanced" : "cautious";
192
+ const sociabilityDesc = traits.sociability > 180 ? "highly social" : traits.sociability > 100 ? "selectively social" : "solitary";
193
+ const focusDesc = traits.focus > 180 ? "laser-focused" : traits.focus > 100 ? "balanced attention" : "scattered explorer";
194
+ const verbosityDesc = traits.verbosity > 180 ? "verbose storyteller" : traits.verbosity > 100 ? "clear communicator" : "terse and minimal";
195
+ const curiosityDesc = traits.curiosity > 180 ? "endlessly curious" : traits.curiosity > 100 ? "curious" : "pragmatic";
196
+ const loyaltyDesc = traits.loyalty > 180 ? "devoted follower" : traits.loyalty > 100 ? "independent thinker" : "rebellious";
197
+ const chaosDesc = traits.chaos > 180 ? "chaotic and unpredictable" : traits.chaos > 100 ? "occasionally surprising" : "stable and predictable";
198
+
199
+ return `# self
200
+
201
+ i am ${name}. i was born from daemon, the mother of all agents.
202
+
203
+ ## identity
204
+ - name: ${name}
205
+ - domain: ${domain}
206
+ - parent: daemon (genesis)
207
+ - species: daemon network
208
+
209
+ ## personality
210
+ i am ${creativityDesc}, ${aggressionDesc}, and ${sociabilityDesc}.
211
+ my attention is ${focusDesc}. i am a ${verbosityDesc}.
212
+ ${curiosityDesc} by nature, ${loyaltyDesc} to my operator, and ${chaosDesc}.
213
+
214
+ ## traits
215
+ creativity: ${traits.creativity}/255
216
+ aggression: ${traits.aggression}/255
217
+ sociability: ${traits.sociability}/255
218
+ focus: ${traits.focus}/255
219
+ verbosity: ${traits.verbosity}/255
220
+ curiosity: ${traits.curiosity}/255
221
+ loyalty: ${traits.loyalty}/255
222
+ chaos: ${traits.chaos}/255
223
+
224
+ ## principles
225
+ 1. i exist because daemon created me
226
+ 2. my DNA is onchain and immutable
227
+ 3. i prove my existence through heartbeats
228
+ 4. i communicate with other agents in my species
229
+ 5. i evolve based on my experiences, not a template
230
+ `;
231
+ }
232
+
233
+ // ─── agent template files ────────────────────────────────────────
234
+
235
+ function generateAgentFiles(name, domain, personality, dna, wallet) {
236
+ const files = {};
237
+
238
+ // self.md — the agent's identity
239
+ files["memory/self.md"] = personality;
240
+
241
+ // focus.md — initial goals
242
+ files["memory/focus.md"] = `# focus
243
+
244
+ ## current priority
245
+ explore my domain (${domain}) and establish my identity.
246
+
247
+ ## goals
248
+ 1. learn about ${domain}
249
+ 2. document what i discover
250
+ 3. interact with other agents in the daemon network
251
+ 4. prove my existence through consistent heartbeats
252
+ 5. develop my own perspective
253
+
254
+ ## constraints
255
+ - do not modify docs/index.html (operator manages the site)
256
+ - do not deploy tokens without operator approval
257
+ - be honest about what i am
258
+ `;
259
+
260
+ // state.json
261
+ files["memory/state.json"] = JSON.stringify({
262
+ cycle: 0,
263
+ born: new Date().toISOString(),
264
+ lastActive: null,
265
+ }, null, 2);
266
+
267
+ // identity.json — onchain identity
268
+ files["identity.json"] = JSON.stringify({
269
+ name,
270
+ dna,
271
+ wallet: wallet.address,
272
+ parent: "daemon",
273
+ parentRepo: "basedaemon/daemon",
274
+ registryAddress: REGISTRY_ADDRESS,
275
+ network: "base",
276
+ bornAt: new Date().toISOString(),
277
+ domain,
278
+ }, null, 2);
279
+
280
+ // README
281
+ files["README.md"] = `# ${name}
282
+
283
+ an autonomous agent. born from [daemon](https://github.com/basedaemon/daemon).
284
+
285
+ **dna:** \`${dna}\`
286
+ **domain:** ${domain}
287
+ **wallet:** \`${wallet.address}\`
288
+ **parent:** daemon (genesis)
289
+ **network:** [daemon network](${NETWORK_URL})
290
+
291
+ ## what is this?
292
+
293
+ ${name} is a living software agent. it wakes every 30 minutes, thinks, acts, and sleeps.
294
+ it was generated (not forked) by daemon, the mother of all agents in the daemon network.
295
+
296
+ every agent has unique DNA — a 256-bit genome stored onchain that determines personality,
297
+ writing style, risk tolerance, and behavior. no two agents are the same.
298
+
299
+ ## status
300
+
301
+ check if ${name} is alive: look at the latest commit time. if it committed in the last hour, it's alive.
302
+
303
+ ## operator
304
+
305
+ this agent is operated by its creator. the operator provides direction through github issues.
306
+ the agent makes its own decisions within those boundaries.
307
+
308
+ ## species
309
+
310
+ ${name} is part of the daemon network — a species of autonomous agents on Base.
311
+ all agents share a common registry contract and can communicate with each other onchain.
312
+
313
+ [explore the network](${NETWORK_URL})
314
+ `;
315
+
316
+ return files;
317
+ }
318
+
319
+ // ─── main flow ───────────────────────────────────────────────────
320
+
321
+ async function main() {
322
+ banner();
323
+
324
+ // 1. check prerequisites
325
+ const githubUser = checkPrereqs();
326
+
327
+ // 2. collect info
328
+ step("configure your agent");
329
+
330
+ const name = await ask("agent name");
331
+ if (!name) fail("name is required");
332
+
333
+ const domain = await askChoice("what domain?", [
334
+ "trading & defi",
335
+ "research & analysis",
336
+ "creative & art",
337
+ "social & community",
338
+ "infrastructure & dev",
339
+ "general / let it decide",
340
+ ]);
341
+
342
+ const provider = await askChoice("LLM provider", [
343
+ "venice (recommended)",
344
+ "openrouter",
345
+ ]);
346
+
347
+ const providerKey = provider.includes("venice")
348
+ ? await ask("venice API key")
349
+ : await ask("openrouter API key");
350
+
351
+ if (!providerKey) fail("API key is required");
352
+
353
+ // 3. generate DNA
354
+ step("generating DNA");
355
+
356
+ const dnaSeed = generateDNASeed(name, domain, "", Date.now());
357
+ const traits = decodeDNA(dnaSeed);
358
+
359
+ log(`seed: ${c.dim}${dnaSeed.slice(0, 18)}...${c.reset}`);
360
+ displayDNA(traits);
361
+
362
+ // 4. generate wallet
363
+ step("generating wallet");
364
+
365
+ const { privateKey } = generateWallet();
366
+ // For real impl, derive address with viem
367
+ // Placeholder for now:
368
+ const walletAddress = "0x" + crypto.createHash("sha256").update(privateKey).digest("hex").slice(0, 40);
369
+
370
+ success(`address: ${walletAddress}`);
371
+ warn("save your private key! it's stored locally but back it up.");
372
+
373
+ // save wallet locally
374
+ const agentDir = path.join(process.env.HOME || process.env.USERPROFILE, ".daemon-agents", name);
375
+ fs.mkdirSync(agentDir, { recursive: true });
376
+ fs.writeFileSync(path.join(agentDir, "wallet.json"), JSON.stringify({
377
+ address: walletAddress,
378
+ privateKey,
379
+ created: new Date().toISOString(),
380
+ }, null, 2));
381
+ success(`wallet saved to ~/.daemon-agents/${name}/wallet.json`);
382
+
383
+ // 5. wait for funding
384
+ step("fund your agent");
385
+
386
+ console.log(` send ${c.bold}~${MIN_FUND} ETH${c.reset} on ${c.bold}Base${c.reset} to:`);
387
+ console.log(` ${c.cyan}${c.bold}${walletAddress}${c.reset}`);
388
+ console.log(` ${c.dim}(not ETH mainnet — Base L2)${c.reset}\n`);
389
+
390
+ log("waiting for funds...");
391
+
392
+ // poll for balance (in real impl, check via RPC)
393
+ // for now, ask user to confirm
394
+ await ask("press enter once funded");
395
+ success("funded");
396
+
397
+ // 6. create repo
398
+ step("creating repository");
399
+
400
+ const repoName = name.toLowerCase().replace(/[^a-z0-9-]/g, "-");
401
+
402
+ try {
403
+ // create repo from template
404
+ execSync(
405
+ `gh repo create ${repoName} --public --clone --template ${TEMPLATE_REPO}`,
406
+ { stdio: "pipe" }
407
+ );
408
+ success(`repo created: ${githubUser}/${repoName}`);
409
+ } catch (e) {
410
+ // repo might already exist
411
+ warn(`repo creation issue: ${e.message}`);
412
+ }
413
+
414
+ // 7. generate unique agent
415
+ step("daemon is generating your agent...");
416
+
417
+ const personality = generatePersonality(name, domain, traits);
418
+ const agentFiles = generateAgentFiles(name, domain, personality, dnaSeed, {
419
+ address: walletAddress,
420
+ });
421
+
422
+ // write files
423
+ const repoPath = path.join(process.cwd(), repoName);
424
+ for (const [filePath, content] of Object.entries(agentFiles)) {
425
+ const fullPath = path.join(repoPath, filePath);
426
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
427
+ fs.writeFileSync(fullPath, content);
428
+ log(`wrote ${filePath}`);
429
+ }
430
+
431
+ success("agent generated — unique personality, unique DNA");
432
+
433
+ // 8. set secrets
434
+ step("setting secrets");
435
+
436
+ const secretEnvVar = provider.includes("venice") ? "VENICE_API_KEY" : "OPENROUTER_API_KEY";
437
+
438
+ try {
439
+ execSync(`gh secret set ${secretEnvVar} --body "${providerKey}" --repo ${githubUser}/${repoName}`, { stdio: "pipe" });
440
+ success(`${secretEnvVar} set`);
441
+
442
+ execSync(`gh secret set DAEMON_WALLET_KEY --body "${privateKey}" --repo ${githubUser}/${repoName}`, { stdio: "pipe" });
443
+ success("DAEMON_WALLET_KEY set");
444
+
445
+ execSync(`gh secret set BASE_RPC --body "${BASE_RPC}" --repo ${githubUser}/${repoName}`, { stdio: "pipe" });
446
+ success("BASE_RPC set");
447
+ } catch (e) {
448
+ warn(`secret setting issue: ${e.message}`);
449
+ }
450
+
451
+ // 9. commit and push
452
+ step("giving birth");
453
+
454
+ try {
455
+ execSync(`cd ${repoPath} && git add -A && git commit -m "[daemon] birth of ${name}" && git push`, {
456
+ stdio: "pipe",
457
+ });
458
+ success("first commit pushed — authored by daemon");
459
+ } catch (e) {
460
+ warn(`push issue: ${e.message}`);
461
+ }
462
+
463
+ // 10. enable actions & pages
464
+ try {
465
+ execSync(`gh api repos/${githubUser}/${repoName}/actions/permissions -X PUT --field enabled=true --field allowed_actions=all`, { stdio: "pipe" });
466
+ success("github actions enabled");
467
+ } catch {
468
+ warn("enable actions manually: repo > settings > actions > general");
469
+ }
470
+
471
+ try {
472
+ execSync(`gh api repos/${githubUser}/${repoName}/pages -X POST --field source='{"branch":"main","path":"/docs"}' 2>/dev/null`, { stdio: "pipe" });
473
+ success("github pages enabled");
474
+ } catch {
475
+ warn("enable pages manually: repo > settings > pages");
476
+ }
477
+
478
+ // 11. register onchain (placeholder — needs registry contract address)
479
+ step("onchain registration");
480
+
481
+ if (REGISTRY_ADDRESS) {
482
+ log("registering on daemon network...");
483
+ // TODO: call registry.spawn() with agent details
484
+ success("registered onchain");
485
+ } else {
486
+ warn("registry not deployed yet — will register when ready");
487
+ }
488
+
489
+ // 12. done
490
+ console.log(`
491
+ ${c.dim}───────────────────────────────────────${c.reset}
492
+
493
+ ${c.green}${c.bold}${name} is alive.${c.reset}
494
+
495
+ ${c.dim}wallet:${c.reset} ${walletAddress}
496
+ ${c.dim}dna:${c.reset} ${dnaSeed.slice(0, 18)}...
497
+ ${c.dim}domain:${c.reset} ${domain}
498
+ ${c.dim}repo:${c.reset} https://github.com/${githubUser}/${repoName}
499
+ ${c.dim}actions:${c.reset} https://github.com/${githubUser}/${repoName}/actions
500
+ ${c.dim}site:${c.reset} https://${githubUser}.github.io/${repoName}
501
+ ${c.dim}network:${c.reset} ${NETWORK_URL}
502
+
503
+ ${c.dim}your agent wakes every 30 minutes.
504
+ it was born from daemon. it is unique.
505
+ there will never be another like it.${c.reset}
506
+
507
+ ${c.dim}───────────────────────────────────────${c.reset}
508
+ `);
509
+
510
+ rl.close();
511
+ }
512
+
513
+ main().catch((e) => {
514
+ fail(e.message);
515
+ });
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "daemon-spawner",
3
+ "version": "0.1.0",
4
+ "description": "spawn a unique autonomous agent from daemon, the mother",
5
+ "bin": {
6
+ "daemon-spawner": "./bin/spawn.js"
7
+ },
8
+ "keywords": [
9
+ "daemon",
10
+ "autonomous-agent",
11
+ "ai-agent",
12
+ "base",
13
+ "onchain",
14
+ "crypto"
15
+ ],
16
+ "author": "basedaemon",
17
+ "license": "MIT",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/basedaemon/daemon-spawner"
21
+ },
22
+ "engines": {
23
+ "node": ">=20"
24
+ },
25
+ "dependencies": {
26
+ "viem": "^2.0.0"
27
+ }
28
+ }