MaiChat Tutorial
Master MaiChat: keyboard-first interface for ChatGPT, Claude, and Gemini
What is MaiChat
MaiChat is a keyboard-centric interface for ChatGPT, Claude, Gemini, and Grok that puts you in control. Unlike standard chat interfaces, MaiChat organizes your conversations into a hierarchical topic tree, lets you filter message history with a powerful CLI-like language, and gives you precise control over what context gets sent to each model. It's designed for power users who want to work faster, stay organized, and maintain complete control over their AI interactions.
Quickstart (5 minutes)
Get MaiChat running and send your first message. This guide covers everything you need to start using the app effectively.
Important: MaiChat is designed for keyboard-first navigation with Vim-style commands (j/k for scrolling, u/d for jumping between messages, etc.). While you can use your mouse, learning the keyboard shortcuts will make you much more efficient. Press F1 anytime to see the full reference.
Step 1: Set up your API key
MaiChat needs API keys to connect to LLM providers (OpenAI, Anthropic, Google, xAI).
- Press Ctrl+; to open API Keys settings
- Enter your API key for at least one provider:
- OpenAI (ChatGPT): Get your key at platform.openai.com/api-keys
- Anthropic (Claude): Get your key at console.anthropic.com
- Google (Gemini): Get your key at aistudio.google.com/apikey
- xAI (Grok): Get your key at console.x.ai
- Click Save
Note: API keys are stored locally in your browser and never leave your device.
Step 2: Choose a model
Before sending your first message, select which AI model to use:
- Press Ctrl+M to open the model selector
- Browse the available models based on your API keys:
- OpenAI: GPT-5.1, GPT-5 mini, GPT-5 nano
- Anthropic: Claude Sonnet 4-5, Claude Opus 4-5, Claude Haiku 4-5
- Google: Gemini 3 Pro Preview, Gemini 2.5 Pro, Gemini 2.5 Flash
- xAI: Grok-4-1-fast-non-reasoning, Grok-4-1-fast-reasoning, Grok-code-fast-1
- Select a model and press Enter
The selected model will be used for all messages until you change it.
Tip: Not sure which to choose? Start with GPT-5 mini (OpenAI), Claude Sonnet 4-5 (Anthropic), or Gemini 2.5 Flash (Google) — they're fast and cost-effective.
Step 3: Send your first message
You start in Input Mode with the cursor already in the message box.
- Type your message (e.g., "Explain what MaiChat is in one sentence")
- Press Enter to send
- Watch the response appear in the history area above
Step 4: Navigate the response
After the response arrives, switch to View Mode to read and navigate:
- Press Esc to enter View Mode
- Use j and k to scroll the conversation history up and down (like Vim)
- Use u and d to scroll to the beginning of the previous/next message
- Press g to jump to the first message, G for the last
Step 5: Organize with topics
MaiChat comes with a starter topic tree (General, Work, Personal, Research) that you can use immediately:
- Press Ctrl+T in Input Mode to see the topic selector
- Use search box to filter the topic list or press Ctrl+J to navigate the tree using
h``j``k``lkeys (vim-style). - Select a topic from the list and press Enter, the selected topic will be displayed at the bottom of the input zone.
- Type a message and send it
All future messages will use this topic until you change it. You can reassign messages to different topics anytime.
Learn more: See the Topics section to learn how to customize your topic tree structure and use to manage the context of your requests.
Step 6: Filter your history
As your history grows, use filters to find messages:
- Press Ctrl+D or (Esc from the View mode) to enter Command Mode (top bar)
- In the filter input box you can type various filters and commands controlling your conversation
- Try these filters:
r10— show last 10 message pairs (request and response)- t - show only current topic messages
t'Learning...'— show all messages in "Learning MaiChat" topic and subtopicsd<7- show all messages of the last 7 daysc'happy'- show all messages with word 'happy' in them.
- Press Enter to apply the filter. The conversation history will be filtered and display only messages matching the filter.
Press Esc in Command Mode to clear filters and see all history.
Step 7: Get a Second Opinion
Not satisfied with the first answer? Press E (on the last message in your current view). MaiChat opens a model picker—choose a different model and confirm (Enter). The new response replaces the current one in place.
You can keep re‑asking with other models. Each new send replaces the current answer and the app always retains the previous one. Press Shift+E anytime to flip between the latest and the previously replaced answer.
Why this matters: Quickly compare multiple models without cluttering history or copying text.
What's next?
You now know the basics! Here's what to explore next:
- Navigation — understand the three modes and how to switch between them
- Topics — learn to structure your conversations with topic trees
- Search & Filtering — master the powerful CLI filter language
- Context Management — control what the model sees in each request
- Working with Images — attach and manage images in your conversations
Quick reference: Press F1 anytime to see all keyboard shortcuts.
Navigation: Understanding Modes
MaiChat uses a vim-inspired modal system where the same keys perform different functions depending on the current mode. This design maximizes keyboard efficiency:
- In Input Mode and Command Mode: Most keys are used for typing text (like a regular editor). Commands and actions typically use Ctrl+Key combinations.
- In View Mode: There's no text entry, so single key presses perform various navigation and management actions.
This modal approach lets you stay on the home row and accomplish tasks without constantly reaching for the mouse or arrow keys.
Understanding Modes
MaiChat organizes your interaction into three distinct modes, each with its own screen area and keyboard commands.
Visual indicator: The current mode is always shown in a badge at the bottom-left corner of the screen (Vim-style), displaying "INPUT", "VIEW", or "COMMAND".
The Three Modes
Input Mode (bottom area)
- Purpose: Compose and send messages to AI models
- Screen: Message input box with model and topic selectors
- Main actions: Type, send messages, select model/topic
- Visual cue: Cursor in the input box, input area highlighted
View Mode (middle area)
- Purpose: Read, navigate, and manage your message history
- Screen: Conversation history display
- Main actions: Scroll, jump between messages, rate messages, change topics, copy message content
- Visual cue: Active message highlighted in history
Command Mode (top area)
- Purpose: Filter and search your message history
- Screen: Command input bar at the top
- Main actions: Type filter commands, navigate command history
- Visual cue: Cursor in the command bar, command area highlighted
Switching Between Modes
Contextual switching with Enter/Esc:
- Enter — Generally moves you "into" action (View → Input, Command → View)
- Esc — Generally moves you "out" or "up" (Input → View, View stays in View, Command → clears)
Direct mode jumps:
- Ctrl+I — Jump directly to Input Mode
- Ctrl+V — Jump directly to View Mode
- Ctrl+D — Jump directly to Command Mode
Tip: Enter and Esc are your primary navigation keys. Learn these first, use the Ctrl shortcuts when you need to jump quickly.
View Mode Navigation
This is where you'll spend most of your reading time. View Mode uses Vim-inspired keys:
Basic scrolling:
- j — Scroll down (toward newer messages)
- k — Scroll up (toward older messages)
Jump to message boundaries:
- u — Jump to the start of the previous message
- d — Jump to the start of the next message
- U — Scroll current message to top (useful for returning to start of long messages)
Jump to extremes:
- g — Jump to the very first message in history
- G — Jump to the last (newest) message
Context navigation:
- o — Jump to the context boundary (first message that will be sent to the model)
- Shift+O — Also jumps to context boundary (same as o)
Why u/d instead of arrows? Keeping your hands on the home row is faster. You'll appreciate it after a few sessions!
View Mode Actions
Beyond navigation, View Mode lets you manage your messages:
Rating messages:
- 1 / 2 / 3 — Set star rating (1-3 stars)
- Space — Clear star rating
- a — Toggle color flag (blue square or grey circle)
Managing messages:
- Ctrl+T — Change the topic of the active message
- e — Re-ask (re-send with different model) or Edit and resend (for error messages)
- Shift+E — Swap between current and previous assistant response (if re-asked)
- w — Delete message (only works on error messages)
Viewing images:
- i — View image(s) in active message (opens immediately for single image)
i1/i2/i3/ ... /i9— Jump directly to specific image
Viewing links:
- l — Show link hints with numbers (press 1-9 to open link)
- Ctrl+Shift+S — Open Sources overlay (view citations from web search)
Input Mode Shortcuts
When composing messages, these editing shortcuts speed up your workflow:
Basic actions:
- Enter — Send the message
- Esc — Return to View Mode (without sending)
- Ctrl+C — Cancel/Abort sending message
- Ctrl+M — Open model selector
- Ctrl+T — Open topic selector
- Ctrl+F — Open file picker to attach images
- Ctrl+Shift+O — View/manage attached images before sending
Emacs-style text editing:
- Ctrl+A — Move cursor to start of line
- Ctrl+E — Move cursor to end of line
- Ctrl+U — Delete from cursor to start of line
- Ctrl+W — Delete word to the left
- Ctrl+Shift+F — Move cursor forward one word
- Ctrl+Shift+B — Move cursor backward one word
Note: These same Emacs-style shortcuts work in Command Mode too!
Attaching images:
- Ctrl+F — Open file picker to select images
Cmd+V(macOS) / Ctrl+V (Windows/Linux) — Paste images from clipboard- Ctrl+Shift+O — View/manage attached images before sending
Command Mode Usage
Command Mode is for searching and filtering. See the Search & Filtering section for detailed filter syntax.
Filter actions:
- Enter — Apply filter and switch to View Mode
- Esc — Clear the command input (stays in Command Mode)
- Ctrl+P — Previous command (command history)
- Ctrl+N — Next command (command history)
Emacs-style text editing:
- Ctrl+A — Move cursor to start of line
- Ctrl+E — Move cursor to end of line
- Ctrl+U — Delete from cursor to start of line
- Ctrl+W — Delete word to the left
- Ctrl+Shift+F — Move cursor forward one word
- Ctrl+Shift+B — Move cursor backward one word
Mouse/Touchpad Behavior
You can use your mouse, but it respects the mode system:
- Clicking the input box → switches to Input Mode
- Clicking a message in history → switches to View Mode and makes that message active
- Clicking the command bar → switches to Command Mode
The app automatically switches modes to avoid conflicts with keyboard shortcuts.
Startup Behavior
When you open or reload MaiChat:
- App starts in Input Mode
- The newest (last) message is scrolled into view
- Cursor is ready in the input box
This lets you immediately continue your conversation.
Common Patterns
Quick send workflow:
- Type message (already in Input Mode)
- Enter to send
- Esc to read response in View Mode
- Enter when ready to reply
Search and respond:
- Ctrl+D to enter Command Mode
- Type filter (e.g.,
t'Work' & d<7d) - Enter to see filtered messages
- Ctrl+I to jump to Input and compose new message
Review and rate:
- g to jump to first message
- Read and use 1/2/3 to rate
- d to jump to next message
- Repeat
Learn more: Press F1 anytime to see the complete keyboard reference with all shortcuts.
Topics and the Topic Tree
Topics are MaiChat's core organizational feature. Every message belongs to exactly one topic in a hierarchical tree structure, letting you organize thousands of messages without chaos.
Why Use Topics?
Unlike standard chat interfaces where conversations become one endless scroll, topics give you:
- Logical grouping: Keep related conversations together (e.g., all Python questions under "Coding > Python")
- Easy filtering: Show only messages from one topic or branch with a simple t command
- Context control: Filter by topic before sending to include only relevant history
- Quick navigation: Jump between different conversation threads without scrolling
- Retrospective organization: Reassign messages to different topics as your needs evolve
The Default Topic Tree
MaiChat starts with a simple topic tree to get you going:
General
Work
Personal
Research
These are intentionally broad. Start using them immediately, then create subtopics as patterns emerge.
Creating and Managing Topics
Quick topic picker (during composition):
- Press Ctrl+T in Input Mode
- Search for existing topics or press n to create a new one
- Select a topic — all future messages use it until you change it
Topic Editor (full management):
- Press Ctrl+Shift+T from any mode to open the Topic Editor
- Use keyboard navigation:
- j/k — Move down/up the tree
- h/l — Collapse/expand branches
- n — Create new child topic
- N — Create new root-level topic
- r — Rename focused topic
- d — Delete topic (requires confirmation)
- Press Ctrl+S to save changes
Tip: The Topic Editor shows keyboard hints at the top. It's a powerful interface once you learn the keys!
Reassigning Messages to Topics
Made a mistake? Want to reorganize? You can change any message's topic:
- Navigate to the message in View Mode
- Press Ctrl+T to open the topic picker
- Select the new topic
The message immediately moves to the new topic. This works on both user requests and assistant responses.
Topic Hierarchy Best Practices
Start broad, go deep gradually:
✓ Good progression:
Work
Work > Client Projects
Work > Client Projects > Acme Corp
Work > Client Projects > Acme Corp > Q4 Campaign
✗ Avoid premature detail:
Work > Client Projects > Acme Corp > Q4 Campaign > Week 1 > Monday
Use 2-4 levels typically:
- Level 1: Major life areas (Work, Personal, Learning)
- Level 2: Broad categories (Coding, Writing, Research)
- Level 3: Specific projects or themes (Python, Blog Posts, AI Papers)
- Level 4: Occasional subcategories (only when clearly needed)
Common patterns:
By domain:
Work
├─ Projects
├─ Meetings
└─ Documentation
Personal
├─ Health
├─ Finance
└─ Travel
Learning
├─ Programming
├─ Languages
└─ History
By project:
Projects
├─ Website Redesign
│ ├─ Frontend
│ ├─ Backend
│ └─ Content
└─ Mobile App
├─ iOS
└─ Android
By technology:
Coding
├─ Python
├─ JavaScript
├─ SQL
└─ DevOps
Topic Naming Tips
- Be specific but not too narrow: "Python Web Scraping" is better than just "Python" or "BeautifulSoup Tutorial Chapter 3"
- Use consistent patterns: If you abbreviate, do it consistently (e.g., "JS" vs "JavaScript")
- Keep names short: Long names clutter the UI and are harder to filter
- Avoid dates in names: Use date filters (
d<7d) instead of "January 2025 Work"
Filtering by Topics
Once you have topics organized, filtering becomes powerful:
Show single topic:
t'Work'— Only "Work" topic (exact match)- t — Current topic (whatever's selected in Input Mode)
t10— Last 10 messages of current topict5— Last 5 messages of current topic
Show topic branch:
t'Work...'— "Work" and all subtopics (recursive)t'Coding...'— Everything under "Coding"
Wildcards:
t'*Python*'— Any topic containing "Python"t'Work > *'— Direct children of "Work" only
Combine with other filters:
t'Coding...' & d<7d— Recent coding conversationst'Work...' & s>=2— Important work messages(t'Python...' | t'JavaScript...') & c'error'— Errors in either language
See the Search & Filtering section for complete filter syntax.
Archive Pattern
Create an "Archive" topic for old conversations you want to keep but rarely need:
Archive
├─ 2024
└─ 2025
Then filter them out by default: !t'Archive...'
When to Split Topics
Consider creating a subtopic when:
- A topic has 50+ messages and distinct themes emerge
- You find yourself wanting to filter within a topic
- Multiple unrelated conversations share a topic
- A project or theme becomes significant enough to track separately
Don't create subtopics prematurely. Let your usage patterns guide the structure.
Topic Metadata (Advanced)
Topics can have additional settings:
System message:
- Custom instructions for the AI model in this topic
- Press Ctrl+E on a topic in the Topic Editor
- Each topic has its own independent system message
Temperature:
- Control creativity (0.0-2.0)
- Press Ctrl+T on a topic in the Topic Editor
Max response length:
- Limit assistant response tokens
- Press Ctrl+L on a topic in the Topic Editor
These are optional and most users can ignore them initially.
Customizing Model Behavior
System messages are powerful tools for shaping how the AI responds in specific topics. Think of them as persistent instructions that apply to every conversation in that topic branch.
When to use custom system messages:
- You want a consistent style or tone for a topic area
- You need specific output formats (citations, code, LaTeX)
- You want the AI to adopt a particular role or expertise level
- You have recurring requirements that shouldn't be repeated in every message
Example system messages:
Style variations:
- Be extremely concise. Use bullet points. No fluff.
- Write in a friendly, conversational tone. Use analogies and examples.
- Respond formally and professionally, suitable for business communications.
Expertise & personas:
- You are an expert Python developer. Focus on best practices, performance, and clean code. Cite PEPs when relevant.
- Act as a patient tutor explaining math concepts to a high school student. Use simple language and step-by-step reasoning.
- You are a creative writing coach. Provide constructive feedback on style, structure, and narrative flow.
Format requirements:
- Always cite sources when making factual claims. Use [Author, Year] format.
- Write mathematical expressions in LaTeX. Use display mode ($$...$$) for equations.
- Respond only with valid JSON. No explanatory text outside the JSON structure.
Domain-specific contexts:
- Focus on front-end web development with React and TypeScript. Assume familiarity with modern JavaScript.
- Discuss health topics from an evidence-based perspective. Remind me to consult healthcare professionals for medical advice.
Tips:
- Keep system messages focused and actionable
- Test them with a few messages to refine the instructions
- Remember: system messages consume tokens from your context budget
- You can update them anytime without affecting existing messages
Common Questions
Q: Can a message belong to multiple topics?
A: No. Each message has exactly one topic. This keeps things simple and unambiguous.
Q: What happens if I delete a topic with messages?
A: MaiChat requires you to reassign those messages first. No accidental data loss.
Q: Can I export/import topic structures?
A: Yes! See the Settings & Tools section for export/import options.
Q: Do topics affect what's sent to the model?
A: Not directly. But you can filter by topic before sending to control context. The topic's system message (if set) is also included.
Search and Filtering Language
MaiChat's filtering language is one of its most powerful features. It lets you slice your message history by any combination of topic, model, date, content, ratings, and more — all with terse, keyboard-friendly commands.
Why Filter?
Filtering serves three main purposes:
- Find specific conversations: Quickly locate messages about a topic, from a date, or containing keywords
- Focus your view: See only what matters right now, reducing clutter
- Control context: Filter before sending a new message to include only relevant history
Quick tip: Press Ctrl+D (or Esc from View Mode) to enter Command Mode and start filtering.
Basic Filters
Each filter targets a specific attribute of your message pairs (user request + assistant response).
Topic: t'work'
- Match messages by topic name
- Case-insensitive
- Supports paths, wildcards, and descendants (see Topic Patterns)
Content: c'error budget'
- Search for text within messages
- Searches both user requests and assistant responses
- Use
*as wildcard:c'*error*'
Model: m'gpt-5-mini'
- Filter by which model generated the response
- Wildcards supported:
m'gpt*'matches all GPT models - Bare m (no quotes) uses your currently selected model
Date: d2025-10-08
- Exact calendar day in your local timezone
- Or relative age:
d<7d(last 7 days) - Units: h (hours), d (days), w (weeks),
mo(months), y (years)
Recent count: r30
- Show last N message pairs by absolute recency
- Common shortcuts:
r1,r10,r50 - Ignores all other context; just gives you the most recent
Stars: s3 or s>=2
- Filter by your star ratings (0-3)
s3— exactly 3 starss>=2— 2 or 3 starss0— unrated messages
Flagged: b or g
- b — blue square flag
- g — grey circle flag
- Use flags for quick visual organization
Attachments: i
- Show only messages with image attachments
- Useful for finding visual content or managing storage
- Combine with topic or date filters to narrow down
Errors: e
- Show only message pairs where the assistant response failed
- Useful for troubleshooting API issues
Tip: The simplest and most common filter is just t (without quotes) — it shows only messages from your currently selected topic. This is a quick way to focus on one conversation thread.
Combining Filters
The real power comes from combining filters with logical operators.
AND (space or &):
r20 s>=2
Last 20 pairs that are rated 2+ stars. Space means AND.
t'Work' d<7d
Work messages from the last 7 days.
OR (| or +):
m'gpt*' | m'claude*'
Messages from either GPT or Claude models.
s3 | b
3-star messages OR blue-flagged messages.
NOT (!):
!t'Archive...'
Everything EXCEPT Archive topic and its subtopics.
d<30d & !e
Last 30 days, excluding errors.
Parentheses for grouping:
(t'Python...' | t'JavaScript...') & c'error'
Errors in either Python or JavaScript topics.
t'Coding...' & (s3 | b)
Coding messages that are either 3-starred OR blue-flagged.
Operator precedence:
()— Parentheses (highest priority)!— NOT&and adjacency (space) — AND|and+— OR (lowest priority)
Topic Patterns (Case-Insensitive)
Topics support powerful pattern matching:
Exact match:
t'AI'— Only the "AI" topic (not children)t'AI > Transformers > GPT'— Full path match
Descendants (...):
t'AI...'— AI topic AND all its subtopics (recursive)t'Work...'— Everything under Work
Wildcards (*):
t'*Learning'— Any topic ending with "Learning"t'Machine*'— Any topic starting with "Machine"t'*Neural*'— Any topic containing "Neural"
Combinations:
t'*AI*...'— Topics containing "AI" and all their descendantst'Work > *'— Direct children of Work only (not recursive)
Bare t:
- t — Use currently selected topic from Input Mode
Model Patterns (Case-Insensitive)
Similar to topics, model filters support patterns:
Exact ID:
m'gpt-5*'m'claude-3.5-sonnet'
Wildcards:
m'gpt*'— All GPT modelsm'*mini*'— Any model with "mini" in the namem'claude*'— All Claude models
Bare m:
- m — Use currently selected model from Input Mode
Common comparisons:
(m'gpt-5*' | m'claude*') & t'Coding...'
Compare GPT-5 vs Claude on coding questions.
Date Filters
Dates are flexible and support both absolute and relative forms.
Absolute dates:
d2025-10-08— Exact day (local timezone)d>=2025-01-01— On or after January 1d<2025-12-31— Before December 31
Relative ages:
d<24h— Last 24 hoursd<7d— Last 7 days (omit unit = days by default)d<=2w— Last 2 weeks or lessd<6mo— Last 6 monthsd<1y— Last year
Date ranges (AND two filters):
Closed interval (inclusive):
d>=2025-09-01 & d<=2025-09-30
All of September 2025.
Relative age range:
d>=3d & d<=14d
Messages between 3 and 14 days old.
Half-open range:
d>=2025-01-01 & d<2025-02-01
January 2025 (excludes February 1).
Default unit is days:
d<7≡d<7dd>=30≡d>=30d
Practical Examples
Here are real-world filtering scenarios you can copy and adapt:
Review recent important conversations:
r30 & s>=2
Last 30 pairs that you rated highly.
Find all discussions about a bug:
c'authentication' & c'bug' & t'Work...'
Work messages containing both "authentication" and "bug".
Compare model outputs on a topic:
(m'gpt-5*' | m'claude*') & t'Writing...'
See which model you used for writing tasks.
Recent conversations excluding archives:
d<14d & !t'Archive...'
Last 2 weeks of active conversations.
Flagged or highly-rated research:
(b | s3) & t'Research...'
Your marked or 3-starred research messages.
Debug recent API errors:
e & d<7d
Failed requests from the last week.
Find conversations about Python errors:
t'Python...' & c'error' & !e
Python discussions mentioning "error" but not actual API failures.
Find screenshot messages from last month:
i & d<30d & t'Screenshots...'
Image attachments from Screenshots topic within 30 days.
Weekly review of all topics:
d>=7d & d<14d
Messages from 1-2 weeks ago (last week).
Current topic, recent, highly rated:
t & d<30d & s>=2
Great recent messages in your active topic.
Workflow Tips
Start broad, then narrow:
t'Coding...'— See all codingt'Coding...' & d<30d— Add time constraintt'Coding...' & d<30d & m'gpt*'— Narrow to GPT models
Save common filters as commands: The command input has history (Ctrl+P/Ctrl+N). Your frequent filters are remembered.
Filter before sending: Apply a filter, verify your visible context, then Ctrl+I to compose a message with that context.
Use filters for retrospective organization:
Find unrated messages: s0 & d<7d — rate them while fresh.
Combine with View Mode actions: Filter to a set, then navigate (j/k) and rate (1/2/3) or flag (a) them.
Actions on Filtered Sets
Once you've filtered messages, you can perform bulk actions on the filtered set using colon commands.
Syntax: filter :command [arguments] [flags]
Where:
filter— Any filter expression (or*for all messages):command— The action to perform on filtered pairs[arguments]— Optional command-specific arguments[flags]— Optional command flags (e.g.,--force,--no-confirm)
Available commands:
:tchange - Bulk Topic Change
Change the topic for all filtered message pairs.
Syntax:
:tchange— Change to your currently selected topic (from topic selector):tchange "Topic Name"— Change to specified topic by name or path
Examples:
# Move all errors to "Debug" topic
e :tchange "Debug"
# Move recent unrated messages to current topic
r20 & s0 :tchange
# Move old messages to Archive
d<2024-01-01 :tchange "Archive"
# Move Python discussions to organized topic
c'python' & t'General' :tchange "Work > Python"
Workflow:
- Apply filter to find messages you want to move
- Verify the filtered set in View Mode
- Execute
:tchangewith target topic - Confirm the action (shows count)
- Messages are reassigned, view refreshes
:delete - Bulk Deletion
Permanently delete all filtered message pairs.
Syntax:
:delete— Delete all filtered pairs (requires confirmation):delete --force— Delete more than 50 pairs (requires force flag)
Safety restrictions:
Cannot use with dynamic filters (they would show different messages after deletion):
- r /
rN— Recent messages (relative) - o /
oN— Context boundary (changes based on content) - t — Bare current topic (UI state)
tN— Last N from topic (relative)
Safe filters for deletion:
t'Topic Name'— Explicit topic name ✓d<7d— Date ranges ✓m'model'— Model name ✓c'text'— Content search ✓s>=2— Star ratings ✓- e — Errors only ✓
- b / g — Flags ✓
- i — Attachments ✓
Examples:
# Delete all error messages
e :delete
# Delete old images to free space
i & d<2024-01-01 :delete --force
# Delete temporary topic content
t'temp' :delete
# Delete unrated non-image messages
s0 & !i :delete
# Clean up low-quality old messages
d<2023-01-01 & s0 :delete --force
Flags:
--force— Required for deleting more than 50 pairs
Safety features:
- Always requires confirmation (no bypass)
- Limit of 50 pairs without
--force - Blocks dynamic filters with clear error message
- Shows count before confirming
- After deletion, filter remains active showing empty view (confirmation)
- Press Esc to clear filter and see remaining messages
Error examples:
# ✗ These will be blocked:
r10 :delete # Error: no 'r'
t & s0 :delete # Error: no 't' (bare)
t5 :delete # Error: no 'tN'
o & e :delete # Error: no 'o'
# ✓ These work:
t'Coding...' & s0 :delete # Explicit topic name
d<30d & e :delete # Date + errors
i & s0 :delete # Attachments unrated
Workflow:
- Apply filter to find messages to delete
- Verify filtered set carefully in View Mode
- Execute
:delete(add--forceif >50 pairs) - Confirm deletion (shows count and "cannot be undone")
- Messages deleted, empty view shows (confirmation)
- Press Esc to clear filter and continue
:export - Export to File
Export filtered messages to JSON, Markdown, or plain text files.
For full details, see Export Data section.
Quick syntax:
s>=2 :export # Export starred as JSON
d<7d :export md # Export week as Markdown
t'Python...' :export txt # Export topic as text
Command Mode Shortcuts
When typing filters in Command Mode:
- Enter — Apply filter and switch to View Mode
- Esc — Clear input (stays in Command Mode)
- Ctrl+P — Previous command from history
- Ctrl+N — Next command from history
- Ctrl+A — Move to start of line
- Ctrl+E — Move to end of line
- Ctrl+U — Delete from cursor to start
- Ctrl+W — Delete previous word
Common Mistakes
Forgetting quotes:
- ✗
t'work— Missing closing quote - ✓
t'work'
Using commas instead of operators:
- ✗
t'work', d<7d— Comma doesn't work - ✓
t'work' & d<7dor justt'work' d<7d
Wrong wildcard syntax:
- ✗
t'work*...'— Wildcard and dots don't mix well - ✓
t'work...'— Just use dots for descendants
Confusing NOT with exclusion:
- ✗
!s3alone often too broad - ✓
r50 & !s0— Recent non-zero-rated (more useful)
Quick reference: Press F1 anytime to see the compact filter syntax cheatsheet in the help overlay.
Context Management
One of MaiChat's most important features is giving you precise control over what context gets sent to the AI model. Unlike standard chat interfaces where you can't see how far back the model's "memory" extends, MaiChat shows you exactly which messages are in-context and lets you control the selection.
Why Context Matters
The context you send affects:
- Response quality: Relevant history helps the model understand your needs
- Token costs: Less context = lower API costs
- Response time: Smaller requests are faster
- Focus: Too much irrelevant context can confuse the model
MaiChat's approach: Visible, flexible control
MaiChat gives you:
- Flexible composition: Use filters + metadata (topics, stars, flags) to select which messages are candidates for context
- Visual feedback: See exactly what's in-context and what's not
- Direct control: What you choose to filter is what gets sent (as long as it fits the model's limits)
- Multiple strategies: Filter by topic, date, rating, model, content — or any combination
Example: Send only your highly-rated Python conversations from the last month:
t'Python...' & s>=2 & d<30d
This level of control helps you balance quality, cost, and relevance for every request.
What Gets Sent?
When you send a message, MaiChat includes three things:
- Your new user request — what you just typed
- The topic's system message — if your current topic has one configured (custom instructions)
- Selected conversation history — the messages you've chosen through filtering
How history selection works:
- You use filters to select which messages are candidates (e.g.,
t'Python...',d<7d,s>=2) - MaiChat takes your filtered/visible messages and includes as many as fit the model's context window
- Newest messages are included first, working backward in time
- The app shows you visually which messages are in-context (will be sent) and which are off-context (won't be sent)
Typical workflow:
In most cases, your filtered history will fit completely into the context. For example:
- Filter to current topic: t → 25 messages → all 25 fit ✓
- Filter to recent starred:
s>=2 & d<30d→ 15 messages → all 15 fit ✓ - Filter to specific project:
t'Project X...'→ 40 messages → all 40 fit ✓
When trimming occurs:
If your filtered history is very large (hundreds of messages) or you're using a small context model, MaiChat may need to trim older messages to fit the token limit. You'll see this happen and can:
- Apply a more restrictive filter to focus on what matters most
- Switch to a larger context model (e.g., Claude Sonnet 4-5 with 200K tokens)
- Accept the automatic trimming (often the best choice — newest messages usually matter most)
The key point: You see what gets sent. The app marks which messages are in-context, so there are no surprises.
The Context Boundary
The context boundary is the dividing line between messages that will be sent to the model (in-context) and messages that won't be sent (off-context).
Why you need to see this:
Knowing where the boundary is lets you:
- Verify that important messages are included
- Understand if you need to filter more restrictively
- See at a glance how much context you're sending
- Make informed decisions about whether to adjust your filter
How MaiChat shows you the boundary:
- In-context messages appear at normal brightness
- Off-context messages are dimmed (grayed out) with an "off" badge in their meta line
- This visual distinction makes it instantly clear what the model will see
Checking the boundary:
Press o or Shift+O in View Mode to jump directly to the first in-context message (the boundary point). The view centers on this message so you can easily review what's included.
The Message Counter (Top-Right)
The message counter shows context status at a glance:
Basic format: X/Y
- X = Predicted in-context pairs (will be sent)
- Y = Currently visible pairs (after filtering)
Example: 15/42 means 15 pairs will be sent out of 42 visible.
Prefix: (-)
- Means your newest message is hidden by the current filter
- Warning: You won't be able to send with this filter active!
Trim indicator: [S-T]/Y
- S = Pairs actually sent (after trimming)
- T = Pairs trimmed out (didn't fit)
- Y = Visible pairs
Example: [12-3]/42 means 12 pairs sent, 3 were trimmed, 42 visible.
Hover for details: The counter's tooltip shows:
- Predicted token count
- Whether URA (User Request Allowance) is active
- How many pairs were trimmed on the last send
- Current model's context window size
How Context is Computed
MaiChat uses a prediction algorithm before you send:
- Start with visible history (after any filters)
- Count tokens for each pair (user + assistant)
- Reserve URA tokens for your new request + expected response (default: 600)
- Include pairs from newest to oldest until space runs out
- Mark the boundary and dim older messages
Model-dependent:
- Each model has a different context window (tokens it can handle)
- GPT-5.1: 400K tokens
- Claude Sonnet 4-5: 200K tokens
- Switching models changes the boundary!
Settings that affect context:
- userRequestAllowance (URA): Default 600. Higher = more room for your new message, but less history included
- charsPerToken (CPT): Default 4. Estimation factor (4 chars ≈ 1 token)
- maxTrimAttempts: How many times to retry if the initial prediction is too large
Context Control Strategies
1. Use filters before sending:
t'Python...' & d<7d
Only include recent Python conversations, then send your question.
2. Switch to a larger context model:
Press Ctrl+M and choose a model with a bigger window if you need more history.
3. Adjust URA in settings:
- Lower URA (e.g., 400) = more history fits, less room for your new message
- Higher URA (e.g., 800) = fewer history pairs, more room for complex prompts
4. Star and filter important messages:
Rate key messages with 1/2/3, then filter by s>=2 to include only high-quality context.
5. Review the boundary:
Press o before sending to see what's included. If something important is off-context, apply a filter to bring it in.
Understanding Token Trimming
Sometimes MaiChat's prediction is slightly off (different models count tokens differently). When this happens:
- Initial send fails (too many tokens)
- MaiChat trims the oldest included pair
- Retries up to
maxTrimAttemptstimes - Updates the counter to show
[S-T]/Yformat
Example scenario:
- Predicted: 15 pairs would fit
- Actual: Only 12 pairs fit
- Result:
[12-3]/42(3 pairs trimmed)
This is normal and automatic. You'll see the trim indicator briefly after sending.
Practical Examples
Review before sending:
- Type your message in Input Mode
- Press Esc to enter View Mode
- Press o to jump to context boundary
- Review what's in-context
- Apply filters if needed: Ctrl+D, type filter, Enter
- Press Ctrl+I to return to Input Mode and send
Focus on recent conversations:
d<7d
Only include messages from the last week, reducing noise from old conversations.
Include only important messages:
s>=2 & t'Work...'
Only highly-rated work messages.
Deep context for complex questions:
- Switch to Claude Sonnet 4-5 (200K context)
- Filter to relevant topic:
t'Project X...' - Check counter: o to see boundary
- Send complex question requiring lots of context
Minimal context for quick questions:
r5
Only last 5 pairs — fast and cheap for simple follow-ups.
Common Patterns
Daily workflow:
- Use t filter to focus on current topic
- Check counter occasionally to ensure context size is reasonable
- Press o when you want to verify what's being sent
Research/analysis:
- Filter by topic and date:
t'Research...' & d<30d - Use larger context models
- Review boundary before sending complex queries
Cost optimization:
- Use smaller models (mini/flash) with filtered context
- Check counter to avoid sending unnecessary history
- Star important messages, filter by stars before sending
Debugging context issues:
- Hover over message counter for token details
- Press o to see boundary
- Check if important messages are dimmed
- Adjust filter or URA settings
Context and System Messages
System messages are your always‑on guardrails: they set role, tone, and constraints that apply to every request in the current topic. Use them to encode stable intent (e.g., “be concise, show steps, prefer TypeScript”) so you don’t repeat it in each prompt—keep them short and specific to preserve room for useful history.
On first launch MaiChat seeds topics with varied system messages (general, tutoring, coding, debate, direct mode) so you can immediately experience different answer styles. Treat them as starting points only: edit, delete, or radically reshape them. Small changes (“show full derivation before summary”, “give 3 counterarguments”, “prefer historical context”) can transform response quality and workflow. Experiment aggressively—system messages are the highest-leverage customization you have.
If your current topic has a system message set:
- It's automatically included in every request
- It doesn't count against your URA
- It appears at the beginning of the context
- Useful for role-setting or custom instructions
Set system messages in the Topic Editor (Ctrl+Shift+T), then press Ctrl+E on a topic.
Troubleshooting
"My important message isn't being sent!"
- Check if it's dimmed (off-context)
- Press o to see the boundary
- Apply a filter to bring it into context, or increase URA
"Counter shows (-) prefix"
- Your newest message is hidden by your filter
- Clear the filter (Esc in Command Mode) before sending
"Trim indicator keeps appearing"
- Your messages are close to the token limit
- Use a larger context model, or filter more aggressively
"Context seems wrong after filtering"
- Remember: filters affect what's visible AND what's sent
- Clear filters to reset: Esc in Command Mode
"How do I know exact token count?"
- Hover over the message counter tooltip
- Or append
?reqdbg=1to URL for Request Debug overlay
Key Takeaways
✓ The context boundary determines what gets sent — press o to see it
✓ The message counter (X/Y) shows predicted context size
✓ Filters control context — apply them before sending
✓ Different models have different context windows
✓ URA setting balances new message space vs history inclusion
✓ Visual dimming shows off-context messages clearly
✓ Token trimming is automatic when predictions are slightly off
Working with Images
MaiChat supports image attachments for all models in the catalogue, making it easy to get help with screenshots, diagrams, code snippets, UI mockups, and other visual content.
Overview
Vision support: All base models in MaiChat's catalogue support vision (image understanding). This is a standard capability across OpenAI, Anthropic, Google, and xAI models.
Common use cases:
- Getting help with error messages shown in screenshots
- Analyzing charts, graphs, or diagrams
- Asking questions about code in images
- Describing or discussing UI/UX designs
- OCR (extracting text from images)
Limits:
- Up to 4 images per message
- Maximum 30MB total per message
- Supported formats: JPEG, PNG, GIF, WebP
Attaching Images (Input Mode)
You can attach images to your message in three ways:
1. File picker (Ctrl+F):
- Press Ctrl+F in Input Mode
- Select one or more images from your file system
- Images are added to your draft message
2. Paste from clipboard (Cmd/Ctrl+V):
- Copy an image to your clipboard (screenshot, image from web, etc.)
- In Input Mode, press
Cmd+V(macOS) or Ctrl+V (Windows/Linux) - The image is immediately added to your draft
Tip: This is the fastest way to attach screenshots! Use Cmd+Shift+4 (macOS) or Win+Shift+S (Windows) to capture a screenshot, then paste it directly into MaiChat.
Visual indicator:
- The input area shows
📎 N imageswhen you have attachments - Hover to see image filenames
Managing Draft Images
Before sending, you can review and manage your attached images:
View draft images (Ctrl+Shift+O):
- Press Ctrl+Shift+O in Input Mode
- Image overlay opens showing all attached images
- Navigate with j/k or arrow keys
- Press
Deleteor x to remove the current image - Press Esc to close the overlay
Viewing Message Images (View Mode)
After sending a message with images, you can view them anytime:
Quick view (i):
- Press i on any message part with images
- If there's only one image, it opens immediately
- If there are multiple images, overlay opens to the first image
Jump to specific image (i1-i9):
- Press
i1to jump to first image - Press
i2to jump to second image - Continue with
i3,i4, etc. up toi9
Visual indicator:
- Messages with images show
📎 Nin the metadata line
Image Overlay Navigation
When viewing images in the overlay:
Navigate between images:
- j / k — Next / previous image
- 1 / 2 / 3 ... 9 — Jump to specific image by number
- Arrow keys — Also work for navigation
Manage images (draft only):
Deleteor x — Remove current image from draft- (Only works when viewing draft images via Ctrl+Shift+O)
Close overlay:
- Esc — Close and return to previous mode
Image Limits and Storage
Technical limits:
- Per-message limit: 4 images
- Size limit: 30MB total per message
- Supported formats: JPEG, PNG, GIF, WebP
Storage:
- Images are stored locally in your browser's IndexedDB
- They never leave your device except when sent to AI providers
- Large image collections can consume browser storage
Managing storage:
- Use the i filter to find all messages with attachments: i
- Combine with date filters to find old images:
i & d<2024-01-01 - Delete messages with attachments to free space (see Deletion Examples)
Common Workflows
Screenshot workflow:
- Capture screenshot (Cmd+Shift+4 on macOS, Win+Shift+S on Windows)
- Switch to MaiChat (Input Mode)
- Paste with
Cmd+V/ Ctrl+V - Type your question
- Press Enter to send
Multiple images:
- Press Ctrl+F to open file picker
- Select multiple images (Shift+click or Cmd+click)
- All images attach at once
- Preview with Ctrl+Shift+O before sending
Finding and cleaning up images:
# Find all messages with images
i
# Find old screenshot messages
i & t'Screenshots...' & d<90d
# Delete old temporary images (requires confirmation)
i & t'temp' :delete
Review images from a conversation:
- Filter to your topic:
t'Project X...' - Navigate with j/k in View Mode
- Press i on any message to view its images
- Use j/k in the overlay to browse all images in sequence
Web Search & Sources
AI models can search the web in real-time and cite their sources. MaiChat makes it easy to enable search and review citations, giving you transparency into where information comes from.
Overview
Search support: All base models in MaiChat's catalogue support web search with citations. This is a standard capability provided by the LLM providers (OpenAI, Anthropic, Google, xAI).
Use cases:
- Getting current information (news, events, stock prices)
- Fact-checking with verifiable sources
- Research with citations
- Finding recent documentation or updates
- Asking about recent developments in any field
Enabling Web Search
Search is controlled per-model in the Model Editor (search is enabled by default for all models):
- Press Ctrl+M to open model selector
- Navigate to any model
- Press Enter to edit the model
- Check the "Search Enabled" checkbox
- Press Ctrl+S to save
When to enable search:
- Research topics requiring current information
- Fact-checking and verification workflows
- Questions about recent events or updates
- Any query where sources matter
When to disable search:
- Creative writing or brainstorming
- Code generation (unless checking current APIs)
- General conversation
- When speed is more important than sources
Performance note: Enabling search slightly increases response time as the model searches before generating.
Viewing Citations (View Mode)
When a model uses web search, it includes numbered citations in the response like [1], [2], etc.
Open Sources overlay (Ctrl+Shift+S):
- Navigate to a message with citations (look for
[1],[2]in text) - Press Ctrl+Shift+S in View Mode
- The Sources overlay opens showing all cited URLs
Sources overlay features:
- List view: All sources numbered with titles and URLs
- Navigate: Use j/k or arrow keys to scroll
- Copy URL: Click the copy button or select text
- Open link: Click the URL to open in browser (or use link hints)
- Close: Press Esc to return
Visual indicator:
- Messages with search results may show additional metadata
- Look for
[1],[2],[3]inline citations in the response
Link Hints
MaiChat provides vim-style link hints to open any link in the response without using your mouse:
Activate link hints (l):
- In View Mode, navigate to a message with links
- Press l (lowercase L)
- Numbers appear next to each link
- Press 1, 2, 3, etc. to open that link
- Links open in a new browser tab
Works with:
- Citation links from web search
- Any URLs in the assistant response
- Markdown links
- Plain text URLs
Tip: Combine with Ctrl+Shift+S for full citation workflow: press Ctrl+Shift+S to see all sources, then l to quickly open any link.
How It Works
Behind the scenes:
- You send a message to a search-enabled model
- The model performs web searches before generating the response
- Search results are analyzed and relevant content is extracted
- The model generates a response using the search results
- Citations are added inline:
[1],[2],[3] - Full URLs are stored and accessible via Ctrl+Shift+S
Citation format:
- Inline:
According to recent studies [1], the approach has proven effective [2]. - Sources overlay: Shows full titles and URLs for each number
Performance impact:
- Adds 2-5 seconds to response time (depending on query complexity)
- Uses additional tokens (search results are part of context)
- Slightly higher API costs
Customizing Reading Experience
Most chat interfaces give you a fixed, narrow column and endless scrolling. MaiChat takes a different approach: it lets you tune how you read. There is no single “optimal” layout — the classic ~70 character line length is an average, not a universal truth. People differ in how they scan text: some prefer wider lines (fewer vertical scroll interruptions), others prefer narrow columns (shorter horizontal eye movements), and many change their preference by task or time of day.
Why Adjust It?
- Reduce friction: Fewer scroll stops can help when skimming long analytical or technical answers.
- Improve focus: Narrowing the field can help when you want to concentrate deeply or avoid peripheral distraction.
- Match your hardware: Wide monitors waste space in single-column UIs; two columns reclaim density.
- Adapt to fatigue: Dimmer text and lighter background can reduce contrast strain in long sessions.
Controls Overview
Open Settings (Ctrl+,) and use two tabs:
Reading tab
- Two Columns (Assistant Text): Enable a dual-column layout for assistant responses. Great on large screens for high information density. Disable if it feels visually busy.
- Justify Text (Two Columns): Optional. Some users like the even edges; others find it introduces uneven spacing “rivers.” Toggle and decide.
- Text Lightness / Font Weights: Adjust perceived contrast and emphasis. Very light weights (200) produce minimalist feel; heavier (400+) increase legibility when skimming.
- Background Lightness: Subtly reduce contrast for comfort or increase it for clarity under bright ambient light.
Spacing tab
- Left / Right Gutters (0–400px): Narrow the reading field or let it breathe edge-to-edge. Large gutters recreate narrower columns without forcing a global layout.
- Message / Assistant Gaps: Vertical rhythm. Tight gaps = density; larger gaps = segmentation and easier scanning.
- Message Padding / Meta Gap: Adjust internal padding around text and spacing between metadata badges and body.
Experiment Strategy
- Start extreme: set gutters to 280–320px, enable two columns, dim text. See how it feels.
- Back off one control at a time: disable columns; brighten text; reduce gutters.
- Identify what actually improves speed vs what just “looks clean.”
- Revisit settings at different times (morning vs late evening) — preferences often shift.
Useful Starting Points
- Dense Research Reading: Two columns ON, gutters 40–80px, moderate text lightness, compact vertical gaps.
- Focused Deep Work: Single column, gutters 200–300px, lighter weight (200–250), slightly dim text.
- Casual Browsing: Single column, minimal gutters, standard contrast, medium gaps.
- Code / Technical Review: Single column, moderate gutters (80–140px), higher contrast for inline code clarity.
Tips
- If two columns feel “too jumpy,” reduce column count (off) or increase gutters instead of forcing justification.
- Large gutters + single column can mimic traditional document widths without losing flexibility.
- Justification is purely aesthetic here; disable it if spacing artifacts distract you.
Key Takeaway
There is no mandated reading layout in MaiChat. Use the controls to shape a workspace that lets you read faster and stay comfortable longer. Revisit the settings as your tasks and environment change.
API Keys and Model Catalogue
MaiChat connects to AI providers through their APIs. To use the app, you need to set up API keys and understand how to manage your model catalog.
Setting Up API Keys
Important: Bring Your Own Key (BYOK)
MaiChat is completely free — you pay nothing to use the app itself. Instead, you use your own API keys from AI providers, and you pay them directly based on your usage.
- You register with OpenAI, Anthropic, and/or Google (see details below)
- You obtain your own API keys from their platforms
- You pay the providers directly for API usage
- MaiChat cost: $0 (the app is free)
- AI provider cost: Pay-as-you-go or subscription plans
Free tiers and costs:
- OpenAI: No free tier; pay per token (roughly $2-20 per 1M tokens depending on model. 1M tokens corresponds to 1200-1500 typical chat messages)
- Anthropic: Some credits for new users; similar pricing to OpenAI
- Google (Gemini): Generous free tier (15 requests/min, 1M tokens/day for Gemini 1.5 Flash)
- xAI: Pay-as-you-go pricing; check console.x.ai for current rates
- Typical usage: Light use might cost $5-20/month; heavy use $50-100+/month
Check each provider's website for current pricing and free tier details.
MaiChat supports four major AI providers. You need at least one API key to use the app.
Opening API Keys settings:
- Press Ctrl+; from any mode
- Or use the menu: Ctrl+. → API Keys
Supported providers:
OpenAI (ChatGPT models)
- Get your key at platform.openai.com/api-keys
- Models: GPT-5.1, GPT-5 mini, GPT-5 nano
Anthropic (Claude models)
- Get your key at console.anthropic.com
- Models: Claude Sonnet 4-5, Claude Opus 4-5, Claude Haiku 4-5
Google (Gemini models)
- Get your key at aistudio.google.com/apikey
- Models: Gemini 3 Pro Preview, Gemini 2.5 Pro, Gemini 2.5 Flash
xAI (Grok models)
- Get your key at console.x.ai
- Models: grok-4-fast-non-reasoning, grok-4-fast-reasoning, grok-code-fast-1
Security and privacy:
- API keys are stored locally in your browser's localStorage
- OpenAI and Google: Keys are sent directly from your browser to their APIs
- Anthropic (Claude): Requests go through a MaiChat proxy server (required due to browser CORS restrictions). The proxy forwards your key and request to Anthropic but doesn't store or log either
- Your conversation data stays between you and the AI providers
- Use your browser's private/incognito mode if on a shared computer
Understanding the Model Catalogue
MaiChat comes with a pre-configured catalog of popular models. You can enable/disable models and add custom ones.
Opening the Model Editor:
- Press Ctrl+Shift+M from any mode
- Or use the menu: Ctrl+. → Model Editor
What you see:
A table showing all available models with:
- Model ID — The unique identifier (e.g.,
gpt-5.1,claude-sonnet-4-5-20250929) - Enabled — Whether the model appears in the model selector (Ctrl+M)
- Context Window — Maximum tokens the model can handle
- TPM/RPM/TPD — Tokens/Requests per Minute, Tokens per Day limits
Model categories:
High-performance models (expensive, powerful):
- GPT-5.1 (OpenAI) — 400K context
- Claude Opus 4-5 (Anthropic) — 200K context
- Claude Sonnet 4-5 (Anthropic) — 200K context
- Gemini 3 Pro Preview (Google) — 1M context
- Gemini 2.5 Pro (Google) — 1M context
- grok-4-1-fast-reasoning (xAI) — 2M context, fast inference with reasoning
Fast/economical models (cheap, quick):
- GPT-5 mini (OpenAI) — 400K context
- GPT-5 nano (OpenAI) — 400K context
- Claude Haiku 4-5 (Anthropic) — 200K context
- Gemini 2.5 Flash (Google) — 1M context
- grok-4-1-fast-non-reasoning (xAI) — 2M context
- grok-code-fast-1 (xAI) — 256K context, optimized for code
Managing Models
Enable/disable models:
- Open Model Editor (Ctrl+Shift+M)
- Click the checkbox next to a model to toggle
- Only enabled models appear in the model selector (Ctrl+M)
- Tip: Disable models you don't have API keys for to declutter the selector
Why disable models:
- No API key for that provider
- Don't want to accidentally use expensive models
- Simplify the model selector
- Testing with specific model subset
Editing model parameters:
Click on any field to edit:
- Context Window: The model's maximum capacity (get from provider docs)
- TPM: Your plan's tokens per minute limit — See "Understanding Rate Limits" below
- RPM: Requests per minute (not yet enforced, set for reference)
- TPD: Tokens per day (not yet enforced, set for reference)
Important: You must set TPM to match YOUR plan, not the model's advertised capacity. MaiChat uses TPM to calculate how much context fits in each message.
Adding More Models
By default, MaiChat includes only the most popular and relevant models from each provider. However, you can add any other official model from OpenAI, Anthropic, Google, or xAI.
Important: You can only add models from the four supported providers. You cannot add models from other providers or use custom/fine-tuned models (those typically have different API endpoints).
How to add a model:
- Open Model Editor (Ctrl+Shift+M)
- Use the Add row at the bottom
- Enter:
- Model ID — Exact API identifier (check provider's documentation)
- Context Window — Maximum tokens (from provider specs)
- TPM/RPM/TPD — Your plan's rate limits (see next section)
- Press Enter or click Save
- The model immediately appears in your selector (Ctrl+M)
When to add models:
- Provider releases a new model not yet in the default catalog
- You have beta access to an experimental model
- You need a specialized model (e.g., specific GPT-4 variant)
- Testing with different model versions
Removing models:
- Click the delete icon next to models you've added
- Default models (pre-configured by MaiChat) can't be deleted, only disabled
How Context Window Affects Your Work
The context window is one of the two key parameters that determine how much history you can include in each message (the other is TPM - see next section).
Small context (8K-32K tokens):
- Limits conversation depth
- Forces aggressive filtering
- Lower cost per request
- Faster responses
Medium context (128K-200K tokens):
- Most modern models (GPT-5, Claude Sonnet 4.5)
- Comfortable for most use cases
- Balances depth and cost
Large context (1M-2M tokens):
- Gemini models (massive windows!)
- Claude Sonnet 4.5 with beta header (1M)
- Include entire project histories
- Expensive per request
- Use when deep context is critical
Switching models changes the boundary:
MaiChat recalculates the context boundary when you switch models:
- Larger window → More messages fit → Boundary moves back
- Smaller window → Fewer messages fit → Boundary moves forward
- You see this instantly (dimming updates in real-time)
Press o after switching models to see the new boundary.
Understanding Rate Limits (TPM vs Context Window)
This is crucial to understand how MaiChat calculates what fits in each message.
Two different limits:
Context Window (CW): The model's theoretical maximum capacity
- Example: GPT-5 can handle up to 128,000 tokens
- This is what providers advertise
Tokens Per Minute (TPM): Your plan's rate limit
- Example: Your tier allows 30,000 tokens per minute
- This is what you're actually limited by
How MaiChat calculates your limit:
For each message, MaiChat uses: MIN(Context Window, TPM)
Whichever is smaller becomes the actual constraint.
Why both matter:
- If TPM < CW (common): TPM is the bottleneck — your plan limits you before the model's capacity
- If CW < TPM (rare): Context Window is the bottleneck — the model's capacity limits you before your plan
Example scenario (TPM is smaller):
- Model: GPT-5 (CW = 128K)
- Your plan: TPM = 30K
- Your actual limit per message: MIN(128K, 30K) = 30K tokens
- MaiChat will trim history to fit within 30K tokens
Provider differences in rate limits:
OpenAI:
- Has a single total TPM limit that applies to input tokens
- Your input (prompt + history) must fit within this limit
- Output tokens don't count toward TPM (but do count toward context window)
Anthropic (Claude):
- Has separate input TPM and output TPM limits
- Input limit: Controls how many tokens you can send (prompt + history)
- Output limit: Controls how many tokens the model can generate in response
- Both limits are enforced independently
Google (Gemini):
- Uses "Tokens per minute (input)" limit
- Similar to OpenAI — only input tokens count toward TPM
- Very generous free tier: 250K-1M TPM depending on model
- Output tokens don't count toward TPM
xAI (Grok):
- Uses TPM limit similar to OpenAI
- Only input tokens count toward TPM
- Check console.x.ai for your plan's specific limits
What this means for you:
- OpenAI/Gemini/xAI: Set TPM to your plan's input token limit
- Anthropic: Set TPM to your plan's input token limit (MaiChat handles output limits separately)
Setting TPM correctly:
This is your responsibility! You must set TPM to match YOUR plan, not the model's advertised capacity.
Check your plan on the provider's website:
- OpenAI: platform.openai.com → Settings → Limits (look for "Tokens per minute")
- Anthropic: console.anthropic.com → Settings → Limits (look for "Input tokens per minute")
- Google: Check your tier — Free tier has very high limits (250K-1M TPM)
- xAI: console.x.ai → Check your account limits
Open Model Editor (Ctrl+Shift+M)
Update TPM for each model to match your plan's input token limit
Default TPM values:
MaiChat ships with conservative defaults that should work for most paid plans. However:
- If you're on a free tier: You might need to lower TPM (except Gemini, which has generous limits)
- If you're on a high-tier plan: You can increase TPM for better performance
RPM and TPD:
- RPM (Requests Per Minute): Currently not enforced by MaiChat (future feature)
- TPD (Tokens Per Day): Currently tracked but not enforced (future feature)
- Set them for your own reference and future proofing
Model Selection Strategy
Daily workflow:
- Use mini/flash/nano models (GPT-5 nano, Gemini 2.5 Flash-Lite, Claude 3.5 Haiku)
- Fast, cheap, good enough for most tasks
- Switch to larger models only when needed
Complex questions:
- Use flagship models (GPT-5, Claude Sonnet 4.5, Gemini 2.5 Pro)
- Better reasoning and understanding
- Worth the cost for important tasks
Deep context needs:
- Use Claude Sonnet 4.5 (200K, 1M beta) or Gemini 2.5 Pro (2M)
- When you need lots of conversation history
- Research, analysis, long-form content
Cost optimization:
- Filter aggressively with nano/flash-lite models
- Check message counter before sending
- Use
r10orr20filters for quick questions - Reserve flagship models for complex work
Speed optimization:
- Flash-lite/nano models are significantly faster
- Use them for rapid iteration
- Switch to larger models only for final versions
Best Practices
✓ Set up all four providers if possible — gives you flexibility and backup options
✓ Start with free tier (Gemini) to experiment before committing budget
✓ Monitor your costs using provider dashboards and Daily Stats (Ctrl+Shift+D)
✓ Disable models you don't use — keeps the selector clean
✓ Start with mini/flash models — upgrade to flagship only when needed
✓ Check the message counter before sending expensive flagship models
✓ Add more models as providers release new ones
✓ Set realistic TPM limits to control context size per message
✓ Press o after switching models to see the new context boundary
Settings and Tools
MaiChat provides several tools for configuration, monitoring, and data management.
Settings
Configure app-wide behavior and appearance through the Settings panel.
Access: Press Ctrl+, from any mode, or use menu (Ctrl+. → Settings)
Settings are organized in 3 tabs:
Spacing Tab — Visual layout controls:
- Fade Zone, Message Gap, Assistant Gap, Message Padding
- Meta Gap, Gutter Left/Right
- Inline Markdown Formatting (experimental)
- Adjust for more spacious or compact reading experience
Scroll Tab — Animation behavior:
- Base Duration, Dynamic Scaling, Min/Max Duration, Easing
- Navigation Animation toggles (j/k, J/K, u/d)
- Disable for instant navigation or adjust for preferred feel
Context Tab — Token estimation and AI request behavior:
- User Request Allowance (URA): Default 600 tokens — Space reserved for your message. Higher = more room for long prompts but less history; Lower = more history but less room for your message. Adjust if you write very long or very short messages.
- Assistant Response Allowance (ARA): Default 800 tokens — Expected response size (OpenAI only). Rarely needs adjustment.
- Chars Per Token (CPT): Default 4 — Estimation factor. Rarely needs adjustment (works well for English).
- Assumed User Tokens: Default 256 — Preview boundary reserve. Rarely needs adjustment.
- Max Trim Attempts: Default 10 — Retry limit for context overflow. Rarely needs adjustment.
- Topic Order Mode: How topics sort in Topic Selector (manual/alpha/recent)
Saving:
- Click "Apply (Ctrl+S)" or press Ctrl+S to save
- Click "Cancel+Close (Esc)" or press Esc to discard
- Settings stored in browser localStorage (persist across sessions)
When changes take effect:
- Spacing: Immediate visual update
- Scroll: Next navigation action
- Context: Next message send (recalculates boundary)
Storage location: Settings, API keys, model catalog, and topic tree are stored in localStorage. Conversation history (message pairs) is stored in IndexedDB for better performance with large datasets.
Activity Statistics
View activity breakdown for your currently filtered conversations with three different perspectives: by date, by model, or by topic.
Access: Press Ctrl+Shift+D from any mode, or use menu (Ctrl+. → Activity Stats)
Three tabs available:
1. By Date tab:
- Date-by-date message count breakdown
- Shows which days you were most active
- Includes median response time per day
- Sorted chronologically
2. By Model tab:
- Message count breakdown by AI model
- Shows which models you use most
- Includes median response time per model
- Sorted by usage count
3. By Topic tab:
- Hierarchical tree view of message counts per topic
- Shows both direct (in topic) and total (including subtopics) counts
- Collapsible/expandable tree structure
- Only displays topics that have messages in the filtered view
- Format:
Topic name (direct/total)
Navigation:
- Switch tabs: Press h / l or
[/]keys - Navigate rows: Use j / k or arrow keys (in Date/Model tabs)
- Navigate tree: Use j / k to move, Enter or click to expand/collapse (in Topic tab)
- Jump: g to top, G to bottom
- Close: Press Esc
Features:
- Respects current filter — Shows stats only for visible messages (filtered set)
- Response times — Median time gives you sense of model speed and API performance
- Context-aware — Filter to a topic first, then check stats for that topic only
- Topic hierarchy — By Topic tab preserves your topic tree structure
Use cases:
- Quick activity overview across time, models, or topics
- Compare model performance (speed) side-by-side
- See message distribution across your topic tree
- Verify filter is working as expected
- Identify usage patterns (which models for which topics, which topics are most active)
- See which days or models had slower responses
What it's NOT:
- Not a cost tracker (no pricing/spending data)
- Not exportable (shows only current data in overlay)
- Not historical in the sense of trends over time
Note: Data comes from IndexedDB (where conversation history is stored). Clearing browser data will delete this history.
Browser and Multi-Tab Usage
MaiChat stores all data locally in your browser using IndexedDB (messages, topics) and localStorage (API keys, settings). Understanding how this works helps you use the app effectively across tabs and browsers.
Multiple Browser Tabs
You can open MaiChat in multiple tabs within the same browser to work on parallel conversations:
Benefits:
- Compare responses from different models side-by-side
- Run long requests in background tabs without blocking your main workflow
- Organize work by topic or project (one tab per conversation stream)
- Switch contexts quickly without losing your place
How it works:
- All tabs share the same IndexedDB database and localStorage
- Messages sent from any tab are immediately persisted
- API keys and settings are shared across tabs
Important limitations:
- No real-time sync — Each tab has its own in-memory state. If you send a message in Tab A, Tab B won't see it automatically
- Refresh to sync — Reload a tab (F5 or Ctrl+R) to see messages created in other tabs
- Avoid simultaneous edits — Don't edit the same message or topic from multiple tabs at once (last write wins)
Recommended workflow:
- Use different topics or models per tab to minimize confusion
- Periodically refresh tabs if you want to see cross-tab changes
- Think of each tab as an independent session that shares underlying storage
Browser Isolation
Your MaiChat data is specific to each browser and browser profile:
What this means:
- Chrome, Firefox, Safari, and Edge each have completely separate data
- Even different Chrome profiles (personal vs work) have isolated databases
- API keys entered in one browser won't appear in another
- Your conversation history is not shared across browsers
Practical implications:
- Privacy/separation — Use different browsers for work vs personal conversations
- Data recovery — If you "lose" your data, check if you're in the right browser/profile
- Fresh start — Want to start over? Use a different browser or profile
- No cloud sync — MaiChat is a pure client app; there's no automatic backup or cross-device sync
Tip: If you need to transfer data between browsers, use the Export feature (:export json) and save the file, then manually import it in the other browser (when import functionality is added) or keep it as a backup.
Export Data
Download your conversations as files for backup, sharing, or analysis.
How it works:
Command Mode syntax:
Where:
— Any filter expression (or*for all messages):export— The export command— Optional:json(default),md, ortxt
Available formats:
JSON (default) — Structured data with full metadata
- Command:
:exportor:export json - Output file:
export_chat-YYYYMMDD-HHMMSS.json - Best for: Backup, re-importing, programmatic processing
- Command:
Markdown (.md) — Human-readable formatted text
- Command:
:export md - Output file:
export_chat-YYYYMMDD-HHMMSS.md - Best for: Reading, sharing, documentation
- Command:
Plain Text (.txt) — Simple unformatted text
- Command:
:export txt - Output file:
export_chat-YYYYMMDD-HHMMSS.txt - Best for: Minimal files, plain text editors
- Command:
Examples:
# Export all messages as JSON
* :export
# Export only starred messages
s>=2 :export
# Export last 5 days as Markdown
d<5 :export md
# Export specific topic as plain text
t'Python...' :export txt
# Export recent high-rated conversations
d<30 & s>=2 :export
What gets exported:
- Message pairs (user request + AI response)
- Timestamps, topics, models, ratings, flags
- Error states (if response failed)
- Full topic paths (e.g., "Work > Python > Debugging")
What does NOT get exported:
- In-context markers (not relevant outside app)
- UI state (dimming, active message, etc.)
- Settings or API keys
- Internal temporary data
JSON structure example:
{
"schemaVersion": "1",
"app": "MaiChat",
"generatedAt": "2025-10-12T10:30:00Z",
"filterInput": "t'Python...' :export",
"count": 42,
"pairs": [
{
"id": "p_123",
"createdAt": "2025-10-12T08:15:00Z",
"topicPath": "Work > Python",
"topicId": "uuid-here",
"model": "gpt-5-mini",
"stars": 2,
"flagColor": "blue",
"userText": "How do I...?",
"assistantText": "Here's how...",
"errorState": false
}
]
}
When to use export:
✓ Regular backups — Download important conversations periodically
✓ Project documentation — Export completed projects as Markdown
✓ Sharing — Export specific topics to share with colleagues
✓ Analysis — Export as JSON to process with other tools
✓ Archiving — Save before cleaning up or browser reset
✓ Migration — Backup before major changes
Tips:
- Filter first — Export exactly what you need, not everything
- Use JSON for backups — Most complete format
- Use Markdown for sharing — Most readable for others
- Check your filter — Verify message count before exporting
Print to PDF
Export conversations as professionally formatted PDF documents for printing, archiving, or sharing.
How to access:
- Press Ctrl+Shift+R (or open menu with Ctrl+. and select "Export to PDF")
- Configure formatting options in the dialog
- Click "Generate PDF" to open print preview
- Print or save as PDF from your browser's print dialog
Formatting options:
Typography:
- Font size — 10pt, 11pt (default), or 12pt for body text
- Code font size — 9pt (default), 10pt, or 11pt for code blocks
- Line spacing — 1.4, 1.6 (default), or 1.8 for readability
Layout:
- Orientation — Portrait (default) or Landscape
- Paper size — Determined by browser print settings (A4, Letter, etc.)
Metadata:
- Include topic name — Show topic path in header (default: on)
- Include date — Show export date in header (default: on)
- Include message count — Show number of messages in header (default: on)
- Custom title — Optional custom title for the document
Settings:
- Auto-open print dialog — Automatically open print preview after generation (default: off)
- Remember settings — Save preferences for next export (default: on)
What gets included:
✓ Filtered message pairs (user + assistant)
✓ Topic paths and timestamps
✓ Code blocks with syntax preservation
✓ Message metadata (model, ratings)
✓ Formatted equations and markdown
What does NOT get included:
✗ Images (attachments are omitted in PDF)
✗ Interactive elements
✗ Error states or pending messages
✗ Off-context markers
Tips:
- Filter first — Use Command Mode filters to select specific conversations before exporting
- Preview before printing — Check formatting in print preview
- Use landscape for code-heavy content — Better fit for wide code blocks
- Adjust font sizes — Smaller fonts fit more content per page
- Save as PDF — Use browser's "Save as PDF" option instead of printing to paper
Example workflow:
# 1. Filter to specific topic
Ctrl+D → t'Python Debugging...' → Enter
# 2. Open PDF export
Ctrl+P
# 3. Configure
- Font: 11pt
- Orientation: Landscape
- Include metadata: Yes
# 4. Generate and save
Click "Generate PDF" → Save as PDF
Common Errors and Solutions
When a message send fails, MaiChat displays an error badge in the message metadata with a short classification code. The full error message appears on hover. You can retry with the "Re-ask" button (or press e in View Mode) or delete the error with the "Delete" button (or press w in View Mode).
Error Classifications
MaiChat categorizes errors into 5 types based on the error message from the provider:
error: auth
- Meaning: Authentication failed — API key is missing, invalid, or expired
- Triggers:
- "API key" in error message
- "Unauthorized" or "401" response
- "Forbidden" response
- How to fix:
- Press Ctrl+; to open API Keys
- Check that the correct API key is entered
- Verify the key is active on the provider's website
- Generate a new key if needed
- Make sure billing is set up (some providers require it)
error: model
- Meaning: The model ID doesn't exist or you don't have access
- Triggers:
- "Model not found" or "unknown model"
- "Invalid model" or "unsupported model"
- "Model doesn't exist" or "deprecated model"
- 404 errors mentioning "model"
- How to fix:
- Open Model Editor (Ctrl+Shift+M)
- Check the model ID matches provider documentation exactly
- Some models require beta access or special enrollment
- Try switching to a different model from the same provider
- Remove the model if it's been deprecated
error: quota
- Meaning: You've hit a rate limit or context size limit
- Triggers:
- 429 status code (too many requests)
- "Rate limit" or "quota" in error message
- "TPM" or "RPM" (tokens/requests per minute)
- "Context length exceeded" or "context window"
- How to fix:
- For rate limits (429/TPM/RPM):
- Wait 60 seconds and try again
- Check your plan limits on provider's website
- Consider upgrading your plan if this happens often
- Use a different model (they often have separate limits)
- For context limits:
- Apply a more restrictive filter to include less history
- Try
r20to include only last 20 message pairs - Switch to a model with larger context window
- Press o to see what's being included
- Check Model Editor (Ctrl+Shift+M) — your TPM might be too low
- For rate limits (429/TPM/RPM):
error: net
- Meaning: Network connection failed
- Triggers:
- "Network error" in message
- "Fetch failed"
- Connection timeouts
- DNS resolution failures
- How to fix:
- Check your internet connection
- Try again in a moment (temporary network issue)
- Check if the provider's API is down (visit status page)
- Disable VPN if using one (might interfere)
- Try a different network if available
error: unknown
- Meaning: Error doesn't match any known pattern
- Triggers: Any error that doesn't fit the above categories
- How to fix:
- Hover over error badge to read full error message
- Search for the error message in provider's documentation
- Check if it's a content policy violation
- Try rephrasing your request
- Try a different model
- Check browser console (F12) for additional details
Common Workflows
After an error occurs:
- Read the error — Hover over the error badge to see the full message
- Retry — Press e (View Mode) or click the ↻ button to re-ask
- Delete — Press w (View Mode) or click the ✕ button to remove the error
- Fix and retry — Fix the underlying issue (add API key, change model, apply filter) then press e to re-ask
The Re-ask feature:
- Copies the original user message to input field
- Sets the model to what was used
- Switches to Input Mode
- You can edit before resending
- Original error message remains until you delete it or send successfully
Interface Issues
"Keys don't respond"
- Cause: You're in the wrong mode
- Solution:
- Check mode indicator (bottom-left: VIEW/INPUT/COMMAND)
- Press Esc to cycle through modes
- Or use Ctrl+V (View), Ctrl+I (Input), Ctrl+D (Command)
"Can't find a message"
- Cause: A filter is hiding it
- Solution:
- Press Ctrl+D to enter Command Mode
- Type
*and press Enter to clear all filters - Or check active filters shown at top of history pane
- Use
c'search term'to search for specific content
"Modal or overlay won't close"
- Cause: Not using the right key
- Solution:
- Press Esc to close most overlays
- Or click outside the overlay
- For Settings/Model Editor: click "Cancel" or press Esc
When All Else Fails
- Refresh the page — Sometimes the app state gets confused
- Check browser console — Press F12 and look for error messages
- Try a different browser — Some extensions can interfere
- Clear browser data — Last resort (you'll lose settings/history)
- Report the issue — Check GitHub issues or create a new one