Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pr-build-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
jobs:
build:
name: Build Validation
runs-on: ubuntu-latest
runs-on: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand Down
6 changes: 4 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,15 @@ The UI morphs between two states: a compact spotlight-style input bar → an exp
- **`App.tsx`** — orchestrates all state: messages, streaming, window resizing via ResizeObserver + Tauri `setSize()`
- **`hooks/useOllama.ts`** — Tauri Channel-based streaming hook; emits `Token`, `Done`, `Cancelled`, `Error` variants
- **`view/ConversationView.tsx`** — smart auto-scroll (pins to bottom unless user scrolls up)
- **`view/AskBarView.tsx`** — auto-expanding textarea (max 144px), morphs logo size
- **`view/AskBarView.tsx`** — auto-expanding textarea (max 144px), morphs logo size, renders slash command tab-completion suggestions
- **`components/ChatBubble.tsx`** — markdown rendering via Streamdown (rehype-sanitize for XSS protection)
- **`config/commands.ts`** — slash command registry: defines supported commands and the `SCREEN_CAPTURE_PLACEHOLDER` sentinel used to show a loading tile in chat while a `/screen` capture is in flight

### Backend (`src-tauri/src/`)

- **`lib.rs`** — app setup: converts window to NSPanel (fullscreen overlay), registers tray, spawns hotkey listener, intercepts close events (hides instead of quits)
- **`commands.rs`** — `ask_ollama` Tauri command: streams newline-delimited JSON from Ollama, sends chunks via Tauri Channel
- **`screenshot.rs`** — `capture_full_screen_command` Tauri command: uses CoreGraphics FFI (`CGWindowListCreateImage`) to capture all displays excluding Thuki's own windows, writes a JPEG to a temp dir, and returns the path
- **`activator.rs`** — Core Graphics event tap watching for double-tap Control key (400ms window, 600ms cooldown); prompts for Accessibility permission, retries up to 6×

### Sandbox (`sandbox/`)
Expand Down Expand Up @@ -102,6 +104,6 @@ Do not consider the task done if either step produces any warnings or errors. Fi

## Key Design Constraints

- **macOS only** — uses NSPanel, Core Graphics event taps, macOS Command key
- **macOS only** — uses NSPanel, Core Graphics event taps, macOS Control key
- **Privacy-first** — Ollama runs locally; Docker sandbox drops all capabilities and isolates network
- **Accessibility permission required** — hotkey listener uses a CGEventTap at session level
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ Most AI tools require accounts, API keys, or subscriptions that bill you per tok
- **Conversation history:** persist and revisit past conversations across sessions
- **Fully local LLM:** powered by Ollama; no API keys, no accounts, no cost per query
- **Isolated sandbox:** optionally run models in a hardened Docker container with capability dropping, read-only volumes, and localhost-only networking
- **Image input:** paste or drag screenshots directly into the chat
- **Image input:** paste or drag images and screenshots directly into the chat
- **Screen capture:** type `/screen` to instantly capture your entire screen and attach it to your question as context
- **Privacy-first:** zero-trust architecture, all data stays on your device

## Getting Started
Expand Down Expand Up @@ -203,7 +204,7 @@ The big leap: from answering questions to taking action.

- **Internet search:** let Thuki look things up in real time, not just reason from its training data
- **Tool integrations via [MCP](https://modelcontextprotocol.io/):** connect Thuki to Gmail, Slack, Discord, Google Calendar, and any other MCP-compatible service; ask it to draft a reply, summarize a thread, or schedule a meeting without ever leaving your current app
- **Slash commands:** type `/summarize`, `/translate`, `/explain`, `/rewrite`, and more to instantly trigger built-in prompts without typing a full question
- **More slash commands:** `/screen` is live; `/summarize`, `/translate`, `/explain`, `/rewrite`, and more are on the way to instantly trigger built-in prompts without typing a full question

### Better AI Control

Expand All @@ -219,7 +220,7 @@ More flexibility over the model powering Thuki.
Give Thuki more to work with.

- **Voice input:** dictate your question instead of typing
- **Auto-capture screen context:** activate Thuki and have it automatically read the active window or selected region as context
- **Auto-capture screen context:** activate Thuki and have it automatically read the active window or selected region as context (partial: `/screen` captures the full screen today; targeted region capture is next)
- **File and document drop:** drag a PDF, image, or text file directly into Thuki as context for your question

---
Expand Down
19 changes: 19 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Commands

Commands are typed at the start of a message using the `/` prefix. Press `/` to open the command suggestion menu, then Tab to complete or Enter to select.

## /screen

Captures your screen and attaches it as context for the current message.

**Usage:** `/screen [optional message]`

**Examples:**
- `/screen`: sends a screenshot with no additional message
- `/screen what is this error?`: attaches a screenshot and asks the question

**Behavior:** The screenshot is taken the moment you press Enter. Thuki's own window is excluded from the capture: no flicker, no hide. The image appears in your message bubble exactly like a pasted screenshot.

**Limit:** One `/screen` capture per message. You may also attach up to 3 images manually (paste, drag, or the camera button) for a total of 4 images per message.

**Permission:** Requires Screen Recording permission. On first use, macOS will prompt you to grant it. If denied, Thuki cannot capture the screen. Grant access in System Settings > Privacy & Security > Screen Recording.
8 changes: 4 additions & 4 deletions src-tauri/src/images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ const MAX_DIMENSION: u32 = 1920;
/// for vision model consumption.
const JPEG_QUALITY: u8 = 85;

/// Maximum number of images allowed per message.
pub const MAX_IMAGES_PER_MESSAGE: usize = 3;
/// Maximum number of images allowed per message (3 manual + 1 /screen = 4).
pub const MAX_IMAGES_PER_MESSAGE: usize = 4;

/// Resolves the root images directory: `<base_dir>/images/`.
pub fn images_root(base_dir: &Path) -> PathBuf {
Expand Down Expand Up @@ -471,8 +471,8 @@ mod tests {
}

#[test]
fn max_images_per_message_is_three() {
assert_eq!(MAX_IMAGES_PER_MESSAGE, 3);
fn max_images_per_message_is_four() {
assert_eq!(MAX_IMAGES_PER_MESSAGE, 4);
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,8 @@ pub fn run() {
images::cleanup_orphaned_images_command,
#[cfg(not(coverage))]
screenshot::capture_screenshot_command,
#[cfg(not(coverage))]
screenshot::capture_full_screen_command,
notify_overlay_hidden,
set_window_frame
])
Expand Down
Loading