# --- Telegram (long polling — no public URL needed) --- TELEGRAM_BOT_TOKEN= ALLOWED_TELEGRAM_USER_ID= # your numeric Telegram user id; everyone else ignored PORT=8080 # health-check endpoint only # --- Transcription --- # Voice goes to Groq when GROQ_API_KEY is set, and to the Parakeet sidecar (always up) # when Groq fails or no key is set. # PARAKEET_URL= # optional; defaults to the bundled sidecar # GROQ_API_KEY= # optional; enables Groq transcription and the Groq enrichment fallback # --- Claude Agent SDK (subscription auth, no API key) --- # Generate once with: claude setup-token CLAUDE_CODE_OAUTH_TOKEN= # --- Obsidian Local REST API (VFB instance) --- OBSIDIAN_API_URL=https://127.0.0.1:27124 # self-signed cert on LAN; TLS verify is skipped OBSIDIAN_API_KEY= OBSIDIAN_INSECURE_TLS=false # set true when API_URL is a non-loopback host with a self-signed cert (homelab LAN) # --- Vault layout (defaults match the Default vault) --- DAILY_NOTES_DIR=notes/daily notes DAILY_NOTE_TEMPLATE=internal/templates/Daily Note JOURNAL_HEADING=Journal TIL_HEADING=TIL # heading a jot starting with "TIL" is written under, one you move with "Move this to TIL?" goes to, and the nightly follow-up checks HABITS_HEADING=Habits # heading whose checklist the nightly habit review walks ASSETS_DIR=internal/assets/journal # --- Tasks (the two task notes /task writes to) --- # Tasks are checklist bullets under ONE heading in each note, tagged, and carrying # `[start:: yyyy-mm-dd]` (planned start, optional) and `[due:: yyyy-mm-dd]` (the deadline). # INSERT says which end a new task goes on: the work note runs newest-first, the personal # one is appended to. TASKS_WORK_NOTE=notes/work notes/What's going on at work.md TASKS_WORK_HEADING=Other Tasks TASKS_WORK_TAG=#type/todo/work TASKS_WORK_INSERT=top TASKS_PERSONAL_NOTE=notes/tracking notes/dashboards/Todos.md TASKS_PERSONAL_HEADING=Things to do TASKS_PERSONAL_TAG=#type/todo TASKS_PERSONAL_INSERT=bottom # Path to the vault. In the container leave unset — it defaults to /vault (the bind-mount # target). Locally, point it at a real vault dir to test the link index. Compose also reads # it to pick the host mount source (falls back to ./vault). # SCRIBA_VAULT_HOST_PATH=/home/you/Documents/Obsidian/Default # --- Storage --- DB_PATH=/data/scriba.db # --- Behaviour --- TZ=Europe/Stockholm SUMMARY_TIME=23:30 # nightly day summary post (local time) RATING_TIME=00:00 # nightly "how was your day?" 1–10 prompt (local time); the default until you set one in /menu HABITS_TIME=00:00 # nightly "did you do yesterday's habits?" prompt (local time) TASKS_TIME=09:00 # morning task summary: what's due today + what's overdue FLUSH_IDLE_MS=30000 FLUSH_MAX_BATCH=8 FLUSH_MAX_WAIT_MS=120000 SQUASH_WINDOW_MS=15000 # text/voice jots within this gap of the previous one fold into one line; 0 disables # Optional: primary Claude model for enrichment # AGENT_MODEL=claude-haiku-5-5 # Optional: Claude model enrichment retries on before falling back to Groq # ENRICH_BACKUP_MODEL=claude-sonnet-5-5 # Optional: override the Groq model enrichment falls back to when the primary Claude call fails # ENRICH_FALLBACK_MODEL=openai/gpt-oss-120b # Optional: cap in milliseconds on one enrichment call, per step of the chain # ENRICH_TIMEOUT_MS=35000 # Optional: model that lightly cleans the voice transcript before enrichment # VOICE_FIX_MODEL=claude-sonnet-5-5 # Optional: override the model /command runs on (default: claude-sonnet-5-5) # COMMAND_MODEL=claude-sonnet-5-5 # Optional: thinking budget for /command. Its reasoning is relayed to the chat as it works, # so this is what there is to see; 0 turns thinking (and those messages) off. # COMMAND_THINKING_TOKENS=4000 # LOG_LEVEL=trace