whiskr is a private, self-hosted web chat interface for interacting with AI models via OpenRouter.
- Private & Self-Hosted: All your data is stored in
indexedDB. - Broad Model Support: Use any model available on your OpenRouter account.
- Real-time Responses: Get streaming responses from models as they are generated.
- Persistent Settings: Your chosen model, temperature, and other parameters are saved between sessions.
- Authentication: Optional user/password authentication for added security.
- Multimodal Output: If a model supports image output (for example,
google/gemini-2.5-flash-image-preview), whiskr will request and render images alongside text. You can enable/disable this globally viasettings.image-generationinconfig.yml(default: true).
- File Output: Models are able to emit text files themselves, which can be downloaded or previewed.
- Full Message Control: Edit, delete, or copy any message in the conversation.
- Collapse/Expand Messages: Collapse large messages to keep your chat history tidy.
- Retry & Regenerate: Easily retry assistant responses or regenerate from any point in the conversation.
- Title Generation: Automatically generate (and refresh) a title for your chat.
- Import & Export: Save and load entire chats as local JSON files.
- File Attachments: Attach text, code, or images to your messages for vision-enabled models.
- Reasoning & Transparency:
- View the model's thought process and tool usage in an expandable "Reasoning" section.
- See detailed statistics for each message: provider, time-to-first-token, tokens-per-second, token count, and cost.
- Keep track of the total cost for the entire conversation.
- Advanced Model Search:
- Tags indicate if a model supports tools, vision, or reasoning.
- Fuzzy matching helps you quickly find the exact model you need.
- Smooth Interface: Built with morphdom to ensure UI updates don't lose your selections, scroll position, or focus.
search_web: Search the web via Exa; returns up to 12 results with short summaries.fetch_contents: Fetch and summarize the contents of one or more URLs.github_repository: Get a comprehensive overview of a GitHub repository. The tool returns:- Core info (URL, description, stars, forks).
- A list of top-level files and directories.
- The full content of the repository's README file.
- restrict model list (optionally allow all for authenticated users)
- make authentication optional (unless no allowed models)
- improved custom prompts
- settings
- auto-retry on edit
- ctrl+enter vs enter for sending
- multiple chats
Frontend
- Vanilla JavaScript and CSS
- morphdom for DOM diffing without losing state
- marked for Markdown rendering
- highlight.js for syntax highlighting
- Fonts: Inter (UI), Comic Code (code)
- Icons: SVGRepo
- Color palette: Catppuccin Macchiato
Backend
- Go
- chi/v5 for the http routing/server
- OpenRouter for model list and completions
- Exa for web search and content retrieval (
/search,/contents)
- Copy
example.config.ymltoconfig.ymland settokens.openrouter:
cp example.config.yml config.yml- Build and run:
go build -o whiskr
./whiskr- Open
http://localhost:3443in your browser.
Optional configuration notes (from config.yml):
settings.image-generation(bool, default: true) - allow models with image output to generate images. If set to false, whiskr requests text-only responses even for image-capable models.settings.title-model(string, default:google/gemini-2.5-flash-lite) - model used to generate chat titles (requires structured output support).tokens.exa(optional) - enables the search tools; without it, web search is unavailable.tokens.github(optional) - increases GitHub API limits for the GitHub repository tool.
whiskr supports simple, stateless authentication. If enabled, users must log in with a username and password before accessing the chat. Passwords are hashed using bcrypt (12 rounds). If authentication.enabled is set to false, whiskr will not prompt for authentication at all.
authentication:
enabled: true
users:
- username: laura
password: "$2a$12$cIvFwVDqzn18wyk37l4b2OA0UyjLYP1GdRIMYbNqvm1uPlQjC/j6e"
- username: admin
password: "$2a$12$mhImN70h05wnqPxWTci8I.RzomQt9vyLrjWN9ilaV1.GIghcGq.Iy"After a successful login, whiskr issues a signed (HMAC-SHA256) token, using the server secret (tokens.secret in config.yml). This is stored as a cookie and re-used for future authentications.
When running behind a reverse proxy like nginx, you can have the proxy serve static files.
server {
listen 443 ssl;
server_name chat.example.com;
http2 on;
root /path/to/whiskr/static;
location / {
index index.html index.htm;
etag on;
add_header Cache-Control "public, max-age=2592000, must-revalidate";
expires 30d;
}
location ~ ^/- {
proxy_pass http://127.0.0.1:3443;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
}- Send a message with
Ctrl+Enteror the send button. - Hover over a message to reveal controls to edit, delete, copy, collapse, or retry.
- Click "Reasoning" on an assistant message to view the model's thought process or tool usage.
- Adjust model, temperature, prompt, or message role from the controls in the bottom-left.
- Attach images using markdown syntax (
) or upload text/code files with the attachment button. - When using an image-output model (e.g.,
google/gemini-2.5-flash-image-preview) andsettings.image-generationis enabled, whiskr will display returned images inline. - Use the buttons in the top-right to import/export the chat or clear all messages.
GPL-3.0 see LICENSE for details.


