Commands & shell
Every input surface — the terminal UI, the HUD, and the Telegram bot — understands the same prefix grammar. The first character of your message decides how it's handled, before the router ever runs.
The prefix grammar
FRIDAY short-circuits four input shapes in _maybe_handle_input_prefix() before the turn orchestrator. This keeps commands deterministic and the LLM out of the hot path.
(no prefix) set brightness to 60 → deterministic router (voice or text)
/ /deep RISC-V vs ARM → slash dispatcher (direct to capability)
! !sudo systemctl restart x → interactive PTY shell
> > my-password → stdin to the running shell commandSlash commands
A /command is dispatched directly by core/slash_commands.py — no intent recognition, no planner. On Telegram these populate the native /-autocomplete menu (pushed via setMyCommands), so the registry is the single source of truth.
| command | what it does |
|---|---|
| /new | Reset the conversation and start a new session |
| /clear | Alias for /new |
| /web <query> | Web search — returns result links |
| /quick <question> | Instant web-backed answer in chat, nothing saved |
| /fast <topic> | Fast research — ~2-minute latest-info summary |
| /deep <topic> | Deep research — heavy multi-source briefing, saved to disk |
| /research <topic> | Hand off to the research agent |
| /fetch <url> | Fetch a URL as plain text |
| /crawl <url> [what to look for] | Crawl a URL with instructions |
| /screenshot | Take a full-screen screenshot |
| /voice on|off|status | Toggle voice mode |
| /lock | Lock the computer screen (OS session lock) |
| /unlock | How to unlock the screen / shell PIN gate |
| /help | List every slash command |
/new, /help, /lock, and /unlock run even when the screen is locked, because they have to. Slash commands that hit a capability are still gated by the executor's lock + consent checks.The ! interactive shell
Prefix any line with ! to run it as a real shell command. On Linux/macOS it runs under a pseudo-terminal (PTY), so commands that need a TTY — sudo password prompts, ssh, read, passwd — actually work.
- Bash by default — uses
/bin/bash(not dash), sosource,[[ ]], arrays, and process substitution work. - venv-aware — if the project has a
.venv/, it's onPATHautomatically, so!python script.pyuses the project interpreter. - Bounded — a 5-minute wall-clock cap per command and an output cap prevent runaway buffering.
- Windows — PTYs are POSIX-only; Windows degrades to a non-interactive run and rejects
>follow-ups with a clear message.
Interactive follow-ups with >
When a command is waiting on input, FRIDAY tells you and keeps the process alive. Reply with a >-prefixed line to pipe it to the command's stdin:
!sudo apt install brightnessctl
[sudo] password for you: ← FRIDAY: "Awaiting password — reply with > …"
> •••••••• ← piped to stdin (not echoed)
Do you want to continue? [Y/n]
> y ← piped to the apt prompt
✓ done · [exit 0]> cancels the running command instead of being interpreted by the LLM. That's the safety rule that stops a casual "yes" from being read as a sudo password or a chat message.Security gating
The shell is gated by the screen lock — while FRIDAY's PIN gate is locked, ! is refused with "Shell access is locked. Run /unlock <pin> first." This matters most for the remote case: the same shell is reachable from Telegram, so the lock is what keeps a remote session from running arbitrary commands. See Telegram & remote.