twokey 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 TwoKey Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,192 @@
1
+ # TwoKey Linux AI Assistant
2
+
3
+ TwoKey is a Linux-first desktop assistant prototype. The goal is a small always-available overlay that will later let users hold two keys, speak, and have the result processed by local or online AI providers without switching to a browser or chat window.
4
+
5
+ Phase 1 implements the foundation only:
6
+
7
+ - Tauri + React project structure
8
+ - Minimal dark overlay pill
9
+ - Dummy modes: Conversation, Edit Text, Dictation, Feedback
10
+ - Clickable mode menu
11
+ - Placeholder settings window
12
+ - Initial architecture and product documentation
13
+ - X11 Phase 2 prototype: hold `Ctrl+Space` to record audio, double tap `Ctrl+Space` to cycle modes
14
+ - Phase 3 prototype: mock STT and external STT command adapter
15
+ - Phase 4 prototype: local Ollama conversation mode with `qwen2.5:3b`
16
+
17
+ No TTS or text injection is implemented yet.
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install twokey
23
+ ```
24
+
25
+ ## Minimal Usage
26
+
27
+ ```ts
28
+ import { getPackageInfo } from "twokey";
29
+
30
+ const info = getPackageInfo();
31
+ console.log(info.name);
32
+ console.log(info.runtimeStatus.waylandGlobalHotkeys);
33
+ ```
34
+
35
+ The package exports runtime status metadata. Current status includes planned/limited areas such as Wayland global hotkeys, TTS, tray menu, SQLite history/audit, and online provider execution until secure API-key storage is implemented.
36
+
37
+ ## Requirements
38
+
39
+ - Linux desktop
40
+ - Node.js 20+
41
+ - npm
42
+ - Rust toolchain with `cargo` for running the Tauri app
43
+ - Tauri Linux system dependencies, for example on Ubuntu/Debian:
44
+
45
+ ```bash
46
+ sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev
47
+ ```
48
+
49
+ This workspace currently has Node/npm available. `cargo` is required before the native app can be started.
50
+
51
+ ## Start Development
52
+
53
+ Install JavaScript dependencies:
54
+
55
+ ```bash
56
+ npm install
57
+ ```
58
+
59
+ Run only the web UI:
60
+
61
+ ```bash
62
+ npm run dev
63
+ ```
64
+
65
+ Run the Linux desktop app:
66
+
67
+ ```bash
68
+ npm run tauri:dev
69
+ ```
70
+
71
+ Phase 2 hotkey behavior on X11:
72
+
73
+ - Hold `Ctrl+Space`: start recording after a short hold delay.
74
+ - Release `Ctrl+Space`: stop recording and save a WAV file under `~/.cache/twokey-ai/recordings/`.
75
+ - Double tap `Ctrl+Space`: cycle to the next mode.
76
+ - Press `Escape`: cancel an active recording.
77
+
78
+ On Wayland, generic global hold-hotkeys are reported as unavailable instead of failing silently.
79
+
80
+ Phase 3 STT behavior:
81
+
82
+ - Default STT provider is a deterministic mock transcriber.
83
+ - To test a real local or custom STT command, set `TWOKEY_STT_COMMAND`.
84
+ - The command must print the transcript to stdout and include `{audio}` as placeholder.
85
+
86
+ Example:
87
+
88
+ ```bash
89
+ TWOKEY_STT_COMMAND='whisper-cli -f {audio} --language de --no-timestamps' npm run tauri:dev
90
+ ```
91
+
92
+ Phase 4 Ollama behavior:
93
+
94
+ - Ollama runs as a systemd service on `127.0.0.1:11434`.
95
+ - Default model: `qwen2.5:3b`.
96
+ - Conversation mode sends finished transcripts to Ollama and displays the answer in the overlay.
97
+ - Override model or endpoint with:
98
+
99
+ ```bash
100
+ TWOKEY_OLLAMA_MODEL='llama3.2:3b' TWOKEY_OLLAMA_URL='http://127.0.0.1:11434' npm run tauri:dev
101
+ ```
102
+
103
+ Phase 5 dictation behavior:
104
+
105
+ - In dictation mode, a finished transcript is pasted at the active cursor position.
106
+ - X11 uses `xclip` or `xsel` plus `xdotool`.
107
+ - Clipboard content is read before insertion and restored afterward when possible.
108
+ - Wayland insertion is deliberately reported as unsupported for now.
109
+
110
+ Phase 6 text editing behavior:
111
+
112
+ - In edit mode, TwoKey reads the current X11 selection with `Ctrl+C`.
113
+ - The spoken instruction and selected text are sent to Ollama.
114
+ - The overlay shows a replacement preview.
115
+ - The selected text is replaced only after pressing `Ersetzen`.
116
+
117
+ Phase 7 settings behavior:
118
+
119
+ - Settings are persisted at `~/.config/twokey-ai/settings.json`.
120
+ - The settings window saves general, hotkey, STT, Ollama, privacy, and update-channel values.
121
+ - Some settings are stored before they are fully applied at runtime; later phases will wire them into the helper/provider layers.
122
+
123
+ Phase 8 provider behavior:
124
+
125
+ - Ollama chat is routed through a provider abstraction.
126
+ - Provider metadata is exposed to the settings UI.
127
+ - OpenAI-compatible and OpenRouter-compatible providers are visible as planned online providers, but disabled until API-key storage and routing are implemented.
128
+
129
+ Phase 9 file context behavior:
130
+
131
+ - File context can be added from the overlay menu.
132
+ - `txt`, `md`, `markdown`, `json`, and `csv` files are read directly.
133
+ - PDFs are extracted with `pdftotext` from `poppler-utils`.
134
+ - Images are registered as context metadata for future vision providers.
135
+ - Extracted text is cached under `~/.cache/twokey-ai/file-contexts/`.
136
+
137
+ Phase 10 packaging behavior:
138
+
139
+ - `npm run tauri:build` creates AppImage and `.deb` bundles.
140
+ - Settings autostart writes `~/.config/autostart/twokey-ai.desktop`.
141
+ - Generated bundles live under `src-tauri/target/release/bundle/`.
142
+
143
+ Phase 11 update behavior:
144
+
145
+ - Settings can check GitHub Releases for a newer version.
146
+ - The app only reports availability; it does not auto-download or auto-install.
147
+
148
+ Current stabilization status:
149
+
150
+ - AppImage and `.deb` builds complete successfully.
151
+ - Ollama runs locally as a systemd service with `qwen2.5:3b`.
152
+ - Production dependency audit reports no vulnerabilities.
153
+ - Wayland limitations, TTS, tray menu, SQLite history, and online provider execution remain future hardening work.
154
+
155
+ Build the frontend:
156
+
157
+ ```bash
158
+ npm run build
159
+ ```
160
+
161
+ Build the desktop bundle:
162
+
163
+ ```bash
164
+ npm run tauri:build
165
+ ```
166
+
167
+ ## Project Layout
168
+
169
+ ```text
170
+ docs/ Product, architecture, security, and status docs
171
+ src/ React frontend
172
+ src-tauri/ Rust/Tauri desktop shell
173
+ ```
174
+
175
+ ## Repository
176
+
177
+ GitHub: https://github.com/meinzeug/twokey
178
+
179
+ ## License
180
+
181
+ MIT. See `LICENSE`.
182
+
183
+ ## Linux Notes
184
+
185
+ TwoKey is designed around Linux conventions:
186
+
187
+ - Config: `~/.config/twokey-ai/`
188
+ - Data: `~/.local/share/twokey-ai/`
189
+ - Cache: `~/.cache/twokey-ai/`
190
+ - Logs/state: `~/.local/state/twokey-ai/`
191
+
192
+ X11 and Wayland will be handled separately in later phases. Phase 1 only detects and displays the current session type.
package/lib/index.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ export type ProviderStatus = "available" | "limited" | "planned-disabled";
2
+ export interface TwokeyRuntimeStatus {
3
+ waylandGlobalHotkeys: ProviderStatus;
4
+ textToSpeech: ProviderStatus;
5
+ trayMenu: ProviderStatus;
6
+ sqliteHistoryAudit: ProviderStatus;
7
+ onlineProviders: ProviderStatus;
8
+ }
9
+ export interface TwokeyPackageInfo {
10
+ name: string;
11
+ repository: string;
12
+ runtimeStatus: TwokeyRuntimeStatus;
13
+ }
14
+ export declare const runtimeStatus: TwokeyRuntimeStatus;
15
+ export declare const packageInfo: TwokeyPackageInfo;
16
+ export declare function getPackageInfo(): TwokeyPackageInfo;
package/lib/index.js ADDED
@@ -0,0 +1,15 @@
1
+ export const runtimeStatus = {
2
+ waylandGlobalHotkeys: "limited",
3
+ textToSpeech: "available",
4
+ trayMenu: "available",
5
+ sqliteHistoryAudit: "available",
6
+ onlineProviders: "available",
7
+ };
8
+ export const packageInfo = {
9
+ name: "twokey",
10
+ repository: "https://github.com/meinzeug/twokey",
11
+ runtimeStatus,
12
+ };
13
+ export function getPackageInfo() {
14
+ return packageInfo;
15
+ }
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "twokey",
3
+ "version": "1.0.0",
4
+ "description": "Linux-first desktop AI assistant built with Tauri, React, and TypeScript.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/meinzeug/twokey.git"
9
+ },
10
+ "bugs": {
11
+ "url": "https://github.com/meinzeug/twokey/issues"
12
+ },
13
+ "homepage": "https://github.com/meinzeug/twokey#readme",
14
+ "type": "module",
15
+ "main": "./lib/index.js",
16
+ "module": "./lib/index.js",
17
+ "types": "./lib/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./lib/index.d.ts",
21
+ "import": "./lib/index.js",
22
+ "default": "./lib/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "lib",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "scripts": {
34
+ "dev": "vite --host 127.0.0.1",
35
+ "typecheck": "tsc --noEmit",
36
+ "build": "npm run build:package && vite build",
37
+ "build:package": "tsc -p tsconfig.package.json",
38
+ "preview": "vite preview --host 127.0.0.1",
39
+ "lint": "npm run typecheck",
40
+ "test": "npm run typecheck",
41
+ "prepublishOnly": "npm run build && npm pack --dry-run",
42
+ "tauri:dev": "tauri dev",
43
+ "tauri:build": "tauri build"
44
+ },
45
+ "dependencies": {
46
+ "@tauri-apps/api": "^2.5.0",
47
+ "lucide-react": "^0.468.0",
48
+ "react": "^18.3.1",
49
+ "react-dom": "^18.3.1"
50
+ },
51
+ "devDependencies": {
52
+ "@tauri-apps/cli": "^2.5.0",
53
+ "@types/react": "^18.3.12",
54
+ "@types/react-dom": "^18.3.1",
55
+ "@vitejs/plugin-react": "^4.3.3",
56
+ "typescript": "^5.6.3",
57
+ "vite": "^5.4.10"
58
+ }
59
+ }