@innominatum/agentforge-cli 1.0.8 → 1.1.3
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.
- package/dist/index.js +83 -30
- package/package.json +1 -1
- package/src/index.ts +92 -31
- package/templates/CLI_MANUAL.md +22 -6
package/dist/index.js
CHANGED
|
@@ -52,7 +52,7 @@ function confirmOverwrite(entityType) {
|
|
|
52
52
|
output: process.stdout
|
|
53
53
|
});
|
|
54
54
|
return new Promise(resolve => {
|
|
55
|
-
rl.question(`⚠️ Atenção: O pull irá
|
|
55
|
+
rl.question(`⚠️ Atenção: O pull irá APAGAR as suas ${entityType} locais e substituí-las pelo estado do servidor. Quaisquer alterações ou entidades não publicadas serão PERDIDAS. Deseja continuar? (s/N) `, answer => {
|
|
56
56
|
rl.close();
|
|
57
57
|
const isYes = answer.toLowerCase() === 's' || answer.toLowerCase() === 'sim' || answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
|
|
58
58
|
resolve(isYes);
|
|
@@ -175,7 +175,7 @@ newCmd
|
|
|
175
175
|
const agentJson = {
|
|
176
176
|
agent_key: slug,
|
|
177
177
|
display_name: name,
|
|
178
|
-
agent_type: "
|
|
178
|
+
agent_type: "predefined",
|
|
179
179
|
status: "active",
|
|
180
180
|
emoji: "🔥",
|
|
181
181
|
context_window: 200000,
|
|
@@ -198,7 +198,7 @@ newCmd
|
|
|
198
198
|
const agentJson = {
|
|
199
199
|
agent_key: slug,
|
|
200
200
|
display_name: name,
|
|
201
|
-
agent_type: "
|
|
201
|
+
agent_type: "predefined",
|
|
202
202
|
provider: config.goclaw?.default_provider || "ollama cloud",
|
|
203
203
|
model: config.goclaw?.default_model || "deepseek-v4-pro",
|
|
204
204
|
other_config: {
|
|
@@ -420,6 +420,38 @@ async function deployContextFiles(slug, config, resolvedId) {
|
|
|
420
420
|
await fs_extra_1.default.remove(tarPath);
|
|
421
421
|
}
|
|
422
422
|
}
|
|
423
|
+
async function deployAgent(slug, config) {
|
|
424
|
+
const basePath = getWorkspaceRoot();
|
|
425
|
+
const agentPath = path_1.default.join(basePath, "agents", slug);
|
|
426
|
+
const agentJsonPath = path_1.default.join(agentPath, "agent.json");
|
|
427
|
+
if (!(await fs_extra_1.default.pathExists(agentJsonPath))) {
|
|
428
|
+
console.error(`❌ agent.json não encontrado em agents/${slug}.`);
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
const agentConfig = await fs_extra_1.default.readJson(agentJsonPath);
|
|
432
|
+
console.log(`🚀 Sincronizando agente "${slug}"...`);
|
|
433
|
+
try {
|
|
434
|
+
const agentId = await resolveAgentId(slug, config);
|
|
435
|
+
const exists = agentId !== null;
|
|
436
|
+
if (!exists) {
|
|
437
|
+
await axios_1.default.post(`${config.goclaw.api_url}/v1/agents`, agentConfig, {
|
|
438
|
+
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
439
|
+
});
|
|
440
|
+
console.log(`✅ Agente "${slug}" criado.`);
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
await axios_1.default.put(`${config.goclaw.api_url}/v1/agents/${agentId}`, agentConfig, {
|
|
444
|
+
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
445
|
+
});
|
|
446
|
+
console.log(`✅ Configuração de "${slug}" atualizada.`);
|
|
447
|
+
}
|
|
448
|
+
await deployContextFiles(slug, config, agentId);
|
|
449
|
+
console.log(`✅ Agente "${slug}" sincronizado com sucesso!`);
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
console.error(`❌ Erro no deploy de "${slug}":`, error.response?.data || error.message);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
423
455
|
deployCmd
|
|
424
456
|
.command("context <slug>")
|
|
425
457
|
.description("Faz upload dos arquivos de contexto diretamente para o agente usando a API de importação")
|
|
@@ -447,37 +479,32 @@ deployCmd
|
|
|
447
479
|
console.error("❌ Configure sua chave de API (token) no agentforge.json.");
|
|
448
480
|
process.exit(1);
|
|
449
481
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
482
|
+
await deployAgent(slug, config);
|
|
483
|
+
});
|
|
484
|
+
deployCmd
|
|
485
|
+
.command("all")
|
|
486
|
+
.description("Faz deploy de todos os agentes do workspace")
|
|
487
|
+
.action(async () => {
|
|
488
|
+
const config = await getConfig();
|
|
489
|
+
if (!config.goclaw || !config.goclaw.token) {
|
|
490
|
+
console.error("❌ Configure sua chave de API (token) no agentforge.json.");
|
|
455
491
|
process.exit(1);
|
|
456
492
|
}
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
if (!exists) {
|
|
463
|
-
await axios_1.default.post(`${config.goclaw.api_url}/v1/agents`, agentConfig, {
|
|
464
|
-
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
465
|
-
});
|
|
466
|
-
console.log("✅ Agente criado com sucesso.");
|
|
467
|
-
}
|
|
468
|
-
else {
|
|
469
|
-
await axios_1.default.put(`${config.goclaw.api_url}/v1/agents/${agentId}`, agentConfig, {
|
|
470
|
-
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
471
|
-
});
|
|
472
|
-
console.log("✅ Configurações do agente atualizadas.");
|
|
473
|
-
}
|
|
474
|
-
console.log(`🚀 Sincronizando arquivos de contexto...`);
|
|
475
|
-
await deployContextFiles(slug, config, agentId);
|
|
476
|
-
console.log("✅ Deploy completo concluído!");
|
|
493
|
+
const basePath = getWorkspaceRoot();
|
|
494
|
+
const agentsDir = path_1.default.join(basePath, "agents");
|
|
495
|
+
if (!(await fs_extra_1.default.pathExists(agentsDir))) {
|
|
496
|
+
console.log("Nenhum agente encontrado em agents/.");
|
|
497
|
+
return;
|
|
477
498
|
}
|
|
478
|
-
|
|
479
|
-
|
|
499
|
+
const agents = await fs_extra_1.default.readdir(agentsDir);
|
|
500
|
+
console.log(`🚀 Iniciando deploy em lote de ${agents.length} agentes...`);
|
|
501
|
+
for (const slug of agents) {
|
|
502
|
+
const agentPath = path_1.default.join(agentsDir, slug);
|
|
503
|
+
if ((await fs_extra_1.default.stat(agentPath)).isDirectory()) {
|
|
504
|
+
await deployAgent(slug, config);
|
|
505
|
+
}
|
|
480
506
|
}
|
|
507
|
+
console.log("🏁 Deploy em lote concluído!");
|
|
481
508
|
});
|
|
482
509
|
const pullCmd = program
|
|
483
510
|
.command("pull")
|
|
@@ -495,6 +522,8 @@ pullCmd
|
|
|
495
522
|
console.log("❌ Pull cancelado pelo utilizador.");
|
|
496
523
|
return;
|
|
497
524
|
}
|
|
525
|
+
console.log("🧹 Limpando a pasta local de skills...");
|
|
526
|
+
await fs_extra_1.default.emptyDir(path_1.default.join(getWorkspaceRoot(), "skills"));
|
|
498
527
|
console.log("📥 Baixando skills do GoClaw...");
|
|
499
528
|
try {
|
|
500
529
|
const url = `${config.goclaw.api_url}${config.goclaw.skills_export_endpoint || '/v1/skills/export'}`;
|
|
@@ -553,6 +582,28 @@ pullCmd
|
|
|
553
582
|
console.warn(`⚠️ Não foi possível transferir os ficheiros da skill ${skill.slug}: ${fileErr.message}`);
|
|
554
583
|
}
|
|
555
584
|
}
|
|
585
|
+
// Remover quaisquer skills fantasmas que o tarball tenha extraído (skills apagadas mas ainda no export)
|
|
586
|
+
const validSlugs = new Set(skills.map((s) => s.is_system === true ? path_1.default.join("system", s.slug) : s.slug));
|
|
587
|
+
const skillsDir = path_1.default.join(getWorkspaceRoot(), "skills");
|
|
588
|
+
if (await fs_extra_1.default.pathExists(skillsDir)) {
|
|
589
|
+
const localItems = await fs_extra_1.default.readdir(skillsDir);
|
|
590
|
+
for (const item of localItems) {
|
|
591
|
+
if (item === "system") {
|
|
592
|
+
const systemDir = path_1.default.join(skillsDir, "system");
|
|
593
|
+
if (await fs_extra_1.default.pathExists(systemDir)) {
|
|
594
|
+
const systemItems = await fs_extra_1.default.readdir(systemDir);
|
|
595
|
+
for (const sysItem of systemItems) {
|
|
596
|
+
if (!validSlugs.has(path_1.default.join("system", sysItem))) {
|
|
597
|
+
await fs_extra_1.default.remove(path_1.default.join(systemDir, sysItem));
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
else if (!validSlugs.has(item)) {
|
|
603
|
+
await fs_extra_1.default.remove(path_1.default.join(skillsDir, item));
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
556
607
|
console.log("✅ Pull concluído com sucesso! As skills foram atualizadas localmente.");
|
|
557
608
|
}
|
|
558
609
|
catch (error) {
|
|
@@ -578,6 +629,8 @@ pullCmd
|
|
|
578
629
|
console.log("❌ Pull cancelado pelo utilizador.");
|
|
579
630
|
return;
|
|
580
631
|
}
|
|
632
|
+
console.log("🧹 Limpando a pasta local de agentes...");
|
|
633
|
+
await fs_extra_1.default.emptyDir(path_1.default.join(getWorkspaceRoot(), "agents"));
|
|
581
634
|
console.log("📥 Buscando lista de agentes do GoClaw...");
|
|
582
635
|
try {
|
|
583
636
|
const listResponse = await axios_1.default.get(`${config.goclaw.api_url}/v1/agents`, {
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -17,7 +17,7 @@ function confirmOverwrite(entityType: string): Promise<boolean> {
|
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
return new Promise(resolve => {
|
|
20
|
-
rl.question(`⚠️ Atenção: O pull irá
|
|
20
|
+
rl.question(`⚠️ Atenção: O pull irá APAGAR as suas ${entityType} locais e substituí-las pelo estado do servidor. Quaisquer alterações ou entidades não publicadas serão PERDIDAS. Deseja continuar? (s/N) `, answer => {
|
|
21
21
|
rl.close();
|
|
22
22
|
const isYes = answer.toLowerCase() === 's' || answer.toLowerCase() === 'sim' || answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
|
|
23
23
|
resolve(isYes);
|
|
@@ -163,7 +163,7 @@ newCmd
|
|
|
163
163
|
const agentJson = {
|
|
164
164
|
agent_key: slug,
|
|
165
165
|
display_name: name,
|
|
166
|
-
agent_type: "
|
|
166
|
+
agent_type: "predefined",
|
|
167
167
|
status: "active",
|
|
168
168
|
emoji: "🔥",
|
|
169
169
|
context_window: 200000,
|
|
@@ -186,7 +186,7 @@ newCmd
|
|
|
186
186
|
const agentJson = {
|
|
187
187
|
agent_key: slug,
|
|
188
188
|
display_name: name,
|
|
189
|
-
agent_type: "
|
|
189
|
+
agent_type: "predefined",
|
|
190
190
|
provider: config.goclaw?.default_provider || "ollama cloud",
|
|
191
191
|
model: config.goclaw?.default_model || "deepseek-v4-pro",
|
|
192
192
|
other_config: {
|
|
@@ -451,6 +451,42 @@ async function deployContextFiles(slug: string, config: any, resolvedId?: string
|
|
|
451
451
|
}
|
|
452
452
|
}
|
|
453
453
|
|
|
454
|
+
async function deployAgent(slug: string, config: any) {
|
|
455
|
+
const basePath = getWorkspaceRoot();
|
|
456
|
+
const agentPath = path.join(basePath, "agents", slug);
|
|
457
|
+
const agentJsonPath = path.join(agentPath, "agent.json");
|
|
458
|
+
|
|
459
|
+
if (!(await fs.pathExists(agentJsonPath))) {
|
|
460
|
+
console.error(`❌ agent.json não encontrado em agents/${slug}.`);
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const agentConfig = await fs.readJson(agentJsonPath);
|
|
465
|
+
console.log(`🚀 Sincronizando agente "${slug}"...`);
|
|
466
|
+
|
|
467
|
+
try {
|
|
468
|
+
const agentId = await resolveAgentId(slug, config);
|
|
469
|
+
const exists = agentId !== null;
|
|
470
|
+
|
|
471
|
+
if (!exists) {
|
|
472
|
+
await axios.post(`${config.goclaw.api_url}/v1/agents`, agentConfig, {
|
|
473
|
+
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
474
|
+
});
|
|
475
|
+
console.log(`✅ Agente "${slug}" criado.`);
|
|
476
|
+
} else {
|
|
477
|
+
await axios.put(`${config.goclaw.api_url}/v1/agents/${agentId}`, agentConfig, {
|
|
478
|
+
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
479
|
+
});
|
|
480
|
+
console.log(`✅ Configuração de "${slug}" atualizada.`);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
await deployContextFiles(slug, config, agentId);
|
|
484
|
+
console.log(`✅ Agente "${slug}" sincronizado com sucesso!`);
|
|
485
|
+
} catch (error: any) {
|
|
486
|
+
console.error(`❌ Erro no deploy de "${slug}":`, error.response?.data || error.message);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
454
490
|
deployCmd
|
|
455
491
|
.command("context <slug>")
|
|
456
492
|
.description("Faz upload dos arquivos de contexto diretamente para o agente usando a API de importação")
|
|
@@ -480,41 +516,38 @@ deployCmd
|
|
|
480
516
|
process.exit(1);
|
|
481
517
|
}
|
|
482
518
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
const agentJsonPath = path.join(agentPath, "agent.json");
|
|
519
|
+
await deployAgent(slug, config);
|
|
520
|
+
});
|
|
486
521
|
|
|
487
|
-
|
|
488
|
-
|
|
522
|
+
deployCmd
|
|
523
|
+
.command("all")
|
|
524
|
+
.description("Faz deploy de todos os agentes do workspace")
|
|
525
|
+
.action(async () => {
|
|
526
|
+
const config = await getConfig();
|
|
527
|
+
if (!config.goclaw || !config.goclaw.token) {
|
|
528
|
+
console.error("❌ Configure sua chave de API (token) no agentforge.json.");
|
|
489
529
|
process.exit(1);
|
|
490
530
|
}
|
|
491
531
|
|
|
492
|
-
const
|
|
493
|
-
|
|
532
|
+
const basePath = getWorkspaceRoot();
|
|
533
|
+
const agentsDir = path.join(basePath, "agents");
|
|
494
534
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if (!exists) {
|
|
500
|
-
await axios.post(`${config.goclaw.api_url}/v1/agents`, agentConfig, {
|
|
501
|
-
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
502
|
-
});
|
|
503
|
-
console.log("✅ Agente criado com sucesso.");
|
|
504
|
-
} else {
|
|
505
|
-
await axios.put(`${config.goclaw.api_url}/v1/agents/${agentId}`, agentConfig, {
|
|
506
|
-
headers: { Authorization: `Bearer ${config.goclaw.token}`, "X-GoClaw-User-Id": config.goclaw.username || "system" }
|
|
507
|
-
});
|
|
508
|
-
console.log("✅ Configurações do agente atualizadas.");
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
console.log(`🚀 Sincronizando arquivos de contexto...`);
|
|
512
|
-
await deployContextFiles(slug, config, agentId);
|
|
535
|
+
if (!(await fs.pathExists(agentsDir))) {
|
|
536
|
+
console.log("Nenhum agente encontrado em agents/.");
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
513
539
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
540
|
+
const agents = await fs.readdir(agentsDir);
|
|
541
|
+
console.log(`🚀 Iniciando deploy em lote de ${agents.length} agentes...`);
|
|
542
|
+
|
|
543
|
+
for (const slug of agents) {
|
|
544
|
+
const agentPath = path.join(agentsDir, slug);
|
|
545
|
+
if ((await fs.stat(agentPath)).isDirectory()) {
|
|
546
|
+
await deployAgent(slug, config);
|
|
547
|
+
}
|
|
517
548
|
}
|
|
549
|
+
|
|
550
|
+
console.log("🏁 Deploy em lote concluído!");
|
|
518
551
|
});
|
|
519
552
|
|
|
520
553
|
const pullCmd = program
|
|
@@ -536,6 +569,9 @@ pullCmd
|
|
|
536
569
|
return;
|
|
537
570
|
}
|
|
538
571
|
|
|
572
|
+
console.log("🧹 Limpando a pasta local de skills...");
|
|
573
|
+
await fs.emptyDir(path.join(getWorkspaceRoot(), "skills"));
|
|
574
|
+
|
|
539
575
|
console.log("📥 Baixando skills do GoClaw...");
|
|
540
576
|
try {
|
|
541
577
|
const url = `${config.goclaw.api_url}${config.goclaw.skills_export_endpoint || '/v1/skills/export'}`;
|
|
@@ -601,6 +637,28 @@ pullCmd
|
|
|
601
637
|
}
|
|
602
638
|
}
|
|
603
639
|
|
|
640
|
+
// Remover quaisquer skills fantasmas que o tarball tenha extraído (skills apagadas mas ainda no export)
|
|
641
|
+
const validSlugs = new Set(skills.map((s: any) => s.is_system === true ? path.join("system", s.slug) : s.slug));
|
|
642
|
+
const skillsDir = path.join(getWorkspaceRoot(), "skills");
|
|
643
|
+
if (await fs.pathExists(skillsDir)) {
|
|
644
|
+
const localItems = await fs.readdir(skillsDir);
|
|
645
|
+
for (const item of localItems) {
|
|
646
|
+
if (item === "system") {
|
|
647
|
+
const systemDir = path.join(skillsDir, "system");
|
|
648
|
+
if (await fs.pathExists(systemDir)) {
|
|
649
|
+
const systemItems = await fs.readdir(systemDir);
|
|
650
|
+
for (const sysItem of systemItems) {
|
|
651
|
+
if (!validSlugs.has(path.join("system", sysItem))) {
|
|
652
|
+
await fs.remove(path.join(systemDir, sysItem));
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
} else if (!validSlugs.has(item)) {
|
|
657
|
+
await fs.remove(path.join(skillsDir, item));
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
604
662
|
console.log("✅ Pull concluído com sucesso! As skills foram atualizadas localmente.");
|
|
605
663
|
} catch (error: any) {
|
|
606
664
|
console.error("❌ Erro durante o pull das skills:");
|
|
@@ -627,6 +685,9 @@ pullCmd
|
|
|
627
685
|
return;
|
|
628
686
|
}
|
|
629
687
|
|
|
688
|
+
console.log("🧹 Limpando a pasta local de agentes...");
|
|
689
|
+
await fs.emptyDir(path.join(getWorkspaceRoot(), "agents"));
|
|
690
|
+
|
|
630
691
|
console.log("📥 Buscando lista de agentes do GoClaw...");
|
|
631
692
|
try {
|
|
632
693
|
const listResponse = await axios.get(`${config.goclaw.api_url}/v1/agents`, {
|
package/templates/CLI_MANUAL.md
CHANGED
|
@@ -41,26 +41,32 @@ agentforge pull all
|
|
|
41
41
|
```
|
|
42
42
|
Downloads all agents and skills from the GoClaw server. It performs a **surgical extraction**, retrieving only the core `agent.json`, `context_files/`, and skill definitions to keep your workspace perfectly clean. Note: This will ask for confirmation before overwriting local files.
|
|
43
43
|
|
|
44
|
+
### Bulk Deployment
|
|
45
|
+
```bash
|
|
46
|
+
agentforge deploy all
|
|
47
|
+
```
|
|
48
|
+
Performs a full deployment (config + context + memory) for **all agents** found in your `agents/` directory. This is the most efficient way to synchronize your entire team after making cross-cutting changes.
|
|
49
|
+
|
|
44
50
|
### Agent Management
|
|
45
51
|
```bash
|
|
46
52
|
agentforge new agent "<Agent Name>"
|
|
47
53
|
```
|
|
48
|
-
Creates a new agent inside the `agents/` directory
|
|
54
|
+
Creates a new agent inside the `agents/` directory. The default `agent_type` is now `predefined`, aligning with GoClaw's official standard for agents with established personalities.
|
|
49
55
|
|
|
50
56
|
```bash
|
|
51
57
|
agentforge pull agents
|
|
52
58
|
```
|
|
53
|
-
Downloads all agents from the GoClaw server and extracts them locally.
|
|
59
|
+
Downloads all agents from the GoClaw server and extracts them locally. It automatically reconstructs memory files from GoClaw's internal JSONL format back into readable Markdown files.
|
|
54
60
|
|
|
55
61
|
```bash
|
|
56
62
|
agentforge deploy agent <slug>
|
|
57
63
|
```
|
|
58
|
-
**Full Deployment:** Reads the local `agent.json` to create
|
|
64
|
+
**Full Deployment:** Reads the local `agent.json` to create or update an agent. Then, it synchronizes all context files and memory (including `MEMORY.md` and the `memory/` folder).
|
|
59
65
|
|
|
60
66
|
```bash
|
|
61
67
|
agentforge deploy context <slug>
|
|
62
68
|
```
|
|
63
|
-
**Hot Reload for Context:** Fast-path deployment that
|
|
69
|
+
**Hot Reload for Context & Memory:** Fast-path deployment that uploads all local context files (`.md`, `.txt`, `.py`) and memory data directly to the server.
|
|
64
70
|
|
|
65
71
|
### Skill Management
|
|
66
72
|
```bash
|
|
@@ -83,8 +89,18 @@ agentforge deploy skill <slug>
|
|
|
83
89
|
```
|
|
84
90
|
Automatically builds your skill into a `.zip` file and securely uploads it to your GoClaw server via the Upload API.
|
|
85
91
|
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Memory Support 🧠
|
|
95
|
+
AgentForge CLI handles agent memory as first-class citizens:
|
|
96
|
+
- **MEMORY.md**: Use this file at the root of your agent folder for curated, long-term memory.
|
|
97
|
+
- **memory/**: Any files inside this folder (e.g., chat histories, user-specific facts) are synchronized.
|
|
98
|
+
- **Auto-Conversion**: When pulling, the CLI converts GoClaw's `.jsonl` exports back into `.md` files for easier editing in VS Code.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Configuration
|
|
103
|
+
Before using the deployment commands, make sure to add your GoClaw Bearer Token to the `agentforge.json` file:
|
|
88
104
|
|
|
89
105
|
```json
|
|
90
106
|
{
|