Voice Codex convierte un escritorio CachyOS + Omarchy en un asistente local de voz para Codex, controlado por atajo global, transcripcion local y respuesta hablada.
El flujo principal es:
Alt+Z -> hablar -> Alt+Z -> Codex actua -> respuesta en voz alta
La aplicacion graba el microfono con PipeWire, transcribe localmente con whisper.cpp, envia la peticion a Codex CLI y lee la respuesta con un motor TTS configurable. Al usar Alt+Z, funciona en segundo plano con un indicador de notificacion para no robar foco ni cambiar de escritorio. Handy queda configurado como fallback y referencia de modelo, pero el flujo por defecto ya no depende de que Handy pegue texto en la ventana.
Warning
La configuracion por defecto da a Codex permisos completos sobre el ordenador (danger-full-access, aprobaciones desactivadas y bypass de sandbox). Es deliberado para este proyecto, pero debe usarse solo en una maquina personal donde entiendas el riesgo.
La demo completa esta subida como MP4 al repositorio. GitHub no renderiza de forma fiable etiquetas HTML <video> en el README, asi que el README muestra un preview animado y enlaza el video completo reproducible desde GitHub.
- Atajo global
Alt+Zintegrado con Hyprland/Omarchy. - Transcripcion local con
whisper.cpppor defecto. - Handy preparado como fallback con modelo
canary-180m-flash. - Idioma por defecto: espanol.
- Sin traduccion automatica al ingles (
translate_to_english = false). - Codex configurable por modelo, esfuerzo de razonamiento, directorio de trabajo y permisos.
- Indicador minimalista por notificacion para
Alt+Z. - Memoria persistente en archivos Markdown/texto.
- Capturas de pantalla bajo criterio de la IA.
- OCR opcional con
tesseract. - Respuesta hablada con Piper TTS en espanol por defecto.
- Fallback a
espeak-ngsi Piper falla. - Logs auditables en
~/.local/state/voice-codex/logs. - Skills instaladas para README, Omarchy, Arch Linux, CachyOS y diagnostico Linux.
Sistema objetivo:
- CachyOS / Arch Linux.
- Omarchy con Hyprland.
- Python 3.11 o superior.
- Codex CLI autenticado.
- Handy instalado.
Comandos esperados en PATH:
codex
hyprctl
grim
slurp
tesseract
pw-recordTTS fallback:
sudo pacman -S espeak-ngPiper TTS real se instala en espacio de usuario:
~/.local/share/voice-codex/piper-tts
Whisper local se instala en espacio de usuario:
~/.local/share/voice-codex/whisper.cpp
Desde el repo:
git clone https://github.com/amcgiluma/AIComputer.git
cd AIComputer
chmod +x scripts/voice-codex scripts/voice-codex-toggle scripts/voice-codex-doctor scripts/voice-codex-ask scripts/install-hypr-binding scripts/install-skillsInstala las skills usadas por el asistente:
./scripts/install-skillsConfigura el atajo de Hyprland:
./scripts/install-hypr-bindingEse script agrega esta linea a ~/.config/hypr/bindings.conf si no existe:
bindd = ALT, Z, Voice Codex, exec, <repo>/scripts/voice-codex-toggle
Tambien ejecuta:
hyprctl reload
hyprctl configerrorsArranca el asistente en segundo plano:
./scripts/voice-codexPor defecto no muestra ventana. Para usar la ventana GTK de depuracion/escritura, cambia temporalmente ui.show_window_on_start = true en ~/.config/voice-codex/config.toml y reinicia el proceso.
Comprueba el entorno:
./scripts/voice-codex-doctorPrueba Codex + TTS sin Handy ni ventana:
./scripts/voice-codex-ask "Di una frase corta confirmando que funcionas"Uso normal:
- Pulsa
Alt+Z. - Habla.
- Pulsa
Alt+Zde nuevo. - Voice Codex transcribe la grabacion con
whisper.cpp. - Codex recibe la peticion, actua y responde.
- La app lee la respuesta con Piper TTS en espanol.
Si activas la ventana GTK de depuracion, tambien puedes escribir directamente y pulsar Enviar a Codex.
Alt+Z no abre la ventana grande. Si la app no estaba viva, el atajo la arranca oculta y muestra una notificacion breve.
La primera ejecucion crea:
~/.config/voice-codex/config.toml
Ejemplo base:
[codex]
model_label = "gpt 5.4 Mini Low"
model = "gpt-5.4-mini"
model_reasoning_effort = "low"
workdir = "~"
sandbox = "danger-full-access"
approval_policy = "never"
bypass_approvals_and_sandbox = true
[handy]
model = "canary-180m-flash"
language = "es"
translate_to_english = false
transcription_settle_ms = 1800
[stt]
engine = "whisper_cpp"
fallback_engine = "handy"
record_command = "pw-record"
source = "@DEFAULT_AUDIO_SOURCE@"
whisper_executable = "~/.local/share/voice-codex/whisper.cpp/build/bin/whisper-cli"
whisper_model = "~/.local/share/voice-codex/whisper.cpp/models/ggml-base.bin"
language = "es"
normalize_audio = true
ffmpeg_executable = "ffmpeg"
audio_filter = "highpass=f=90,lowpass=f=7600,afftdn=nf=-25,dynaudnorm=f=150:g=15:p=0.95"
suppress_non_speech_tokens = true
initial_prompt = "Transcribe solamente voz hablada en espanol."
transcription_settle_ms = 250
vad_enabled = true
vad_model = "~/.local/share/voice-codex/whisper.cpp/models/ggml-silero-v6.2.0.bin"
vad_threshold = 0.35
[tts]
engine = "piper"
fallback_engine = "espeak-ng"
voice = "es"
rate = 165
piper_executable = "~/.local/share/voice-codex/piper-tts/bin/piper/piper"
piper_model = "~/.local/share/voice-codex/piper-tts/voices/es_ES-davefx-medium.onnx"
piper_length_scale = 1.0
[screen]
mode = "ai_decides"
ocr_enabled = true
[memory]
enabled = true
dir = "~/.codex/memories/voice-codex"
max_bytes = 20000
[ui]
auto_focus_on_record = false
show_window_on_start = false
indicator = "notification"
notification_icon = "assistant"
notification_timeout_ms = 1800Important
El perfil por defecto prioriza latencia baja para uso por voz: model = "gpt-5.4-mini" y model_reasoning_effort = "low". Para tareas complejas puedes subir temporalmente a gpt-5.4 o gpt-5.5 con razonamiento medium o high.
- Modelo Codex: seccion
[codex], clavesmodelymodel_reasoning_effort. - Transcriptor principal: seccion
[stt], clavesengine,whisper_executable,whisper_model,language,vad_enabledyvad_threshold. - Handy fallback: seccion
[handy], clavemodel. - Voz hablada: seccion
[tts], clavesengine,piper_executable,piper_model,voice,rateypiper_length_scale. - Comportamiento de
Alt+Z: seccion[ui], especialmenteauto_focus_on_record,indicatorynotification_icon.
Voice Codex lee memoria desde:
~/.codex/memories/voice-codex
Estructura creada:
preferences/
projects/
system/
voice/
notes/
Guarda ahi archivos .md o .txt. Se cargan en cada peticion hasta memory.max_bytes. El README.md de esa carpeta es solo guia y no entra en el prompt.
Voice Codex no captura pantalla de forma continua.
La captura se dispara en dos casos:
- La peticion contiene pistas visuales, por ejemplo: "te gusta este fondo?", "que ves en pantalla?", "por que se ve mal esta ventana?".
- Codex solicita una captura con el marcador interno:
[[VOICE_CODEX_REQUEST_SCREENSHOT:fullscreen]]
Las capturas se guardan en:
~/.local/state/voice-codex/screenshots
Instaladas por scripts/install-skills:
create-readme: estructura y calidad del README.arch-linux-triage: diagnostico Arch Linux,pacman,systemd, logs y kernel.cachyos-linux-assistant: contexto CachyOS, kernels y repos.system-admin: administracion Linux general.linux-perf: diagnostico avanzado de rendimiento.
Omarchy esta disponible localmente y se usa como criterio base para escritorio, Hyprland, Waybar, atajos, capturas y configuracion de usuario.
Los logs quedan en:
~/.local/state/voice-codex/logs/voice-codex.log
Incluyen estados, prompts enviados, comandos Codex y respuestas finales.
Ejecutar pruebas:
PYTHONPATH=src python -m unittest discover -s tests -vCompilar modulos:
python -m compileall srcEste proyecto se distribuye bajo la licencia Apache License 2.0.
Instala espeak-ng:
sudo pacman -S espeak-ngPrueba directa:
espeak-ng -v es "Voice Codex listo"Voice Codex usa por defecto el binario oficial de Rhasspy/Piper y la voz espanola es_ES-davefx-medium:
[tts]
engine = "piper"
piper_executable = "~/.local/share/voice-codex/piper-tts/bin/piper/piper"
piper_model = "~/.local/share/voice-codex/piper-tts/voices/es_ES-davefx-medium.onnx"Note
En Arch/CachyOS, el paquete piper de repos es la app GTK para configurar ratones gaming, no Piper TTS. voice-codex-doctor detecta el Piper TTS real configurado por ruta.
Comprueba que el binding existe:
rg "Voice Codex|ALT, Z" ~/.config/hypr/bindings.confValida Hyprland:
hyprctl reload
hyprctl configerrorsEl flujo por defecto ya no depende de que Handy escriba en la ventana. Si quieres volver a Handy como backend principal, cambia:
[stt]
engine = "handy"Despues arranca Voice Codex y pulsa dentro del cuadro de texto antes de usar Alt+Z. Si necesitas que el atajo enfoque la ventana como antes, cambia ui.auto_focus_on_record = true.
Comprueba que PipeWire puede grabar:
timeout 2s pw-record --target @DEFAULT_AUDIO_SOURCE@ --rate 16000 --channels 1 --format s16 /tmp/voice-codex-test.wav
file /tmp/voice-codex-test.wavComprueba Whisper:
~/.local/share/voice-codex/whisper.cpp/build/bin/whisper-cli \
-m ~/.local/share/voice-codex/whisper.cpp/models/ggml-base.bin \
-f /tmp/voice-codex-test.wav \
-l es -nt -npEdita:
~/.config/voice-codex/config.toml
y ajusta:
[codex]
model = "gpt-5.5"
model_reasoning_effort = "high"Tambien puedes borrar la linea model para dejar que Codex use su modelo por defecto local.
Quita el binding de ~/.config/hypr/bindings.conf:
bindd = ALT, Z, Voice Codex, exec, <repo>/scripts/voice-codex-toggle
Recarga Hyprland:
hyprctl reload
hyprctl configerrorsOpcionalmente borra configuracion y estado:
rm -rf ~/.config/voice-codex ~/.local/state/voice-codex