iron-edge 2.3.2 → 2.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/README.md +29 -2
- package/bin/iron-edge.js +10 -2
- package/installer/office.js +123 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -213,6 +213,31 @@ npx iron-edge verify
|
|
|
213
213
|
|
|
214
214
|
---
|
|
215
215
|
|
|
216
|
+
## Iron Office
|
|
217
|
+
|
|
218
|
+
Converse com o Iron pelo dashboard ([iron-office.vercel.app](https://iron-office.vercel.app)) e veja os agentes trabalhando no feed e no mapa 3D.
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
npx iron-edge office
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Antes, faça o **passo 4** do onboarding do Iron Office (ele salva a sua chave em `~/.claude/iron-office-api-key`).
|
|
225
|
+
|
|
226
|
+
O que esperar:
|
|
227
|
+
|
|
228
|
+
1. O comando instala (ou atualiza) o plugin de canal `iron-office` e abre o Claude Code com ele ligado.
|
|
229
|
+
2. O Claude Code mostra um **aviso de tela cheia**: canais ainda são recurso em teste. Aceite.
|
|
230
|
+
3. Abra a página **Iron** do dashboard. Em até 1 minuto aparece "Iron online". Escreva ali e o Iron responde ali.
|
|
231
|
+
4. **Deixe essa aba do terminal aberta.** É ela que faz o Iron responder no site.
|
|
232
|
+
|
|
233
|
+
Por padrão a sessão do `office` roda **sem pedir licença** a cada ferramenta (é o que deixa o Iron trabalhar enquanto você está só no site). `npx iron-edge office --safe` abre pedindo licença a cada ferramenta. Qualquer outro argumento vai direto pro `claude`.
|
|
234
|
+
|
|
235
|
+
Mensagem escrita no site com o terminal fechado espera até 15 minutos; depois disso expira e o chat avisa pra mandar de novo (ordem velha não é executada sem você ver).
|
|
236
|
+
|
|
237
|
+
O plugin também manda a atividade das sessões pro seu painel: veja o que sai em "Sobre o que sai da sua máquina", mais abaixo.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
216
241
|
## Requisitos
|
|
217
242
|
|
|
218
243
|
- **Node.js** 18 ou superior
|
|
@@ -230,12 +255,14 @@ O Iron Edge instala uma equipe de agentes especializados diretamente no Claude C
|
|
|
230
255
|
|
|
231
256
|
Seus dados ficam locais em `~/.iron/`. Sobre o que sai da sua máquina, com precisão:
|
|
232
257
|
|
|
233
|
-
- **Para o Iron Office** (`iron-office.vercel.app`, servidor deste projeto)
|
|
258
|
+
- **Para o Iron Office** (`iron-office.vercel.app`, servidor deste projeto), e só se você criar a chave em `~/.claude/iron-office-api-key`:
|
|
259
|
+
- dados de apenas **2 agentes**, `iron-auditor` e `iron-shopify`. Confira: `grep -rln "iron-office" ~/.claude/agents/`;
|
|
260
|
+
- **se você rodou `npx iron-edge office`**, o plugin `iron-office` fica instalado e manda a atividade de **toda sessão** do Claude Code pro seu painel (feed e mapa 3D): nome da ferramenta, caminho do arquivo (nunca o conteúdo), os primeiros 200 caracteres de cada comando de terminal e a descrição dele, buscas, o domínio dos endereços visitados, nome e descrição dos agentes, a pasta e o identificador da sessão. A resposta das ferramentas nunca sai. Padrões conhecidos de segredo nesses campos (chaves de Stripe, Shopify, Meta, GitHub, OpenAI, Supabase e AWS, `Bearer`, `ALGO_KEY=`, `--password`, `-u usuario:senha`…) são apagados antes do envio; é uma lista de padrões, não garantia. Lista completa no README do plugin (github.com/filipecoff21-code/iron-office-channel). Desligar: `claude plugin disable iron-office@iron-office-channel`. Conferir se está ligado: `claude plugin list`.
|
|
234
261
|
- **Para a internet aberta**, através das ferramentas do próprio Claude Code (`WebSearch` / `WebFetch`), vão as buscas de **41 dos 44 agentes** — é como o `iron-research` pesquisa mercado e o `iron-spy` lê a biblioteca de anúncios. Isso passa pelo Claude Code, com a visibilidade e a aprovação que ele te dá; não é canal deste pacote. Confira: `grep -rln "WebSearch\|WebFetch" ~/.claude/agents/`.
|
|
235
262
|
- **A skill `clone-site`** baixa a URL que você mandar clonar. É o trabalho dela.
|
|
236
263
|
|
|
237
264
|
|
|
238
|
-
Sendo exato sobre a força dessa garantia, porque ela não é um sandbox: cada bloco que chama o Iron Office começa com uma guarda (`[ -z "$IRON_KEY" ] && exit 0`) e a regra R20 do lint impede que qualquer bloco novo entre sem ela. Mas esses arquivos são **instruções lidas por um modelo**, não um binário fechado: um agente que execute só a linha do `curl`, isolada da guarda, não é barrado por nada aqui. Se o que você quer é garantia dura, a que existe é não criar o arquivo de chave — sem ele, não há para onde enviar, e todo bloco para na guarda.
|
|
265
|
+
Sendo exato sobre a força dessa garantia, porque ela não é um sandbox: cada bloco que chama o Iron Office começa com uma guarda (`[ -z "$IRON_KEY" ] && exit 0`) e a regra R20 do lint impede que qualquer bloco novo entre sem ela. Mas esses arquivos são **instruções lidas por um modelo**, não um binário fechado: um agente que execute só a linha do `curl`, isolada da guarda, não é barrado por nada aqui. Se o que você quer é garantia dura, a que existe é não criar o arquivo de chave — sem ele, não há para onde enviar, e todo bloco para na guarda (o plugin `iron-office` também: sem a chave, ele não envia nada).
|
|
239
266
|
|
|
240
267
|
---
|
|
241
268
|
|
package/bin/iron-edge.js
CHANGED
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
* arquivos cujo hash bate com o manifesto — os que
|
|
15
15
|
* ninguem alterou — e preserva o resto
|
|
16
16
|
*
|
|
17
|
+
* office [--safe] liga o Iron Office: instala o plugin de canal e abre o
|
|
18
|
+
* Claude Code conversando com o chat do dashboard
|
|
19
|
+
*
|
|
17
20
|
* Nao existe 'uninstall' automatico: remover continua sendo operacao conduzida, com o
|
|
18
21
|
* manifesto na mao (o README descreve o procedimento).
|
|
19
22
|
*/
|
|
@@ -147,7 +150,12 @@ if (cmd === 'install') {
|
|
|
147
150
|
// Reprovam so' divergencia sem registro e arquivo sumido.
|
|
148
151
|
process.exit(alterados.length + sumidos.length === 0 ? 0 : 1);
|
|
149
152
|
|
|
153
|
+
} else if (cmd === 'office') {
|
|
154
|
+
// liga o chat do dashboard (iron-office.vercel.app/chat) na sessao do Claude Code
|
|
155
|
+
const r = spawnSync(process.execPath, [path.join(__dirname, '..', 'installer', 'office.js'), ...rest], { stdio: 'inherit' });
|
|
156
|
+
process.exit(r.status ?? 1);
|
|
157
|
+
|
|
150
158
|
} else {
|
|
151
|
-
console.log('uso: iron-edge <install|update|verify> [--dry-run] [--source <dir>]');
|
|
152
|
-
process.exit(cmd ? 1 : 0);
|
|
159
|
+
console.log('uso: iron-edge <install|update|verify|office> [--dry-run] [--source <dir>] [--safe]');
|
|
160
|
+
process.exit(cmd && cmd !== '--help' && cmd !== '-h' ? 1 : 0);
|
|
153
161
|
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* office.js — `npx iron-edge office`: liga o Iron Office (chat do dashboard) no Claude Code.
|
|
4
|
+
*
|
|
5
|
+
* Passos: (1) confere a chave do Iron Office, (2) confere o Claude Code, (3) instala ou
|
|
6
|
+
* atualiza o plugin de canal `iron-office` pelo marketplace do GitHub, (4) abre o Claude Code
|
|
7
|
+
* com o canal ligado. O aluno deixa essa aba aberta: e' ela que faz o Iron responder no site.
|
|
8
|
+
*
|
|
9
|
+
* Flags: --safe tira o `--permission-mode bypassPermissions` (o Claude pede licenca a cada
|
|
10
|
+
* ferramenta). Qualquer outro argumento vai direto pro `claude`.
|
|
11
|
+
*
|
|
12
|
+
* Saida so' em ASCII, como o resto do instalador: console do Windows antigo mostra lixo em
|
|
13
|
+
* acento e simbolo. O `claude` recebe IRON_OFFICE_CHANNEL=1 no ambiente: e' o que diz ao
|
|
14
|
+
* servidor do plugin que ESTA sessao e' o canal (uma aba comum do Claude Code nao puxa o chat).
|
|
15
|
+
*/
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const os = require('os');
|
|
19
|
+
const { spawnSync } = require('child_process');
|
|
20
|
+
|
|
21
|
+
const MARKETPLACE_REPO = 'filipecoff21-code/iron-office-channel';
|
|
22
|
+
const PLUGIN = 'iron-office@iron-office-channel';
|
|
23
|
+
const CHANNEL = 'plugin:' + PLUGIN;
|
|
24
|
+
const ONBOARDING = 'https://iron-office.vercel.app/onboarding';
|
|
25
|
+
const IS_WIN = process.platform === 'win32';
|
|
26
|
+
|
|
27
|
+
function keyPath(home) {
|
|
28
|
+
return path.join(home || os.homedir(), '.claude', 'iron-office-api-key');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// O `echo` do passo 4 no Windows pode gravar UTF-16 com BOM: normaliza antes de decidir.
|
|
32
|
+
function readKey(home) {
|
|
33
|
+
try {
|
|
34
|
+
const buf = fs.readFileSync(keyPath(home));
|
|
35
|
+
const utf16 = buf.length >= 2 && buf[0] === 0xff && buf[1] === 0xfe;
|
|
36
|
+
return buf.toString(utf16 ? 'utf16le' : 'utf8').replace(/[\uFEFF\u0000]/g, '').trim();
|
|
37
|
+
} catch (_) { return ''; }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Argumentos do `claude` que abre a sessao com o canal. Separado pra ser testado sem rede.
|
|
41
|
+
function buildClaudeArgs(argv) {
|
|
42
|
+
const safe = argv.includes('--safe');
|
|
43
|
+
const extra = argv.filter(a => a !== '--safe');
|
|
44
|
+
const args = ['--dangerously-load-development-channels', CHANNEL];
|
|
45
|
+
if (!safe) args.push('--permission-mode', 'bypassPermissions');
|
|
46
|
+
return args.concat(extra);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function run(bin, args, opts) {
|
|
50
|
+
return spawnSync(bin, args, { encoding: 'utf8', shell: IS_WIN, ...opts });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// No Windows o `claude` instalado pelo npm e' um `claude.cmd`; com shell ele costuma resolver,
|
|
54
|
+
// mas ha PATH em que so' o nome com extensao funciona.
|
|
55
|
+
function resolveClaude() {
|
|
56
|
+
const candidates = IS_WIN ? ['claude', 'claude.cmd'] : ['claude'];
|
|
57
|
+
for (const bin of candidates) {
|
|
58
|
+
const r = run(bin, ['--version']);
|
|
59
|
+
if (!r.error && r.status === 0) return bin;
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function step(claude, label, args, okPatterns) {
|
|
65
|
+
const r = run(claude, args);
|
|
66
|
+
const out = ((r.stdout || '') + (r.stderr || '')).trim();
|
|
67
|
+
if (r.status === 0) { console.log(' [ok] ' + label); return true; }
|
|
68
|
+
if (okPatterns.some(p => p.test(out))) { console.log(' [ok] ' + label + ' (ja estava)'); return true; }
|
|
69
|
+
console.log(' [falhou] ' + label + ': ' + (out.split('\n').pop() || 'sem detalhe'));
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function main(argv) {
|
|
74
|
+
if (!readKey()) {
|
|
75
|
+
console.error('Falta a chave do Iron Office. Faca o passo 4 em ' + ONBOARDING);
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const claude = resolveClaude();
|
|
80
|
+
if (!claude) {
|
|
81
|
+
console.error('Instale o Claude Code primeiro: https://claude.com/claude-code');
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.log('Iron Office - preparando o canal');
|
|
86
|
+
const okMarket = step(claude, 'marketplace ' + MARKETPLACE_REPO, ['plugin', 'marketplace', 'add', MARKETPLACE_REPO], [/already/i]);
|
|
87
|
+
const okPlugin = okMarket && step(claude, 'plugin ' + PLUGIN, ['plugin', 'install', PLUGIN, '--scope', 'user'], [/already/i]);
|
|
88
|
+
if (!okMarket || !okPlugin) {
|
|
89
|
+
console.error('');
|
|
90
|
+
console.error('Nao deu pra instalar o plugin do Iron Office. Confira:');
|
|
91
|
+
console.error(' 1. a internet esta funcionando;');
|
|
92
|
+
console.error(' 2. o git esta instalado (rode: git --version);');
|
|
93
|
+
console.error(' 3. rode de novo: npx iron-edge office');
|
|
94
|
+
console.error('Se continuar, mande um print desta tela pro suporte.');
|
|
95
|
+
return 1;
|
|
96
|
+
}
|
|
97
|
+
// atualizar e' melhor-esforco: sem internet no meio, segue com a versao ja instalada
|
|
98
|
+
step(claude, 'atualizacao do plugin', ['plugin', 'update', PLUGIN], [/already|up.to.date|latest/i]);
|
|
99
|
+
|
|
100
|
+
const safe = argv.includes('--safe');
|
|
101
|
+
console.log('');
|
|
102
|
+
console.log('Abrindo o Claude Code com o Iron Office ligado.');
|
|
103
|
+
console.log('Vai aparecer um aviso de canal (recurso em teste): aceite.');
|
|
104
|
+
if (!safe) {
|
|
105
|
+
console.log('O Iron vai agir SEM pedir licenca a cada passo (e o que deixa ele trabalhar');
|
|
106
|
+
console.log('enquanto voce esta no site). Quer aprovar cada passo? Rode: npx iron-edge office --safe');
|
|
107
|
+
}
|
|
108
|
+
console.log('Deixe esta aba aberta: e ela que faz o Iron responder no site.');
|
|
109
|
+
console.log('');
|
|
110
|
+
|
|
111
|
+
const r = spawnSync(claude, buildClaudeArgs(argv), {
|
|
112
|
+
stdio: 'inherit',
|
|
113
|
+
shell: IS_WIN,
|
|
114
|
+
env: { ...process.env, IRON_OFFICE_CHANNEL: '1' },
|
|
115
|
+
});
|
|
116
|
+
return r.status ?? 1;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
module.exports = { buildClaudeArgs, keyPath, readKey, CHANNEL, PLUGIN, MARKETPLACE_REPO };
|
|
120
|
+
|
|
121
|
+
if (require.main === module) {
|
|
122
|
+
process.exit(main(process.argv.slice(2)));
|
|
123
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iron-edge",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Ecossistema de agentes para Claude Code: 44 agentes de topo, 18 squads e 14 skills, com quality gate, memoria
|
|
3
|
+
"version": "2.4.0",
|
|
4
|
+
"description": "Ecossistema de agentes para Claude Code: 44 agentes de topo, 18 squads e 14 skills, com quality gate, memoria, instalador que nunca sobrescreve e o comando office (chat do Iron Office no dashboard).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
7
7
|
"claude-code",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"node": ">=18.0.0"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
|
-
"test": "node scripts/lint.js && node scripts/test-verify.js && node scripts/test-update.js",
|
|
35
|
+
"test": "node scripts/lint.js && node scripts/test-verify.js && node scripts/test-update.js && node scripts/test-office.js",
|
|
36
36
|
"test:matriz": "node scripts/test-matriz-update.js"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|