# ============================================================================ # Javis Bot — environment configuration # Copy to `.env` and fill in. Never commit your real `.env`. # ============================================================================ # --------------------------------------------------------------------------- # Discord bot (normal bot account) — voice I/O + slash commands # --------------------------------------------------------------------------- # OPTIONAL — leave BLANK to run in userbot/selfbot mode (a single user account # does voice + broadcast; see DISCORD_SELFBOT_TOKEN below). When this is empty # and a selfbot token is present, the app runs as a userbot automatically. # Only fill this in if you specifically want the legacy normal-bot path. # From https://discord.com/developers/applications → your app DISCORD_BOT_TOKEN= DISCORD_APP_ID= # The (single) server this bot serves. Guild-scoped commands appear instantly. DISCORD_GUILD_ID= # Voice channel used by the stream-test scripts (bot/scripts/stream-test). DISCORD_VOICE_CHANNEL_ID= # Optional text channel for posting conversation transcripts (blank = disabled). DISCORD_TRANSCRIPT_CHANNEL_ID= # --------------------------------------------------------------------------- # Brain bridge (Python service in bridge/) — STT + reply engine + TTS # --------------------------------------------------------------------------- BRIDGE_URL=http://127.0.0.1:8765 BRIDGE_HOST=127.0.0.1 BRIDGE_PORT=8765 JARVIS_BRAIN_ENABLED=1 JARVIS_TTS_ENABLED=1 # faster-whisper device/compute. GPU by default (RTX 5050 / sm_120, verified). # Falls back to CPU automatically if no GPU is passed to the container. WHISPER_DEVICE=cuda WHISPER_COMPUTE_TYPE=float16 # Optional explicit Piper voice model (.onnx). If empty, the jarvis default is used. TTS_PIPER_MODEL_PATH= # TTS engine: "melo" (default) uses the MeloTTS Korean voice served by the warm # melo-worker (Korean speaker, speed 1.5). Set to "piper" to use Piper directly. TTS_ENGINE=melo # Melo-only by default: if MeloTTS synthesis fails the bridge returns no audio # rather than speaking Korean through the English Piper voice (which mangles it). # Set to 1 only if you explicitly want the Piper fallback. MELO_FALLBACK_PIPER=0 # Where the bridge reaches the in-container MeloTTS worker, and how long it # waits for a synthesis. Speaking rate is set on the worker via MELO_SPEED. MELO_WORKER_URL=http://127.0.0.1:8770 MELO_TIMEOUT=30 MELO_SPEED=1.5 # --------------------------------------------------------------------------- # Jarvis brain (Ollama-backed). In Docker these populate the rendered # config (docker/jarvis-config.template.json). See src/jarvis/config.py. # --------------------------------------------------------------------------- # In docker-compose this is overridden to http://ollama:11434 automatically. OLLAMA_BASE_URL=http://127.0.0.1:11434 # qwen2.5:3b — small non-reasoning instruct model. ~2.4GB, runs 100% on the GPU # (the 8B offloads ~8% to CPU), warm voice turns ~2-4s vs ~5-7s on 8B. Clean # Korean on factual/tool replies; can occasionally leak a trailing CJK phrase on # free-form chit-chat. Swap back to qwen3:8b for the strongest tool-calling. OLLAMA_CHAT_MODEL=qwen2.5:3b # Model for the auxiliary small-model calls: intent judge, tool router, weather # place extraction, query decomposition. BLANK (default) reuses OLLAMA_CHAT_MODEL # so the stack runs on one already-warm model. The code's built-in default # (gemma4:e2b) is NOT pulled by this stack, so leaving this unset previously made # every router/extractor call silently fail. Only set this if you also pull the # model into Ollama. OLLAMA_INTENT_MODEL= OLLAMA_EMBED_MODEL=nomic-embed-text WHISPER_MODEL=small # Lock every reply to one language, e.g. OUTPUT_LANGUAGE=Korean. Leave BLANK to # keep the default behaviour of replying in whatever language the user wrote in. # A fixed value also suppresses stray characters from other scripts (e.g. the # occasional trailing CJK fragment small models leak on free-form chat). OUTPUT_LANGUAGE= # --------------------------------------------------------------------------- # Docker desktop (VNC) — used only by the container image # --------------------------------------------------------------------------- # Host ports the container publishes the VNC + noVNC servers on. Defaults match # the compose file (5901 / 6080); override if the host already uses them. VNC_PORT=5901 NOVNC_PORT=6080 # VNC viewer password (max 8 chars effective). Watch the screen at localhost:5901. # Also used by the broadcast keepalive: TigerVNC only refreshes its framebuffer # while a VNC client is attached, so the stream keeps a tiny client connected to # avoid a choppy (~1.5 fps) capture. Must match the VNC server's password. If # unset, the keepalive falls back to the obfuscated passwd file (VNC_PASSWD_FILE, # default ~/.config/tigervnc/passwd). VNC_PASSWORD=javis123 # VNC_PASSWD_FILE=/home/claude/.config/tigervnc/passwd # Auto-opened page in the in-container Chrome. CHROME_START_URL=about:blank # --------------------------------------------------------------------------- # Screen-share + browser mode. # true = the bot may go Live (screen-share the VNC desktop) and drive the # on-screen browser for real-time info (search / play / read screen). # false = no screen share; voice only, real-time info via the Gemini API. STREAM_BROWSER=true # Gemini auth for real-time info when STREAM_BROWSER=false. # oauth = use the Gemini CLI with a Google-account login (no API key). # Install once: npm i -g @google/gemini-cli ; then run `gemini` and # "Sign in with Google". Uses the CLI's built-in web-search grounding. # apikey = legacy REST path; needs GEMINI_API_KEY below # (get one at https://aistudio.google.com/app/apikey). GEMINI_AUTH=oauth GEMINI_API_KEY= GEMINI_MODEL=gemini-2.0-flash # OAuth login source for Docker. The container mounts this into ~/.gemini. # Default (blank) = ./docker/gemini-oauth (project-local, cross-platform). Seed # it once: cp -r ~/.gemini/. docker/gemini-oauth/ (copy the whole login state). # Or point at an existing host login instead, e.g. GEMINI_OAUTH_DIR=~/.gemini GEMINI_OAUTH_DIR= # --------------------------------------------------------------------------- # VNC screen broadcast # selfbot = real live "Go Live" stream (needs a USER/burner token; ToS risk) # novnc = share a noVNC browser link (safe, real-time, not native) # screenshot = periodic screenshots to the channel (safe, low fps) # none = disabled # --------------------------------------------------------------------------- STREAM_BACKEND=selfbot # The VNC desktop runs on X display :1 (see docs/vnc-xfce-setup.md) VNC_DISPLAY=:1 VNC_RESOLUTION=1920x1080 # 1080p60 broadcast. 8 Mbps suits 60fps (YouTube-style 1080p60 sits ~8-12 Mbps); # drop to 30/4000 for a lighter stream. Max bitrate is 1.5x this value. VNC_FRAMERATE=60 VNC_BITRATE_KBPS=8000 # --- selfbot backend --- # A THROWAWAY/burner Discord user account token. NEVER your main account. # Using a selfbot violates Discord ToS and can get the account banned. DISCORD_SELFBOT_TOKEN= # Dedicated burner account for the Go-Live BROADCAST, separate from the # conversation account above. REQUIRED in userbot mode for the broadcast to # work: Discord allows only one voice presence per account, so the conversation # and the broadcast cannot share one account (the broadcaster's voice connection # never connects). Leave empty in normal-bot mode (the conversation runs on the # bot account, so the selfbot account is already broadcast-only). Both burner # accounts must be in the server. Use a second throwaway account, never a main. DISCORD_STREAM_TOKEN= # Hardware (NVENC) encode for the stream. 1 = use the GPU (recommended for # 1080p60), 0 = software x264. Requires an NVIDIA GPU + ffmpeg built with nvenc. STREAM_HW=1 # Capture desktop audio into the broadcast so the stream has sound. 1 = on, # 0 = mute. Pulls the PipeWire/Pulse monitor of the default sink; override the # source with STREAM_AUDIO_SOURCE (e.g. a specific ".monitor"). STREAM_AUDIO=1 STREAM_AUDIO_SOURCE=@DEFAULT_MONITOR@ # --- novnc backend --- # e.g. http://192.168.10.9:6080/vnc.html (websockify --web=/usr/share/novnc 6080 localhost:5901) NOVNC_URL= # --- screenshot backend --- SCREENSHOT_INTERVAL_SEC=5 # --------------------------------------------------------------------------- # Voice behaviour # --------------------------------------------------------------------------- # Silence (ms) that marks the end of an utterance before sending to the brain. VOICE_SILENCE_MS=800 # =========================================================================== # Split deployment & cross-platform (Ubuntu + Windows 11) # =========================================================================== # JARVIS_ROLE selects what this machine runs (see docker/run-if-role.sh): # full (default) everything in one container # browser ONLY the desktop + Chrome + control-server (driven over the LAN) # bot ONLY the bot + bridge + TTS (drives a REMOTE browser) JARVIS_ROLE=full # --- GPU per OS: pick the matching compose override via COMPOSE_FILE --- # Ubuntu (nvidia-container-toolkit / CDI): # COMPOSE_FILE=docker-compose.yml:docker-compose.gpu-linux.yml # Windows 11 (Docker Desktop + WSL2 + NVIDIA): # COMPOSE_FILE=docker-compose.yml:docker-compose.gpu-windows.yml # Browser-only host (no GPU needed): leave COMPOSE_FILE unset (base only). COMPOSE_FILE=docker-compose.yml:docker-compose.gpu-linux.yml # --- Browser HOST (JARVIS_ROLE=browser) — e.g. this LAN machine --- # Expose Chrome control to the internal network (no auth, internal only): # CDP_BIND=0.0.0.0 # BROWSER_CONTROL_BIND=0.0.0.0 # CDP_PUBLISH_BIND=0.0.0.0 # Defaults are loopback-only. # --- BOT host (JARVIS_ROLE=bot) — e.g. your PC driving the remote browser --- # Point the controlBrowser tool at the browser host's control-server: # BROWSER_CONTROL_URL=http://192.168.10.9:8777 # (Leave BROWSER_CONTROL_URL empty on full/browser layouts.) # --- Models (tune per machine) --- # OLLAMA_CHAT_MODEL=qwen2.5:7b # quality (needs ~5GB VRAM + whisper small) # OLLAMA_CHAT_MODEL=qwen2.5:3b # speed (fits easily, faster on 8GB GPUs) # WHISPER_MODEL=small # small frees VRAM for a bigger LLM; medium=more accurate # MELO_DEVICE=cuda # cpu if no GPU on the bot host # --- Settings web UI (http://localhost:8765/settings on the bot host) --- # To reach it, expose the bridge to the host loopback: # BRIDGE_HOST=0.0.0.0 # SETTINGS_PUBLISH_BIND=127.0.0.1 # 0.0.0.0 to allow LAN access (no auth) # Change models / STT / TTS speed / language / LLM instructions live; "적용" # restarts the bridge + TTS worker so changes take effect.