grimoire-framework 1.2.0 → 1.4.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.
- package/.grimoire/install-manifest.yaml +2 -2
- package/README.md +150 -112
- package/bin/commands/backup.js +165 -0
- package/bin/commands/exportall.js +200 -0
- package/bin/commands/memory.js +14 -0
- package/bin/commands/report.js +200 -0
- package/bin/commands/search.js +171 -0
- package/bin/commands/session.js +217 -0
- package/bin/commands/story.js +254 -0
- package/bin/grimoire-cli.js +193 -55
- package/package.json +1 -1
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
# - SHA256 hashes for change detection
|
|
8
8
|
# - File types for categorization
|
|
9
9
|
#
|
|
10
|
-
version: 1.
|
|
11
|
-
generated_at: "2026-02-
|
|
10
|
+
version: 1.4.0
|
|
11
|
+
generated_at: "2026-02-22T17:13:01.000Z"
|
|
12
12
|
generator: scripts/generate-install-manifest.js
|
|
13
13
|
file_count: 1011
|
|
14
14
|
files:
|
package/README.md
CHANGED
|
@@ -1,171 +1,209 @@
|
|
|
1
|
-
# Grimoire
|
|
1
|
+
# 🔮 Grimoire Framework
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[](https://opensource.org/licenses/MIT)
|
|
5
|
-
[](https://nodejs.org)
|
|
3
|
+
> **CLI de gestão para frameworks de agentes de IA** — instale uma vez, use em todos os seus projetos
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/grimoire-framework)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://nodejs.org)
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## ⚡ Quick Start (5 passos)
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
#
|
|
14
|
+
# 1. Instale no projeto
|
|
15
15
|
npx grimoire-framework install
|
|
16
16
|
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
```
|
|
17
|
+
# 2. Gere o prompt de início de sessão
|
|
18
|
+
grimoire session start
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
# 3. Cole o prompt no chat da sua IDE e ative um agente
|
|
21
|
+
# @dev @qa @architect @grimoire-master
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
# 4. Crie e rastreie stories
|
|
24
|
+
grimoire story create "Implementar autenticação JWT"
|
|
25
|
+
|
|
26
|
+
# 5. Veja o relatório ao final do dia
|
|
27
|
+
grimoire report
|
|
26
28
|
```
|
|
27
29
|
|
|
28
30
|
---
|
|
29
31
|
|
|
30
|
-
##
|
|
31
|
-
|
|
32
|
-
### Gerenciamento do Framework
|
|
33
|
-
|
|
34
|
-
| Comando | Descrição |
|
|
35
|
-
|---|---|
|
|
36
|
-
| `npx grimoire-framework install` | Instalar no projeto atual |
|
|
37
|
-
| `npx grimoire-framework update` | Atualizar preservando customizações |
|
|
38
|
-
| `npx grimoire-framework update --force` | Forçar resync de todos os arquivos |
|
|
39
|
-
| `npx grimoire-framework update --dry-run` | Simular update (sem aplicar) |
|
|
40
|
-
|
|
41
|
-
### Diagnóstico
|
|
32
|
+
## 🧙 O que é o Grimoire?
|
|
42
33
|
|
|
43
|
-
|
|
44
|
-
|---|---|
|
|
45
|
-
| `grimoire status` | Saúde do framework + integração IDE |
|
|
46
|
-
| `grimoire doctor` | Diagnóstico detalhado com dicas de fix |
|
|
47
|
-
| `grimoire agents list` | Listar agentes com personas |
|
|
48
|
-
| `grimoire whoami` | Contexto da sessão atual |
|
|
49
|
-
| `grimoire --version` | Versão instalada |
|
|
34
|
+
O Grimoire é um framework que adiciona **agentes de IA especializados** ao chat da sua IDE (Gemini CLI, Cursor, VS Code, Claude). Cada agente tem uma persona, expertise e estilo próprios.
|
|
50
35
|
|
|
51
|
-
|
|
36
|
+
```
|
|
37
|
+
CLI (terminal) → gerencia o framework
|
|
38
|
+
Agentes (IDE) → @dev, @qa, @architect no chat da IDE
|
|
39
|
+
```
|
|
52
40
|
|
|
53
41
|
---
|
|
54
42
|
|
|
55
|
-
##
|
|
56
|
-
|
|
57
|
-
Após instalar, ative os agentes diretamente no chat da sua IDE:
|
|
43
|
+
## 🤖 Agentes incluídos
|
|
58
44
|
|
|
59
|
-
|
|
|
45
|
+
| Agente | Persona | Especialidade |
|
|
60
46
|
|---|---|---|
|
|
61
|
-
| `@grimoire-master` | 👑 Michelangelo | Orquestração
|
|
62
|
-
| `@dev` | 🎨 Da Vinci |
|
|
63
|
-
| `@qa` | 🖌️ Dürer |
|
|
64
|
-
| `@architect` | 🏛️ Gaudí | Arquitetura
|
|
65
|
-
| `@pm` | 📋 Raphael |
|
|
66
|
-
| `@
|
|
67
|
-
| `@devops` | ⚡ Boccioni | DevOps
|
|
68
|
-
| `@data-engineer` | 📊 Escher |
|
|
69
|
-
| `@analyst` | 🔍 Vermeer | Pesquisa
|
|
70
|
-
| `@ux-design-expert` | 🎭 Matisse | UX/UI Design |
|
|
47
|
+
| `@grimoire-master` | 👑 Michelangelo | Orquestração |
|
|
48
|
+
| `@dev` | 🎨 Da Vinci | Full-stack |
|
|
49
|
+
| `@qa` | 🖌️ Dürer | QA & testes |
|
|
50
|
+
| `@architect` | 🏛️ Gaudí | Arquitetura |
|
|
51
|
+
| `@pm` | 📋 Raphael | Produto |
|
|
52
|
+
| `@ux-design-expert` | 🎭 Matisse | UX/Design |
|
|
53
|
+
| `@devops` | ⚡ Boccioni | DevOps |
|
|
54
|
+
| `@data-engineer` | 📊 Escher | Dados |
|
|
55
|
+
| `@analyst` | 🔍 Vermeer | Pesquisa |
|
|
71
56
|
| `@po` | 🎯 Velázquez | Product Owner |
|
|
57
|
+
| `@sm` | 🌊 Monet | Scrum Master |
|
|
58
|
+
| `@squad-creator` | 🗿 Rodin | Criação de squads |
|
|
72
59
|
|
|
73
60
|
---
|
|
74
61
|
|
|
75
|
-
##
|
|
76
|
-
|
|
77
|
-
### Gemini CLI (Recomendado)
|
|
78
|
-
O Grimoire configura automaticamente o arquivo `GEMINI.md` na raiz do projeto. O Michelangelo se apresenta ao abrir o Gemini CLI.
|
|
62
|
+
## 📋 Referência de comandos
|
|
79
63
|
|
|
64
|
+
### Essenciais
|
|
80
65
|
```bash
|
|
81
|
-
|
|
82
|
-
#
|
|
83
|
-
#
|
|
66
|
+
grimoire status # saúde do framework
|
|
67
|
+
grimoire whoami # contexto completo (config+pro+stories)
|
|
68
|
+
grimoire doctor # diagnóstico completo com dicas
|
|
69
|
+
grimoire update # atualiza agentes e arquivos
|
|
70
|
+
grimoire update --dry-run # preview sem aplicar
|
|
84
71
|
```
|
|
85
72
|
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
|
|
73
|
+
### Sessão & Workflow
|
|
74
|
+
```bash
|
|
75
|
+
grimoire session start # prompt para IDE (squad+stories+memória)
|
|
76
|
+
grimoire session start --squad dev # com squad específico
|
|
77
|
+
grimoire story create "Título" # nova story
|
|
78
|
+
grimoire story list # stories ativas
|
|
79
|
+
grimoire story done US-001 # marcar concluída
|
|
80
|
+
grimoire story note US-001 "obs" # adicionar nota
|
|
81
|
+
grimoire story show US-001 # detalhes + memórias linkadas
|
|
82
|
+
grimoire report # relatório de hoje
|
|
83
|
+
grimoire report --period week # relatório da semana (7 dias)
|
|
84
|
+
grimoire report --md # exportar relatório para Markdown
|
|
89
85
|
```
|
|
90
86
|
|
|
91
|
-
###
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
### Agentes
|
|
88
|
+
```bash
|
|
89
|
+
grimoire agents list # lista com personas
|
|
90
|
+
grimoire agent create # wizard interativo
|
|
91
|
+
grimoire agent validate dev # valida YAML e campos (score 0-100)
|
|
92
|
+
grimoire agent edit dev # abre no $EDITOR
|
|
93
|
+
grimoire agent remove dev # remove agente customizado
|
|
94
|
+
```
|
|
98
95
|
|
|
99
|
-
|
|
96
|
+
### Squads
|
|
97
|
+
```bash
|
|
98
|
+
grimoire squads list # lista squads disponíveis
|
|
99
|
+
grimoire squads use fullstack # prompt de ativação para IDE
|
|
100
|
+
grimoire squads info fullstack # detalhes do squad
|
|
101
|
+
```
|
|
100
102
|
|
|
103
|
+
### Memória
|
|
104
|
+
```bash
|
|
105
|
+
grimoire memory save "texto" # salvar entrada
|
|
106
|
+
grimoire memory save --tag decisão "txt" # com tag
|
|
107
|
+
grimoire memory save --story US-001 "txt" # linkada a story
|
|
108
|
+
grimoire memory show # entradas de hoje
|
|
109
|
+
grimoire memory search "termo" # buscar em sessões
|
|
110
|
+
grimoire memory list-tags # tags únicas com contagem
|
|
111
|
+
grimoire memory export # exportar para Markdown
|
|
112
|
+
grimoire memory clear --older-than 30 # limpar antigas
|
|
101
113
|
```
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
114
|
+
|
|
115
|
+
### Busca & Backup
|
|
116
|
+
```bash
|
|
117
|
+
grimoire search "JWT" # busca global (memória+stories+agentes)
|
|
118
|
+
grimoire search "JWT" --memory # só memória
|
|
119
|
+
grimoire search "JWT" --stories # só stories
|
|
120
|
+
grimoire backup # backup de .grimoire/
|
|
121
|
+
grimoire backup --list # listar backups
|
|
122
|
+
grimoire backup --restore <arq> # restaurar backup
|
|
123
|
+
grimoire export --all # bundle Markdown completo
|
|
124
|
+
grimoire export --all --json # bundle JSON completo
|
|
111
125
|
```
|
|
112
126
|
|
|
113
|
-
|
|
127
|
+
### Métricas
|
|
128
|
+
```bash
|
|
129
|
+
grimoire metrics # dashboard do mês
|
|
130
|
+
grimoire metrics --period week # últimos 7 dias
|
|
131
|
+
grimoire metrics --period all # histórico completo
|
|
132
|
+
grimoire metrics export --csv # exportar para CSV
|
|
133
|
+
grimoire metrics track session "desc" # registrar evento manual
|
|
134
|
+
```
|
|
114
135
|
|
|
115
|
-
|
|
136
|
+
### Config & Hooks
|
|
137
|
+
```bash
|
|
138
|
+
grimoire config list # todas as configurações
|
|
139
|
+
grimoire config get default_agent # valor de uma chave
|
|
140
|
+
grimoire config set default_agent dev # definir valor
|
|
141
|
+
grimoire config reset # restaurar defaults
|
|
142
|
+
grimoire hooks install # git post-commit (auto-tracking)
|
|
143
|
+
grimoire hooks status # verificar status do hook
|
|
144
|
+
grimoire hooks uninstall # remover hook
|
|
145
|
+
```
|
|
116
146
|
|
|
117
|
-
|
|
147
|
+
### Sync Global
|
|
148
|
+
```bash
|
|
149
|
+
grimoire sync --global # envia agentes → ~/.grimoire/agents/
|
|
150
|
+
grimoire sync --from-global # puxa agentes do store global
|
|
151
|
+
grimoire sync --list # lista agentes no store
|
|
152
|
+
```
|
|
118
153
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
154
|
+
### Marketplace
|
|
155
|
+
```bash
|
|
156
|
+
grimoire marketplace list # navega agentes da comunidade
|
|
157
|
+
grimoire marketplace install slug # instala agente
|
|
158
|
+
grimoire marketplace search "termo" # busca por especialidade
|
|
159
|
+
grimoire marketplace submit # guia para publicar
|
|
160
|
+
```
|
|
122
161
|
|
|
162
|
+
### Grimoire Pro
|
|
123
163
|
```bash
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
164
|
+
grimoire pro activate <chave> # ativa licença Pro
|
|
165
|
+
grimoire pro status # status e features
|
|
166
|
+
grimoire pro features # lista features Pro
|
|
167
|
+
grimoire pro deactivate # remove licença
|
|
127
168
|
```
|
|
128
169
|
|
|
129
170
|
---
|
|
130
171
|
|
|
131
|
-
##
|
|
172
|
+
## 📁 Estrutura do projeto
|
|
132
173
|
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
|
|
174
|
+
```
|
|
175
|
+
seu-projeto/
|
|
176
|
+
├── .grimoire/
|
|
177
|
+
│ ├── memory/sessions/ # memória JSONL
|
|
178
|
+
│ ├── metrics/ # métricas JSONL
|
|
179
|
+
│ ├── stories/ # stories JSON
|
|
180
|
+
│ ├── backups/ # backups .grimbak
|
|
181
|
+
│ ├── exports/ # bundles exportados
|
|
182
|
+
│ └── config.yaml # configurações do projeto
|
|
183
|
+
├── .codex/agents/ # agentes Gemini CLI
|
|
184
|
+
├── .gemini/ # config Gemini CLI
|
|
185
|
+
├── .cursor/ # regras Cursor
|
|
186
|
+
└── GEMINI.md # persona principal
|
|
187
|
+
```
|
|
136
188
|
|
|
137
189
|
---
|
|
138
190
|
|
|
139
|
-
##
|
|
191
|
+
## 📦 Versões
|
|
140
192
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
- [ ] **Enterprise Connectors** — Integração com Jira, Notion e Slack
|
|
193
|
+
| Versão | Features |
|
|
194
|
+
|---|---|
|
|
195
|
+
| v1.0.x | Setup, agents, sync global |
|
|
196
|
+
| v1.1.x | Marketplace, Grimoire Pro |
|
|
197
|
+
| v1.2.0 | Squads use, config, hooks, agent validate, memory tags |
|
|
198
|
+
| v1.3.0 | Report, story, session start, doctor v3, whoami v2 |
|
|
199
|
+
| **v1.4.0** | **Search global, backup, export --all, memory --story, story note** |
|
|
149
200
|
|
|
150
201
|
---
|
|
151
202
|
|
|
152
203
|
## 🤝 Contribuindo
|
|
153
204
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
git clone https://github.com/gabrielrlima/grimoire.git
|
|
158
|
-
cd grimoire
|
|
159
|
-
npm install
|
|
160
|
-
npm test
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## 📄 Licença
|
|
166
|
-
|
|
167
|
-
Distribuído sob a licença MIT. Veja [LICENSE](LICENSE) para mais informações.
|
|
205
|
+
Veja [CONTRIBUTING.md](CONTRIBUTING.md) e [docs/CHANGELOG.md](docs/CHANGELOG.md).
|
|
168
206
|
|
|
169
207
|
---
|
|
170
208
|
|
|
171
|
-
|
|
209
|
+
*Grimoire Framework · MIT License · Made with ❤️ by the community*
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* grimoire backup — Backup & Restore .grimoire/
|
|
3
|
+
*
|
|
4
|
+
* grimoire backup Cria backup zip de .grimoire/
|
|
5
|
+
* grimoire backup --restore <file> Restaura a partir de um zip
|
|
6
|
+
* grimoire backup --list Lista backups existentes
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const zlib = require('zlib');
|
|
14
|
+
|
|
15
|
+
function findGrimoireDir() {
|
|
16
|
+
const cwd = process.cwd();
|
|
17
|
+
const direct = path.join(cwd, '.grimoire');
|
|
18
|
+
const sub = path.join(cwd, 'grimoire', '.grimoire');
|
|
19
|
+
if (fs.existsSync(direct)) return { dir: direct, root: cwd };
|
|
20
|
+
if (fs.existsSync(sub)) return { dir: sub, root: path.join(cwd, 'grimoire') };
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getBackupDir(grimoireDir) {
|
|
25
|
+
const d = path.join(grimoireDir, 'backups');
|
|
26
|
+
if (!fs.existsSync(d)) fs.mkdirSync(d, { recursive: true });
|
|
27
|
+
return d;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Simple tar-like serialization using NDJSON (no native zip without deps)
|
|
31
|
+
// Format: one header line + files as base64 encoded NDJSON entries
|
|
32
|
+
function createBackup(grimoireDir, backupDir) {
|
|
33
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
34
|
+
const backupFile = path.join(backupDir, `backup-${timestamp}.grimbak`);
|
|
35
|
+
|
|
36
|
+
const SKIP_DIRS = new Set(['backups', 'exports']);
|
|
37
|
+
const entries = [];
|
|
38
|
+
|
|
39
|
+
function walk(dir, rel = '') {
|
|
40
|
+
for (const item of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
41
|
+
const relPath = rel ? `${rel}/${item.name}` : item.name;
|
|
42
|
+
const abs = path.join(dir, item.name);
|
|
43
|
+
if (item.isDirectory()) {
|
|
44
|
+
if (!SKIP_DIRS.has(item.name)) walk(abs, relPath);
|
|
45
|
+
} else {
|
|
46
|
+
try {
|
|
47
|
+
const content = fs.readFileSync(abs).toString('base64');
|
|
48
|
+
entries.push({ path: relPath, content, size: fs.statSync(abs).size });
|
|
49
|
+
} catch (_) { }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
walk(grimoireDir);
|
|
55
|
+
|
|
56
|
+
const header = JSON.stringify({
|
|
57
|
+
version: 1,
|
|
58
|
+
createdAt: new Date().toISOString(),
|
|
59
|
+
files: entries.length,
|
|
60
|
+
source: grimoireDir
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const lines = [header, ...entries.map(e => JSON.stringify(e))];
|
|
64
|
+
const raw = lines.join('\n');
|
|
65
|
+
const buf = zlib.gzipSync(Buffer.from(raw, 'utf8'));
|
|
66
|
+
fs.writeFileSync(backupFile, buf);
|
|
67
|
+
|
|
68
|
+
return { file: backupFile, count: entries.length, size: buf.length };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function restoreBackup(backupFile, grimoireDir) {
|
|
72
|
+
if (!fs.existsSync(backupFile)) {
|
|
73
|
+
throw new Error(`Arquivo não encontrado: ${backupFile}`);
|
|
74
|
+
}
|
|
75
|
+
const buf = fs.readFileSync(backupFile);
|
|
76
|
+
const raw = zlib.gunzipSync(buf).toString('utf8');
|
|
77
|
+
const lines = raw.split('\n').filter(l => l.trim());
|
|
78
|
+
const header = JSON.parse(lines[0]);
|
|
79
|
+
|
|
80
|
+
let restored = 0;
|
|
81
|
+
for (const line of lines.slice(1)) {
|
|
82
|
+
try {
|
|
83
|
+
const entry = JSON.parse(line);
|
|
84
|
+
const dest = path.join(grimoireDir, entry.path);
|
|
85
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
86
|
+
fs.writeFileSync(dest, Buffer.from(entry.content, 'base64'));
|
|
87
|
+
restored++;
|
|
88
|
+
} catch (_) { }
|
|
89
|
+
}
|
|
90
|
+
return { count: restored, header };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function listBackups(backupDir) {
|
|
94
|
+
if (!fs.existsSync(backupDir)) return [];
|
|
95
|
+
return fs.readdirSync(backupDir)
|
|
96
|
+
.filter(f => f.endsWith('.grimbak'))
|
|
97
|
+
.map(f => {
|
|
98
|
+
const stat = fs.statSync(path.join(backupDir, f));
|
|
99
|
+
return { name: f, size: stat.size, mtime: stat.mtime };
|
|
100
|
+
})
|
|
101
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ── run ───────────────────────────────────────────────────────────────────────
|
|
105
|
+
function run(args) {
|
|
106
|
+
const found = findGrimoireDir();
|
|
107
|
+
if (!found) {
|
|
108
|
+
console.error('❌ .grimoire/ not found. Run: npx grimoire-framework install');
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const { dir: grimoireDir } = found;
|
|
112
|
+
const backupDir = getBackupDir(grimoireDir);
|
|
113
|
+
|
|
114
|
+
if (args.includes('--list')) {
|
|
115
|
+
const backups = listBackups(backupDir);
|
|
116
|
+
console.log(`\n💾 Backups (${backups.length}):\n`);
|
|
117
|
+
if (backups.length === 0) {
|
|
118
|
+
console.log(' (nenhum backup encontrado)');
|
|
119
|
+
console.log(' grimoire backup ← criar agora\n');
|
|
120
|
+
} else {
|
|
121
|
+
backups.forEach(b => {
|
|
122
|
+
const kb = (b.size / 1024).toFixed(1);
|
|
123
|
+
const d = b.mtime.toLocaleDateString('pt-BR');
|
|
124
|
+
console.log(` 📦 ${b.name} (${kb} KB · ${d})`);
|
|
125
|
+
});
|
|
126
|
+
console.log(`\n grimoire backup --restore <arquivo> ← restaurar\n`);
|
|
127
|
+
}
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const restoreIdx = args.indexOf('--restore');
|
|
132
|
+
if (restoreIdx !== -1) {
|
|
133
|
+
const file = args[restoreIdx + 1];
|
|
134
|
+
if (!file) {
|
|
135
|
+
console.log('Usage: grimoire backup --restore <arquivo.grimbak>\n');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const absFile = path.isAbsolute(file) ? file : path.join(backupDir, file);
|
|
139
|
+
console.log(`\n⏳ Restaurando backup: ${path.basename(absFile)}...\n`);
|
|
140
|
+
try {
|
|
141
|
+
const { count, header } = restoreBackup(absFile, grimoireDir);
|
|
142
|
+
console.log(`✅ ${count} arquivos restaurados`);
|
|
143
|
+
console.log(` Backup criado em: ${new Date(header.createdAt).toLocaleString('pt-BR')}\n`);
|
|
144
|
+
} catch (e) {
|
|
145
|
+
console.error(`❌ Erro ao restaurar: ${e.message}\n`);
|
|
146
|
+
}
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Default: create backup
|
|
151
|
+
console.log('\n⏳ Criando backup de .grimoire/ ...\n');
|
|
152
|
+
try {
|
|
153
|
+
const { file, count, size } = createBackup(grimoireDir, backupDir);
|
|
154
|
+
const kb = (size / 1024).toFixed(1);
|
|
155
|
+
const rel = path.relative(process.cwd(), file);
|
|
156
|
+
console.log(`✅ Backup criado: ${rel}`);
|
|
157
|
+
console.log(` ${count} arquivos · ${kb} KB\n`);
|
|
158
|
+
console.log(`💡 Para restaurar: grimoire backup --restore ${path.basename(file)}`);
|
|
159
|
+
console.log(` Para listar: grimoire backup --list\n`);
|
|
160
|
+
} catch (e) {
|
|
161
|
+
console.error(`❌ Erro ao criar backup: ${e.message}\n`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = { run };
|