Ekodide 🦜
Envia e recebe arquivos pela rede, lacrados (HMAC) e cifrados (AES-256-GCM),
chegando byte-idênticos. Quase tudo é biblioteca padrão do Python — a única
dependência é a cryptography (a cifra).
O nome é de um papagaio africano (odídẹ): repete com perfeição (o arquivo chega cópia exata, sha256 idêntico) e voa (vai de um aparelho a outro pela rede, sem cabo). É código determinístico — não tem IA dentro. Algo aciona o Ekodide (um humano no terminal, um script, um agente); o trabalho é deste maquinário fixo.
Instalar
Precisa de Python (a única dependência, a cryptography, instala junto):
# do PyPI, isolado e no PATH (recomendado):
pipx install ekodide
# ou sem pipx (cai em ~/.local/bin):
pip install --user ekodide
# versão de desenvolvimento, direto do GitHub:
pipx install git+https://github.com/MatheusGustav/ekodide.git
# pra desenvolver localmente:
git clone https://github.com/MatheusGustav/ekodide.git
pip install -e ekodide
# com a tomada MCP (pra plugar num agente de IA — ver mais abaixo):
pipx install 'ekodide[agente]'
A ideia central: sempre há 2 pontas
Toda transferência tem quem recebe e quem envia:
- Quem RECEBE deixa a caixa de correio aberta →
ekodide serve(fica escutando). - Quem ENVIA joga a carta →
ekodide send.
Início rápido (sem digitar IP nem inventar senha) ⭐
Quem recebe abre a caixa na rede (já se anuncia sozinho pros outros acharem):
ekodide serve --host 0.0.0.0
Pareie o segredo uma vez — um lado mostra o código, o outro adota:
# aparelho A:
ekodide pair # sorteia e mostra: QR no terminal + o código, ex.: K7TP3-XQ9FM-H
# aparelho B (digite o MESMO código que apareceu em A):
ekodide pair K7TP3-XQ9FM-H
No celular (app Ekodide): Parear com o computador → escanear o QR — ou digitar o mesmo código. O código é o segredo — vai pela tela, câmera ou voz; nunca trafega pela rede.
Veja quem está disponível e envie pelo nome (o IP é descoberto sozinho, mesmo que mude por DHCP):
ekodide devices # lista os aparelhos na rede
ekodide send foto.jpg --para celular-matheus
Cadastrar um apelido fixo (escolhendo da rede)
Se preferir um apelido fixo (em vez de resolver pelo nome toda vez), cadastre sem digitar IP — o Ekodide lista quem está na rede e você só escolhe qual é:
ekodide config destino celular
# Procurando aparelhos na rede pra cadastrar 'celular'…
# 1) galaxy-do-mat http://192.168.0.9:8778
# 2) notebook-sala http://192.168.0.20:8778
# Qual é o aparelho? [número]: 1
# Destino 'celular' = http://192.168.0.9:8778
ekodide send foto.jpg --para celular # daí em diante, só o apelido
Só aparece quem está com a caixa aberta (ekodide serve) — que é justamente quem
pode receber. Se a lista vier vazia, é sinal de abrir a caixa no outro aparelho.
Configurar na mão (avançado / scripts)
ekodide config segredo "uma-chave-bem-secreta" # IGUAL nos dois aparelhos
ekodide config destino pc 192.168.0.10 # IP cru (completa http+porta) ou URL inteira
ekodide config nome meu-pc # como apareço no 'devices'
ekodide config show # confere (segredo mascarado)
Os comandos
send — enviar
ekodide send arquivo.pdf --para celular # um arquivo
ekodide send ~/projeto --para pc # uma PASTA inteira (com subpastas)
ekodide send video.mp4 --para celular # arquivo grande? pica e remonta sozinho
ekodide send foto.jpg --para pc -m "print do erro" # -m: etiqueta pro histórico
ekodide send foto.jpg --para pc --descobrir # acha o IP na rede (ignora a config)
--para usa o apelido do destino. Se ele estiver na config, usa o IP de lá;
senão (ou com --descobrir), acha o aparelho pelo nome na rede. O caminho é
como no git: relativo à pasta atual.
zipar — juntar tudo num arquivo só
ekodide zipar ~/Fotos # a pasta vira 'Fotos.zip' ao lado dela
ekodide zipar ~/Fotos -o /tmp/mala.zip # escolhendo onde gravar
ekodide zipar relatorio.pdf # também vale pra arquivo solto
Pasta com 500 arquivinhos são 500 envios, cada um com sua ida e volta de rede.
Fechada na mala, vira um envio: ekodide zipar ~/Fotos && ekodide send ~/Fotos.zip --para pc.
É comando à parte de propósito: zipar muda os bytes, e byte-idêntico é pilar da
casa — então isso nunca acontece sozinho dentro do send. Gera arquivo novo (o
original fica intocado), recusa passar por cima de um .zip que já exista, e se
der erro no meio não deixa mala pela metade no disco. Só biblioteca padrão do Python,
zero dependência nova.
devices — quem está na rede
ekodide devices # lista os aparelhos Ekodide que estão com a caixa aberta
ekodide devices --tempo 4 # escuta por mais tempo (padrão: 2.5s)
pair — combinar o segredo (sem inventar/digitar chave aleatória)
ekodide pair # mostra o código deste lado: QR no terminal + escrito embaixo
ekodide pair K7TP3-XQ9FM-H # ADOTA um código vindo de outra tela (traço e caixa não importam)
ekodide pair --novo # sorteia OUTRO código (o antigo deixa de valer nas duas pontas)
Quem sorteia é sempre a máquina: 10 caracteres + 1 verificador que acusa erro de
digitação na hora, num alfabeto sem os confundíveis (0/O e 1/I/L). "Definir a própria
senha" não existe de propósito — senha humana cai em dicionário, sorteio não. O
desenho do QR no terminal vem com o extra opcional (pipx install 'ekodide[qr]');
sem ele, o código escrito resolve igual.
firewall — liberar a entrada (no lado que recebe)
ekodide firewall # detecta o firewall, diz o que falta e mostra o comando
ekodide firewall --abrir # executa pra liberar (você autoriza)
Sabe lidar com Linux (firewalld/ufw — por porta, pede sudo), Windows (netsh — por porta, precisa de um Prompt de Administrador) e macOS (Application Firewall — é por aplicativo, libera o Python; e costuma vir desligado, aí nem precisa).
serve — receber (abrir a caixa)
ekodide serve # escuta e grava o que chegar (padrão: ~/Downloads)
ekodide serve --host 0.0.0.0 # abre na LAN (pra receber de outro aparelho)
ekodide serve --dir ~/Recebidos # escolhe a pasta destino
ekodide serve --compartilhar ~/Publica # deixa o outro lado PUXAR dessa pasta (ver abaixo)
Deixe rodando num terminal; Ctrl+C para parar.
list / pull — puxar de outro aparelho
O contrário do send: em vez de empurrar, você puxa um arquivo que o outro lado
deixou disponível. O outro precisa estar servindo com a pasta compartilhada
(ekodide serve --compartilhar <pasta>); sem isso, nada é exposto pra leitura.
ekodide list --de pc # vê o que o 'pc' compartilha pra puxar
ekodide pull relatorio.pdf --de pc # puxa o arquivo pra cá (padrão: ~/Downloads)
ekodide pull Fotos/foto.jpg --de pc --dir ~/Recebidos # de subpasta, salvando onde quiser
Puxar é opt-in: só funciona contra quem serviu com --compartilhar. O conteúdo
volta cifrado (cofre) e lacrado (HMAC), e a pasta compartilhada é cercada — um
pedido com ../ nunca escapa dela.
Navegar pelas pastas do celular (--pasta): com o app Android e o acesso a
todos os arquivos concedido (o wizard leva na tela do sistema), o PC navega o
armazenamento em vista rasa — um nível por vez, como um ls remoto:
ekodide list --de celular --pasta "" # raiz do armazenamento
ekodide list --de celular --pasta "DCIM/Camera" # desce um nível por vez
ekodide pull IMG_001.jpg --de celular --pasta "DCIM/Camera"
Sem a permissão — e contra um servidor de PC, sempre — pedido com --pasta é
recusado explícito (403 com motivo), nunca a pasta errada calada. Android/data e
Android/obb são barradas em código, e vale a mesma cerca (travessia/symlink).
config — ajustar
ekodide config show # ver segredo (mascarado) e destinos
ekodide config destino pc http://IP:8778 # cadastrar/atualizar um destino
ekodide config segredo "a-chave" # trocar o segredo
A config fica em ~/.config/ekodide/config.json (cadeado 600, porque tem o segredo).
mcp — a tomada pra agentes de IA 🔌
O Ekodide continua burro e determinístico — o que este comando faz é dar a ele um encaixe de formato padrão (MCP), pra que qualquer agente de IA que fale esse padrão o enxergue sem ninguém escrever adaptador. Antes: cada agente traduzia as funções pro dialeto dele. Agora o Ekodide se apresenta sozinho.
pipx install 'ekodide[agente]' # o SDK do MCP é extra OPCIONAL
ekodide mcp # sobe a tomada (conversa por stdin/stdout)
O agente passa a enxergar cinco ferramentas:
| ferramenta | o que faz |
|---|---|
aparelhos |
quem tem Ekodide nesta rede, e com que apelido |
listar_arquivos |
o que o outro aparelho está compartilhando pra puxar |
espiar_arquivo |
lê um texto do outro aparelho — na memória, sem gravar nada |
puxar_arquivo |
baixa um arquivo pra este computador (grava em disco) |
enviar_arquivo |
manda um arquivo ou pasta daqui pro outro aparelho |
A configuração no cliente MCP é o comando de sempre — por exemplo:
{ "mcpServers": { "ekodide": { "command": "ekodide", "args": ["mcp"] } } }
⚠️ Isto é poder na mão de quem decide sozinho. A tomada não dá ao agente nada além do que o
ekodide send/pulljá fazem — mas quem pluga está deixando um agente mandar arquivos deste computador pra outro aparelho e trazer de lá. Plugue em agente que você controla.
Sem o extra instalado o comando recusa com a receita, em vez de estourar — e o resto do Ekodide funciona igual, sem carregar o SDK junto.
Receitas
📤 PC → celular (com o celular já escutando):
# no PC:
ekodide send relatorio.pdf --para celular
📥 celular → PC (abra a caixa do PC primeiro):
# no PC (deixe rodando):
ekodide serve --host 0.0.0.0
# no outro aparelho:
ekodide send foto.jpg --para pc
3 pegadinhas
- A caixa precisa estar aberta: o lado que recebe tem que estar com
ekodide serveno ar. - Mesmo segredo nos dois lados — é a chave do cadeado.
- Firewall: quem recebe precisa liberar TCP 8778 (transferência) e UDP 8779
(descoberta). O jeito fácil:
ekodide firewall --abrir(detecta firewalld/ufw e roda com sudo). Na mão (Fedora):sudo firewall-cmd --add-port=8778/tcp --add-port=8779/udp --permanent && sudo systemctl restart firewalld. Sintoma de porta fechada:No route to hostno envio (ou ninguém aparece nodevices).
Usar como biblioteca
from pathlib import Path
from ekodide import enviar, servir
r = enviar(Path("foto.png"), "http://192.168.0.10:8778", segredo="...")
print(r.ok, r.destino)
# na outra ponta:
servir(Path("~/Downloads").expanduser(), segredo="...", host="0.0.0.0")
Android
Tem app nativo (Kotlin) que põe o celular como ponta passiva — recebe e deixa
o PC puxar, falando o mesmo protocolo no fio (lacre + cofre, byte-idêntico). Roda em
segundo plano (volta no boot), com seletor de pasta (SAF) e pareamento por
QR ou código digitado (o PC mostra, o celular adota). O código, o roadmap e como
compilar/instalar estão em
android/ — o APK sai como artefato a cada build no GitHub Actions.
Como é por dentro
| cômodo | papel |
|---|---|
lacre.py |
fechadura HMAC — o segredo nunca trafega |
cofre.py |
cifra o conteúdo (AES-256-GCM) — embaralhado na rede, idêntico no destino |
carteiro.py |
envia arquivo/pasta; arquivo grande vai picado em pedaços |
mala.py |
junta pasta/arquivo num .zip só (fora do caminho do send — gera arquivo novo) |
caixa_postal.py |
grava cercado (sem travessia, sem sobrescrever) e remonta os pedaços |
acervo.py |
LÊ cercado a pasta compartilhada pro "puxar" (sem travessia, sem fuga por symlink) |
buscador.py |
PUXA arquivo de outra ponta (pede, decifra, grava reusando a caixa postal) |
recebedor.py |
servidor HTTP leve que escuta e grava (e expõe /listar e /buscar pro puxar) |
vizinhanca.py |
descoberta na LAN: anuncia presença e acha aparelhos pelo nome (sem IP) |
frase.py |
sorteia o segredo como código curto digitável/escaneável, com verificador (pareamento out-of-band) |
cortina.py |
detecta o firewall e monta/roda o comando pra liberar as portas |
config.py |
lê/grava ~/.config/ekodide/config.json (segredo + destinos + nome) |
cli.py |
o comando ekodide (send/zipar/serve/list/pull/devices/pair/firewall/config) |
Segurança (honesto)
Duas camadas, ambas chaveadas pelo segredo que as pontas compartilham (o código de pareamento — nunca trafega):
- Lacre (HMAC-SHA256): prova quem mandou, que ninguém mexeu no caminho, e que a mensagem é recente (janela de 5 min).
- Cofre (AES-256-GCM): cifra o conteúdo — na rede passa só embaralhado; só remetente e destinatário leem. O arquivo gravado fica byte-idêntico ao original.
Ainda é mesma rede (Wi-Fi) por foco, não por limite de cifra. O que falta pra "rua" (internet) é endereçamento/NAT, não proteção do conteúdo.
Licença
MIT — veja LICENSE.
Metadata
Release files for ekodide 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ekodide-0.5.0.tar.gz | 61.8 kB | Without provenance | Details for ekodide-0.5.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ekodide-0.5.0-py3-none-any.whl | Python 3 | none | any | Details for ekodide-0.5.0-py3-none-any.whl |
Total release size: 110.0 kB
Release files / ekodide-0.5.0.tar.gz
| Download URL | ekodide-0.5.0.tar.gz |
|---|---|
| Size | 61.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2213ab0c66208a8342e50e9ead4eee69be7c5b19ab1403db71eace11a6e4c28a
|
|
BLAKE2b-256 checksum How to use checksums |
91ad4a2f19bf72b140d88e8310bee218d47ec811e80b7e06560b5aed506e9164
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / ekodide-0.5.0-py3-none-any.whl
| Download URL | ekodide-0.5.0-py3-none-any.whl |
|---|---|
| Size | 48.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dbb984eebce2c56b1abf7cb050a508c3b1041f2f1b2b02c5e9a675eb1bbfadcc
|
|
BLAKE2b-256 checksum How to use checksums |
0e175f5c3071ac95c201c23088627a011f51095fc830056e4e0bf2e9f651301b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Security for ekodide 0.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.