FLASH (Fast Local Agent SHell) CLI is an AI-powered command-line interface that allows you to interact with local (or remote) Ollama models while having the ability to execute shell commands directly or through the AI.
- Interactive AI Chat: Chat with local or self-hosted models served by Ollama, directly from your terminal.
- Switchable Backend: Point Flash at
localhostor any remote Ollama server via a single config option. - Shell Command Execution:
- AI can use a
shelltool to execute commands and see their output. - Manually execute shell commands using the
!prefix.
- AI can use a
flash://Links: Open Flash from a browser or another app with a prompt ready to go (flash://?prompt=What+is+Python).- Image Recognition: Send a local image to a vision-capable model with
/image <path> [prompt], or let the AI open one itself with itsview_imagetool. - Page Screenshots: The AI renders a page it built in a headless browser with its
screenshottool and looks at the result, so it can see a broken layout instead of guessing from the HTML. - Page Control: The AI opens a page with
open_pageand then clicks buttons, fills forms, presses keys, and runs JavaScript on it withinteract, seeing a fresh screenshot, the page's elements, and its console errors after every step, so it can debug what a page does, not just how it looks. - Voice Mode:
/voice ondownloads a Vosk speech model and a Piper voice, then lets you talk to Flash and hear its replies, with typing still available at any time. - Context Management: Automatic history trimming to stay within token limits.
- Markdown Support: Rich formatting for AI responses in the terminal.
Install Flash with a single command. The script clones this repo into a temporary directory, installs it with pipx, and cleans up after itself:
curl -fsSL https://raw.githubusercontent.com/Natuworkguy/Flash/main/install.sh | bashOnce installed, run it with:
flashTo uninstall:
curl -fsSL https://raw.githubusercontent.com/Natuworkguy/Flash/main/install.sh | bash -s -- --uninstallOr, if you already have the repo cloned locally:
./install.sh --uninstall-
Clone the repository:
git clone https://github.com/Natuworkguy/Flash cd Flash -
Install dependencies:
pip install -r requirements.txt
-
Install and start Ollama:
Flash talks to an Ollama server. Install Ollama, start it, and pull a model that supports tool calling:
ollama pull llama3.1
By default, Flash connects to a local server at
http://localhost:11434. To use a remote server, setOLLAMA_HOST(see Configuration).
Flash Onyx is a series of custom Ollama models built for Flash: a base
model with Flash's persona and tuned parameters baked in. Each one lives in a
single Modelfile under models/ that declares its name and sizes at the top,
and models/build.py builds whatever a Modelfile declares.
The current release, Flash Onyx 2, is gemma4 in two sizes. 12b runs on
consumer hardware; 31b is the flagship and wants a bigger GPU.
python3 models/build.py models/flash-onyx-2.Modelfile # every size
python3 models/build.py models/flash-onyx-2.Modelfile --size 31b # just oneFlash Onyx 1 is the previous release, built on llama3.1:
python3 models/build.py models/flash-onyx-1.ModelfileThen set MODEL to whichever you built (flash-onyx-2:31b, flash-onyx-1,
and so on) in ~/.flash.env or your environment.
python3 run.pyFLASH CLI is configured through environment variables. You can create a .flash.env file in your home directory:
MODEL=llama3.1
OLLAMA_HOST=http://localhost:11434- Local (default): leave
OLLAMA_HOSTunset, or set it tohttp://localhost:11434. - Remote server: set
OLLAMA_HOSTto the other machine, e.g.OLLAMA_HOST=http://192.168.1.50:11434orOLLAMA_HOST=https://ollama.example.com.
Make sure the target server is reachable and that MODEL has been pulled on it.
Start the CLI by running:
python run.py/helpor/?: Display the help message./model: Show the currently active model and Ollama host./clear: Clear the conversation history./image <path> [prompt]: Send a local image to the model./version: Show the current version and check GitHub for updates./update: Update Flash to the latest version (requires pipx)./bye: Exit the application.
/image <path> [prompt] attaches a local image (.png, .jpg, .jpeg,
.webp, .gif, .bmp) to your next message and sends both to the model.
If you leave off the prompt, Flash asks it to describe the image. This
requires a vision-capable model text-only models will ignore the image
or error. Pull one and switch to it first, e.g.:
ollama pull llama3.2-visionFlash Onyx 2+ is vision capable.
/model llama3.2-vision
/image ~/Pictures/screenshot.png What's going on in this UI?The model can also open an image on its own with the view_image tool, so
you can just name the file in a normal message and let it look:
Why does the legend in ~/Desktop/plot.png overlap the bars?
It accepts the same file types (up to 20 MB) and sees the image for that
turn only, calling view_image again later if it needs another look.
/voice on turns Flash into something you can talk to. The first time it
runs it downloads the two models it needs into ~/.flash/models: a Vosk
speech-recognition model for listening (about 40 MB) and a Piper voice for
speaking (about 60 MB). After that everything runs locally, with no audio
leaving the machine.
/voice on
With voice mode on, press Enter on an empty prompt to start talking. Flash
records until you stop, prints what it heard, and sends it as your message;
the reply is printed as usual and read aloud. It then listens again on its
own, so a conversation carries on hands-free with no keypress between
turns. Say nothing for eight seconds (VOICE_NO_SPEECH_SECONDS), or press
Ctrl+C, and it hands the prompt back. Typing works exactly as before, so
slash commands and long paths can still be typed rather than dictated.
Say "interrupt" while Flash is talking and it stops mid-sentence and
listens for what you say next, so you never have to sit through an answer
that started off wrong. "stop talking" and "be quiet" work too, as does
Ctrl+C, and the word can be changed with VOICE_INTERRUPT_WORD. It is
matched as a whole word, so "the interrupted process" is just a message.
Say "voice off" (or "stop listening", "exit voice mode") to end the
conversation. That hands the prompt back but leaves voice mode armed, so
pressing Enter starts talking again without re-enabling anything. To turn
the feature off altogether, type /voice off; the setting is saved in
~/.flash.env as VOICE, so voice mode survives a restart either way.
Only the prose of a reply is spoken. Code blocks, tables, and URLs are
skipped, because they are on screen already and unpleasant to listen to,
and a long answer is cut at a sentence once it passes VOICE_MAX_CHARS.
Flash also tells the model that it is being heard rather than read, so
replies in voice mode come back shorter and plainer.
Voice mode needs three extra packages: vosk, piper-tts, and
sounddevice. install.sh and install.ps1 install them for you, so
this is only needed if you installed Flash some other way. Flash installed
with pipx keeps its own environment, so the packages go in with inject:
pipx inject flash vosk piper-tts sounddeviceFor a plain pip install of Flash it is the extra instead:
pip install "flash[voice]"/voice on prints whichever of the two commands fits your install. On
Linux
sounddevice also needs PortAudio from the system (apt install libportaudio2); the macOS and Windows wheels bundle it. The voice and the
listening model can be swapped with VOICE_PIPER_VOICE and
VOICE_VOSK_MODEL, and the microphone's sensitivity tuned with
VOICE_SILENCE_THRESHOLD; see docs/CONFIGURATION.md.
The screenshot tool renders a local .html file or a URL in a headless
Chromium and attaches the picture, so a vision-capable model can check
what it built rather than trusting its own source:
Build me a pricing page in ~/Desktop/pricing.html, then check how it
looks on a phone.
It takes a viewport width and height, captures the whole scrollable
page with full_page, and reports any JavaScript errors the page threw
while rendering, which is usually what explains a section that came out
empty.
A screenshot is a still picture, so for a page with buttons or a form the
AI opens it with open_page and then drives it with interact, one
action per call:
Open ~/Desktop/signup.html, fill in the form, submit it, and tell me why
the confirmation never shows up.
The browser stays open between calls, so the page keeps its state while
the AI works through a flow. interact takes an action (click,
fill, press, hover, select, scroll, wait, eval, back,
reload, close) and a selector, which can be the number Flash prints
beside each element, a CSS selector, or the text on the element itself.
Every call answers with where the page is now, what can be clicked or
typed into next, and the JavaScript errors the page threw, with a
screenshot attached. The eval action runs JavaScript against the live
page and returns the result, which is how the AI inspects state a picture
cannot show.
Both tools need Playwright's Chromium, which install.sh and
install.ps1 download for you. Installing Flash another way means
running it yourself:
playwright install chromiumFlash checks main on GitHub for a newer version on startup and shows it
in the banner if one is available. Run /version anytime to check on
demand, or /update to install it. Flash re-runs the same pipx-based
steps install.sh uses, so it needs pipx on PATH. If you cloned the repo
manually, update with git pull instead.
You can also check and update from outside the REPL:
flash --update # check for a newer version and, if found, confirm and install it
flash --update --force # reinstall from `main` unconditionally, no confirmationYou can run shell commands directly without AI intervention:
!ls -la!git status!echo "Hello"
Flash can open from a link. install.sh and install.ps1 register the handler
for you; after a manual install, register it once yourself:
flash --register-url-schemeThen a link like flash://?prompt=What+is+Python starts a Flash session with
that prompt queued. Pass the same URL on the command line to test it without a
browser:
flash "flash://?prompt=What+is+Python"The prompt is URL-encoded, so use + or %20 for spaces. Flash always shows
the prompt and asks before sending it to the model. Any web page can open a
flash:// link, so nothing runs unattended. For the same reason, URL prompts
may not start with / or !: they carry questions for the model, never Flash
commands or shell escapes.
To remove the handler (the uninstallers do this too):
flash --unregister-url-schemeRegistration is per-user: it writes HKCU\Software\Classes\flash on Windows and
~/.local/share/applications/flash-url.desktop on Linux/BSD. It cannot be
installed on macOS, which resolves URL schemes from application bundles only.
Passing a flash:// URL on the command line still works everywhere.
Simply type your request. If the AI needs to see the contents of a file or run a command to answer your question, it can invoke the shell tool automatically. It can also look at an image file with the view_image tool, search the web via Duck Duck Go, and show it's reasoning.
The Flash CLI, the Modelfiles under models/, and the system prompts in them
are MIT licensed. See LICENSE.
A published Flash Onyx model is a derivative of the base model it is built on, and that base license travels with it. The MIT license above covers the Modelfile and the prompt, not the weights underneath:
- Flash Onyx 2.x is built on
gemma4, which Ollama ships under the Apache License 2.0. - Flash Onyx 1 is built on
llama3.1, which ships under the Llama 3.1 Community License. Its terms include a naming requirement for any derivative model you distribute.
models/build.py copies this repository's LICENSE into every model it
builds, together with a pointer to the base model's own terms, so
ollama show --license flash-onyx-2.2:12b prints both. Check the base model's
license with ollama show --license gemma4 before publishing a build.
