{"slug": "solveit-reference", "title": "Solveit reference", "summary": "Solveit is a \"Dialog Engineering\" web application that combines code execution, markdown notes, and AI prompts in a single interactive workspace, unlike ChatGPT or Jupyter. Users build solutions incrementally, with the AI accessing the full dialog context above the current message, and can edit any message at any time. The platform uses a running ipykernel instance, supports standard Jupyter functionality, and includes features like CRAFT.ipynb files for reusable AI context and TEMPLATE.ipynb files for dialog templates.", "body_md": "# Solveit Reference\n\n## What is Solveit?\n\nSolveit is a \"Dialog Engineering\" web application for interactive development. Unlike ChatGPT (pure chat) or Jupyter (pure code), Solveit combines three message types in one workspace: code execution, markdown notes, and AI prompts. Users build solutions incrementally—writing a few lines, understanding them, then continuing—rather than generating large code blocks.\n\nThe AI sees the full dialog context (code, outputs, notes, prompts) when responding -- but only those ABOVE the current message. Users can edit any message at any time, including AI responses—the dialog is a living document, not an append-only log.\n\nThe dialog is a running ipykernel instance. A \"dialog\" is like a \"Jupyter notebook\", and uses a compatible ipynb file format, but provides a superset of functionality (in particular, \"prompt messages\"). A \"message\" is like a \"Jupyter cell\", with additional attributes stored as ipynb cell metadata. Most standard jupyter functionality is supported (including cell magics like `%%js`, `%%html`, `%%bash`, and custom magics via `@line_magic`/`@cell_magic` decorators), except for ipywidgets. Cell magics can be async; if an async magic returns a FastHTML FT component, it's auto-converted to HTML.\n\n## Architecture\n\n- **Instance**: A persistent Linux container (virtual private server) with home dir at `/app/data`. Each user can have multiple instances. Instances have private URLs (for the solveit interface) and public URLs (for hosting apps on port 8000).\n- **Dialog**: An `.ipynb` file containing messages. Each open dialog runs its own Python kernel (ipykernel). Dialogs can be organized into folders.\n- **Kernel**: A running Python 3.12 interpreter maintaining state. Variables persist between code messages. Each dialog has its own isolated kernel. Kernels keep running when navigating away; must explicitly stop via UI or shutdown. Use `%load_ext autoreload` and `%autoreload 2` to auto-reload modules when files change. The current dialog name is available as `__dialog_name` in the kernel namespace and as the `__DIALOG_NAME` environment variable.\n\n### CRAFT and TEMPLATE Files\n\n**CRAFT.ipynb** files provide reusable AI context and auto-executed code for a folder:\n- **Note/prompt messages** are prepended to the AI's context for all dialogs in that folder and subfolders\n- **Code messages** are automatically executed in the kernel when opening a dialog\n\n\n**CRAFT.css** and **CRAFT.js** files can be placed alongside `CRAFT.ipynb`. They follow the same parent-chain hierarchy and are injected as `<style>` and `<script type=\"module\">` tags when a dialog opens. Useful for custom theming or adding client-side behavior without touching the main app.\n**TEMPLATE.ipynb** files serve as dialog templates—their cells are prepended to new dialogs created in that folder.\n\nBoth use path hierarchy: files from parent folders are included too, letting you build layered configurations (e.g., org-wide settings in root, project-specific in subfolders).\n\n### Optional CRAFTs (CRAFTs Folders)\n\nIn addition to `CRAFT.ipynb` files (which are always loaded), you can place notebooks in a `CRAFTs/` subfolder at any level of the folder hierarchy. These are **optional crafts** — they are discovered but not automatically loaded.\n\nThe AI always sees optional crafts listed in its context on every prompt: only the first message and the file size are shown, wrapped in `<optional-craft-block>` tags. This gives the AI enough information to decide whether a particular optional craft is relevant to the current task. If so, the AI can call the `load_dialog` tool, which runs all its code cells in the kernel and returns the full contents.\n\nExample structure:\n```\nproject/\n├── CRAFT.ipynb          # Always loaded (required)\n├── CRAFTs/\n│   ├── testing.ipynb    # Optional — AI loads on demand\n│   └── advanced.ipynb   # Optional — AI loads on demand\n└── my_dialog.ipynb\n```\n\nOptional crafts loaded via `load_dialog` are automatically re-imported when the kernel restarts, so you don't need to re-load them manually after a restart. Solveit achieves this by scanning the dialog's prompt history for prior `load_dialog` calls and replaying them during startup.\n\n\n### AUTORUN Folders\n\nPlace notebooks inside an `AUTORUN/` folder at the root of your instance to have them automatically opened and run on startup. Useful for persistent background processes (Discord bots, FastHTML apps, scheduled tasks). Dialogs in `AUTORUN/` folders are exempt from idle shutdown.\n\n## Message Types\n\n| Type | Purpose | Input | Output |\n|------|---------|-------|--------|\n| `code` | Python execution | Python source | ipynb-format output list (stream, execute_result, display_data, error) |\n| `note` | Documentation | Markdown with optional attachments | None |\n| `prompt` | AI interaction | User question/instruction | AI response (markdown string) |\n| `raw` | Frontmatter/metadata | Raw text (no processing, no variable injection) | None |\n\nThe Monaco editor dynamically switches syntax highlighting based on cell magics — `%%html` switches to HTML highlighting, `%%js` to JavaScript, etc. Raw messages also pick up highlighting from magic headers. `Markdown()` objects returned from code cells render with full formatting. Markdown is rendered using mistlefoot (an extension of mistletoe) with support for header attributes, todo lists, and other extensions.\n\n\n### Message ID Hyperlinks\nUse `#_msg_id` syntax in markdown to create clickable links to specific messages within a dialog. You can also link to messages in other dialogs by including the dialog path: `#path/to/dialog/_msg_id`. Clicking a cross-dialog link opens that dialog and scrolls to the target message.\n### Output Editing\n- **Prompt outputs**: Editable via `n` key or clicking title bar. Can undo AI responses with `Cmd+Z`.\n- **Code outputs**: NOT directly editable. Clear with `Backspace`, or re-run message.\n\n## AI Context System\n\nWhen a user sends a prompt, solveit builds context for the AI:\n\n1. **Message Collection**: Gather all messages up to and including the current prompt\n2. **Filtering**: Exclude messages where `skipped=True` (hidden via `h` key or 👁️ button). Hiding propagates to children when applied to a collapsed section.\n3. **Truncation**: If total tokens exceed model limit, oldest non-pinned messages are dropped\n4. **History**: Messages grouped into chunks by prompt boundaries and LLM history recreated\n\n### Pinning (`p` key)\nPinned messages serve three purposes:\n- **Context preservation**: Pinned messages stay available even when long dialogs get truncated\n- **Export control**: Pinned messages are excluded from exports (Python files, gists, published dialogs)\n- **Bulk management**: Pinning a collapsed header pins all child messages too\n\nUse for API docs, examples, and reference materials that should persist but not be exported.\n\n**Context Window Implications**: The AI only sees messages ABOVE the current prompt. Working at the bottom of a dialog includes MORE context (all messages above). Working higher up includes LESS context. Adding messages earlier in the dialog doesn't increase context for prompts below them.\n\n### Variable and Expression Injection\nUsers can inject Python values into AI context using **$`name`** syntax in prompts. This works with:\n- **Variables**: `$`myvar`` — injects the current value\n- **Expressions**: `$`len(items)`**, `$`df.shape`**, `$`random()`** — evaluated fresh each prompt\n\nWhen the AI sees the prompt, values are fetched from the kernel and included in a separate section of the chat history. Expressions are re-evaluated on every prompt, so `$`random()`** gives a new value each time.\n\nImages stored in variables (as bytes) are also supported and sent as base64, as are message image attachments if referred to in the content in a link with a `#ai` hash.\n\n## Tools System\n\nTools let the AI call Python functions to accomplish tasks. This is the mechanism for AI to read files, search code, modify the dialog, etc.\n\n### Exposing Tools\nUsers declare tools in any message using & followed by `` `function_name` `` or `` `[func1, func2, func3]` ``. Object methods can be exposed using dotted syntax: `` & `obj.method` `` — dots are converted to dashes for API compatibility and back when calling. Solveit then:\n\n1. Finds the function in the kernel's namespace\n2. Extracts the schema from type annotations and docstring\n3. Sends the schema to the AI via standard tool calling mechanisms\n4. When AI calls the tool, solveit executes `function_name(**kwargs)` in the kernel\n5. Returns the result to the AI\n\n### Tool Requirements\nA function becomes a valid tool if it has:\n- Type annotations for ALL parameters\n- A docstring describing what it does\n- Fastcore param docments are passed in the json schema if present\n\n```python\ndef get_user(user_id: int) -> dict:\n    \"Fetch user data by ID.\"\n    return {\"id\": user_id, \"name\": \"Alice\"}\n```\n\n### Built-in Tools (dialoghelper.stdtools)\nWhen `use_tools` setting is enabled (🔧 wrench icon), tools from `dialoghelper.stdtools` are added. This includes:\n- **Python execution**: `pyrun` — safe sandboxed access to the running interpreter via [safepyrun](https://github.com/AnswerDotAI/safepyrun) (see below)\n- File tools: `view`, `create`, `insert`, `str_replace`, `strs_replace`, `replace_lines`. Enhanced variants with regex filtering: `file_str_replace`, `file_strs_replace`, `file_replace_lines`, `file_insert_line`, `file_del_lines`, `file_pyrun`\n- Search tools: `rg`, `sed`, `ast_grep`\n- Dialog tools: `add_msg`, `update_msg`, `del_msg`, `find_msgs`, `read_msg`, `read_msgid`, `view_msg`, `view_dlg`, `dialog_link`, `create_or_run_dialog`, `stop_dialog`, `toggle_comment`, `toggle_bookmark`, `toggle_header`, `copy_msg`, `paste_msg`\n- Inspection tools: `symsrc`, `symval`, `symdir`, `symtype`, `symlen`, `symslice`, `symsearch`, `symnth`. `symtype` and `symval` accept comma-separated symbol lists.\n- Utility tools: `doc` returns a function's full signature with parameter docments, useful for checking how to call any function before using it\n- Web tools: `read_url`, `web_answer`, `search`, and `searches`. Models without native web search (Kimi, DeepSeek, Qwen) get fallback search tools so SolveitAI can search the web when needed; no setup required.\n\n### The `pyrun` Tool\nGives the AI safe, direct access to the running Python interpreter via [safepyrun](https://github.com/AnswerDotAI/safepyrun), an allowlist-based Python sandbox. The AI can write and execute arbitrary Python — iterate over data, filter, parse, define helpers — all autonomously within a single tool loop. Access includes: all non-callable globals, registered tools, most builtins (`dict`, `list`, `Path`, comprehensions, `sorted`, etc.). Callable object attributes are gated — only methods registered via `allow()` can be called. Symbols named with a trailing `_` (e.g. `result_`) are exported back to the namespace. Async/await is supported. `print()` and warnings are captured and returned alongside the result. File writes are controlled via `ok_dests` — a list of directory prefixes where writes are permitted; writes elsewhere raise `PermissionError`.\n\n### dialoghelper Module\nThe `dialoghelper` module provides async functions for programmatic dialog manipulation:\n- `await add_msg(content, msg_type='note')` - Add message below current (supports `placement='add_after'`/`'add_before'` with `id` in other dialogs via `dname`)\n- `await add_prompt(content, dname=None)` - Add and run a prompt, optionally in another running dialog. Returns the AI response text when complete. Useful for running sub-prompts in parallel with different context.\n- `await update_msg(id, content=None, ...)` - Update existing message. `log_changed=True` inserts a diff note.\n- `await del_msg(id)` - Delete message. `log_changed=True` inserts a note showing deleted content.\n- `await find_msgs(re_pattern)` - Search messages by content. `headers_only=True` returns just headings. `header_section=\"## Name\"` returns a section and its children. `before`/`after`/`context` params include surrounding messages (like `grep -B`/`-A`/`-C`), which helps the AI understand the context of matched messages.\n- `await read_msg()` - Read message at index\n- `await read_msgid(id)` - Read message by ID. `add_to_dlg=True` copies content into current dialog.\n- `await view_msg(id)` - View message content with line numbers (returns just content string; use `read_msgid` for full metadata)\n- `dialog_link(path, msg_id)` - Generate clickable HTML link to a dialog. Path is optional — with just `msg_id`, links to a message in the current dialog.\n- `create_or_run_dialog(name)` - Create a new dialog, or set an existing one running\n- `stop_dialog(name)` - Stop a running dialog kernel\n- `toggle_comment(id)` - Toggle line comments on code message(s)\n- `url2note(url)` - Fetch URL and add as markdown note\n- Browser integration: `js_eval(expr)` evaluates a JS expression and returns the result, `js_run(code)` runs JS that calls `done()` when finished, `add_mod(code)` injects a script module, `event_once(evt)` provides safe one-shot browser event handling. All have `_a` async variants.\n- Message editing tools (`msg_str_replace`, `msg_replace_lines`, `msg_insert_line`, `msg_del_lines`, `msg_strs_replace`, `msg_pyrun`) all support `update_output=True` to edit message output instead of content, and `log_changed=True` to record diffs. String/line tools also support `re_filter` (like `g/pattern/` in vi) and `start_line`/`end_line` for range limiting. All `msg_` editing tools have `file_` counterparts for editing regular text files.\n\n**Note**: Nearly all dialoghelper tools are async. Use `await` when calling from code cells.\n\nWhen tools are enabled, SolveitAI can call available tools directly. If tools are disabled, the AI writes code or instructions for you to run yourself.\n\n### Tool Result Handling\nTool results are truncated if too long, to 2000 chars. The `ToolResponse` class can wrap results with metadata. Code eval and tool call results include the Python type of return values in metadata, helping the AI distinguish between different types. Tools can call `input()` to prompt the user mid-execution — the prompt appears in the message output and the tool waits for a response. This enables permission gates and interactive feedback within a single AI tool loop. Input form buttons display underlined access-key labels and respond to bare keypresses, so you can respond without reaching for the mouse. When a sandbox `PermissionError` is raised by a tool call, Solveit stops the AI loop and adds a new code message containing the blocked call. You can run it yourself, edit it first, or `allow()` it so the AI can do that kind of thing directly next time; `Cmd+Shift+.` runs the message and lets the AI immediately see the result and continue. This replaces the modal \"ask for permission\" flow used by tools like Claude Code and Codex CLI.\n\n## File System\n\n- `datapath`: `/app/data` (production) or current working directory (local/test)\n- Dialogs stored at: `{datapath}/some/folders/{dialog_name}.ipynb`\n- Static files served at: `/static/some/folders/` → maps to `{datapath}/some/folders/`\n- Per-dialog Python modules: `{datapath}/some/folders/{dialog_name}.py` (auto-generated from exported messages)\n\n### Dialog Persistence\nDialogs are saved as Jupyter notebooks (`.ipynb`). Solveit converts messages to notebook cells when saving:\n- `note`/`prompt` → markdown cells\n  - Prompt responses stored by appending to message content with separator\n- `code`/`raw` → code/raw cells\n- Metadata stored in cell metadata (skipped, pinned, collapsed states, etc.)\n\n## Keyboard Shortcuts (Selection Mode)\n\nWhen not editing (blue border shows selected message):\n- `↑/↓` or `j/k`: Navigate messages (`Shift` extends multi-selection)\n- `a/b`: Add message above/below\n- `x/c/v`: Cut/copy/paste messages (`c` also copies to system clipboard as markdown). Paste also works on closed dialogs. Works with multi-select.\n- `,`: Copy message input to clipboard\n- `.`: Copy message output to clipboard\n- `h`: Toggle hidden from AI (`skipped`). Works with multi-select.\n- `p`: Toggle pinned. Works with multi-select.\n- `e`: Toggle export. Works with multi-select.\n- `1-6`: Set heading level (converts to `## Heading` etc.)\n- `Enter`: Edit selected message\n- `Cmd+Enter`: Run code or send prompt (stay on message)\n- `Shift+Enter`: Run and go to next message\n- `Opt+Enter`: Run and create new message\n- `Shift+R`: Restart kernel\n- `Shift+T`: Open terminal\n- `Shift+S`: Stop AI/code execution\n- `Shift+A/B`: Run all code above/below (skips prompts)\n- `Cmd+Slash`: Toggle comments on code messages. Works with multi-select.\n- `w`: Extract fenced code blocks to new code messages\n- `Shift+W`: Extract AI tool calls to new code messages (useful for inspecting, editing, or re-running what the AI did)\n- `n`: Edit AI response (output) of prompt message\n- `Cmd+Shift+J/K/L/;`: Switch to code/note/prompt/raw mode\n- `g`: Wrap selected messages in a collapsible section (or unwrap if on a section start header). Works with multi-select.\n- `←/→`: Collapse/expand section (based on markdown headers)\n- `r`: Re-run all code messages in dialog (skips prompts)\n- `m`: Copy code blocks from AI response\n- `d`: Duplicate dialog (opens duplicate with bomb icon 💣 to discard)\n- `s`: Save dialog (commits to git if versioning enabled)\n- `0`: Jump to last edited message\n- `/`: Focus bottom editor/input field\n- `Shift+Esc`: Focus back on message list\n- `Home/End`: Jump to first/last message\n- `Cmd+A`: Select all messages\n- `F`: Open find/search modal (`Shift+F` to clear filters)\n- `Backspace`: Clear outputs from selected message(s). Works with multi-select.\n- `i/o`: Toggle collapse on message input/output. Works with multi-select.\n- `q`: Duplicate message. Works with multi-select.\n- `Shift+O`: Clamp output height\n\n### Multi-Selection\nUse `Shift+↑/↓` or `Shift+j/k` to extend selection. `Cmd+A` selects all. Operations marked \"Works with multi-select\" above apply to all selected messages at once. Shift up/down moves the entire selected block as a unit.\n\n### Editor Shortcuts\nWhen editing a message:\n- `Shift+Tab`: Show parameter info/documentation\n- `Cmd+I`: Manually trigger symbol dropdown\n- `Ctrl+Shift+Minus`: Split message at cursor(s)\n- `Cmd+Shift+Comma`: Screenshot last output into context\n- `Cmd+Shift+Period`: Super completion (prefill in prompts) or super edit (with selection)\n- `Cmd+Shift+S`: Save file (in full-page editor view)\n- `Ctrl+Shift+Right/Left` (Mac) / `Alt+Shift+Right/Left` (Windows): Smart select — progressively expands or shrinks the selection by semantic scope (variable → expression → statement → block → function). Very useful for quickly selecting exactly the right amount of code.\n- `ESC`: Save changes and exit edit mode\n- `→` (Right Arrow): Accept ghost text suggestion\n- `Tab`: Select from symbol dropdown\n\n## AI Modes\n\nSet per-dialog, affects AI behavior:\n\n| Mode | Behavior | Ghost Text |\n|------|----------|------------|\n| `learning` | Pedagogical, asks clarifying questions, explains step-by-step | Disabled by default |\n| `concise` | Minimal responses, compact code, no boilerplate | Enabled |\n| `standard` | Default Claude behavior, verbose explanations | Enabled |\n\n## Ghost Text / Completions\n\n### Ghost Text\nInline AI suggestions as you type (faded gray text). Uses smaller/faster FIM model. Press `→` to accept.\n\n### Super Completions (`Cmd+Shift+.`)\nUses main model for larger completions. Can prefill AI response start in prompt messages.\n\n### Super Edits\nSelect text + `Cmd+Shift+.` + instruction → AI rewrites selection. Uses `edit_call()` with GPT-4.1.\n\n\n### Path Autocomplete\nFile and dialog paths autocomplete as you type in note and prompt messages, making it easy to reference files in your prompts.\n## Export System\n\n### Message Export\nPress `e` on code message to mark `is_exported=True`. Adds `#| export` marker. When dialog is saved, exported messages are combined into `{dialog_name}.py`. Splitting an exported message preserves the export flag on both halves. Merging messages exports the result if any source message was exported. Image attachments are preserved when splitting and merging—they are distributed to the correct resulting messages based on which attachments are referenced in each message's content.\n\n### Publish\nSee \"Publishing and Sharing\" section for full details. Creates shareable view at `share.solve.it.com`. Pinned messages excluded.\n\n### Download Options\n- `.ipynb`: Full notebook\n- `.py` (Full Script): All code messages concatenated  \n- `.py` (Exported): Only `is_exported=True` messages\n- `.md`: Markdown format\n- GitHub Gist: Upload to gist\n\n## FastHTML Integration\n\nSolveit is built with FastHTML. Users can also build FastHTML apps inside dialogs:\n\n```python\nfrom fasthtml.common import *\nfrom fasthtml.jupyter import JupyUvi\n\napp = FastHTML()\nrt = app.route\n\n@rt\ndef index(): return H1(\"Hello\")\n\nsrv = JupyUvi(app)  # Serves on port 8000 → accessible at public URL\n```\n\n`JupyUvi` runs uvicorn in a way compatible with notebook contexts. Changes to routes take effect immediately without restart.\n\n**Note**: The root route `/` is used by Solveit itself. Use different routes like `@rt def homepage()` for your app's entry point.\n\n### Rendering Components\n- `render_ft()` - Render FastHTML components as HTML in message outputs\n- `show()` - Alternative with optional iframe wrapping and HTMX processing\n\n## Feature Flags (Secrets)\n\nStored in `solveit_settings.json` under `secrets` key. Accessed via `get_secret(name)`.\n\n| Flag | Values | Effect |\n|------|--------|--------|\n| `USE_KATEX` | `1`/`true` | Enable LaTeX with safe delimiters (`$$`, `\\[`, `\\(`) |\n| `USE_KATEX` | `dollar` | Also enable `$...$` inline math |\n| `USE_VIM` | any truthy | Vim keybindings in editor |\n| `LITELLM_USAGE` | any truthy | Append token usage and cost summary to each prompt output |\n\n## Image Handling\n\n### Pasted Images\nPaste into note/prompt → stored as message attachment → visible to AI automatically.\n\nIf the clipboard contains both an image AND HTML (e.g., from a DOM screenshot tool), solveit automatically appends the HTML in a fenced code block after the image link—useful for sharing UI screenshots with their underlying markup.\n\nAttachments are stored in notebook message metadata (standard Jupyter format), referenced as `![name](attachment:uuid)`. Attachments are message-specific—cannot be referenced from other messages.\n\n### Markdown Images\n- `![alt](path)` in notes → displays but NOT sent to AI\n- `![alt](path#ai)` → displays AND sent to AI\n- For reusable images, save to `/app/data/` and use `/static/` URLs\n\n### Code Output Images\nImages in code output (matplotlib, PIL) are captured and can be sent to AI.\n\n### Static Images\nUse `/static/` URLs to reference files in `/app/data/`. Example: `Img(src='/static/myapp/image.png')` for FastHTML, or `![alt](/static/image.png)` in markdown.\n\n## Collapsible Sections\n\nMarkdown headings (`# H1` through `###### H6`) create collapsible sections:\n- `heading_collapsed=True` on heading message → children have `hidden=True`\n- Token count shows: `heading_tokens + hidden_content_tokens`\n- Cut/copy on collapsed heading includes all children\n- `←` jumps to section start, `→` to section end\n\n### Section Wrapping (`g` key)\n\nSelect one or more messages and press `g` to wrap them in a collapsible section. This creates a pair of start/end section header messages around the selected messages. The section level is auto-detected from the surrounding context. Press `g` again on the start header to unwrap (remove the start/end pair). This is useful for organizing long dialogs into logical groups you can collapse and expand.\n\n## Token Counting\n\nToken counts estimated and used for:\n- Display in UI (message headers show token counts)\n- Context truncation decisions\n- Image tokens calculated separately\n\n## Error Handling\n\n- Errors trigger `msg.uncollapse()` to show the problematic message\n- Missing variables, broken tools, oversized values, and truncated context are collected as warnings and passed to the AI via `important_prompt`. The AI continues with what's available and informs the user about issues, rather than failing entirely.\n\n## Settings\n\nStored in `{datapath}/solveit_settings.json`. Common settings:\n- `use_tools`: Enable standard tools (🔧 wrench icon in navbar)\n- `use_thinking`: Enable extended thinking mode. Click the 🧠 brain icon or press `Cmd+Shift+D` to toggle between standard and reasoning models. Hover over the brain icon to open a popover where you can choose standard and reasoning models separately, and set effort levels for each. Available models include Anthropic (Sonnet/Opus) and Kimi.\n- `use_diff`: Enable diff mode (shows changed messages as unified diffs)\n- `default_code`: After AI response, default to code mode (not prompt)\n- `idle_timeout_hours`: Hours before idle dialogs are automatically closed (default: 3). Dialogs in `AUTORUN/` folders are exempt.\n\n## Feature Flags (Secrets)\n\nStored in `solveit_settings.json` under `secrets` key. Accessed via `get_secret(name)`.\n\n| Flag | Values | Effect |\n|------|--------|--------|\n| `USE_KATEX` | `1`/`true` | Enable LaTeX with safe delimiters (`$$`, `\\[`, `\\(`) |\n| `USE_KATEX` | `dollar` | Also enable `$...$` inline math |\n| `USE_VIM` | any truthy | Vim keybindings in editor |\n| `LITELLM_USAGE` | any truthy | Append token usage and cost summary to each prompt output |\n\n## UI Controls\n\n### Header Bar\n\nFrom left to right:\n\n**Left section:**\n| Element | Description |\n|---------|-------------|\n| 📚 **solveit** | Logo/home link - closes dialog, returns to dialog list |\n| 🟢 Green dot | WebSocket connection indicator |\n| Dialog name | Editable - click to rename dialog |\n\n**Mode dropdown:**\n| Element | Description |\n|---------|-------------|\n| `learning`/`standard`/`concise` | AI mode selector - affects response style and ghost text |\n\n**Toggle group (blue when active):**\n| Icon | Tooltip | Setting | Shortcut |\n|------|---------|---------|----------|\n| `<>` | \"Default new message type to code?\" | `default_code` | — |\n| 🔧 | \"Include dialoghelper standard tools in prompts?\" | `use_tools` | — |\n| 🧠 | \"Toggle thinking / model chooser (hover)\" | `use_thinking` + model selection | `Cmd+Shift+D` |\n| Diff | \"Toggle diff mode\" | `use_diff` | — |\n\n**Action buttons:**\n| Icon | Tooltip | Action | Shortcut |\n|------|---------|--------|----------|\n| ? | \"Keyboard Shortcuts\" | Open info modal | `?` |\n| Git | \"Checkpoint\" | Create git checkpoint | `Shift+C` |\n| Share | \"Share your dialog\" | Publish to share.solve.it.com | — |\n| Cloud ↑ | \"Upload File\" | Open upload modal | — |\n| ⊗ | \"Stop\" | Stop AI/code execution | `Shift+S` |\n| ▶ | \"Run all\" | Run all code messages | `r` |\n| ↺ | \"Restart\" | Restart Python kernel | `Shift+R` |\n| ⚙ | \"Settings\" | Open settings modal | — |\n| Copy+ | \"Duplicate Dialog\" | Duplicate and open | `d` |\n| 💣 | \"DELETE and close\" | Delete duplicate (hidden until duplicated) | — |\n| Terminal | \"Open Terminal\" | Open terminal in new tab | `Shift+T` |\n| TOC | \"Contents\" | Toggle sidebar | `Ctrl+Shift+V` |\n| ↗ | \"Dialogs\" | Open dialog list in new tab | — |\n\n### Message Bar\n\nEach message has a header bar for input (and optionally output). Click the header text to edit. On mobile, the button bar collapses behind a ☰ hamburger menu.\n\n**Left side:**\n| Element | Description |\n|---------|-------------|\n| Message type | `Code`, `Note`, `Prompt`, or `Raw` |\n| Token count | Estimated tokens for this message |\n\n**Button bar (left to right):**\n| Icon | Tooltip | Shortcut | Action |\n|------|---------|----------|--------|\n| 📋 | \"Copy\" | `,` | Copy message to clipboard |\n| ▷ | \"Run Message\" | `Cmd+Enter` | Execute code or send prompt (code/prompt only) |\n| 👁 | \"Toggle AI visibility\" | `h` | Hide/show message from AI context |\n| 🔖 | \"Toggle message export\" | `e` | Mark for export to .py file |\n| 🗑 | \"Delete Message\" | `Shift+D` | Delete this message |\n| ↑⚡ | \"Delete above\" | — | Delete all messages above (confirms) |\n| ↓⚡ | \"Delete below\" | — | Delete all messages below (confirms) |\n| ↳ | \"Run Above\" | `Shift+A` | Run all code messages above |\n| ↲ | \"Run Below\" | `Shift+B` | Run all code messages below |\n| ↑ | \"Add Above\" | `a` | Insert new message above |\n| ↓ | \"Add Below\" | `b` | Insert new message below |\n| 📖↑ | \"Shift up\" | — | Move message up (works with multi-select) |\n| 📖↓ | \"Shift down\" | — | Move message down (works with multi-select) |\n| 💬+ | \"Add copy of message\" | `q` | Duplicate this message |\n| 🔀 | \"Merge with message below\" | `Shift+M` | Combine with next message |\n| ↔ | \"Split message\" | `Shift+Minus` | Split into multiple messages (regular notes: at headings, code blocks, and paragraph boundaries; notes with only one fenced block: using ast-grep blocks; code: using python ast) |\n| 📌 | \"Toggle message pin\" | `p` | Pin/unpin message |\n| 🔗 | \"Copy link to message\" | — | Copy URL with message anchor |\n| ⌃ | \"Collapse contents\" | `i` | Collapse/expand input |\n| ↗ | \"Open in new tab\" | `t` | View and edit message in standalone Monaco editor tab |\n\n### Message Output Bar\n\nOnly code and prompt messages have outputs. Click the header text to edit (prompt outputs only—code outputs are not editable).\n\n**Left side:**\n| Element | Description |\n|---------|-------------|\n| Label | `Output` (code) or `Assistant` (prompt) |\n| Token count | Estimated tokens for this output |\n\n**Button bar (left to right):**\n| Icon | Tooltip | Shortcut | Action |\n|------|---------|----------|--------|\n| 📋 | \"Copy\" | `.` | Copy output to clipboard |\n| 📋 | \"Copy code\" | `m` | Copy fenced code blocks to clipboard |\n| 💬+ | \"Add fenced block messages\" | `w` | Extract fenced blocks to new code messages |\n| 💬+ | \"Add tool call messages\" | `Shift+W` | Extract AI tool calls to new code messages |\n| ✨ | \"Re-run AI\" | — | Re-send prompt to AI (prompt outputs only) |\n| ⌃ | \"Collapse contents\" | `o` | Collapse/expand output |\n| ↗ | \"Open in new tab\" | `t` | View and edit output in standalone tab |\n\n\nWhen copying AI outputs (via `.`, `m`, or `c`), tool call details, tool extraction controls, and brain emojis (🧠) are stripped for clean clipboard content.\n### Variable Sidebar\n\nToggle with `Ctrl+Shift+V` (or the TOC icon in the header bar). Displays collapsible sections:\n- **Bookmarks**: Numbered bookmarks (1–9) with click-to-navigate\n- **Headings**: Markdown heading hierarchy with exported/hidden indicators\n- **Variables**: Live kernel variables\n- **Functions & Classes**: All defined functions and classes (including async) with signatures extracted via `codesigs`. Click to navigate to the definition message. Populates on dialog open/reset, not just after running code.\n\n## Terminal\n\nPress `Shift+T` to open an integrated terminal in the current dialog's folder. Useful for:\n- File operations (`ls`, `mv`, `rm`, etc.)\n- Git commands\n- Package installation (`pip install`)\n- Running shell scripts\n\n## Find/Search\n\nPress `F` to open find panel (selection mode, not editing). All filtering and highlighting happens client-side for instant responsiveness. Features:\n- Regex search across message content and outputs using the CSS Custom Highlight API\n- Filter by message type (colored buttons match UI colors)\n- Filter by: changed in git diff, errors, pinned, bookmarked, exported\n- Hidden messages (skipped with `h`) are excluded from results by default\n- `Shift+F` clears all filters and restores heading collapse state\n- `Enter` in the search box returns focus to the message list; `Escape` closes the panel\n- `headers_only` and `header_section` parameters available programmatically via `find_msgs`, along with `before`/`after`/`context` for surrounding messages\n\n## Dialog Duplication and Branching\n\nPress `d` to duplicate current dialog. The duplicate preserves the dialog options, opens immediately, and gets a bomb icon (💣) in the navbar. This supports a \"branching\" workflow:\n- Duplicate before experimenting with risky changes\n- If the branch is useful, keep it\n- If not, click the bomb icon to delete and return to the original\n\n## Git/Versioning System\n\nSolveit integrates git for version control at the folder level.\n\n### Enabling Versioning\nClick \"Enable versioning\" button in any folder to initialize a git repo there. Can create nested repos (repo-in-repo) at any directory level.\n\n### Saving and Committing\n- Press `s` to save the dialog and auto-commit with Solveit's distinctive message template\n- Dialogs auto-save on most actions (submit, cancel edit, etc.) but do not commit without `s` or checkpoint\n\n### Checkpoints\nClick \"checkpoint\" button (appears after versioning enabled) to create a manual commit with a custom message. Useful for marking significant milestones.\n\n### Squashing\nSolveit automatically squashes commits that match its auto-save message template. This keeps history clean—many small saves become one commit, while checkpoint commits with custom messages are preserved.\n\n### Diff Mode\nToggle the diff icon in the header bar to highlight messages that have changed since the last git commit. Changed messages display as syntax-highlighted unified diffs (additions in green, deletions in red). New messages are tagged as added. The diff auto-refreshes when HEAD changes. Requires versioning to be enabled. Combine with the \"changed\" filter in Find/Search (`F`) to see only modified messages with their diffs. Clicking to edit a diff-toggled message opens a side-by-side Monaco diff editor, focused at the first change. Click the `→` between sides to revert individual changes.\n\n### Publish Button\nCreates a read-only shareable view at `https://share.solve.it.com/d/[hash]`. Pinned messages are excluded from published output. Brain emoji chains (🧠) from AI thinking are stripped from published output. The scrollspy sidebar is visible on medium-width screens and above.\n\nURL suffixes:\n- `.html` - Blog-style rendered view\n- `.md` - Raw markdown\n\n## Dialog index page\n\nThe dialog index page shows dialogs, folders, and files in a grid layout with name, size, and last modified date. A clickable breadcrumb path sits at the top. File actions (duplicate, download, delete) are available via a `⋮` dropdown menu on each row.\n\nThe page has two main panels: the file grid on the left, and a **Recent Dialogs** sidebar on the right showing your last 40 opened dialogs. Press `Shift+1` through `Shift+9` to quickly jump to a recent dialog.\n\n**Type-to-filter**: Just start typing on the index page to fuzzy-filter the file list by name, with matching text highlighted. No need to click a search box first. Fuzzy matching is case-aware: lowercase letters match after word boundaries and separators, uppercase letters match anywhere. `Backspace` deletes one character, `Escape` clears the filter entirely. If fuzzy matching yields no results, it falls back to exact substring matching.\n\nOther features of this page:\n- \"Show all files\" toggle to see non-ipynb files (editable in Monaco)\n- Secrets management (API keys stored as environment variables)\n- Running dialogs (can shut down here)\n- Upload files/folders (zip and unzip for folders)\n\n### Keyboard Shortcuts\n\n| Key | Action |\n|-----|--------|\n| `↑/↓` | Navigate rows |\n| `Enter` | Open dialog/folder |\n| `N` | Focus \"new dialog\" input |\n| `T` | Open terminal |\n| `D` | Delete selected |\n| `C` | Duplicate selected |\n| `?` | Show keyboard shortcuts |\n| `/` | Focus search/filter input |\n| `Shift+1-9` | Open recent dialog by number |\n| `Shift+Backspace` | Navigate up one directory |\n| `Shift+S` | Toggle \"Show all files\" |\n| `Backspace` | Delete one filter character |\n| `Escape` | Clear filter |\n| Any letter/digit | Type-to-filter dialogs and files (with highlighting) |\n\n\n### Secrets\nAdd name-value pairs in Secrets section. Common secrets:\n- `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` - LLM API access\n- `AOC_SESSION` - Advent of Code session cookie\n- `USE_KATEX`, `USE_VIM`, `LITELLM_USAGE` - Feature flags (see Feature Flags section)\n\nSecrets load when opening a dialog or terminal; add secret then open new dialog to use it.\n\n### Show All Files\nToggle in dialog list view to see all files, not just `.ipynb` dialogs. Enables:\n- Click text files to open in Monaco editor (VS Code-based)\n- Download files via three-dot menu\n- Append `#L<n>` to a file editor URL (e.g. `#L50`) to scroll directly to that line number\n\n## Folder Operations\n\n- Create folders: `mkdir` in terminal, or create dialog with path like `newfolder/dialogname`\n- Move dialogs to folders: Rename dialog to include folder path (e.g., `myfolder/mydialog`)\n\n## Dashboard\n\nThe dashboard at `solve.it.com/dashboard` provides:\n- Instance management (start/stop/restart; rename public instance and get URL; share; allow guests)\n- Live session times for courses\n- Version updates (stop → wait → start to upgrade)\n\n### Instance Sharing (Dashboard)\n- **Copy Public URL**: Get URL for apps running on port 8000 (one URL per instance, all dialogs share it)\n- **Share button**: Add collaborators by email (requires Solveit account)\n- **Lock icon (Allow Guests)**: Enable public access to entire instance without authentication\n\n## Raw Message Type\n\nRaw messages (`Cmd+Shift+;`) are for content that shouldn't be processed:\n- Large documents as AI context (no sidebar headings, no variable injection)\n- Quarto/YAML frontmatter\n- Content with special characters that might interfere with markdown\n\nAccess any message content programmatically in dialoghelper: `read_msg()['msg']['content']` from code message below it.", "url": "https://wpnews.pro/news/solveit-reference", "canonical_source": "https://gist.github.com/jph00/9e7b444aba5ecf6d14295ba2cee890c3", "published_at": "2026-01-18 02:45:08+00:00", "updated_at": "2026-05-22 00:39:33.918280+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "large-language-models", "products"], "entities": ["Solveit", "ChatGPT", "Jupyter", "FastHTML"], "alternates": {"html": "https://wpnews.pro/news/solveit-reference", "markdown": "https://wpnews.pro/news/solveit-reference.md", "text": "https://wpnews.pro/news/solveit-reference.txt", "jsonld": "https://wpnews.pro/news/solveit-reference.jsonld"}}