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
25 changes: 14 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<h1 align="center">
Thuki - WIP
Thuki
</h1>

<p align="center">
Expand All @@ -15,7 +15,7 @@
</p>

<p align="center">
<img src="https://img.shields.io/badge/status-beta-yellow.svg" alt="Beta" />
<img src="https://img.shields.io/badge/status-maintenance-blue.svg" alt="Maintenance" />
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License" /></a>
<a href="https://www.thuki.app/" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/thuki.app-000000?style=flat" alt="thuki.app" /></a>
<a href="https://github.com/quiet-node/thuki/actions/workflows/pr-pipeline.yml"><img src="https://github.com/quiet-node/thuki/actions/workflows/pr-pipeline.yml/badge.svg" alt="CI" /></a>
Expand All @@ -36,6 +36,18 @@

Thuki (thư kí, Vietnamese for secretary) is a lightweight macOS overlay powered by local AI models running entirely on your own machine, built for quick, uninterrupted asks without ever leaving what you're doing.

## Project status

Thuki is in maintenance mode. The app is stable, free, and fully open source, and it keeps doing everything described below.

My focus has moved to other early-stage products, so new feature work has stopped. What continues:

- Reported bugs, crashes, and security issues get triaged and fixed. [Open an issue](https://github.com/quiet-node/thuki/issues).
- Dependency, engine, and macOS compatibility updates keep landing.
- Pull requests are welcome and reviewed.

If Thuki is part of your workflow it will keep working, and the Apache 2.0 license means you are free to fork it and take it further.

## Install on macOS

> **Requirements:** macOS 13.4 (Ventura) or later, Apple Silicon (M1-M5).
Expand Down Expand Up @@ -88,7 +100,6 @@ A bundled llama.cpp `llama-server` that Thuki spawns, supervises, and shuts down
Thuki can also run inference through an external provider instead of the built-in engine.

- **Ollama.** Prefer your own [Ollama](https://ollama.com) install? Switch to it anytime from Settings.
- **Your own OpenAI-compatible server (coming soon).** Support for pointing Thuki at any OpenAI-compatible endpoint you run yourself (a local or self-hosted server) is on the [roadmap](#roadmap).

See [docs/models-and-providers.md](docs/models-and-providers.md) for the full model library and provider guide.

Expand All @@ -112,14 +123,6 @@ Contributions are welcome! Read [CONTRIBUTING.md](CONTRIBUTING.md) to get starte

Community-maintained Windows ports: [ThukiWin](https://github.com/ayzekhdawy/thukiwin) and [Mate](https://github.com/M31i55a/windowsMate-Thuki).

## Roadmap

MCP tool integrations (Gmail, Slack, Calendar), voice input, meeting notes, task automation, and bring-your-own OpenAI-compatible server. Have an idea? [Open an issue](https://github.com/quiet-node/thuki/issues).

## Founder note

Hey, Logan here. I'm building Thuki around how people actually use it, so if you have feedback, an idea, or just want to say hi, [reach out on X](https://x.com/quiet_node). Or [leave your email](https://thuki.app/subscribe) and I'll reach out personally. I read everything.

## License

Copyright 2026 Logan Nguyen. Licensed under the [Apache License, Version 2.0](LICENSE).
9 changes: 0 additions & 9 deletions docs/configurations.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,15 +338,6 @@ Settings for the conversation history panel (where you scroll back through past
| `SEARCH_DEBOUNCE_MS` | `200` | No | UX tuning; no meaningful user signal for changing this. Raising it makes search feel sluggish; lowering it wastes cycles on every keystroke. | — | When you type in the history search box, Thuki waits this many milliseconds after your last keystroke before actually running the search. Stops Thuki from running a fresh search on every single character you type, while still feeling instant. |
| `STRIP_PATTERNS` | 17 token strings | No | Defense-in-depth bound on external/attacker-controlled data: special turn-boundary tokens leaked by fine-tuned models would corrupt cross-model history if persisted. Exposing this list as a config knob would let a malformed or adversarial model response disable the sanitization layer. | — | The set of special delimiters (e.g. `<\|im_start\|>`, `[INST]`, `<think>`) that major model families use internally. Some fine-tuned models leak these into `message.content`; Thuki strips them before storing an assistant reply and again at render time so switching between model families does not produce visible garbage in the chat window. The TypeScript mirror of this list (`src/utils/sanitizeAssistantContent.ts`) must be kept in sync when new model families are added. |

### Email capture (not in TOML)

Backs the optional "Help shape Thuki" email ask (the onboarding roadmap screen and Settings ▸ About). Thuki sends your email only when you click the button, and POSTs just `{ email, source }` to a public proxy that holds the email-service key, so no secret ever lives in the app. Not user-tunable.

| Constant | Default | Tunable? | Why not tunable | Bounds | Description |
| :--------------------------- | :------------------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DEFAULT_SUBSCRIBE_ENDPOINT` | `https://thuki.app/api/subscribe` | No | Fixed external-service endpoint, not a knob: the proxy at this origin holds the email-service key and enforces the contract, so pointing it elsewhere would silently break the subscribe flow. | — | The public proxy URL the "Help shape Thuki" ask POSTs `{ email, source }` to. A `200` (including already-subscribed) is success; any other response surfaces a generic, retryable error. |
| `DEFAULT_SUBSCRIBE_TIMEOUT_SECS` | `15` | No | Internal robustness bound on a one-shot network call, not a preference: it caps how long the sending state can last if the proxy stalls. | — | Per-request timeout (seconds) for the subscribe POST. If the proxy does not respond in time the request fails into the same generic, retryable error rather than hanging. |

### Built-in web search (not in TOML)

Governs the invisible auto-search that runs on the built-in engine: a deterministic pre-filter and a persona-free classifier decide whether a turn needs the web and which source tier (weather, sports, news, Wikipedia, or the general engines) best answers it. The constants below are the deterministic guards that keep the Wikipedia vertical from answering a volatile question from a static encyclopedia summary even when the classifier mis-routes one there, the operators that bias DuckDuckGo and Google News toward recent results on a freshness-seeking question (Mojeek does not get one: see `mojeek_request`'s rustdoc for why), the thresholds that decide what language a question is written in (so a Vietnamese or Japanese question searches the Vietnamese or Japanese web, and its Wikipedia edition, rather than the English one), the keyword map that routes a question to ESPN's live scoreboard, and the recency-prior fusion that, on that same freshness-seeking question, re-ranks the general engine tier's already-fetched sources toward the newest one instead of relevance alone. None are user-tunable. Defaults and bounds live in `src-tauri/src/config/defaults.rs`. Pipeline design: [built-in-web-search.md](./built-in-web-search.md).
Expand Down
13 changes: 0 additions & 13 deletions src-tauri/src/config/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,19 +676,6 @@ pub const BOUNDS_UPDATER_CHECK_INTERVAL_HOURS: (u64, u64) = (1, 168);
pub const DEFAULT_UPDATER_MANIFEST_URL: &str =
"https://github.com/quiet-node/thuki/releases/latest/download/latest.json";

// Email capture
/// Public proxy endpoint that the optional "Help shape Thuki" email ask POSTs to.
/// The proxy holds the email-service key; Thuki sends only `{ email, source }`
/// and never sees a secret. Not user-tunable: it is a fixed external-service
/// endpoint, not a knob, and pointing it elsewhere would silently break the
/// subscribe flow.
pub const DEFAULT_SUBSCRIBE_ENDPOINT: &str = "https://thuki.app/api/subscribe";
/// Per-request timeout for the optional email-subscribe POST, in seconds. Caps
/// how long the "Help shape Thuki" button can sit in its sending state if the
/// proxy stalls without responding, so the request fails into the generic
/// retryable error instead of hanging indefinitely. Not user-tunable: it is an
/// internal robustness bound on a one-shot network call, not a preference.
pub const DEFAULT_SUBSCRIBE_TIMEOUT_SECS: u64 = 15;
/// Filename of the JSON sidecar that persists snooze deadlines across restarts.
/// Lives next to `config.toml` in `app_config_dir`. Single source of truth so
/// the writer (commands.rs) and the loader (lib.rs) cannot drift.
Expand Down
5 changes: 1 addition & 4 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ pub mod openai;
pub mod screenshot;
pub mod settings_commands;
pub mod startup_guard;
pub mod subscribe;
pub mod trace;
pub mod updater;
pub mod warmup;
Expand Down Expand Up @@ -3192,9 +3191,7 @@ pub fn run() {
#[cfg(not(coverage))]
keychain::clear_provider_api_key,
#[cfg(not(coverage))]
keychain::has_provider_api_key,
#[cfg(not(coverage))]
subscribe::subscribe_email
keychain::has_provider_api_key
])
.build(tauri::generate_context!())
.expect("error while building tauri application")
Expand Down
Loading