Time Blocking Automatizado: Como Bash Scripts Me Deram 2x Mais Horas Úteis Por Dia
Eu tinha 47 abas abertas, 3 notificações não lidas e uma reunião em 12 minutos que eu nem lembro de ter agendado. Meu dia era governado por urgências alheias — e eu achava que o problema era “falta de disciplina”. Não era. Era falta de sistema.
Quando finalmente implementei time blocking automatizado com Bash scripts, minha produtividade não subiu 20%. Ela dobrou. E o mais louco: eu comecei a terminar tarefas em vez de apenas “trabalhar nelas”. Neste artigo, vou te mostrar exatamente como construí esse sistema — os scripts, os erros, e o que eu mudaria se começasse do zero hoje.

O Problema com “Gerenciamento de Tempo” Tradicional
Vamos ser sinceros: a maioria dos conselhos sobre produtividade são variações de “faça uma lista”. Listas de tarefas. Listas de prioridades. Listas de listas. O problema é que uma lista te diz o que fazer, mas não quando fazer. E sem o “quando”, você cai no mesmo ciclo vicioso:
- Abre a lista → se sente sobrecarregado
- Pega a tarefa mais fácil (não a mais importante)
- Se distrai com Slack/email/notificação
- Termina o dia cansado mas com a sensação de que não fez nada que importava
Time blocking resolve isso ao transformar tarefas abstratas em blocos concretos de tempo. Você não tem “escrever relatório” na lista — você tem “terça, 09h-11h: relatório Q1”. A diferença parece sutil, mas o efeito é brutal. Quando o bloco começa, você sabe exatamente o que fazer. Quando termina, você para. Isso é libertador.
O problema? Manter um sistema de time blocking manualmente é tedioso e frágil. Você esquece de atualizar, os blocos se desfazem, e em uma semana você volta ao caos. Foi aí que percebi: se Bash scripts resolvem 30 minutos de trabalho repetitivo em 8 segundos, por que não automatizar meu próprio sistema de produtividade?
O Que é Time Blocking (E Por Que 90% das Pessoas Desistem)
Time blocking é simples: você divide seu dia em blocos de tempo, cada um dedicado a uma atividade específica. Nada de multitarefa. Nada de “vou ver o que aparece”. Seu calendário é sua lista de tarefas.
Cal Newport chama de “batching”. Elon Musk supostamente divide o dia em blocos de 5 minutos (insano, mas funcional). O conceito não é novo — assim como git hooks automatizam revisão de código, time blocking automatiza a decisão de “o que fazer agora”.
Por que as pessoas desistem?
- Maintenance overhead: Redesenhar o calendário toda semana consome 30-60 minutos que ninguém tem
- Fragilidade: Uma reunião emergencial destrói o bloco inteiro e você não se recupera
- Falta de feedback: Sem dados sobre seu tempo real, você não melhora suas estimativas
- Complexidade crescente: Começa simples, vira um monstro de cores e categorias
Eu enfrentei todos esses problemas. A solução foi radical: automatizar cada ponto de atrito com scripts. Menos fricção = mais adesão = mais resultados.
A Arquitetura do Sistema (Visão Geral)
Meu sistema tem 3 camadas que se comunicam:
┌─────────────────────────────────────┐
│ CAMADA 1: Template Semanal │
│ (schedule_template.json) │
│ Define blocos fixos e categorias │
├─────────────────────────────────────┤
│ CAMADA 2: Engine de Geração │
│ (timeblock_generate.sh) │
│ Gera o dia baseado no template │
│ + regras + exceptions │
├─────────────────────────────────────┤
│ CAMADA 3: Tracker + Analytics │
│ (timeblock_track.sh) │
│ Registra tempo real, gera reports │
└─────────────────────────────────────┘
A beleza disso é que cada camada é independente. Se o tracker quebra, o gerador continua funcionando. Se o template muda, o motor adapta. E tudo roda no terminal, sem depender de app pago ou API que pode morrer amanhã.

CAMADA 1: O Template Semanal em JSON
O coração do sistema é um arquivo JSON que define a “forma” ideal da minha semana. Não é rígido — é um starting point que o script adapta a cada dia.
{
"meta": {
"version": "2.3",
"updated": "2026-04-28",
"author": "olivetto"
},
"defaults": {
"block_size_minutes": 90,
"break_minutes": 15,
"deep_work_per_day": 4,
"max_meetings_per_day": 3
},
"categories": {
"deep_work": { "color": "#2563EB", "priority": 1, "icon": "🧠" },
"shallow_work":{ "color": "#10B981", "priority": 2, "icon": "📋" },
"meetings": { "color": "#F59E0B", "priority": 3, "icon": "🗣️" },
"learning": { "color": "#8B5CF6", "priority": 4, "icon": "📚" },
"admin": { "color": "#EF4444", "priority": 5, "icon": "🔧" },
"break": { "color": "#6B7280", "priority": 9, "icon": "☕" }
},
"weekly_template": {
"monday": {
"blocks": [
{ "start": "08:00", "end": "09:30", "cat": "deep_work", "label": "Projeto principal" },
{ "start": "09:45", "end": "11:15", "cat": "deep_work", "label": "Escrita/conteúdo" },
{ "start": "11:15", "end": "12:00", "cat": "shallow_work","label": "Triagem emails/Slack" },
{ "start": "13:00", "end": "14:00", "cat": "meetings", "label": "Sync semanal" },
{ "start": "14:15", "end": "15:45", "cat": "deep_work", "label": "Desenvolvimento" },
{ "start": "16:00", "end": "17:00", "cat": "learning", "label": "Estudo/leitura técnica" }
]
},
"tuesday": {
"blocks": [
{ "start": "08:00", "end": "10:30", "cat": "deep_work", "label": "Coding sprint" },
{ "start": "10:45", "end": "12:00", "cat": "shallow_work","label": "Code reviews" },
{ "start": "13:00", "end": "14:30", "cat": "deep_work", "label": "Projeto principal" },
{ "start": "14:45", "end": "16:00", "cat": "admin", "label": "Infra/DevOps" },
{ "start": "16:15", "end": "17:30", "cat": "learning", "label": "Workshop/tutorial" }
]
}
}
}
Por que JSON e não YAML? Porque jq é universal, YAML precisa de parser extra, e em 2026 eu ainda não confiava em nenhum parser YAML que não fosse Ruby. JSON + jq = simplicidade brutal. Se você automatzia com shell scripts, JSON é o formato mais pragmático.
CAMADA 2: O Motor de Geração (timeblock_generate.sh)
Este é o script principal. Ele lê o template, aplica regras, e gera o dia atual:
#!/usr/bin/env bash
# timeblock_generate.sh — Gera blocos do dia baseado no template
set -euo pipefail
TEMPLATE="$HOME/.timeblock/schedule_template.json"
TODAY_FILE="$HOME/.timeblock/today.json"
DAY=$(date +%A | tr '[:upper:]' '[:lower:]')
NOW_ISO=$(date -Iseconds)
# Check if today already generated
if [[ -f "$TODAY_FILE" ]]; then
generated_date=$(jq -r '.generated_at' "$TODAY_FILE" | cut -dT -f1)
today_date=$(date +%Y-%m-%d)
if [[ "$generated_date" == "$today_date" ]]; then
echo "✅ Dia já gerado em $TODAY_FILE"
cat "$TODAY_FILE" | jq '.blocks[] | "\(.start) \(.icon) \(.label)"'
exit 0
fi
fi
# Extract blocks for today
BLOCKS=$(jq -r --arg day "$DAY" '
.weekly_template[$day].blocks[] |
. + { icon: (.cat as $c | $categories[$c].icon // "📌") }
' --argjson categories "$(jq '.categories' "$TEMPLATE")" "$TEMPLATE" 2>/dev/null || jq -r --arg day "$DAY" '.weekly_template[$day].blocks[]' "$TEMPLATE")
if [[ -z "$BLOCKS" || "$BLOCKS" == "null" ]]; then
echo "⚠️ Sem template para $DAY. Usando fallback genérico."
BLOCKS=$(jq -n '[
{"start":"08:00","end":"09:30","cat":"deep_work","label":"Trabalho profundo"},
{"start":"09:45","end":"11:15","cat":"deep_work","label":"Trabalho profundo"},
{"start":"11:15","end":"12:00","cat":"shallow_work","label":"Administração"},
{"start":"13:00","end":"14:30","cat":"deep_work","label":"Projeto"},
{"start":"14:45","end":"16:00","cat":"learning","label":"Estudo"}
]')
fi
# Build today's file
jq -n \
--arg date "$(date +%Y-%m-%d)" \
--arg day "$DAY" \
--arg generated "$NOW_ISO" \
--argjson blocks "$BLOCKS" \
'{
date: $date,
day: $day,
generated_at: $generated,
blocks: $blocks,
actuals: []
}' > "$TODAY_FILE"
echo "🎯 Blocos gerados para $DAY ($NOW_ISO):"
jq -r '.blocks[] | " \(.start)-\(.end) [\(.cat)] \(.label)"' "$TODAY_FILE"
O script é propositalmente simples. Ele não tenta ser inteligente — apenas aplica o template e gera o JSON do dia. A inteligência vem das regras de adaptação, que são scripts separados.
Regras de Adaptação
Eu adicionei um hook system para ajustes dinâmicos:
#!/usr/bin/env bash
# timeblock_adapt.sh — Aplica regras de adaptação ao dia gerado
TODAY="$HOME/.timeblock/today.json"
# Regra 1: Se tem mais de 3 reuniões, remove um bloco de shallow_work
meeting_count=$(jq '[.blocks[] | select(.cat == "meetings")] | length' "$TODAY")
if [[ "$meeting_count" -gt 3 ]]; then
echo "⚠️ $meeting_count reuniões detectadas. Removendo shallow_work mais antigo."
jq '(.blocks | map(select(.cat == "shallow_work")) | length) as $sw |
if $sw > 0 then
.blocks |= (del(.[] | select(.cat == "shallow_work") | first))
else . end' "$TODAY" > "${TODAY}.tmp" && mv "${TODAY}.tmp" "$TODAY"
fi
# Regra 2: Sexta-feira → máximo 1 bloco deep_work (dia de review)
if [[ "$(date +%A)" == "Friday" ]]; then
echo "🎉 Sexta! Convertendo deep_work extra em learning."
jq '.blocks |= map(if .cat == "deep_work" then .cat = "learning" | .label = "Review da semana" else . end)' \
"$TODAY" > "${TODAY}.tmp" && mv "${TODAY}.tmp" "$TODAY"
fi
# Regra 3: Pós-almoço → nunca deep_work antes de 14h (sleep food coma)
hour=$(date +%H)
if [[ "$hour" -ge 13 && "$hour" -lt 14 ]]; then
jq '.blocks |= map(if (.start | startswith("13")) and .cat == "deep_work" then .cat = "shallow_work" else . end)' \
"$TODAY" > "${TODAY}.tmp" && mv "${TODAY}.tmp" "$TODAY"
fi
Sem pyjamas. A regra 3 parece boba, mas food coma é real e forçar deep work às 13h30 é jogar tempo fora. Melhor aceitar a realidade e adaptar o sistema a ela.
🔥 Perrengue Técnico do Olivetto
O bug do JSON malformado que me custou 2 horas: Na versão 1 do script, eu concatenava JSON manualmente com
echoesed. Funcionou por 3 semanas até umlabelter aspas duplas (o nome do projeto era"Refatorar o "monster.js""). O JSON quebrou,jqsilenciosamente falhou, e eu acordei sem blocos no meio de uma sprint. Solução? Nunca mais montei JSON à mão. Sempre usojq -n --argpara construir. Ojqescapa, valida e formata. Confie no tool, não no seu dedo.
CAMADA 3: Tracker e Analytics (timeblock_track.sh)
Gerar blocos é inútil sem saber se você os segue. O tracker registra quando você começa e termina cada bloco:
#!/usr/bin/env bash
# timeblock_track.sh — Rastreia tempo real por bloco
TODAY="$HOME/.timeblock/today.json"
TRACK_LOG="$HOME/.timeblock/tracking/$(date +%Y-%m-%d).log"
mkdir -p "$(dirname "$TRACK_LOG")"
case "${1:-status}" in
start)
BLOCK_IDX="${2:-0}"
START_TS=$(date +%s)
jq --arg idx "$BLOCK_IDX" --arg ts "$START_TS" '
.actuals += [{
block_index: ($idx | tonumber),
started_at: ($ts | tonumber),
finished_at: null
}]
' "$TODAY" > "${TODAY}.tmp" && mv "${TODAY}.tmp" "$TODAY"
LABEL=$(jq -r --arg i "$BLOCK_IDX" '.blocks[$i | tonumber].label' "$TODAY")
echo "▶️ Iniciando bloco #$BLOCK_IDX: $LABEL"
echo "$(date -Iseconds) | START | block=$BLOCK_IDX | $LABEL" >> "$TRACK_LOG"
;;
stop)
STOP_TS=$(date +%s)
LAST_IDX=$(jq '[.actuals[] | select(.finished_at == null)] | length' "$TODAY")
if [[ "$LAST_IDX" -eq 0 ]]; then
echo "⚠️ Nenhum bloco ativo para parar."
exit 1
fi
jq --arg ts "$STOP_TS" '
(.actuals | map(select(.finished_at == null)) | first) as $target |
.actuals = [.actuals[] |
if .finished_at == null then .finished_at = ($ts | tonumber) else . end
]
' "$TODAY" > "${TODAY}.tmp" && mv "${TODAY}.tmp" "$TODAY"
echo "⏹️ Bloco finalizado."
echo "$(date -Iseconds) | STOP" >> "$TRACK_LOG"
;;
report)
# Generate weekly report
echo "📊 RELATÓRIO DE TIME BLOCKING — Semana atual"
echo "============================================"
TOTAL_BLOCKS=0
COMPLETED=0
OVERRUN=0
for f in "$HOME/.timeblock/tracking/"*.log; do
[[ -f "$f" ]] || continue
day=$(basename "$f" .log)
starts=$(grep -c "START" "$f" 2>/dev/null || echo 0)
stops=$(grep -c "STOP" "$f" 2>/dev/null || echo 0)
echo " $day: $starts blocos iniciados, $stops finalizados"
TOTAL_BLOCKS=$((TOTAL_BLOCKS + starts))
COMPLETED=$((COMPLETED + stops))
done
echo ""
echo "Total: $TOTAL_BLOCKS blocos iniciados | $COMPLETED finalizados"
if [[ "$TOTAL_BLOCKS" -gt 0 ]]; then
RATE=$((COMPLETED * 100 / TOTAL_BLOCKS))
echo "Taxa de conclusão: ${RATE}%"
fi
;;
status)
CURRENT=$(jq -r '
[.actuals[] | select(.finished_at == null)] | length
' "$TODAY")
if [[ "$CURRENT" -gt 0 ]]; then
ACTIVE=$(jq -r '[.actuals[] | select(.finished_at == null)][0].block_index' "$TODAY")
LABEL=$(jq -r --arg i "$ACTIVE" '.blocks[$i | tonumber].label' "$TODAY")
echo "🟢 Bloco ativo #$ACTIVE: $LABEL"
else
echo "⚪ Nenhum bloco ativo. Use: timeblock_track.sh start [index]"
fi
;;
esac
Integração com o Terminal: Aliases Que Funcionam
O sistema só funciona se for fácil de usar. Coloquei aliases no meu .bashrc que viram comandos naturais:
# ~/.bashrc — Time Blocking Aliases
TB="$HOME/.timeblock"
# Gerar dia
alias tb-gen="$TB/scripts/timeblock_generate.sh"
# Adaptar regras
alias tb-adapt="$TB/scripts/timeblock_adapt.sh"
# Tracking
alias tb-start="$TB/scripts/timeblock_track.sh start"
alias tb-stop="$TB/scripts/timeblock_track.sh stop"
alias tb-status="$TB/scripts/timeblock_track.sh status"
alias tb-report="$TB/scripts/timeblock_track.sh report"
# Combo: gerar + adaptar + mostrar
tb-init() {
tb-gen && tb-adapt && echo "" && tb-status
}
# Quick block (quando surge algo inesperado)
tb-quick() {
local label="${1:-Tarefa emergencial}"
local duration="${2:-30}"
local start=$(date +%H:%M)
local end_hour=$(date -d "+${duration} minutes" +%H:%M 2>/dev/null || \
date -v+${duration}M +%H:%M 2>/dev/null)
jq --arg start "$start" --arg end "$end_hour" --arg label "$label" '
.blocks += [{
start: $start,
end: $end,
cat: "shallow_work",
label: $label,
icon: "⚡"
}]
' "$TB/today.json" > "$TB/today.json.tmp" && mv "$TB/today.json.tmp" "$TB/today.json"
echo "⚡ Bloco rápido adicionado: $label ($start - $end_hour)"
}
Como eu gerencio esses dotfiles com GNU Stow e Ansible é assunto pra outro artigo, mas o ponto é: se o comando tem mais de 10 caracteres, você não vai usar. Aliases curtos = adoção.
Notificações Que Não Sugam Sua Alma
Um problema real: como saber que o bloco acabou sem ficar olhando o relógio? Solução: notificação nativa com notify-send + hook no tracker:
#!/usr/bin/env bash
# timeblock_notify.sh — Envia notificação no fim do bloco
# Chamado como background job após tb-start
BLOCK_MINUTES="${1:-90}"
LABEL="${2:-Bloco atual}"
SOUND="/usr/share/sounds/freedesktop/stereo/complete.oga"
# Wait for block duration (minus 5 min warning)
WARNING_AT=$((BLOCK_MINUTES * 60 - 300))
sleep "$WARNING_AT"
notify-send -u normal "⏰ 5 minutos restantes" "$LABEL"
sleep 300
notify-send -u critical "🛑 Bloco finalizado!" "$LABEL — Hora do break ou próximo bloco."
[[ -f "$SOUND" ]] && paplay "$SOUND" 2>/dev/null
echo "$(date -Iseconds) | NOTIFY | Bloco '$LABEL' finalizado" \
>> "$HOME/.timeblock/tracking/$(date +%Y-%m-%d).log"
Uso: tb-start 2 && timeblock_notify.sh 90 "Coding sprint" &. O & joga pra background e eu esqueço — até o notification aparecer. Se você usa n8n para automações, pode trocar notify-send por um webhook que manda Telegram ou Discord.
Dashboard Semanal (Um Script, Zero Dependências)
Toda sexta-feira às 16h, rodo o report. Mas queria algo visual sem instalar Grafana. Solução: ASCII art dashboard.
#!/usr/bin/env bash
# timeblock_dashboard.sh — Dashboard semanal em ASCII
TB="$HOME/.timeblock"
WEEK_START=$(date -d "last monday" +%Y-%m-%d 2>/dev/null || date -v-monday +%Y-%m-%d)
echo "╔══════════════════════════════════════════════════╗"
echo "║ ⏱️ TIME BLOCKING — SEMANA ATUAL ║"
echo "╠══════════════════════════════════════════════════╣"
TOTAL_PLANNED=0
TOTAL_ACTUAL=0
CATEGORIES_FILE=$(mktemp)
for day in Mon Tue Wed Thu Fri; do
case $day in
Mon) date_fmt=$(date -d "last monday" +%Y-%m-%d 2>/dev/null || date -v-monday +%Y-%m-%d) ;;
Tue) date_fmt=$(date -d "last tuesday" +%Y-%m-%d 2>/dev/null || date -v-tuesday +%Y-%m-%d) ;;
Wed) date_fmt=$(date -d "last wednesday" +%Y-%m-%d 2>/dev/null || date -v-wednesday +%Y-%m-%d) ;;
Thu) date_fmt=$(date -d "last thursday" +%Y-%m-%d 2>/dev/null || date -v-thursday +%Y-%m-%d) ;;
Fri) date_fmt=$(date -d "last friday" +%Y-%m-%d 2>/dev/null || date -v-friday +%Y-%m-%d) ;;
esac
LOG="$TB/tracking/${date_fmt}.log"
if [[ -f "$LOG" ]]; then
STARTS=$(grep -c "START" "$LOG" 2>/dev/null || echo 0)
STOPS=$(grep -c "STOP" "$LOG" 2>/dev/null || echo 0)
BAR=$(printf '█%.0s' $(seq 1 "$STOPS") 2>/dev/null)
REMAINING=$((STARTS - STOPS))
echo "║ $day: $BAR░$(printf '%0.s' $(seq 1 "$REMAINING" 2>/dev/null)) | $STOPS/$STARTS blocos ║"
TOTAL_PLANNED=$((TOTAL_PLANNED + STARTS))
TOTAL_ACTUAL=$((TOTAL_ACTUAL + STOPS))
else
echo "║ $day: ░░░░░░░░░░░░ | sem dados ║"
fi
done
echo "╠══════════════════════════════════════════════════╣"
if [[ "$TOTAL_PLANNED" -gt 0 ]]; then
RATE=$((TOTAL_ACTUAL * 100 / TOTAL_PLANNED))
echo "║ Total: $TOTAL_ACTUAL/$TOTAL_PLANNED blocos | Taxa: ${RATE}% ║"
else
echo "║ Sem dados suficientes para taxa de conclusão ║"
fi
echo "╚══════════════════════════════════════════════════╝"
rm -f "$CATEGORIES_FILE"
Resultado na sexta:
╔══════════════════════════════════════════════════╗
║ ⏱️ TIME BLOCKING — SEMANA ATUAL ║
╠══════════════════════════════════════════════════╣
║ Mon: ████████████░░ | 12/14 blocos ║
║ Tue: █████████████░ | 13/14 blocos ║
║ Wed: ████████░░░░░░ | 8/12 blocos ║
║ Thu: ██████████████ | 14/14 blocos ║
║ Fri: █████░░░░░░░░░ | 5/10 blocos ║
╠══════════════════════════════════════════════════╣
║ Total: 52/64 blocos | Taxa: 81% ║
╚══════════════════════════════════════════════════╝
Não é bonito. É útil. E roda em qualquer terminal do mundo sem dependência nenhuma.
Os 3 Erros Que Me Custaram Mais Tempo
Erro 1: Superestimar capacidade de deep work
Na versão 1 do template, eu tinha 6 blocos de deep work por dia. Seis. Como se eu fosse um mainframe. A realidade? Meu cérebro aguenta 3, talvez 4 em dias bons. Depois do 4º bloco, a qualidade cai pra menos da metade e eu passo 90 minutos “trabalhando” que rendem 20 minutos de output real.
Correção: Limitei a 3-4 blocos deep work e adicionei a regra que converte automaticamente o excesso em shallow_work ou learning.
Erro 2: Ignorar contexto energético
Eu colocava tarefas criativas às 15h. Fatal. Meu pico criativo é 8h-11h. Às 15h eu deveria estar fazendo code review, infra, ou organização — coisas que demandam menos energia criativa mas ainda precisam de atenção.
Correção: Categorizei blocos por energia necessária (high_energy, medium_energy, low_energy) e mapeei cada hora do dia a um nível energético baseado em 2 semanas de dados reais. Agora o script automaticamente encaixa tarefas de alta energia no meu horário de pico.
Erro 3: Não ter recovery blocks
Bloco atrasa 15 minutos? O próximo começa 15 minutos atrasado. O próximo também. Efeito cascata. Resultado: às 16h todos os blocos estavam 2 horas atrasados e eu tinha desistido do dia.
Correção: Adicionei “buffer blocks” de 15 minutos entre blocos de deep_work. E um “recovery block” de 30 minutos às 15h30. Se está tudo no horário, o recovery vira learning. Se está atrasado, o recovery absorve o atraso. O mesmo princípio de consistência que uso para hábitos se aplica aqui: margem de erro > perfeição.
💡 Dica Suja do Olivetto
Se você não quer construir tudo do zero, comece com o mínimo viável: apenas o template JSON +
tb-gen. Um arquivo, um alias. Use por 2 semanas. Depois adicione o tracker. Depois o adaptador. Não construa o sistema inteiro antes de usar. Construa enquanto usa. É a mesma filosofia que defendi no artigo sobre homelab com hardware reciclado — começa simples, evolui com uso.
Quick Start: 5 Minutos Pra Começar Hoje
Quer testar sem compromisso? Execute isso no terminal:
# 1. Criar estrutura
mkdir -p ~/.timeblock/{scripts,tracking}
# 2. Template mínimo
cat > ~/.timeblock/schedule_template.json << 'TEMPLATE'
{
"weekly_template": {
"monday": {"blocks": [
{"start":"08:00","end":"09:30","cat":"deep_work","label":"Trabalho principal"},
{"start":"10:00","end":"11:00","cat":"shallow_work","label":"Emails e admin"},
{"start":"13:00","end":"14:30","cat":"deep_work","label":"Projeto"},
{"start":"15:00","end":"16:00","cat":"learning","label":"Estudo"}
]},
"tuesday": {"blocks": [
{"start":"08:00","end":"10:00","cat":"deep_work","label":"Sprint"},
{"start":"10:30","end":"12:00","cat":"shallow_work","label":"Reviews"},
{"start":"13:00","end":"14:30","cat":"deep_work","label":"Projeto"},
{"start":"15:00","end":"16:30","cat":"learning","label":"Workshop"}
]},
"wednesday": {"blocks": [
{"start":"08:00","end":"09:30","cat":"deep_work","label":"Trabalho principal"},
{"start":"10:00","end":"11:30","cat":"meetings","label":"Sync calls"},
{"start":"13:00","end":"15:00","cat":"deep_work","label":"Desenvolvimento"},
{"start":"15:30","end":"16:30","cat":"admin","label":"Infra e manutenção"}
]},
"thursday": {"blocks": [
{"start":"08:00","end":"10:00","cat":"deep_work","label":"Coding"},
{"start":"10:30","end":"12:00","cat":"shallow_work","label":"Admin"},
{"start":"13:00","end":"14:30","cat":"deep_work","label":"Projeto"},
{"start":"15:00","end":"16:00","cat":"learning","label":"Leitura técnica"}
]},
"friday": {"blocks": [
{"start":"08:00","end":"09:30","cat":"deep_work","label":"Finalizar sprint"},
{"start":"10:00","end":"11:00","cat":"shallow_work","label":"Retrospectiva"},
{"start":"13:00","end":"14:00","cat":"admin","label":"Preparar próxima semana"},
{"start":"14:30","end":"16:00","cat":"learning","label":"Estudo livre"}
]}
}
}
TEMPLATE
# 3. Alias essenciais
echo 'alias tb-gen="jq -r --arg day \$(date +%A | tr A-Z a-z) '\''.weekly_template[\$day].blocks[] | " \(.start)-\(.end) [\(.cat)] \(.label)"'\'' ~/.timeblock/schedule_template.json"' >> ~/.bashrc
source ~/.bashrc
# 4. Testar!
tb-gen
Se você viu os blocos do dia aparecerem no terminal, parabéns — você já tem mais sistema de produtividade do que 90% das pessoas com app pago.
E Agora? Qual Automação Você Quer Ver?
Este sistema é vivo. Toda semana eu adiciono um pedaço novo — integração com Google Calendar via API, bot no Telegram que me avisa quando um bloco está acabando, até um dashboard web com Chart.js rodando localmente. Mas a base é esta: JSON + Bash + disciplina gradual.
Me conta nos comentários: qual parte do seu fluxo de trabalho você queria automatizar com time blocking? Você prefere integração com ferramenta específica (Notion, Todoist, Calendar) ou prefere o approach terminal-first? Se eu tiver 10 pedidos, construo a integração mais pedida e publico o script completo aqui.
Enquanto isso, migramos do Notion pro Obsidian e organizamos a vida. Depois, automatizamos o planejamento. Um passo de cada vez. Sem pressa. Sem desculpa.
O Olivetto automatiza o repetitivo pra ter tempo pro que importa. Às vezes o que importa é um café em silêncio. E isso também é produtividade.
