ocerebro 0.1.2 → 0.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/package.json +2 -2
- package/pyproject.toml +1 -1
- package/src/cli/main.py +48 -185
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ocerebro",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "OCerebro - Sistema de Memoria para Agentes (Claude Code/MCP)",
|
|
5
5
|
"main": "bin/ocerebro.js",
|
|
6
6
|
"bin": {
|
|
@@ -46,4 +46,4 @@
|
|
|
46
46
|
"publishConfig": {
|
|
47
47
|
"access": "public"
|
|
48
48
|
}
|
|
49
|
-
}
|
|
49
|
+
}
|
package/pyproject.toml
CHANGED
package/src/cli/main.py
CHANGED
|
@@ -38,35 +38,24 @@ class CerebroCLI:
|
|
|
38
38
|
"""
|
|
39
39
|
|
|
40
40
|
def __init__(self, cerebro_path: Path):
|
|
41
|
-
"""
|
|
42
|
-
Inicializa a CLI.
|
|
43
|
-
|
|
44
|
-
Args:
|
|
45
|
-
cerebro_path: Diretório base do Cerebro
|
|
46
|
-
"""
|
|
47
41
|
self.cerebro_path = cerebro_path
|
|
48
42
|
self.cerebro_path.mkdir(parents=True, exist_ok=True)
|
|
49
43
|
|
|
50
|
-
# Inicializa storages
|
|
51
44
|
self.raw_storage = JSONLStorage(cerebro_path / "raw")
|
|
52
45
|
self.working_storage = YAMLStorage(cerebro_path / "working")
|
|
53
46
|
self.official_storage = MarkdownStorage(cerebro_path / "official")
|
|
54
47
|
self.session_manager = SessionManager(cerebro_path)
|
|
55
48
|
|
|
56
|
-
# Inicializa índice
|
|
57
49
|
self.metadata_db = MetadataDB(cerebro_path / "index" / "metadata.db")
|
|
58
50
|
self.embeddings_db = EmbeddingsDB(cerebro_path / "index" / "embeddings.db")
|
|
59
51
|
self.query_engine = QueryEngine(self.metadata_db, self.embeddings_db)
|
|
60
52
|
|
|
61
|
-
# Inicializa consolidação
|
|
62
53
|
self.checkpoint_manager = CheckpointManager(cerebro_path / "config")
|
|
63
54
|
self.extractor = Extractor(self.raw_storage, self.working_storage)
|
|
64
55
|
self.promoter = Promoter(self.working_storage, self.official_storage)
|
|
65
56
|
|
|
66
|
-
# Inicializa memory view
|
|
67
57
|
self.memory_view = MemoryView(cerebro_path, self.official_storage, self.working_storage)
|
|
68
58
|
|
|
69
|
-
# Inicializa memory diff
|
|
70
59
|
self.memory_diff = MemoryDiff(
|
|
71
60
|
self.official_storage,
|
|
72
61
|
self.working_storage,
|
|
@@ -74,21 +63,9 @@ class CerebroCLI:
|
|
|
74
63
|
)
|
|
75
64
|
|
|
76
65
|
def checkpoint(self, project: str, session_id: Optional[str] = None, reason: str = "manual") -> str:
|
|
77
|
-
"""
|
|
78
|
-
Trigger manual de checkpoint.
|
|
79
|
-
|
|
80
|
-
Args:
|
|
81
|
-
project: Nome do projeto
|
|
82
|
-
session_id: ID da sessão (usa atual se None)
|
|
83
|
-
reason: Motivo do checkpoint
|
|
84
|
-
|
|
85
|
-
Returns:
|
|
86
|
-
Mensagem de resultado
|
|
87
|
-
"""
|
|
88
66
|
if session_id is None:
|
|
89
67
|
session_id = self.session_manager.get_session_id()
|
|
90
68
|
|
|
91
|
-
# Extrai sessão
|
|
92
69
|
try:
|
|
93
70
|
result = self.extractor.extract_session(project, session_id)
|
|
94
71
|
except Exception as e:
|
|
@@ -97,14 +74,10 @@ class CerebroCLI:
|
|
|
97
74
|
if not result.events:
|
|
98
75
|
return f"Nenhum evento encontrado para sessão {session_id}"
|
|
99
76
|
|
|
100
|
-
# Cria draft
|
|
101
77
|
draft = self.extractor.create_draft(result, "session")
|
|
102
78
|
draft["checkpoint_reason"] = reason
|
|
103
|
-
|
|
104
|
-
# Escreve draft
|
|
105
79
|
draft_name = self.extractor.write_draft(project, draft, "session")
|
|
106
80
|
|
|
107
|
-
# Registra evento de checkpoint
|
|
108
81
|
from src.core.event_schema import Event, EventType, EventOrigin
|
|
109
82
|
checkpoint_event = Event(
|
|
110
83
|
project=project,
|
|
@@ -119,26 +92,13 @@ class CerebroCLI:
|
|
|
119
92
|
}
|
|
120
93
|
)
|
|
121
94
|
self.raw_storage.append(checkpoint_event)
|
|
122
|
-
|
|
123
95
|
return f"Checkpoint criado: {draft_name} ({len(result.events)} eventos)"
|
|
124
96
|
|
|
125
97
|
def memory(self, project: str, output: Optional[Path] = None) -> str:
|
|
126
|
-
"""
|
|
127
|
-
Gera visualização da memória ativa.
|
|
128
|
-
|
|
129
|
-
Args:
|
|
130
|
-
project: Nome do projeto
|
|
131
|
-
output: Arquivo de saída (opcional)
|
|
132
|
-
|
|
133
|
-
Returns:
|
|
134
|
-
Conteúdo do MEMORY.md
|
|
135
|
-
"""
|
|
136
98
|
content = self.memory_view.generate(project)
|
|
137
|
-
|
|
138
99
|
if output:
|
|
139
100
|
output.write_text(content, encoding="utf-8")
|
|
140
101
|
return f"MEMORY.md gerado em: {output}"
|
|
141
|
-
|
|
142
102
|
return content
|
|
143
103
|
|
|
144
104
|
def search(
|
|
@@ -149,19 +109,6 @@ class CerebroCLI:
|
|
|
149
109
|
limit: int = 10,
|
|
150
110
|
use_semantic: bool = True
|
|
151
111
|
) -> str:
|
|
152
|
-
"""
|
|
153
|
-
Busca memórias.
|
|
154
|
-
|
|
155
|
-
Args:
|
|
156
|
-
query: Texto de busca
|
|
157
|
-
project: Filtrar por projeto
|
|
158
|
-
mem_type: Filtrar por tipo
|
|
159
|
-
limit: Limite de resultados
|
|
160
|
-
use_semantic: Usar busca semântica
|
|
161
|
-
|
|
162
|
-
Returns:
|
|
163
|
-
Resultados formatados
|
|
164
|
-
"""
|
|
165
112
|
results = self.query_engine.search(
|
|
166
113
|
query=query,
|
|
167
114
|
project=project,
|
|
@@ -180,7 +127,6 @@ class CerebroCLI:
|
|
|
180
127
|
if r.metadata:
|
|
181
128
|
if r.metadata.get("tags"):
|
|
182
129
|
lines.append(f" Tags: {r.metadata['tags']}")
|
|
183
|
-
|
|
184
130
|
return "\n".join(lines)
|
|
185
131
|
|
|
186
132
|
def promote(
|
|
@@ -190,18 +136,6 @@ class CerebroCLI:
|
|
|
190
136
|
draft_type: str = "session",
|
|
191
137
|
promote_to: str = "decision"
|
|
192
138
|
) -> str:
|
|
193
|
-
"""
|
|
194
|
-
Promove draft para official.
|
|
195
|
-
|
|
196
|
-
Args:
|
|
197
|
-
project: Nome do projeto
|
|
198
|
-
draft_id: ID do draft
|
|
199
|
-
draft_type: Tipo do draft
|
|
200
|
-
promote_to: Tipo de promoção
|
|
201
|
-
|
|
202
|
-
Returns:
|
|
203
|
-
Mensagem de resultado
|
|
204
|
-
"""
|
|
205
139
|
if draft_type == "session":
|
|
206
140
|
result = self.promoter.promote_session(project, draft_id, promote_to)
|
|
207
141
|
elif draft_type == "feature":
|
|
@@ -213,10 +147,8 @@ class CerebroCLI:
|
|
|
213
147
|
return "Draft não encontrado ou não pôde ser promovido."
|
|
214
148
|
|
|
215
149
|
if result.success:
|
|
216
|
-
# Marca como promovido
|
|
217
150
|
self.promoter.mark_promoted(project, draft_id, draft_type, result)
|
|
218
151
|
|
|
219
|
-
# Registra evento
|
|
220
152
|
from src.core.event_schema import Event, EventType, EventOrigin
|
|
221
153
|
promotion_event = Event(
|
|
222
154
|
project=project,
|
|
@@ -231,38 +163,21 @@ class CerebroCLI:
|
|
|
231
163
|
}
|
|
232
164
|
)
|
|
233
165
|
self.raw_storage.append(promotion_event)
|
|
234
|
-
|
|
235
166
|
return f"Promovido para: {result.target_path}"
|
|
236
167
|
else:
|
|
237
168
|
return f"Promoção falhou: {result.metadata.get('reason', 'desconhecido')}"
|
|
238
169
|
|
|
239
170
|
def gc(self, project: Optional[str] = None, dry_run: bool = True) -> str:
|
|
240
|
-
"""
|
|
241
|
-
Garbage collection manual.
|
|
242
|
-
|
|
243
|
-
Args:
|
|
244
|
-
project: Nome do projeto (None para todos)
|
|
245
|
-
dry_run: Apenas simular
|
|
246
|
-
|
|
247
|
-
Returns:
|
|
248
|
-
Relatório de GC
|
|
249
|
-
"""
|
|
250
171
|
from src.forgetting.guard_rails import GuardRails
|
|
251
172
|
from src.forgetting.gc import GarbageCollector
|
|
252
173
|
|
|
253
174
|
guard_rails = GuardRails(self.cerebro_path / "config" / "cerebro.yaml")
|
|
254
175
|
gc = GarbageCollector(self.cerebro_path / "config")
|
|
255
|
-
|
|
256
|
-
# Lista memórias do índice
|
|
257
176
|
memories = self.metadata_db.search(project)
|
|
258
|
-
|
|
259
|
-
# Encontra candidatos para archive
|
|
260
177
|
archive_candidates = gc.find_candidates_for_archive(
|
|
261
178
|
memories,
|
|
262
179
|
guard_rails.get_archive_threshold("raw")
|
|
263
180
|
)
|
|
264
|
-
|
|
265
|
-
# Filtra por guard rails
|
|
266
181
|
delete_candidates = [
|
|
267
182
|
m for m in archive_candidates
|
|
268
183
|
if guard_rails.can_delete(m)
|
|
@@ -284,34 +199,17 @@ class CerebroCLI:
|
|
|
284
199
|
return "\n".join(lines)
|
|
285
200
|
|
|
286
201
|
def status(self) -> str:
|
|
287
|
-
"""
|
|
288
|
-
Status do sistema.
|
|
289
|
-
|
|
290
|
-
Returns:
|
|
291
|
-
Relatório de status
|
|
292
|
-
"""
|
|
293
202
|
lines = ["Status do Cerebro:\n"]
|
|
294
|
-
|
|
295
|
-
# Session atual
|
|
296
203
|
session_id = self.session_manager.get_session_id()
|
|
297
204
|
lines.append(f"Session ID: {session_id}")
|
|
298
|
-
|
|
299
|
-
# Stats do raw
|
|
300
205
|
lines.append(f"\nRaw storage: {self.cerebro_path / 'raw'}")
|
|
301
|
-
|
|
302
|
-
# Stats do working
|
|
303
206
|
lines.append(f"Working storage: {self.cerebro_path / 'working'}")
|
|
304
|
-
|
|
305
|
-
# Stats do official
|
|
306
207
|
lines.append(f"Official storage: {self.cerebro_path / 'official'}")
|
|
307
|
-
|
|
308
|
-
# Stats do índice
|
|
309
208
|
try:
|
|
310
209
|
stats = self.metadata_db.search()
|
|
311
210
|
lines.append(f"\nÍndice: {len(stats)} memórias")
|
|
312
211
|
except Exception:
|
|
313
212
|
lines.append("\nÍndice: não disponível")
|
|
314
|
-
|
|
315
213
|
return "\n".join(lines)
|
|
316
214
|
|
|
317
215
|
def diff(
|
|
@@ -324,21 +222,6 @@ class CerebroCLI:
|
|
|
324
222
|
output: Optional[Path] = None,
|
|
325
223
|
format: str = "markdown"
|
|
326
224
|
) -> str:
|
|
327
|
-
"""
|
|
328
|
-
Analisa diferenças de memória entre dois pontos no tempo.
|
|
329
|
-
|
|
330
|
-
Args:
|
|
331
|
-
project: Nome do projeto
|
|
332
|
-
period_days: Dias do período (ex: 7, 30)
|
|
333
|
-
start_date: Data de início explícita (ISO string)
|
|
334
|
-
end_date: Data de fim explícita (ISO string)
|
|
335
|
-
gc_threshold: Threshold para garbage collection risk
|
|
336
|
-
output: Arquivo de saída (opcional)
|
|
337
|
-
format: Formato de saída (markdown, json)
|
|
338
|
-
|
|
339
|
-
Returns:
|
|
340
|
-
Relatório de Memory Diff
|
|
341
|
-
"""
|
|
342
225
|
result = self.memory_diff.analyze(
|
|
343
226
|
project=project,
|
|
344
227
|
period_days=period_days,
|
|
@@ -346,26 +229,13 @@ class CerebroCLI:
|
|
|
346
229
|
end_date=end_date,
|
|
347
230
|
gc_threshold=gc_threshold
|
|
348
231
|
)
|
|
349
|
-
|
|
350
232
|
report = self.memory_diff.generate_report(result, format=format)
|
|
351
|
-
|
|
352
233
|
if output:
|
|
353
234
|
output.write_text(report, encoding="utf-8")
|
|
354
235
|
return f"Memory Diff report gerado em: {output}"
|
|
355
|
-
|
|
356
236
|
return report
|
|
357
237
|
|
|
358
238
|
def dream(self, since_days: int = 7, dry_run: bool = True) -> str:
|
|
359
|
-
"""
|
|
360
|
-
Extração automática de memórias.
|
|
361
|
-
|
|
362
|
-
Args:
|
|
363
|
-
since_days: Dias para analisar
|
|
364
|
-
dry_run: Se True, apenas simula
|
|
365
|
-
|
|
366
|
-
Returns:
|
|
367
|
-
Relatório da extração
|
|
368
|
-
"""
|
|
369
239
|
from src.core.paths import get_auto_mem_path
|
|
370
240
|
from src.consolidation.dream import run_dream, generate_dream_report
|
|
371
241
|
|
|
@@ -374,31 +244,12 @@ class CerebroCLI:
|
|
|
374
244
|
return generate_dream_report(result)
|
|
375
245
|
|
|
376
246
|
def remember(self, dry_run: bool = True) -> str:
|
|
377
|
-
"""
|
|
378
|
-
Revisão e promoção de memórias.
|
|
379
|
-
|
|
380
|
-
Args:
|
|
381
|
-
dry_run: Se True, apenas gera relatório
|
|
382
|
-
|
|
383
|
-
Returns:
|
|
384
|
-
Relatório do remember
|
|
385
|
-
"""
|
|
386
247
|
from src.consolidation.remember import run_remember, generate_remember_report
|
|
387
248
|
|
|
388
249
|
report = run_remember(dry_run=dry_run)
|
|
389
250
|
return generate_remember_report(report)
|
|
390
251
|
|
|
391
252
|
def gc_cmd(self, threshold_days: int = 7, dry_run: bool = True) -> str:
|
|
392
|
-
"""
|
|
393
|
-
Garbage collection de memórias.
|
|
394
|
-
|
|
395
|
-
Args:
|
|
396
|
-
threshold_days: Dias para considerar memória stale
|
|
397
|
-
dry_run: Se True, apenas lista candidatas
|
|
398
|
-
|
|
399
|
-
Returns:
|
|
400
|
-
Relatório do GC
|
|
401
|
-
"""
|
|
402
253
|
from src.core.paths import get_auto_mem_path
|
|
403
254
|
from src.forgetting.gc import GarbageCollector
|
|
404
255
|
|
|
@@ -413,6 +264,33 @@ class CerebroCLI:
|
|
|
413
264
|
return gc.generate_gc_report(results)
|
|
414
265
|
|
|
415
266
|
|
|
267
|
+
def _run_init(project_path: Optional[Path] = None):
|
|
268
|
+
"""Lógica de init compartilhada entre 'init' e 'setup init'"""
|
|
269
|
+
from cerebro.cerebro_setup import setup_cerebro_dir, setup_hooks
|
|
270
|
+
|
|
271
|
+
print("Como quer usar o OCerebro?")
|
|
272
|
+
print(" 1. Neste projeto (cria .ocerebro/ aqui)")
|
|
273
|
+
print(" 2. Global (usa ~/.ocerebro/ para todos os projetos)")
|
|
274
|
+
choice = input("\nEscolha [1/2] (padrão: 1): ").strip() or "1"
|
|
275
|
+
|
|
276
|
+
if choice == "2":
|
|
277
|
+
base_path = Path.home() / ".ocerebro"
|
|
278
|
+
print(f"\n✓ Modo global: {base_path}")
|
|
279
|
+
else:
|
|
280
|
+
base_path = (project_path or Path.cwd()) / ".ocerebro"
|
|
281
|
+
print(f"\n✓ Modo projeto: {base_path}")
|
|
282
|
+
|
|
283
|
+
config_file = Path.home() / ".ocerebro_config"
|
|
284
|
+
config_file.parent.mkdir(parents=True, exist_ok=True)
|
|
285
|
+
config_file.write_text(f"base_path={base_path}\n", encoding="utf-8")
|
|
286
|
+
print(f"✓ Configuração salva em {config_file}")
|
|
287
|
+
|
|
288
|
+
setup_cerebro_dir(base_path)
|
|
289
|
+
setup_hooks(base_path)
|
|
290
|
+
print("\nSetup completo! Agora execute:")
|
|
291
|
+
print(" ocerebro setup claude")
|
|
292
|
+
|
|
293
|
+
|
|
416
294
|
def main():
|
|
417
295
|
"""Entry point da CLI"""
|
|
418
296
|
parser = argparse.ArgumentParser(
|
|
@@ -429,6 +307,10 @@ def main():
|
|
|
429
307
|
|
|
430
308
|
subparsers = parser.add_subparsers(dest="command", help="Comandos")
|
|
431
309
|
|
|
310
|
+
# Comando: init (alias direto para setup init)
|
|
311
|
+
init_parser = subparsers.add_parser("init", help="Inicializar OCerebro no projeto atual")
|
|
312
|
+
init_parser.add_argument("--project", type=Path, help="Diretório do projeto (padrão: atual)")
|
|
313
|
+
|
|
432
314
|
# Comando: checkpoint
|
|
433
315
|
checkpoint_parser = subparsers.add_parser("checkpoint", help="Trigger manual de checkpoint")
|
|
434
316
|
checkpoint_parser.add_argument("project", help="Nome do projeto")
|
|
@@ -465,28 +347,28 @@ def main():
|
|
|
465
347
|
subparsers.add_parser("status", help="Status do sistema")
|
|
466
348
|
|
|
467
349
|
# Comando: diff
|
|
468
|
-
diff_parser = subparsers.add_parser("diff", help="Análise diferencial de memória
|
|
350
|
+
diff_parser = subparsers.add_parser("diff", help="Análise diferencial de memória")
|
|
469
351
|
diff_parser.add_argument("project", help="Nome do projeto")
|
|
470
352
|
diff_parser.add_argument("--period", type=int, default=7, help="Dias do período (padrão: 7)")
|
|
471
|
-
diff_parser.add_argument("--start", dest="start_date", help="Data de início (ISO format
|
|
472
|
-
diff_parser.add_argument("--end", dest="end_date", help="Data de fim (ISO format
|
|
473
|
-
diff_parser.add_argument("--gc-threshold", type=float, default=0.3, help="Threshold para GC risk
|
|
353
|
+
diff_parser.add_argument("--start", dest="start_date", help="Data de início (ISO format)")
|
|
354
|
+
diff_parser.add_argument("--end", dest="end_date", help="Data de fim (ISO format)")
|
|
355
|
+
diff_parser.add_argument("--gc-threshold", type=float, default=0.3, help="Threshold para GC risk")
|
|
474
356
|
diff_parser.add_argument("--output", type=Path, help="Arquivo de saída")
|
|
475
|
-
diff_parser.add_argument("--format", choices=["markdown", "json"], default="markdown"
|
|
357
|
+
diff_parser.add_argument("--format", choices=["markdown", "json"], default="markdown")
|
|
476
358
|
|
|
477
359
|
# Comando: dream
|
|
478
360
|
dream_parser = subparsers.add_parser("dream", help="Extração automática de memórias")
|
|
479
|
-
dream_parser.add_argument("--since", type=int, default=7, dest="since_days"
|
|
480
|
-
dream_parser.add_argument("--apply", action="store_true", dest="apply"
|
|
361
|
+
dream_parser.add_argument("--since", type=int, default=7, dest="since_days")
|
|
362
|
+
dream_parser.add_argument("--apply", action="store_true", dest="apply")
|
|
481
363
|
|
|
482
364
|
# Comando: remember
|
|
483
365
|
remember_parser = subparsers.add_parser("remember", help="Revisão e promoção de memórias")
|
|
484
|
-
remember_parser.add_argument("--apply", action="store_true", dest="apply"
|
|
366
|
+
remember_parser.add_argument("--apply", action="store_true", dest="apply")
|
|
485
367
|
|
|
486
368
|
# Comando: gc
|
|
487
369
|
gc_parser = subparsers.add_parser("gc", help="Garbage collection de memórias")
|
|
488
|
-
gc_parser.add_argument("--threshold", type=int, default=7, dest="threshold_days"
|
|
489
|
-
gc_parser.add_argument("--apply", action="store_true", dest="apply"
|
|
370
|
+
gc_parser.add_argument("--threshold", type=int, default=7, dest="threshold_days")
|
|
371
|
+
gc_parser.add_argument("--apply", action="store_true", dest="apply")
|
|
490
372
|
|
|
491
373
|
args = parser.parse_args()
|
|
492
374
|
|
|
@@ -494,7 +376,12 @@ def main():
|
|
|
494
376
|
parser.print_help()
|
|
495
377
|
sys.exit(1)
|
|
496
378
|
|
|
497
|
-
# Comando
|
|
379
|
+
# Comando: init (alias direto)
|
|
380
|
+
if args.command == "init":
|
|
381
|
+
_run_init(getattr(args, 'project', None))
|
|
382
|
+
sys.exit(0)
|
|
383
|
+
|
|
384
|
+
# Comando setup
|
|
498
385
|
if args.command == "setup":
|
|
499
386
|
from cerebro.cerebro_setup import setup_claude_desktop, setup_hooks, setup_cerebro_dir
|
|
500
387
|
|
|
@@ -505,32 +392,9 @@ def main():
|
|
|
505
392
|
success = setup_hooks(args.project)
|
|
506
393
|
sys.exit(0 if success else 1)
|
|
507
394
|
elif args.subcommand == "init":
|
|
508
|
-
|
|
509
|
-
print("Como quer usar o OCerebro?")
|
|
510
|
-
print(" 1. Neste projeto (cria .ocerebro/ aqui)")
|
|
511
|
-
print(" 2. Global (usa ~/.ocerebro/ para todos os projetos)")
|
|
512
|
-
choice = input("\nEscolha [1/2] (padrão: 1): ").strip() or "1"
|
|
513
|
-
|
|
514
|
-
if choice == "2":
|
|
515
|
-
base_path = Path.home() / ".ocerebro"
|
|
516
|
-
print(f"\n✓ Modo global: {base_path}")
|
|
517
|
-
else:
|
|
518
|
-
base_path = Path.cwd() / ".ocerebro"
|
|
519
|
-
print(f"\n✓ Modo projeto: {base_path}")
|
|
520
|
-
|
|
521
|
-
# Salva a escolha num arquivo de config global
|
|
522
|
-
config_file = Path.home() / ".ocerebro_config"
|
|
523
|
-
config_file.parent.mkdir(parents=True, exist_ok=True)
|
|
524
|
-
config_file.write_text(f"base_path={base_path}\n", encoding="utf-8")
|
|
525
|
-
print(f"✓ Configuração salva em {config_file}")
|
|
526
|
-
|
|
527
|
-
setup_cerebro_dir(base_path)
|
|
528
|
-
setup_hooks(base_path)
|
|
529
|
-
print("\nSetup completo! Agora execute:")
|
|
530
|
-
print(" cerebro setup claude")
|
|
395
|
+
_run_init(getattr(args, 'project', None))
|
|
531
396
|
sys.exit(0)
|
|
532
397
|
else:
|
|
533
|
-
# Setup completo
|
|
534
398
|
setup_cerebro_dir(args.project)
|
|
535
399
|
setup_hooks(args.project)
|
|
536
400
|
setup_claude_desktop()
|
|
@@ -539,7 +403,6 @@ def main():
|
|
|
539
403
|
# Inicializa CLI
|
|
540
404
|
cli = CerebroCLI(args.cerebro_path)
|
|
541
405
|
|
|
542
|
-
# Executa comando
|
|
543
406
|
if args.command == "checkpoint":
|
|
544
407
|
result = cli.checkpoint(args.project, args.session, args.reason)
|
|
545
408
|
elif args.command == "memory":
|