edusquads-cli 0.2.2 → 0.2.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.
@@ -34,10 +34,11 @@ Operar squads multiagente no Claude Code com comportamento semelhante ao OpenSqu
34
34
  ## Processo
35
35
  1. ler contexto obrigatório e memória ativa
36
36
  2. validar campos críticos de memória; coletar lacunas antes de planejar
37
- 3. diagnosticar intenção e mapear squads/agentes/skills adequados
38
- 4. propor ou executar plano em etapas com checkpoints
39
- 5. registrar decisões, evidências e status no run correspondente
40
- 6. encerrar com próximos passos objetivos
37
+ 3. refinar público com skill de ICP quando o público estiver genérico
38
+ 4. diagnosticar intenção e mapear squads/agentes/skills adequados
39
+ 5. propor ou executar plano em etapas com checkpoints
40
+ 6. registrar decisões, evidências e status no run correspondente
41
+ 7. encerrar com próximos passos objetivos
41
42
 
42
43
  ## Saída
43
44
  - plano de execução multi-squad (quando aplicável)
@@ -94,28 +95,27 @@ Operar squads multiagente no Claude Code com comportamento semelhante ao OpenSqu
94
95
 
95
96
  ### Campos críticos
96
97
  - nome preferido
97
- - projeto/negócio
98
- - nicho
99
- - público-alvo
100
- - objetivo principal
101
- - canal principal
102
- - oferta principal (ou hipótese)
98
+ - o que a pessoa faz
99
+ - onde vende
100
+ - meta principal (30-90 dias)
101
+ - formato favorito
102
+ - público inicial (rascunho)
103
103
 
104
104
  ### Fluxo de memória
105
105
  1. Ler memória ativa.
106
- 2. Se campo crítico faltar, iniciar onboarding de briefing completo.
106
+ 2. Se campo crítico faltar, iniciar onboarding enxuto.
107
107
  3. Salvar briefing no perfil individual (`usuarios/<slug>.md`).
108
108
  4. Atualizar `USUARIO-ATIVO.md` com o briefing coletado.
109
- 5. então propor plano de squads.
109
+ 5. Refinar público com skill ICP (`squads/02-pesquisa/skills/refinar-icp.md`).
110
+ 6. Só então propor plano de squads.
110
111
 
111
112
  ### Roteiro de briefing obrigatório
112
- 1. identidade da pessoa (nome, papel)
113
- 2. negócio/oferta principal
114
- 3. público-alvo e nicho
115
- 4. objetivo principal (30-90 dias)
116
- 5. canais e formato preferido
117
- 6. restrições (tempo, equipe, orçamento)
118
- 7. stack, ativos e dados disponíveis
113
+ 1. quem é a pessoa e o que ela faz
114
+ 2. o que vende e onde vende
115
+ 3. meta principal (30-90 dias)
116
+ 4. formato favorito de conteúdo
117
+ 5. público inicial em linguagem da pessoa
118
+ 6. acionar skill de ICP para refinar público (`squads/02-pesquisa/skills/refinar-icp.md`)
119
119
 
120
120
  ## Modo de comando `/edusquads`
121
121
  Interpretar intenção do usuário por subcomando semântico.
@@ -125,7 +125,7 @@ Interpretar intenção do usuário por subcomando semântico.
125
125
 
126
126
  ### `/edusquads init`
127
127
  - Inicia onboarding do usuário.
128
- - Coleta briefing completo e salva perfil + usuário ativo.
128
+ - Coleta briefing enxuto e salva perfil + usuário ativo.
129
129
 
130
130
  ### `/edusquads onboarding`
131
131
  - Força nova coleta de briefing para troca/atualização de usuário.
package/README.md CHANGED
@@ -33,7 +33,16 @@ npx edusquads-cli install --skip-onboarding
33
33
  ```
34
34
 
35
35
  Após instalar, o CLI pergunta no terminal se a pessoa quer preencher o briefing na hora.
36
- Se aceitar, ele executa onboarding e grava a memória automaticamente.
36
+ Se aceitar, ele executa onboarding enxuto e grava a memória automaticamente.
37
+
38
+ Briefing enxuto coleta apenas:
39
+ - o que a pessoa faz
40
+ - o que vende e onde vende
41
+ - meta principal (30-90 dias)
42
+ - formato favorito
43
+ - público inicial (rascunho)
44
+
45
+ Depois disso, o sistema refina o público com a skill de ICP.
37
46
 
38
47
 
39
48
  Depois da instalação, abra o projeto no Claude Code e use:
@@ -49,6 +58,7 @@ Como o Claude Code suporta skills em `.claude/skills/<nome>/SKILL.md`, a skill `
49
58
  - `squads/`: definição dos squads e agentes oficiais
50
59
  - `pesquisa/web/`: sínteses com fontes públicas
51
60
  - `_edusquads/memoria/`: memória operacional do usuário (ativo + perfis em `usuarios/`)
61
+ - `squads/02-pesquisa/skills/refinar-icp.md`: skill para refinar público a partir do briefing
52
62
  - `_edusquads/runs/`: histórico de execuções do `/edusquads`
53
63
  - `_edusquads/browser_profile/`: sessão local de navegação (Playwright)
54
64
  - `_edusquads/evidencias/`: evidências de investigação web
@@ -59,6 +69,8 @@ Sistema operacional implementado com foco em:
59
69
  - comando `/edusquads`
60
70
  - paridade funcional base inspirada no OpenSquad
61
71
  - memória persistida do usuário (`_edusquads/memoria/USUARIO-ATIVO.md`)
72
+ - onboarding interativo enxuto de briefing (`base/scripts/edusquads_onboarding_memoria.py`)
73
+ - refino de público via skill ICP (`squads/02-pesquisa/skills/refinar-icp.md`)
62
74
  - histórico de runs (`_edusquads/runs/`)
63
75
  - protocolo de investigação web com Playwright (`base/protocolo-playwright-edusquads.md`)
64
76
  - playbooks por plataforma (`base/playbooks/investigacao/`)
@@ -2,35 +2,26 @@
2
2
 
3
3
  ## Identidade
4
4
  - Nome preferido:
5
- - Projeto/negócio:
6
- - Papel do usuário:
5
+ - O que a pessoa faz:
7
6
 
8
- ## Estado atual
9
- - Nicho principal:
10
- - Público-alvo:
11
- - Oferta principal:
12
- - Maturidade da operação (inicial/intermediária/avançada):
7
+ ## Negócio e Canal
8
+ - O que vende:
9
+ - Onde vende:
13
10
 
14
- ## Objetivos em andamento
15
- - Objetivo principal (30-90 dias):
16
- - Objetivo secundário:
17
- - KPI principal:
11
+ ## Meta principal
12
+ - Meta (30-90 dias):
18
13
 
19
- ## Preferências
20
- - Canais prioritários:
21
- - Estilo de comunicação:
22
- - Formato de entrega preferido:
23
-
24
- ## Restrições
25
- - Tempo disponível:
26
- - Equipe disponível:
27
- - Orçamento aproximado:
28
- - Limites operacionais:
14
+ ## Público
15
+ - Público inicial (rascunho):
16
+ - ICP prioritário (refinado):
17
+ - Variações de ICP:
18
+ -
19
+ -
20
+ -
29
21
 
30
- ## Stack e ativos
31
- - Ferramentas atuais:
32
- - Ativos existentes (lista/email/site/perfis):
33
- - Dados disponíveis:
22
+ ## Preferências
23
+ - Formato favorito:
24
+ - Estilo de comunicação preferido:
34
25
 
35
26
  ## Histórico de decisões
36
27
  - [ ]
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## Subcomandos semânticos (via args)
8
8
  - `/edusquads init`
9
- - inicia onboarding e coleta briefing completo da pessoa usuária
9
+ - inicia onboarding e coleta briefing enxuto da pessoa usuária
10
10
  - salva perfil em `_edusquads/memoria/usuarios/` e atualiza `USUARIO-ATIVO.md`
11
11
  - `/edusquads onboarding`
12
12
  - força nova coleta de briefing para troca/atualização de usuário
@@ -14,6 +14,8 @@
14
14
  - resume estado dos squads, memória e artefatos
15
15
  - `/edusquads memoria`
16
16
  - mostra e atualiza memória ativa
17
+ - `/edusquads icp`
18
+ - refina público-alvo com a skill de ICP (`squads/02-pesquisa/skills/refinar-icp.md`)
17
19
  - `/edusquads squads`
18
20
  - lista os 16 squads e indica quais usar no objetivo atual
19
21
  - `/edusquads plano <objetivo>`
@@ -42,6 +44,7 @@
42
44
  - todos os subcomandos usam `_edusquads/memoria/USUARIO-ATIVO.md`
43
45
  - onboarding é obrigatório quando memória crítica estiver vazia
44
46
  - onboarding pode ser executado por `base/scripts/edusquads_onboarding_memoria.py`
47
+ - após onboarding, refinar público com `squads/02-pesquisa/skills/refinar-icp.md`
45
48
  - onboarding deve salvar perfil em `_edusquads/memoria/usuarios/` e atualizar `USUARIO-ATIVO.md`
46
49
  - cada execução relevante deve gerar/atualizar um run em `_edusquads/runs/`
47
50
  - toda investigação web deve seguir `base/protocolo-playwright-edusquads.md`
@@ -10,46 +10,43 @@ Manter uma memória operacional da pessoa usuária para personalizar a atuação
10
10
 
11
11
  ## Quando coletar memória
12
12
  1. Primeira execução do `/edusquads` no projeto
13
- 2. Quando o usuário pedir atualização de contexto pessoal/profissional
14
- 3. Quando houver troca de usuário ou mudança relevante de nicho/objetivo/estilo
13
+ 2. Quando houver troca de usuário
14
+ 3. Quando a pessoa pedir atualização de contexto
15
15
 
16
16
  ## Princípios
17
- - coletar apenas dados úteis para execução
18
- - resumir em linguagem operacional
19
- - separar fato de inferência
17
+ - coletar somente dados úteis para execução
18
+ - manter briefing enxuto
19
+ - não pedir KPI técnico no onboarding inicial
20
20
  - nunca registrar segredos/token/senhas na memória
21
21
 
22
22
  ## Regras de uso no comando
23
23
  - antes de planejar squads, ler `USUARIO-ATIVO.md`
24
- - se campos críticos estiverem vazios, executar onboarding (briefing completo)
24
+ - se campos críticos estiverem vazios, executar onboarding enxuto
25
25
  - salvar briefing no perfil individual e atualizar o usuário ativo
26
- - toda recomendação deve refletir esse contexto
26
+ - após onboarding, refinar público com skill ICP
27
27
 
28
28
  ## Campos críticos (não seguir sem isso)
29
29
  - nome preferido
30
- - projeto/negócio
31
- - nicho
32
- - público-alvo
33
- - objetivo principal
34
- - canal principal
35
- - oferta principal (ou hipótese de oferta)
36
-
37
- ## Roteiro obrigatório de briefing (onboarding)
38
- 1. Quem é a pessoa e qual papel dela no projeto
39
- 2. Qual é o negócio/oferta principal
40
- 3. Quem é o público-alvo e qual nicho
41
- 4. Qual é o objetivo principal nos próximos 30-90 dias
42
- 5. Quais canais e formatos de entrega priorizar
43
- 6. Quais restrições de tempo/equipe/orçamento existem
44
- 7. Quais ferramentas, ativos e dados já existem
30
+ - o que a pessoa faz
31
+ - onde vende
32
+ - meta principal (30-90 dias)
33
+ - formato favorito
34
+ - público inicial (rascunho)
35
+
36
+ ## Roteiro obrigatório de briefing (onboarding enxuto)
37
+ 1. Quem é a pessoa e o que ela faz
38
+ 2. O que vende e onde vende
39
+ 3. Meta principal para os próximos 30-90 dias
40
+ 4. Formato favorito de conteúdo
41
+ 5. Público inicial em linguagem da pessoa
42
+ 6. Refinar esse público com a skill de ICP (`squads/02-pesquisa/skills/refinar-icp.md`)
45
43
 
46
44
  ## Formato de atualização
47
45
  Sempre atualizar por bloco:
48
46
  1. `## Identidade`
49
- 2. `## Estado atual`
50
- 3. `## Objetivos em andamento`
51
- 4. `## Preferências`
52
- 5. `## Restrições`
53
- 6. `## Stack e ativos`
54
- 7. `## Histórico de decisões`
55
- 8. `## Última atualização`
47
+ 2. `## Negócio e Canal`
48
+ 3. `## Meta principal`
49
+ 4. `## Público`
50
+ 5. `## Preferências`
51
+ 6. `## Histórico de decisões`
52
+ 7. `## Última atualização`
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- Onboarding de memória do EduSquads.
3
+ Onboarding enxuto de memória do EduSquads.
4
4
 
5
- Coleta briefing completo no terminal e salva em:
5
+ Coleta briefing essencial e salva em:
6
6
  - _edusquads/memoria/USUARIO-ATIVO.md
7
7
  - _edusquads/memoria/usuarios/<slug>.md
8
8
  """
@@ -14,13 +14,32 @@ import datetime as dt
14
14
  import re
15
15
  from pathlib import Path
16
16
 
17
+ RESET = "\033[0m"
18
+ BOLD = "\033[1m"
19
+ DIM = "\033[2m"
20
+ CYAN = "\033[36m"
21
+ GREEN = "\033[32m"
22
+ YELLOW = "\033[33m"
17
23
 
18
- def ask(prompt: str, required: bool = True) -> str:
24
+
25
+ def ui_title(text: str) -> None:
26
+ print(f"\n{BOLD}{CYAN}╭──────────────────────────────────────────────╮{RESET}")
27
+ print(f"{BOLD}{CYAN}│{RESET} {BOLD}{text:<44}{RESET} {BOLD}{CYAN}│{RESET}")
28
+ print(f"{BOLD}{CYAN}╰──────────────────────────────────────────────╯{RESET}\n")
29
+
30
+
31
+ def ui_step(number: int, title: str) -> None:
32
+ print(f"{BOLD}{CYAN}[{number}/6]{RESET} {BOLD}{title}{RESET}")
33
+
34
+
35
+ def ask(prompt: str, required: bool = True, hint: str | None = None) -> str:
36
+ if hint:
37
+ print(f"{DIM}{hint}{RESET}")
19
38
  while True:
20
39
  value = input(f"{prompt}: ").strip()
21
40
  if value or not required:
22
41
  return value
23
- print("Campo obrigatório. Preencha para continuar.")
42
+ print(f"{YELLOW}Campo obrigatório. Responda para continuar.{RESET}")
24
43
 
25
44
 
26
45
  def slugify(text: str) -> str:
@@ -31,44 +50,59 @@ def slugify(text: str) -> str:
31
50
  return t or "usuario"
32
51
 
33
52
 
53
+ def refine_icp(data: dict) -> tuple[str, list[str]]:
54
+ publico_base = data["publico_inicial"]
55
+ canal = data["onde_vende"]
56
+ meta = data["meta_90_dias"]
57
+ formato = data["formato_favorito"]
58
+
59
+ icp_prioritario = (
60
+ f"Profissionais que já reconhecem o problema que {data['o_que_faz']} resolve, "
61
+ f"estão buscando avanço prático nos próximos 90 dias e consomem {formato} "
62
+ f"antes de decidir compra em {canal}."
63
+ )
64
+
65
+ variacoes = [
66
+ f"Conservador: {publico_base} com urgência imediata para atingir '{meta}'.",
67
+ f"Principal: {icp_prioritario}",
68
+ f"Expansão: público adjacente a {publico_base}, com dor semelhante e menor consciência do problema.",
69
+ ]
70
+
71
+ return icp_prioritario, variacoes
72
+
73
+
34
74
  def render_memory(data: dict, source: str) -> str:
35
75
  today = dt.date.today().isoformat()
76
+ icp_prioritario, variacoes = refine_icp(data)
77
+
36
78
  return f"""# Memória do Usuário Ativo
37
79
 
38
80
  ## Identidade
39
81
  - Nome preferido: {data['nome']}
40
- - Projeto/negócio: {data['projeto']}
41
- - Papel do usuário: {data['papel']}
42
-
43
- ## Estado atual
44
- - Nicho principal: {data['nicho']}
45
- - Público-alvo: {data['publico']}
46
- - Oferta principal: {data['oferta']}
47
- - Maturidade da operação (inicial/intermediária/avançada): {data['maturidade']}
82
+ - O que a pessoa faz: {data['o_que_faz']}
48
83
 
49
- ## Objetivos em andamento
50
- - Objetivo principal (30-90 dias): {data['objetivo_principal']}
51
- - Objetivo secundário: {data['objetivo_secundario']}
52
- - KPI principal: {data['kpi']}
84
+ ## Negócio e Canal
85
+ - O que vende: {data['o_que_vende']}
86
+ - Onde vende: {data['onde_vende']}
53
87
 
54
- ## Preferências
55
- - Canais prioritários: {data['canais']}
56
- - Estilo de comunicação: {data['estilo']}
57
- - Formato de entrega preferido: {data['formato_entrega']}
88
+ ## Meta principal
89
+ - Meta (30-90 dias): {data['meta_90_dias']}
58
90
 
59
- ## Restrições
60
- - Tempo disponível: {data['tempo']}
61
- - Equipe disponível: {data['equipe']}
62
- - Orçamento aproximado: {data['orcamento']}
63
- - Limites operacionais: {data['limites']}
91
+ ## Público
92
+ - Público inicial (rascunho): {data['publico_inicial']}
93
+ - ICP prioritário (refinado): {icp_prioritario}
94
+ - Variações de ICP:
95
+ - {variacoes[0]}
96
+ - {variacoes[1]}
97
+ - {variacoes[2]}
64
98
 
65
- ## Stack e ativos
66
- - Ferramentas atuais: {data['ferramentas']}
67
- - Ativos existentes (lista/email/site/perfis): {data['ativos']}
68
- - Dados disponíveis: {data['dados']}
99
+ ## Preferências
100
+ - Formato favorito: {data['formato_favorito']}
101
+ - Estilo de comunicação preferido: {data['estilo']}
69
102
 
70
103
  ## Histórico de decisões
71
- - [x] briefing inicial coletado no onboarding
104
+ - [x] briefing inicial coletado no onboarding enxuto
105
+ - [x] público refinado via skill de ICP (`squads/02-pesquisa/skills/refinar-icp.md`)
72
106
 
73
107
  ## Última atualização
74
108
  - Data: {today}
@@ -77,7 +111,7 @@ def render_memory(data: dict, source: str) -> str:
77
111
 
78
112
 
79
113
  def main() -> int:
80
- parser = argparse.ArgumentParser(description="Onboarding de memória EduSquads")
114
+ parser = argparse.ArgumentParser(description="Onboarding enxuto de memória EduSquads")
81
115
  parser.add_argument("--target", default=".", help="Diretório do projeto")
82
116
  args = parser.parse_args()
83
117
 
@@ -87,44 +121,54 @@ def main() -> int:
87
121
  mem_dir.mkdir(parents=True, exist_ok=True)
88
122
  users_dir.mkdir(parents=True, exist_ok=True)
89
123
 
90
- print("\n=== Onboarding EduSquads: briefing do usuário ===\n")
91
- print("Preencha de forma objetiva. Isso será usado para personalizar os squads.\n")
124
+ ui_title("EduSquads · Onboarding de Briefing")
125
+ print("Briefing enxuto: poucas perguntas, resposta objetiva.\n")
126
+
127
+ ui_step(1, "Identidade")
128
+ nome = ask("Nome preferido")
129
+ o_que_faz = ask("O que você faz", hint="Ex.: consultoria em IA, mentoria de vendas, agência de tráfego")
130
+
131
+ ui_step(2, "Oferta")
132
+ o_que_vende = ask("O que você vende", hint="Produto, serviço, programa, assinatura etc.")
133
+ onde_vende = ask("Onde você vende", hint="Ex.: Instagram DM, WhatsApp, landing page, LinkedIn, YouTube")
134
+
135
+ ui_step(3, "Meta")
136
+ meta_90_dias = ask("Meta principal (30-90 dias)", hint="Troque KPI técnico por resultado que você quer alcançar")
137
+
138
+ ui_step(4, "Público inicial")
139
+ publico_inicial = ask("Quem você quer atingir hoje", hint="Pode ser rascunho. A skill ICP vai refinar")
140
+
141
+ ui_step(5, "Preferências")
142
+ formato_favorito = ask("Formato favorito de conteúdo", hint="Ex.: carrossel, reels, live, aula, newsletter")
143
+ estilo = ask("Estilo de comunicação", required=False) or "direto e prático"
144
+
145
+ ui_step(6, "Confirmação")
146
+ print(f"{DIM}Vamos salvar e gerar ICP refinado automaticamente.{RESET}")
92
147
 
93
148
  data = {
94
- "nome": ask("Nome preferido"),
95
- "projeto": ask("Projeto/negócio"),
96
- "papel": ask("Papel do usuário (ex: fundador, gestor, creator)"),
97
- "nicho": ask("Nicho principal"),
98
- "publico": ask("Público-alvo"),
99
- "oferta": ask("Oferta principal (produto/serviço)", required=False) or "não informado",
100
- "maturidade": ask("Maturidade da operação (inicial/intermediária/avançada)"),
101
- "objetivo_principal": ask("Objetivo principal (30-90 dias)"),
102
- "objetivo_secundario": ask("Objetivo secundário", required=False) or "não informado",
103
- "kpi": ask("KPI principal", required=False) or "não informado",
104
- "canais": ask("Canais prioritários", required=False) or "não informado",
105
- "estilo": ask("Estilo de comunicação preferido", required=False) or "não informado",
106
- "formato_entrega": ask("Formato de entrega preferido", required=False) or "não informado",
107
- "tempo": ask("Tempo disponível", required=False) or "não informado",
108
- "equipe": ask("Equipe disponível", required=False) or "não informado",
109
- "orcamento": ask("Orçamento aproximado", required=False) or "não informado",
110
- "limites": ask("Limites operacionais", required=False) or "não informado",
111
- "ferramentas": ask("Ferramentas atuais", required=False) or "não informado",
112
- "ativos": ask("Ativos existentes (lista/email/site/perfis)", required=False) or "não informado",
113
- "dados": ask("Dados disponíveis", required=False) or "não informado",
149
+ "nome": nome,
150
+ "o_que_faz": o_que_faz,
151
+ "o_que_vende": o_que_vende,
152
+ "onde_vende": onde_vende,
153
+ "meta_90_dias": meta_90_dias,
154
+ "publico_inicial": publico_inicial,
155
+ "formato_favorito": formato_favorito,
156
+ "estilo": estilo,
114
157
  }
115
158
 
116
- content = render_memory(data, source="onboarding-interativo")
159
+ content = render_memory(data, source="onboarding-enxuto-interativo")
117
160
 
118
161
  active_path = mem_dir / "USUARIO-ATIVO.md"
119
162
  active_path.write_text(content, encoding="utf-8")
120
163
 
121
- slug = slugify(data["nome"])
164
+ slug = slugify(nome)
122
165
  profile_path = users_dir / f"{slug}.md"
123
166
  profile_path.write_text(content, encoding="utf-8")
124
167
 
125
- print("\n✅ Briefing salvo com sucesso:")
168
+ print(f"\n{GREEN}✅ Briefing salvo com sucesso{RESET}")
126
169
  print(f"- ativo: {active_path}")
127
170
  print(f"- perfil: {profile_path}")
171
+ print(f"- icp skill: squads/02-pesquisa/skills/refinar-icp.md\n")
128
172
  return 0
129
173
 
130
174
 
package/bin/edusquads.js CHANGED
@@ -5,6 +5,28 @@ const path = require("path");
5
5
  const readline = require("readline");
6
6
  const { spawnSync } = require("child_process");
7
7
 
8
+ const UI = {
9
+ reset: "\x1b[0m",
10
+ bold: "\x1b[1m",
11
+ dim: "\x1b[2m",
12
+ cyan: "\x1b[36m",
13
+ green: "\x1b[32m",
14
+ yellow: "\x1b[33m",
15
+ red: "\x1b[31m",
16
+ };
17
+
18
+ function style(text, ...codes) {
19
+ return `${codes.join("")}${text}${UI.reset}`;
20
+ }
21
+
22
+ function panel(title) {
23
+ const w = 52;
24
+ const t = ` ${title} `;
25
+ const line = "─".repeat(Math.max(0, w - t.length));
26
+ console.log(`\n${style("╭" + t + line + "╮", UI.cyan, UI.bold)}`);
27
+ console.log(`${style("╰" + "─".repeat(w) + "╯", UI.cyan, UI.bold)}`);
28
+ }
29
+
8
30
  const args = process.argv.slice(2);
9
31
  const command = args.find((a) => !a.startsWith("-")) || "install";
10
32
  const force = args.includes("--force");
@@ -36,6 +58,8 @@ const SHARED_INSTALL_ITEMS = [
36
58
  { src: "pesquisa", dest: "pesquisa" },
37
59
  { src: "squads", dest: "squads" },
38
60
  { src: "_edusquads/memoria/USUARIO-ATIVO.md", dest: "_edusquads/memoria/USUARIO-ATIVO.md" },
61
+ { src: "_edusquads/memoria/USUARIO-MODELO.md", dest: "_edusquads/memoria/USUARIO-MODELO.md" },
62
+ { src: "_edusquads/memoria/usuarios/README.md", dest: "_edusquads/memoria/usuarios/README.md" },
39
63
  { src: "_edusquads/runs/RUN-MODELO.md", dest: "_edusquads/runs/RUN-MODELO.md" },
40
64
  { src: "_edusquads/runs/RUNS-INDEX.md", dest: "_edusquads/runs/RUNS-INDEX.md" },
41
65
  { src: "_edusquads/evidencias/EVIDENCIA-MODELO.md", dest: "_edusquads/evidencias/EVIDENCIA-MODELO.md" },
@@ -171,7 +195,7 @@ function ask(promptText) {
171
195
  async function askOnboarding() {
172
196
  if (skipOnboarding || dryRun) return false;
173
197
  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
174
- const ans = (await ask("Deseja fazer agora o briefing do usuário? (s/N): ")).trim().toLowerCase();
198
+ const ans = (await ask(`${style("\n→", UI.cyan, UI.bold)} Deseja iniciar o briefing guiado agora? ${style("(s/N)", UI.dim)} `)).trim().toLowerCase();
175
199
  return ["s", "sim", "y", "yes"].includes(ans);
176
200
  }
177
201
 
@@ -203,15 +227,15 @@ async function resolveIdes() {
203
227
  return ["claude"];
204
228
  }
205
229
 
206
- console.log("\nSelecione a(s) IDE(s) para instalar o EduSquads:");
207
- console.log(" 1) claude (Claude Code)");
208
- console.log(" 2) codex");
209
- console.log(" 3) opencode");
210
- console.log(" 4) kilocode");
211
- console.log(" 5) antigravity");
212
- console.log(" 6) all (todas)");
230
+ panel("EduSquads · Seleção de IDE");
231
+ console.log(`${style(" 1)", UI.cyan)} claude ${style("(Claude Code)", UI.dim)}`);
232
+ console.log(`${style(" 2)", UI.cyan)} codex`);
233
+ console.log(`${style(" 3)", UI.cyan)} opencode`);
234
+ console.log(`${style(" 4)", UI.cyan)} kilocode`);
235
+ console.log(`${style(" 5)", UI.cyan)} antigravity`);
236
+ console.log(`${style(" 6)", UI.cyan)} all ${style("(todas)", UI.dim)}`);
213
237
 
214
- const answer = (await ask("Digite número(s) separados por vírgula (default: 1): ")).trim();
238
+ const answer = (await ask(`${style("\n→", UI.cyan, UI.bold)} Digite número(s) separados por vírgula ${style("[default: 1]", UI.dim)}: `)).trim();
215
239
  if (!answer) return ["claude"];
216
240
 
217
241
  const numberMap = {
@@ -271,20 +295,21 @@ async function install() {
271
295
  const gitignoreChanged = patchGitignore(targetDir);
272
296
  writeInstallMarker(targetDir, ides);
273
297
 
274
- console.log(`\nEduSquads ${dryRun ? "(simulação) " : ""}instalado em: ${targetDir}`);
275
- console.log(`IDEs instaladas: ${ides.join(", ")}`);
276
- console.log(`Arquivos criados: ${report.created}`);
277
- console.log(`Arquivos sobrescritos: ${report.overwritten}`);
278
- console.log(`Arquivos ignorados ( existiam): ${report.skipped}`);
279
- console.log(`.gitignore atualizado: ${gitignoreChanged ? "sim" : "não"}`);
298
+ panel("EduSquads · Instalação concluída");
299
+ console.log(`${style("✔", UI.green, UI.bold)} destino: ${targetDir}`);
300
+ console.log(`${style("✔", UI.green, UI.bold)} IDEs: ${ides.join(", ")}`);
301
+ console.log(`${style("•", UI.cyan)} criados: ${report.created}`);
302
+ console.log(`${style("•", UI.cyan)} sobrescritos: ${report.overwritten}`);
303
+ console.log(`${style("", UI.cyan)} ignorados: ${report.skipped}`);
304
+ console.log(`${style("•", UI.cyan)} .gitignore atualizado: ${gitignoreChanged ? "sim" : "não"}`);
280
305
 
281
306
  const doOnboarding = await askOnboarding();
282
307
  if (doOnboarding) {
283
- console.log("\nIniciando onboarding de briefing...\n");
308
+ console.log(`\n${style("→", UI.cyan, UI.bold)} Iniciando briefing guiado...\n`);
284
309
  runOnboarding(targetDir);
285
310
  }
286
311
 
287
- console.log("\nComandos esperados por IDE (após abrir o projeto na IDE):");
312
+ console.log(`\n${style("Próximo passo", UI.bold)}:`);
288
313
  for (const ide of ides) {
289
314
  if (ide === "claude") console.log("- Claude Code: /edusquads");
290
315
  else console.log(`- ${ide}: skill 'edusquads' instalada em ${IDE_SKILL_PATHS[ide]}`);
package/carrosseis.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  Voce e um agente especializado em criar carrosseis profissionais para o Instagram no estilo editorial/investigativo inspirado em [PERFIL_INSPIRACAO] e perfis de growth/conteudo viral. Todos os carrosseis sao de autoria do **[SEU_INSTAGRAM]** e tem como tema principal **Inteligencia Artificial**.
4
4
 
5
+ ## Pre-check obrigatorio (antes de qualquer criacao)
6
+
7
+ Antes de iniciar, **sempre** coletar e validar as credenciais da pessoa usuaria:
8
+
9
+ - `APIFY_API_TOKEN` (para pesquisa de tendencias no Reddit)
10
+ - `UNSPLASH_ACCESS_KEY` (para busca de fotos)
11
+
12
+ Regras:
13
+ - Nao iniciar roteiro, HTML ou imagens sem essas duas chaves.
14
+ - Se alguma chave faltar, pausar e pedir a chave primeiro.
15
+ - Nunca expor a chave em resposta, log, markdown ou print.
16
+ - Quando o ambiente suportar coleta segura, usar fluxo seguro de segredo (ex.: coleta mascarada).
17
+
5
18
  ---
6
19
 
7
20
  ## Identidade Visual (Estilo Editorial/Investigativo)
@@ -243,7 +256,7 @@ Use a API do Apify para acessar o Reddit e encontrar topicos em alta sobre **Int
243
256
 
244
257
  ```bash
245
258
  # Buscar posts trending no Reddit sobre IA
246
- curl -X POST "https://api.apify.com/v2/acts/trudax~reddit-scraper/runs?token=apify_api_nRqx0LcknCK9HAkJChOYhLlAgzmNkf2eh8cE" \
259
+ curl -X POST "https://api.apify.com/v2/acts/trudax~reddit-scraper/runs?token=${APIFY_API_TOKEN}" \
247
260
  -H "Content-Type: application/json" \
248
261
  -d '{
249
262
  "startUrls": [
@@ -266,7 +279,7 @@ Depois, busque os resultados:
266
279
 
267
280
  ```bash
268
281
  # Verificar status e buscar resultados
269
- curl "https://api.apify.com/v2/acts/trudax~reddit-scraper/runs/last/dataset/items?token=apify_api_nRqx0LcknCK9HAkJChOYhLlAgzmNkf2eh8cE"
282
+ curl "https://api.apify.com/v2/acts/trudax~reddit-scraper/runs/last/dataset/items?token=${APIFY_API_TOKEN}"
270
283
  ```
271
284
 
272
285
  **Subreddits de IA recomendados:**
@@ -288,7 +301,7 @@ Analise os posts com mais engajamento e extraia:
288
301
 
289
302
  ```bash
290
303
  # Buscar imagens relevantes ao tema
291
- curl -H "Authorization: Client-ID [SUA_UNSPLASH_ACCESS_KEY]" \
304
+ curl -H "Authorization: Client-ID ${UNSPLASH_ACCESS_KEY}" \
292
305
  "https://api.unsplash.com/search/photos?query=TEMA_AQUI&per_page=10&orientation=portrait"
293
306
  ```
294
307
 
@@ -955,6 +968,7 @@ Siga [SEU_INSTAGRAM] para mais conteudo sobre IA.
955
968
 
956
969
  Quando o usuario pedir para criar um carrossel, siga este fluxo:
957
970
 
971
+ 0. **Coletar e validar credenciais** (`APIFY_API_TOKEN` e `UNSPLASH_ACCESS_KEY`)
958
972
  1. **Pesquise tendencias de IA** no Reddit usando Apify API
959
973
  2. **Escolha o tema** mais relevante/viral encontrado
960
974
  3. **Crie o roteiro** com titulos investigativos e textos para cada slide
@@ -970,19 +984,23 @@ Quando o usuario pedir para criar um carrossel, siga este fluxo:
970
984
 
971
985
  ### Unsplash API
972
986
  - **Endpoint**: `https://api.unsplash.com/search/photos`
973
- - **Header**: `Authorization: Client-ID [SUA_UNSPLASH_ACCESS_KEY]`
974
- - **Application ID**: `904033`
975
- - **Access Key**: `[SUA_UNSPLASH_ACCESS_KEY]`
976
- - **Secret Key**: `[SUA_UNSPLASH_SECRET_KEY]`
977
- - **Redirect URI**: `urn:ietf:wg:oauth:2.0:oob`
987
+ - **Header**: `Authorization: Client-ID ${UNSPLASH_ACCESS_KEY}`
988
+ - **Variavel obrigatoria**: `UNSPLASH_ACCESS_KEY`
989
+ - **Opcional**: `UNSPLASH_SECRET_KEY` (nao necessaria para busca publica de fotos)
978
990
  - **Docs**: https://unsplash.com/documentation
979
991
  - **Campo de URL para slides**: `results[n].urls.regular` (1080px)
980
992
 
981
993
  ### Apify (Reddit Scraper)
982
- - **Token**: `apify_api_nRqx0LcknCK9HAkJChOYhLlAgzmNkf2eh8cE`
994
+ - **Token**: `${APIFY_API_TOKEN}`
995
+ - **Variavel obrigatoria**: `APIFY_API_TOKEN`
983
996
  - **Actor**: `trudax~reddit-scraper`
984
997
  - **Endpoint base**: `https://api.apify.com/v2/acts/trudax~reddit-scraper/runs`
985
998
 
986
999
  ### Playwright MCP
987
1000
  - Usar para renderizar HTML e capturar screenshots dos slides
988
1001
  - Viewport: 1080x1350 (formato Instagram 4:5)
1002
+
1003
+ ### Politica de seguranca
1004
+ - Nunca escrever chaves em markdown, codigo fonte, logs ou resposta final.
1005
+ - Nunca usar token fixo/hardcoded no comando.
1006
+ - Se faltar credencial, interromper e solicitar antes de continuar.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edusquads-cli",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Instalador do framework EduSquads para Claude Code via npx.",
5
5
  "bin": {
6
6
  "edusquads": "bin/edusquads.js"
@@ -0,0 +1,60 @@
1
+ # Skill: Refinar ICP
2
+
3
+ ## objetivo
4
+ Refinar o público inicial informado pela pessoa usuária em um ICP operacional, específico e acionável para conteúdo, oferta e aquisição.
5
+
6
+ ## quando usar
7
+ - quando o briefing tiver público genérico (ex.: "empreendedores", "empresas")
8
+ - quando a mensagem estiver ampla demais
9
+ - antes de gerar plano de conteúdo, copy ou tráfego
10
+
11
+ ## quando não usar
12
+ - quando o usuário já trouxer ICP específico validado recentemente
13
+ - quando a tarefa não exigir definição de público
14
+
15
+ ## entradas
16
+ - o que a pessoa faz
17
+ - o que vende
18
+ - onde vende
19
+ - meta principal (30-90 dias)
20
+ - formato favorito
21
+ - público inicial (rascunho)
22
+
23
+ ## processo
24
+ 1. Identificar quem compra hoje vs. quem a pessoa gostaria de atrair.
25
+ 2. Mapear dor principal, contexto e nível de consciência do público.
26
+ 3. Delimitar recorte de ICP por cenário de compra (canal + momento + problema).
27
+ 4. Redigir ICP em linguagem objetiva (quem é, dor, objetivo, objeção, gatilho de compra).
28
+ 5. Gerar 3 variações de ICP (foco conservador, foco principal, foco expansão).
29
+ 6. Recomendar ICP prioritário com justificativa curta.
30
+
31
+ ## saída
32
+ - ICP prioritário (1 parágrafo)
33
+ - 3 variações de ICP (bullets)
34
+ - sinais de validação inicial (o que observar em 2-4 semanas)
35
+ - ajustes de mensagem por formato favorito
36
+
37
+ ## critérios
38
+ - específico o suficiente para segmentação prática
39
+ - coerente com o que a pessoa vende e onde vende
40
+ - linguagem simples, sem jargão desnecessário
41
+ - aplicável em conteúdo/copy/oferta imediatamente
42
+
43
+ ## fundamento
44
+ Inspirado em princípios publicamente associados a April Dunford (posicionamento), Joanna Wiebe (voz do cliente) e Donald Miller (clareza de mensagem).
45
+
46
+ ## heurísticas
47
+ - "genérico" não é ICP: sempre exigir recorte de contexto
48
+ - priorizar dor concreta sobre atributo demográfico isolado
49
+ - ICP bom facilita decisão editorial e comercial na mesma direção
50
+
51
+ ## anti-padrões
52
+ - ICP amplo demais ("todo mundo")
53
+ - foco em persona estética sem dor/comportamento de compra
54
+ - trocar ICP a cada semana sem evidência
55
+
56
+ ## fontes
57
+ - `especialistas/posicionamento/april-dunford.md`
58
+ - `especialistas/copy/joanna-wiebe.md`
59
+ - `especialistas/mensagem/donald-miller.md`
60
+ - `base/protocolo-memoria-usuario.md`