sidekick-agent 0.1.1__tar.gz
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.
- sidekick_agent-0.1.1/.gitignore +15 -0
- sidekick_agent-0.1.1/LICENSE +21 -0
- sidekick_agent-0.1.1/PKG-INFO +250 -0
- sidekick_agent-0.1.1/README.md +188 -0
- sidekick_agent-0.1.1/docs/shot.py +43 -0
- sidekick_agent-0.1.1/docs/tui-chat.svg +184 -0
- sidekick_agent-0.1.1/docs/tui-complete.svg +184 -0
- sidekick_agent-0.1.1/packaging/README.md +62 -0
- sidekick_agent-0.1.1/pyproject.toml +82 -0
- sidekick_agent-0.1.1/src/sk/__init__.py +2 -0
- sidekick_agent-0.1.1/src/sk/__main__.py +4 -0
- sidekick_agent-0.1.1/src/sk/agent.py +649 -0
- sidekick_agent-0.1.1/src/sk/auth.py +78 -0
- sidekick_agent-0.1.1/src/sk/brief.py +80 -0
- sidekick_agent-0.1.1/src/sk/cli.py +1105 -0
- sidekick_agent-0.1.1/src/sk/clip.py +89 -0
- sidekick_agent-0.1.1/src/sk/config.py +156 -0
- sidekick_agent-0.1.1/src/sk/daemon.py +97 -0
- sidekick_agent-0.1.1/src/sk/router.py +39 -0
- sidekick_agent-0.1.1/src/sk/skills.py +179 -0
- sidekick_agent-0.1.1/src/sk/slash.py +287 -0
- sidekick_agent-0.1.1/src/sk/store.py +349 -0
- sidekick_agent-0.1.1/src/sk/tools.py +776 -0
- sidekick_agent-0.1.1/src/sk/tui.py +1036 -0
- sidekick_agent-0.1.1/src/sk/voice.py +288 -0
- sidekick_agent-0.1.1/tests/conftest.py +26 -0
- sidekick_agent-0.1.1/tests/test_auth.py +193 -0
- sidekick_agent-0.1.1/tests/test_brief.py +14 -0
- sidekick_agent-0.1.1/tests/test_clip.py +132 -0
- sidekick_agent-0.1.1/tests/test_daemon.py +32 -0
- sidekick_agent-0.1.1/tests/test_eval.py +371 -0
- sidekick_agent-0.1.1/tests/test_memory.py +42 -0
- sidekick_agent-0.1.1/tests/test_provider.py +110 -0
- sidekick_agent-0.1.1/tests/test_router.py +31 -0
- sidekick_agent-0.1.1/tests/test_sessions.py +90 -0
- sidekick_agent-0.1.1/tests/test_shell.py +31 -0
- sidekick_agent-0.1.1/tests/test_skills.py +62 -0
- sidekick_agent-0.1.1/tests/test_slash.py +80 -0
- sidekick_agent-0.1.1/tests/test_todos.py +31 -0
- sidekick_agent-0.1.1/tests/test_tools.py +137 -0
- sidekick_agent-0.1.1/tests/test_tui.py +863 -0
- sidekick_agent-0.1.1/tests/test_voice.py +310 -0
- sidekick_agent-0.1.1/tests/test_web.py +35 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Irfanwani and Sidekick 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.
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: sidekick-agent
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Local-first terminal companion agent (Ollama-powered)
|
|
5
|
+
Project-URL: Homepage, https://github.com/Faisal01011/sidekick
|
|
6
|
+
Project-URL: Repository, https://github.com/Faisal01011/sidekick
|
|
7
|
+
Project-URL: Issues, https://github.com/Faisal01011/sidekick/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/Faisal01011/sidekick/tree/main/README.md
|
|
9
|
+
Project-URL: Changelog, https://github.com/Faisal01011/sidekick/releases
|
|
10
|
+
Author-email: Irfanwani <irfanwani347@gmail.com>
|
|
11
|
+
License: MIT License
|
|
12
|
+
|
|
13
|
+
Copyright (c) 2026 Irfanwani and Sidekick contributors
|
|
14
|
+
|
|
15
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
16
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
17
|
+
in the Software without restriction, including without limitation the rights
|
|
18
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
19
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
20
|
+
furnished to do so, subject to the following conditions:
|
|
21
|
+
|
|
22
|
+
The above copyright notice and this permission notice shall be included in all
|
|
23
|
+
copies or substantial portions of the Software.
|
|
24
|
+
|
|
25
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
26
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
27
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
28
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
29
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
30
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
31
|
+
SOFTWARE.
|
|
32
|
+
License-File: LICENSE
|
|
33
|
+
Keywords: agent,cli,llm,local-first,ollama,terminal,tui,voice
|
|
34
|
+
Classifier: Development Status :: 3 - Alpha
|
|
35
|
+
Classifier: Environment :: Console
|
|
36
|
+
Classifier: Intended Audience :: Developers
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Operating System :: MacOS
|
|
39
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
40
|
+
Classifier: Programming Language :: Python :: 3
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
44
|
+
Classifier: Topic :: System :: Shells
|
|
45
|
+
Classifier: Topic :: Terminals
|
|
46
|
+
Requires-Python: >=3.12
|
|
47
|
+
Requires-Dist: httpx>=0.27
|
|
48
|
+
Requires-Dist: openai>=1.0
|
|
49
|
+
Requires-Dist: python-dotenv>=1.0
|
|
50
|
+
Requires-Dist: rich>=13.0
|
|
51
|
+
Requires-Dist: textual>=8.0
|
|
52
|
+
Requires-Dist: typer>=0.12
|
|
53
|
+
Provides-Extra: dev
|
|
54
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
55
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
56
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
57
|
+
Provides-Extra: test
|
|
58
|
+
Requires-Dist: pytest>=8.0; extra == 'test'
|
|
59
|
+
Provides-Extra: voice
|
|
60
|
+
Requires-Dist: faster-whisper; extra == 'voice'
|
|
61
|
+
Description-Content-Type: text/markdown
|
|
62
|
+
|
|
63
|
+
<div align="center">
|
|
64
|
+
|
|
65
|
+
# Sidekick
|
|
66
|
+
|
|
67
|
+
**A local-first terminal companion you can talk to — chat, voice, and 17 tools, on your hardware.**
|
|
68
|
+
|
|
69
|
+
[](https://www.python.org/)
|
|
70
|
+
[](https://textual.textualize.io/)
|
|
71
|
+
[](https://ollama.com/)
|
|
72
|
+
[](LICENSE)
|
|
73
|
+
[](tests/)
|
|
74
|
+
|
|
75
|
+
*No cloud account required. No API bill by default. Your files, memory, and voice never leave your machine unless you hand it a key.*
|
|
76
|
+
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
## See it
|
|
80
|
+
|
|
81
|
+
Slash autocomplete with fuzzy filtering, right in the prompt:
|
|
82
|
+
|
|
83
|
+

|
|
84
|
+
|
|
85
|
+
A grounded answer — real tools, real system data, streamed live:
|
|
86
|
+
|
|
87
|
+

|
|
88
|
+
|
|
89
|
+
*Screenshots are real SVG captures of the app running headless (`docs/shot.py`), not mockups.*
|
|
90
|
+
|
|
91
|
+
```console
|
|
92
|
+
$ sk brief
|
|
93
|
+
╭─ sidekick brief Sat 2026-09-19 11:58 ─╮
|
|
94
|
+
│ CPU: AMD Ryzen 7 4800H (16 threads) │
|
|
95
|
+
│ Mem: 7.2Gi · GPU: GTX 1650 4GB │
|
|
96
|
+
│ /dev/nvme0n1p8 133G 117G 8.5G 94% / │
|
|
97
|
+
╰─────────────────────────────────────────╯
|
|
98
|
+
│ ! disk 94% full — clean ~/Downloads… │
|
|
99
|
+
|
|
100
|
+
$ sk run "what is the ideal llm i can run on my device"
|
|
101
|
+
• qwen3:4b (2.5 GB): fits comfortably in your 4096 MiB VRAM.
|
|
102
|
+
• llama3.2:3b (2.0 GB): another good option.
|
|
103
|
+
|
|
104
|
+
$ sk talk
|
|
105
|
+
[Enter] to record, [Enter] to stop. /quit exits.
|
|
106
|
+
heard> what files are in the sidekick repo
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Why sidekick
|
|
110
|
+
|
|
111
|
+
| | Sidekick | Typical cloud agent |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| Runs fully offline (Ollama) | ✅ | ❌ |
|
|
114
|
+
| Voice input, transcribed on your CPU | ✅ | ❌ |
|
|
115
|
+
| Copy/paste that works in-terminal | ✅ drag-select, `ctrl+y`, `/copy` | varies |
|
|
116
|
+
| Answers grounded in *your* system, not guessed | ✅ deterministic grounding | prompt-only |
|
|
117
|
+
| Skills you can read (`SKILL.md`, incl. superpowers) | ✅ | varies |
|
|
118
|
+
| 167-test suite incl. prompt-regression evals | ✅ | rare |
|
|
119
|
+
|
|
120
|
+
## Quickstart
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
uv tool install sidekick-agent[voice] # global `sk`, STT included
|
|
124
|
+
sk doctor # checks provider + model
|
|
125
|
+
sk tui # fullscreen chat — start here
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
No clone, no build — installs straight from PyPI. Requires Python 3.12+.
|
|
129
|
+
Without `[voice]` you get everything except Talk/mic (installs on first use instead). Local path needs Ollama (`ollama serve`, pull `qwen2.5-coder:7b` for smarts or `llama3.2:3b` for speed).
|
|
130
|
+
|
|
131
|
+
## Install
|
|
132
|
+
|
|
133
|
+
| Channel | Command |
|
|
134
|
+
|---|---|
|
|
135
|
+
| PyPI / uv | `uv tool install sidekick-agent[voice]` |
|
|
136
|
+
| PyPI / pipx | `pipx install sidekick-agent[voice]` |
|
|
137
|
+
| PyPI / pip | `pip install sidekick-agent[voice]` |
|
|
138
|
+
| AUR (Arch) | `yay -S python-sidekick-agent` |
|
|
139
|
+
| conda-forge | `conda install -c conda-forge sidekick-agent` *(feedstock lives in a separate repo)* |
|
|
140
|
+
|
|
141
|
+
The published name is **`sidekick-agent`** (the `sidekick` name is taken on
|
|
142
|
+
PyPI); the command stays `sk`. Version is a single source of truth in
|
|
143
|
+
`src/sk/__init__.py`. Publishing is automatic and credential-free: when a PR
|
|
144
|
+
is merged to `main` of the canonical repo
|
|
145
|
+
[`Faisal01011/sidekick`](https://github.com/Faisal01011/sidekick) with a bumped
|
|
146
|
+
`__version__`, GitHub Actions trusted-publishes to PyPI and opens a GitHub
|
|
147
|
+
Release (forks can never publish) — details in [`packaging/README.md`](packaging/README.md).
|
|
148
|
+
|
|
149
|
+
**From source (dev):**
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
git clone https://github.com/Faisal01011/sidekick && cd sidekick
|
|
153
|
+
uv tool install -e ".[voice]" # editable dev install; STT included
|
|
154
|
+
sk doctor
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Chat
|
|
158
|
+
|
|
159
|
+
One input, two surfaces — REPL and fullscreen TUI share every command:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
sk chat # type /help once you're in
|
|
163
|
+
sk tui # same, fullscreen with streaming + themes
|
|
164
|
+
sk tui --model fast
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Type `/` and an autocomplete popup filters all 20+ commands — Enter completes, Tab too, Esc dismisses, ↑/↓ navigates. `F1` opens a generated cheatsheet (keys + commands, built from the same tables as the dispatcher, so it can't rot).
|
|
168
|
+
|
|
169
|
+
TUI keys: **Enter** sends · **ctrl+j**/**alt+enter** newline · **↑/↓** history · **ctrl+y** copies · **ctrl+t** push-to-talk · **ctrl+b/f** scroll · **F1** help. Answers stream live with role colors; the footer shows model · session · last-turn time/tokens.
|
|
170
|
+
|
|
171
|
+
## Voice
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
sk talk [-d SECS] [--stt-model base] [--device hw:2,0] # Enter records, Enter stops
|
|
175
|
+
sk mic-test # peak dB + silent/quiet/good verdict
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Capture via the OS-native recorder (arecord/ALSA on Linux, sox/ffmpeg on macOS), transcription via local faster-whisper int8, transcript lands editable in the prompt. In the TUI, `ctrl+t` (or the mic pill) does the same. Voice never leaves your machine; recordings are temp files, deleted after each take.
|
|
179
|
+
|
|
180
|
+
## Providers (BYO key)
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
sk connect # pick provider → paste key (hidden) → pick model → ping. Done.
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
One guided flow: numbered provider list (local ones skip keys), live validation *before* anything saves, curated model list (TTS/image junk filtered, recommended pre-highlighted, Enter accepts), and a 5-token ping instead of a full agent turn. Advanced paths still work: `sk auth add/list/status/remove`, `sk model`, `sk setup` (connect + hook), `sk config --provider openai --api-key sk-...`, `/provider groq` inside chat.
|
|
187
|
+
|
|
188
|
+
Presets: `ollama|openai|groq|together|deepseek|openrouter|google|lmstudio|custom`. Any OpenAI-compatible endpoint works via `--provider custom --base-url https://... --api-key ...`. Preferred: `SIDEKICK_API_KEY` env (never touches disk); file keys are chmod 600 and masked in `--show`. Note: true Anthropic-native API isn't wrapped — reach Claude via OpenRouter.
|
|
189
|
+
|
|
190
|
+
## Command reference
|
|
191
|
+
|
|
192
|
+
| Command | What |
|
|
193
|
+
|---|---|
|
|
194
|
+
| `sk chat [--continue]` / `sk tui [--continue]` | Interactive chat, fresh session each launch |
|
|
195
|
+
| `/sessions`, `/resume <n>`, `/sessions delete <n>` | List, switch, delete past sessions |
|
|
196
|
+
| `sk run "task" [--yes] [--model auto\|fast\|smart\|name]` | Single-shot agent run (auto-router picks the model) |
|
|
197
|
+
| `sk brief [-p PATH] [--smart]` | Morning digest: system + git + todos + memories, instant without LLM |
|
|
198
|
+
| `sk remember/recall/memories/forget` | Long-term memory (FTS5 search, auto-injected) |
|
|
199
|
+
| `sk todo add/list/done/clear` | Todos |
|
|
200
|
+
| `sk history` / `sk oops` | Shell log / explain last failure |
|
|
201
|
+
| `sk hook-install [--write]` | Bash/zsh logging hook |
|
|
202
|
+
| `sk skills` / `sk skills-install superpowers` / `sk daemon [--once]` | Skill packs (obra/superpowers) / background watcher |
|
|
203
|
+
| `sk doctor` / `sk models` / `sk config` / `sk version` | Health / models / settings / build |
|
|
204
|
+
|
|
205
|
+
Packs use the `SKILL.md` frontmatter format. The prompt carries a relevance-ranked index; the agent loads full instructions on demand via the `skill` tool. `fast`/`smart` resolve per provider (Ollama: llama3.2:3b/qwen2.5-coder:7b, Groq: gpt-oss-20b/120b).
|
|
206
|
+
|
|
207
|
+
## Architecture
|
|
208
|
+
|
|
209
|
+
```mermaid
|
|
210
|
+
flowchart TB
|
|
211
|
+
U([you]) --> CLI[sk chat / sk run]
|
|
212
|
+
U --> TUI[sk tui: autocomplete, streaming, mic pill]
|
|
213
|
+
U --> VOICE[sk talk: arecord + faster-whisper]
|
|
214
|
+
CLI --> SLASH[slash.py: /commands, no LLM]
|
|
215
|
+
TUI --> SLASH
|
|
216
|
+
VOICE --> AGENT
|
|
217
|
+
CLI --> AGENT[agent.py: stream → tools → synthesize]
|
|
218
|
+
TUI --> AGENT
|
|
219
|
+
AGENT --> GROUND[deterministic grounding: ~/paths, URLs,\nsysinfo — injected before the model sees the prompt]
|
|
220
|
+
AGENT --> TOOLS[tools.py: 17 tools, allowlists,\nhard-blocks, SSRF guard]
|
|
221
|
+
AGENT --> MEM[(store.py: history, memories FTS5,\ntodos, shell log)]
|
|
222
|
+
AGENT --> SKILLS[skills: relevance-ranked SKILL.md index]
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Design bets that paid off: **deterministic grounding beats prompt instructions** (small models ignore rules but can't argue with injected facts), **text-JSON fallback** (coders emit tools as text over the OpenAI endpoint), **FTS5 over vectors** (zero deps, instant, no embedding server on a 4GB box).
|
|
226
|
+
|
|
227
|
+
## Safety
|
|
228
|
+
|
|
229
|
+
Reads auto-run. Writes, deletes, and general shell need approval (inline `[y/N]` in TUI, prompt in CLI), HOME/`/tmp` only, ≤100KB, never `~/.ssh`, `~/.gnupg`, `/etc`, `/usr`. `shell` hard-refuses `rm -rf /`, `mkfs`, `dd` to devices, fork bombs even with approval. `read_url`/`web_search` block localhost/private IPs. API keys chmod 600, masked in output.
|
|
230
|
+
|
|
231
|
+
## Tests
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
uv run --python 3.12 --with ".[test]" pytest tests -q # 167 passed: unit + regression + Textual pilot, no Ollama needed
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The eval harness (`tests/test_eval.py`) locks in every past quality bug as an offline regression test. A suite-wide fixture guarantees tests never touch your live `~/.sidekick/`.
|
|
238
|
+
|
|
239
|
+
## Config
|
|
240
|
+
|
|
241
|
+
`~/.sidekick/config.toml` (`provider`, `model`, `base_url` override, `api_key`, …). Env overrides: `SIDEKICK_PROVIDER`, `SIDEKICK_MODEL`, `SIDEKICK_BASE_URL`, `SIDEKICK_API_KEY`. Data stays home: `history.db`, `skills/`, `nudges.log`, `input_history`, `tui-errors.log`.
|
|
242
|
+
|
|
243
|
+
## Roadmap
|
|
244
|
+
|
|
245
|
+
- [x] Voice input (local STT) · [x] Skills (superpowers) · [x] Sessions · [x] Providers/BYOK · [x] Eval harness
|
|
246
|
+
- [ ] Spoken replies (offline TTS) · [ ] Native Anthropic provider · [ ] Daemon as a systemd service · [ ] `sk skills search`
|
|
247
|
+
|
|
248
|
+
## License
|
|
249
|
+
|
|
250
|
+
MIT — do what you want, shout-outs appreciated.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Sidekick
|
|
4
|
+
|
|
5
|
+
**A local-first terminal companion you can talk to — chat, voice, and 17 tools, on your hardware.**
|
|
6
|
+
|
|
7
|
+
[](https://www.python.org/)
|
|
8
|
+
[](https://textual.textualize.io/)
|
|
9
|
+
[](https://ollama.com/)
|
|
10
|
+
[](LICENSE)
|
|
11
|
+
[](tests/)
|
|
12
|
+
|
|
13
|
+
*No cloud account required. No API bill by default. Your files, memory, and voice never leave your machine unless you hand it a key.*
|
|
14
|
+
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
## See it
|
|
18
|
+
|
|
19
|
+
Slash autocomplete with fuzzy filtering, right in the prompt:
|
|
20
|
+
|
|
21
|
+

|
|
22
|
+
|
|
23
|
+
A grounded answer — real tools, real system data, streamed live:
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
*Screenshots are real SVG captures of the app running headless (`docs/shot.py`), not mockups.*
|
|
28
|
+
|
|
29
|
+
```console
|
|
30
|
+
$ sk brief
|
|
31
|
+
╭─ sidekick brief Sat 2026-09-19 11:58 ─╮
|
|
32
|
+
│ CPU: AMD Ryzen 7 4800H (16 threads) │
|
|
33
|
+
│ Mem: 7.2Gi · GPU: GTX 1650 4GB │
|
|
34
|
+
│ /dev/nvme0n1p8 133G 117G 8.5G 94% / │
|
|
35
|
+
╰─────────────────────────────────────────╯
|
|
36
|
+
│ ! disk 94% full — clean ~/Downloads… │
|
|
37
|
+
|
|
38
|
+
$ sk run "what is the ideal llm i can run on my device"
|
|
39
|
+
• qwen3:4b (2.5 GB): fits comfortably in your 4096 MiB VRAM.
|
|
40
|
+
• llama3.2:3b (2.0 GB): another good option.
|
|
41
|
+
|
|
42
|
+
$ sk talk
|
|
43
|
+
[Enter] to record, [Enter] to stop. /quit exits.
|
|
44
|
+
heard> what files are in the sidekick repo
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Why sidekick
|
|
48
|
+
|
|
49
|
+
| | Sidekick | Typical cloud agent |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| Runs fully offline (Ollama) | ✅ | ❌ |
|
|
52
|
+
| Voice input, transcribed on your CPU | ✅ | ❌ |
|
|
53
|
+
| Copy/paste that works in-terminal | ✅ drag-select, `ctrl+y`, `/copy` | varies |
|
|
54
|
+
| Answers grounded in *your* system, not guessed | ✅ deterministic grounding | prompt-only |
|
|
55
|
+
| Skills you can read (`SKILL.md`, incl. superpowers) | ✅ | varies |
|
|
56
|
+
| 167-test suite incl. prompt-regression evals | ✅ | rare |
|
|
57
|
+
|
|
58
|
+
## Quickstart
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uv tool install sidekick-agent[voice] # global `sk`, STT included
|
|
62
|
+
sk doctor # checks provider + model
|
|
63
|
+
sk tui # fullscreen chat — start here
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
No clone, no build — installs straight from PyPI. Requires Python 3.12+.
|
|
67
|
+
Without `[voice]` you get everything except Talk/mic (installs on first use instead). Local path needs Ollama (`ollama serve`, pull `qwen2.5-coder:7b` for smarts or `llama3.2:3b` for speed).
|
|
68
|
+
|
|
69
|
+
## Install
|
|
70
|
+
|
|
71
|
+
| Channel | Command |
|
|
72
|
+
|---|---|
|
|
73
|
+
| PyPI / uv | `uv tool install sidekick-agent[voice]` |
|
|
74
|
+
| PyPI / pipx | `pipx install sidekick-agent[voice]` |
|
|
75
|
+
| PyPI / pip | `pip install sidekick-agent[voice]` |
|
|
76
|
+
| AUR (Arch) | `yay -S python-sidekick-agent` |
|
|
77
|
+
| conda-forge | `conda install -c conda-forge sidekick-agent` *(feedstock lives in a separate repo)* |
|
|
78
|
+
|
|
79
|
+
The published name is **`sidekick-agent`** (the `sidekick` name is taken on
|
|
80
|
+
PyPI); the command stays `sk`. Version is a single source of truth in
|
|
81
|
+
`src/sk/__init__.py`. Publishing is automatic and credential-free: when a PR
|
|
82
|
+
is merged to `main` of the canonical repo
|
|
83
|
+
[`Faisal01011/sidekick`](https://github.com/Faisal01011/sidekick) with a bumped
|
|
84
|
+
`__version__`, GitHub Actions trusted-publishes to PyPI and opens a GitHub
|
|
85
|
+
Release (forks can never publish) — details in [`packaging/README.md`](packaging/README.md).
|
|
86
|
+
|
|
87
|
+
**From source (dev):**
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
git clone https://github.com/Faisal01011/sidekick && cd sidekick
|
|
91
|
+
uv tool install -e ".[voice]" # editable dev install; STT included
|
|
92
|
+
sk doctor
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Chat
|
|
96
|
+
|
|
97
|
+
One input, two surfaces — REPL and fullscreen TUI share every command:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
sk chat # type /help once you're in
|
|
101
|
+
sk tui # same, fullscreen with streaming + themes
|
|
102
|
+
sk tui --model fast
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Type `/` and an autocomplete popup filters all 20+ commands — Enter completes, Tab too, Esc dismisses, ↑/↓ navigates. `F1` opens a generated cheatsheet (keys + commands, built from the same tables as the dispatcher, so it can't rot).
|
|
106
|
+
|
|
107
|
+
TUI keys: **Enter** sends · **ctrl+j**/**alt+enter** newline · **↑/↓** history · **ctrl+y** copies · **ctrl+t** push-to-talk · **ctrl+b/f** scroll · **F1** help. Answers stream live with role colors; the footer shows model · session · last-turn time/tokens.
|
|
108
|
+
|
|
109
|
+
## Voice
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
sk talk [-d SECS] [--stt-model base] [--device hw:2,0] # Enter records, Enter stops
|
|
113
|
+
sk mic-test # peak dB + silent/quiet/good verdict
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Capture via the OS-native recorder (arecord/ALSA on Linux, sox/ffmpeg on macOS), transcription via local faster-whisper int8, transcript lands editable in the prompt. In the TUI, `ctrl+t` (or the mic pill) does the same. Voice never leaves your machine; recordings are temp files, deleted after each take.
|
|
117
|
+
|
|
118
|
+
## Providers (BYO key)
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
sk connect # pick provider → paste key (hidden) → pick model → ping. Done.
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
One guided flow: numbered provider list (local ones skip keys), live validation *before* anything saves, curated model list (TTS/image junk filtered, recommended pre-highlighted, Enter accepts), and a 5-token ping instead of a full agent turn. Advanced paths still work: `sk auth add/list/status/remove`, `sk model`, `sk setup` (connect + hook), `sk config --provider openai --api-key sk-...`, `/provider groq` inside chat.
|
|
125
|
+
|
|
126
|
+
Presets: `ollama|openai|groq|together|deepseek|openrouter|google|lmstudio|custom`. Any OpenAI-compatible endpoint works via `--provider custom --base-url https://... --api-key ...`. Preferred: `SIDEKICK_API_KEY` env (never touches disk); file keys are chmod 600 and masked in `--show`. Note: true Anthropic-native API isn't wrapped — reach Claude via OpenRouter.
|
|
127
|
+
|
|
128
|
+
## Command reference
|
|
129
|
+
|
|
130
|
+
| Command | What |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `sk chat [--continue]` / `sk tui [--continue]` | Interactive chat, fresh session each launch |
|
|
133
|
+
| `/sessions`, `/resume <n>`, `/sessions delete <n>` | List, switch, delete past sessions |
|
|
134
|
+
| `sk run "task" [--yes] [--model auto\|fast\|smart\|name]` | Single-shot agent run (auto-router picks the model) |
|
|
135
|
+
| `sk brief [-p PATH] [--smart]` | Morning digest: system + git + todos + memories, instant without LLM |
|
|
136
|
+
| `sk remember/recall/memories/forget` | Long-term memory (FTS5 search, auto-injected) |
|
|
137
|
+
| `sk todo add/list/done/clear` | Todos |
|
|
138
|
+
| `sk history` / `sk oops` | Shell log / explain last failure |
|
|
139
|
+
| `sk hook-install [--write]` | Bash/zsh logging hook |
|
|
140
|
+
| `sk skills` / `sk skills-install superpowers` / `sk daemon [--once]` | Skill packs (obra/superpowers) / background watcher |
|
|
141
|
+
| `sk doctor` / `sk models` / `sk config` / `sk version` | Health / models / settings / build |
|
|
142
|
+
|
|
143
|
+
Packs use the `SKILL.md` frontmatter format. The prompt carries a relevance-ranked index; the agent loads full instructions on demand via the `skill` tool. `fast`/`smart` resolve per provider (Ollama: llama3.2:3b/qwen2.5-coder:7b, Groq: gpt-oss-20b/120b).
|
|
144
|
+
|
|
145
|
+
## Architecture
|
|
146
|
+
|
|
147
|
+
```mermaid
|
|
148
|
+
flowchart TB
|
|
149
|
+
U([you]) --> CLI[sk chat / sk run]
|
|
150
|
+
U --> TUI[sk tui: autocomplete, streaming, mic pill]
|
|
151
|
+
U --> VOICE[sk talk: arecord + faster-whisper]
|
|
152
|
+
CLI --> SLASH[slash.py: /commands, no LLM]
|
|
153
|
+
TUI --> SLASH
|
|
154
|
+
VOICE --> AGENT
|
|
155
|
+
CLI --> AGENT[agent.py: stream → tools → synthesize]
|
|
156
|
+
TUI --> AGENT
|
|
157
|
+
AGENT --> GROUND[deterministic grounding: ~/paths, URLs,\nsysinfo — injected before the model sees the prompt]
|
|
158
|
+
AGENT --> TOOLS[tools.py: 17 tools, allowlists,\nhard-blocks, SSRF guard]
|
|
159
|
+
AGENT --> MEM[(store.py: history, memories FTS5,\ntodos, shell log)]
|
|
160
|
+
AGENT --> SKILLS[skills: relevance-ranked SKILL.md index]
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Design bets that paid off: **deterministic grounding beats prompt instructions** (small models ignore rules but can't argue with injected facts), **text-JSON fallback** (coders emit tools as text over the OpenAI endpoint), **FTS5 over vectors** (zero deps, instant, no embedding server on a 4GB box).
|
|
164
|
+
|
|
165
|
+
## Safety
|
|
166
|
+
|
|
167
|
+
Reads auto-run. Writes, deletes, and general shell need approval (inline `[y/N]` in TUI, prompt in CLI), HOME/`/tmp` only, ≤100KB, never `~/.ssh`, `~/.gnupg`, `/etc`, `/usr`. `shell` hard-refuses `rm -rf /`, `mkfs`, `dd` to devices, fork bombs even with approval. `read_url`/`web_search` block localhost/private IPs. API keys chmod 600, masked in output.
|
|
168
|
+
|
|
169
|
+
## Tests
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
uv run --python 3.12 --with ".[test]" pytest tests -q # 167 passed: unit + regression + Textual pilot, no Ollama needed
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The eval harness (`tests/test_eval.py`) locks in every past quality bug as an offline regression test. A suite-wide fixture guarantees tests never touch your live `~/.sidekick/`.
|
|
176
|
+
|
|
177
|
+
## Config
|
|
178
|
+
|
|
179
|
+
`~/.sidekick/config.toml` (`provider`, `model`, `base_url` override, `api_key`, …). Env overrides: `SIDEKICK_PROVIDER`, `SIDEKICK_MODEL`, `SIDEKICK_BASE_URL`, `SIDEKICK_API_KEY`. Data stays home: `history.db`, `skills/`, `nudges.log`, `input_history`, `tui-errors.log`.
|
|
180
|
+
|
|
181
|
+
## Roadmap
|
|
182
|
+
|
|
183
|
+
- [x] Voice input (local STT) · [x] Skills (superpowers) · [x] Sessions · [x] Providers/BYOK · [x] Eval harness
|
|
184
|
+
- [ ] Spoken replies (offline TTS) · [ ] Native Anthropic provider · [ ] Daemon as a systemd service · [ ] `sk skills search`
|
|
185
|
+
|
|
186
|
+
## License
|
|
187
|
+
|
|
188
|
+
MIT — do what you want, shout-outs appreciated.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Capture real TUI screenshots headless for the README. No LLM, no network."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
|
|
5
|
+
from sk.tui import SidekickTUI
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
async def main() -> None:
|
|
9
|
+
# 1. chat view with content + slash popup open
|
|
10
|
+
app = SidekickTUI()
|
|
11
|
+
async with app.run_test(size=(100, 30)) as pilot:
|
|
12
|
+
log = app.query_one("#chat-log")
|
|
13
|
+
log.write("sidekick online. Enter sends · ctrl+j newline · ↑ history · ctrl+t to talk.")
|
|
14
|
+
from sk.tui import _role
|
|
15
|
+
|
|
16
|
+
_role(log, "you", "what files are in ~/sidekick?")
|
|
17
|
+
_role(log, "tool", "○ tool: list_dir {'path': '~/sidekick'}")
|
|
18
|
+
_role(log, "sidekick", "")
|
|
19
|
+
log.write("**~/sidekick**: `pyproject.toml`, `src/sk/`, `tests/`, `README.md`")
|
|
20
|
+
area = app.query_one("#chat-input")
|
|
21
|
+
area.focus()
|
|
22
|
+
area.text = "/mo"
|
|
23
|
+
await pilot.pause()
|
|
24
|
+
await pilot.pause()
|
|
25
|
+
app.save_screenshot("docs/tui-complete.svg")
|
|
26
|
+
print("shot 1: complete popup")
|
|
27
|
+
|
|
28
|
+
# 2. rich conversation: tools + answer + stats line
|
|
29
|
+
area.text = ""
|
|
30
|
+
await pilot.pause()
|
|
31
|
+
from sk.tui import _role
|
|
32
|
+
|
|
33
|
+
_role(log, "you", "summarize disk usage in ~/")
|
|
34
|
+
_role(log, "tool", "○ tool: exec {'cmd': 'df -h'}")
|
|
35
|
+
_role(log, "sidekick", "")
|
|
36
|
+
log.write("/dev/nvme0n1p8 133G 117G 8.5G 94% /")
|
|
37
|
+
await pilot.pause()
|
|
38
|
+
await pilot.pause()
|
|
39
|
+
app.save_screenshot("docs/tui-chat.svg")
|
|
40
|
+
print("shot 2: conversation")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
asyncio.run(main())
|