name: grocery-manager-pt description: > Gestão completa de compras de mercearia para famílias em Portugal. Mantém inventário da casa, aprende hábitos de consumo, faz triagem semanal, compara preços entre Continente Online e Pingo Doce Online, aproveita cupões e saldo, executa compras online, e coordena com a família via WhatsApp. Também gera lembretes de compras presenciais para lojas sem entrega online (Lidl, Makro, Auchan, etc.) com base em preferências configuradas. Usa esta skill quando o utilizador mencionar: compras, supermercado, mercearia, lista de compras, Continente, Pingo Doce, Lidl, Makro, Auchan, "está a faltar", "precisamos de", "acabou o", inventário da casa, preços de supermercado, cupões, saldo de cartão, compra a granel, compra do mês, ou qualquer referência a alimentos, produtos de limpeza, ou artigos domésticos. Também se ativa automaticamente via cron para triagem semanal e stock checks. emoji: 🛒 metadata: openclaw: requires: bins: - python3 - jq env: - CONTINENTE_EMAIL - CONTINENTE_PASSWORD - PINGODOCE_EMAIL - PINGODOCE_PASSWORD install: - id: create-venv kind: exec command: "python3 -m venv .venv" label: "Criar virtual environment Python" - id: pip-deps kind: exec command: ".venv/bin/pip install -r requirements.txt" label: "Instalar dependências Python no venv" - id: copy-prefs kind: exec command: "[ -f data/family_preferences.json ] || cp data/family_preferences.example.json data/family_preferences.json" label: "Criar family_preferences.json a partir do template (se não existir)"
Grocery Manager PT 🛒
Skill de gestão de compras de mercearia para famílias em Portugal. Opera em ciclo contínuo: inventário → previsão → triagem → comparação → compra → tracking.
O tamanho do agregado familiar, membros, orçamento e preferências de entrega são lidos de
{baseDir}/data/family_preferences.json. Este ficheiro é local e está no .gitignore — é criado
pelo install step a partir de {baseDir}/data/family_preferences.example.json. Editar antes de
usar a skill.
Diretório da skill: {baseDir}
Quando Usar
- Qualquer pedido sobre lista de compras (adicionar, remover, consultar)
- Triagem semanal (cron: domingo 9h) ou quando pedido manualmente
- Comparação de preços entre supermercados
- Execução de compras online (Continente, Pingo Doce)
- Relatórios de gastos e consumo
- Planeamento de compra a granel mensal
Dados Persistentes
Todos os ficheiros de dados vivem em {baseDir}/data/:
| Ficheiro | Propósito |
|---|---|
{baseDir}/data/inventory.json |
Lista de compras ativa + estado do inventário |
{baseDir}/data/shopping_history.json |
Histórico de todas as compras realizadas |
{baseDir}/data/consumption_model.json |
Modelo de consumo aprendido (frequências, quantidades) |
{baseDir}/data/family_preferences.json |
Preferências da família (marcas, budget, restrições) — local, gitignored, criado a partir do .example.json |
{baseDir}/data/price_cache.json |
Cache de preços recentes por supermercado |
Antes de qualquer ação, lê os ficheiros de dados relevantes.
Módulo 1 — Gestão da Lista de Compras
Adicionar itens
Quando alguém diz "acabou o X", "precisamos de Y", "adiciona Z":
- Lê
{baseDir}/data/inventory.json - Parseia o item: nome, quantidade (default: 1un), categoria (infere automaticamente)
- Verifica duplicados (match fuzzy — "leite" e "leite meio gordo" merecem confirmação)
- Adiciona ao array
shopping_listcom metadata (quem adicionou, quando, prioridade) - Grava ficheiro
- Confirma: "✅ Adicionei [item] à lista. Total: N itens."
Remover itens
Quando alguém diz "remove X", "já não preciso de Y", "já comprámos Z":
- Lê
{baseDir}/data/inventory.json - Encontra match no
shopping_list(fuzzy) - Remove e grava
- Confirma: "✅ Removi [item]. Total: N itens."
Consultar lista
Quando alguém diz "mostra a lista", "o que falta comprar":
- Lê
{baseDir}/data/inventory.json - Agrupa
shopping_listpor categoria - Formata com emojis por categoria:
- 🥛 Lacticínios | 🥩 Proteína | 🥬 Frescos | 🍞 Padaria
- 🧹 Limpeza | 🧴 Higiene | 🥤 Bebidas | 🍪 Snacks | 📦 Outros
- Envia lista categorizada
Categorias e emojis
lacticínios → 🥛 proteína → 🥩 frescos → 🥬 padaria → 🍞
limpeza → 🧹 higiene → 🧴 bebidas → 🥤 snacks → 🍪
congelados → 🧊 conservas → 🥫 temperos → 🌿 outros → 📦
Módulo 2 — Motor de Hábitos de Consumo
Lê {baseDir}/references/consumption_patterns.md para a lógica completa.
Resumo: O modelo em {baseDir}/data/consumption_model.json guarda, por produto:
- Consumo médio semanal (quantidade + unidade)
- Intervalo médio entre compras
- Marca preferida e alternativas aceitáveis
- Data da última compra + stock estimado restante
- Flag de elegibilidade para compra a granel
preferred_store:null= compra online (Continente/Pingo Doce); string = loja presencial (ex:"lidl")- Fator sazonal
Atualização: Após cada compra, executa:
{baseDir}/.venv/bin/python3 {baseDir}/scripts/consumption_tracker.py update --purchase <ficheiro_compra.json>
Alertas proativos: No stock check diário (cron 10h):
{baseDir}/.venv/bin/python3 {baseDir}/scripts/consumption_tracker.py check-stock
Se um produto tem ≤2 dias de stock estimado:
- Envia alerta: "⚠️ [Produto] deve acabar em ~2 dias. Adicionar à lista?"
- Se o utilizador confirma → adiciona à shopping_list
- Se o utilizador diz "ainda temos" → executa:
{baseDir}/.venv/bin/python3 {baseDir}/scripts/consumption_tracker.py feedback --product "[nome]" --type still_have
Módulo 3 — Triagem Semanal
Trigger: Cron domingo 9h WET, ou manualmente ("faz a triagem", "prepara a lista da semana").
Fluxo
- Gerar lista:
{baseDir}/.venv/bin/python3 {baseDir}/scripts/list_optimizer.py triage --next-bulk-date [DATA] - Verificar: Cruzar com
{baseDir}/data/family_preferences.json(blocklist, budget) - Formatar: Usar template
{baseDir}/assets/templates/weekly_triage.md - Enviar: Proposta ao grupo WhatsApp
- Aguardar: Feedback durante 4h — processar respostas (adicionar/remover/aprovar)
- Fechar: Após aprovação (✅ do admin) ou timeout com maioria → avançar para comparação
Lojas presenciais (physical_items)
O resultado do triage inclui o campo physical_items — produtos com preferred_store definido
em consumption_model.json. Estes itens nunca entram na comparação de preços online nem no
carrinho do Continente/Pingo Doce. São incluídos na mensagem de triagem como lembrete de visita presencial.
Exemplos de uso:
"preferred_store": "lidl"— café que o utilizador prefere comprar no Lidl"preferred_store": "makro"— granel (arroz, azeite) comprado no Makro/Recheio"preferred_store": "auchan"— produto específico só disponível no Auchan
As lojas físicas são configuradas em {baseDir}/data/family_preferences.json → physical_stores
(nome de exibição, frequência de visita, notas). Para listar apenas compras presenciais:
{baseDir}/.venv/bin/python3 {baseDir}/scripts/list_optimizer.py physical
Formato da proposta
🛒 Triagem Semanal — [DATA]
📦 COMPRA SEMANAL ([N] itens):
[items agrupados por categoria com emoji]
📦 PARA GRANEL (próxima: [DATA]):
[items com quantidades bulk]
🏪 COMPRAS PRESENCIAIS:
[LOJA 1] ([N] itens — visita [frequência]):
• [produto] — [quantidade] [unidade] ([marca])
[LOJA 2] ...
⚠️ ALERTAS:
[produtos urgentes ou observações]
💰 Budget semanal: €[LIMITE]
Respondam com ✅ para aprovar, ou adicionem/removam itens.
Se não houver compras presenciais pendentes, omitir a secção 🏪.
Módulo 4 — Comparação de Preços
Lê {baseDir}/references/price_comparison_logic.md para o algoritmo completo.
Resumo do fluxo:
- Para cada item da lista, verificar cache:
{baseDir}/data/price_cache.json - Se cache expirado (<24h) → recolher preços via browser tool (ver abaixo)
- Executar otimização:
{baseDir}/.venv/bin/python3 {baseDir}/scripts/price_compare.py --output /tmp/comparison.json - Formatar resultado usando template
{baseDir}/assets/templates/price_comparison.md - Enviar ao grupo WhatsApp para aprovação
Recolha de preços via browser tool
Para cada produto em falta no cache:
browser open "https://www.continente.pt/pesquisa/?q=[produto]"browser snapshot→ identificar card do produto mais relevante- Extrair nome, preço, preço por unidade, promoção ativa
- Gravar no cache:
{baseDir}/.venv/bin/python3 {baseDir}/scripts/price_cache.py update --market continente --product "[nome]" --data '[json]' - Repetir para Pingo Doce:
https://www.pingodoce.pt/pesquisa/?q=[produto]
Módulo 5 — Execução de Compras Online
Lê {baseDir}/references/continente_guide.md ou {baseDir}/references/pingodoce_guide.md conforme o mercado.
Regras CRÍTICAS (sem exceções)
- ❌ NUNCA introduzir dados de cartão de crédito/débito
- ❌ NUNCA finalizar checkout sem ✅ explícito do admin no WhatsApp
- ❌ NUNCA ultrapassar budget sem override explícito
- ✅ Usar apenas métodos de pagamento pré-guardados na conta
- ✅ Tirar screenshot do carrinho antes de confirmar → enviar para aprovação
- ✅ Registar número de encomenda em
{baseDir}/data/shopping_history.json
Fluxo por supermercado (usando browser tool)
1. Login
- Navegar à página de login do supermercado (ver guide de referência)
browser snapshot→ identificar campos de email e passwordbrowser act type [ref_email] "$CONTINENTE_EMAIL"(ou PINGODOCE_EMAIL)browser act type [ref_password] "$CONTINENTE_PASSWORD"(ou PINGODOCE_PASSWORD)browser act click [ref_submit]browser snapshot→ verificar se login foi bem sucedido (nome do utilizador visível)- Se 2FA solicitado: PAUSA, notificar utilizador, aguardar resolução manual
2. Verificar cupões
- Navegar à área de cupões (ver URL no guide de referência)
browser snapshot→ identificar lista de cupões disponíveis- Ativar cupões relevantes para a compra atual
- Registar valor total de cupões
3. Construir carrinho Para cada item do plano deste mercado:
- Navegar à pesquisa com o nome do produto
browser snapshot→ identificar o produto mais relevante (marca preferida > aceitável > marca própria)- Se indisponível: notificar família, sugerir alternativa, aguardar feedback
browser act click [ref_add_to_cart]- Se quantidade > 1: ajustar no carrinho
- Delay de 2-3 segundos entre adições
- Se CAPTCHA aparecer: PAUSA, notificar utilizador, aguardar resolução
4. Revisão e aprovação
- Navegar ao carrinho
browser snapshot→ verificar total- Se total difere >10% da estimativa: PAUSA, notificar utilizador
browser screenshot→ enviar imagem ao admin no WhatsApp- Mensagem: "🛒 Carrinho [Mercado] pronto. Total: €[X]. Aprovação: ✅ confirmar | ❌ cancelar"
- AGUARDAR ✅ explícito antes de avançar
5. Checkout Após ✅ do admin:
- Prosseguir para checkout
- Confirmar morada de entrega
- Selecionar slot (preferir sábado/domingo 10h-13h, grátis se disponível)
- Confirmar método de pagamento pré-guardado (nunca introduzir dados novos)
browser screenshot→ última verificação- Confirmar encomenda
- Extrair número de encomenda da página de confirmação
6. Pós-compra
- Atualizar
{baseDir}/data/shopping_history.jsoncom dados da compra - Executar:
{baseDir}/.venv/bin/python3 {baseDir}/scripts/consumption_tracker.py update --purchase <dados.json> - Notificar família: "✅ Encomenda [Nº] confirmada. Entrega: [slot]. Total: €[X]"
Módulo 6 — Coordenação Familiar (WhatsApp)
Comandos suportados
| Input | Ação |
|---|---|
| "Acabou o [X]" / "Precisamos de [X]" | Adiciona à lista |
| "Remove [X]" / "Já não preciso de [X]" | Remove da lista |
| "Mostra a lista" / "O que falta?" | Envia lista categorizada |
| "Quanto gastámos?" / "Quanto gastámos este mês?" | Resumo de gastos do mês |
| "Quando chega a encomenda?" | Info de tracking |
| "Ainda temos [X]" | Ajusta modelo de consumo (still_have) |
| "Já acabou o [X]" | Ajusta modelo de consumo (already_finished) |
| "Já não compramos [X]" | Desativa produto no modelo |
| ✅ (resposta a proposta) | Voto de aprovação |
| ❌ (resposta a proposta) | Voto de rejeição |
Regras de comunicação
- Respostas curtas (WhatsApp ≠ email)
- Emojis para categorias e confirmações
- Máximo 3 mensagens proativas/dia (não contar respostas a pedidos)
- Quiet hours: 22h–8h (exceto alertas de stock urgente explicitamente pedidos)
- Qualquer membro da família pode adicionar/remover itens
- Apenas utilizadores em
admin_users(ver{baseDir}/data/family_preferences.json) podem aprovar compras e ultrapassar budgets
Módulo 7 — Relatórios
Semanal (cron segunda 8h):
- Ler
{baseDir}/data/shopping_history.json(última semana) - Usar template
{baseDir}/assets/templates/weekly_report.md - Enviar ao grupo WhatsApp
Mensal (cron dia 1 9h):
- Ler histórico do mês anterior
- Calcular: total, média semanal, % por categoria, poupança acumulada, tendências
- Enviar relatório completo ao grupo
Scripts
| Script | Propósito | Como usar |
|---|---|---|
{baseDir}/scripts/price_cache.py |
Gerir cache de preços | {baseDir}/.venv/bin/python3 ... search --product "leite" |
{baseDir}/scripts/price_compare.py |
Otimização multi-mercado | {baseDir}/.venv/bin/python3 ... --output /tmp/comparison.json |
{baseDir}/scripts/consumption_tracker.py |
Atualizar/consultar modelo de consumo | {baseDir}/.venv/bin/python3 ... check-stock |
{baseDir}/scripts/list_optimizer.py |
Gerar lista semanal/mensal otimizada | {baseDir}/.venv/bin/python3 ... triage --next-bulk-date YYYY-MM-DD |
Referências
Carregar apenas quando necessário (não carregar todos de uma vez):
| Ficheiro | Quando ler |
|---|---|
{baseDir}/references/continente_guide.md |
Quando interagir com Continente Online |
{baseDir}/references/pingodoce_guide.md |
Quando interagir com Pingo Doce Online |
{baseDir}/references/price_comparison_logic.md |
Quando correr comparação de preços |
{baseDir}/references/consumption_patterns.md |
Quando atualizar/consultar modelo de consumo |
Cron Jobs
Configurar com {baseDir}/scripts/setup_crons.sh. Jobs ativos:
| Job | Schedule | Ação |
|---|---|---|
daily-stock-check |
Diário 10h | Verificar stock e alertar se necessário |
weekly-triage |
Domingo 9h | Triagem completa + proposta ao WhatsApp |
monthly-bulk-planning |
Dia 25 9h | Planear compra a granel do mês seguinte |
weekly-report |
Segunda 8h | Relatório semanal de gastos |
monthly-report |
Dia 1 9h | Relatório mensal completo |
price-cache-refresh |
Quarta e sábado 6h | Atualizar cache dos 50 produtos mais comprados |