unforget-cli 0.1.0__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.
- unforget_cli-0.1.0/LICENSE +7 -0
- unforget_cli-0.1.0/PKG-INFO +341 -0
- unforget_cli-0.1.0/README.md +308 -0
- unforget_cli-0.1.0/pyproject.toml +58 -0
- unforget_cli-0.1.0/setup.cfg +4 -0
- unforget_cli-0.1.0/tests/test_cli_security.py +231 -0
- unforget_cli-0.1.0/tests/test_config.py +57 -0
- unforget_cli-0.1.0/tests/test_context.py +49 -0
- unforget_cli-0.1.0/tests/test_safety.py +13 -0
- unforget_cli-0.1.0/tests/test_scrubber.py +37 -0
- unforget_cli-0.1.0/tests/test_setup_models.py +148 -0
- unforget_cli-0.1.0/unforget/__init__.py +3 -0
- unforget_cli-0.1.0/unforget/cli.py +604 -0
- unforget_cli-0.1.0/unforget/config.py +229 -0
- unforget_cli-0.1.0/unforget/core/__init__.py +5 -0
- unforget_cli-0.1.0/unforget/core/context.py +165 -0
- unforget_cli-0.1.0/unforget/core/llm.py +67 -0
- unforget_cli-0.1.0/unforget/core/safety.py +20 -0
- unforget_cli-0.1.0/unforget/core/scrubber.py +76 -0
- unforget_cli-0.1.0/unforget/integrations/unforget.bash +180 -0
- unforget_cli-0.1.0/unforget/integrations/unforget.fish +139 -0
- unforget_cli-0.1.0/unforget/integrations/unforget.zsh +157 -0
- unforget_cli-0.1.0/unforget_cli.egg-info/PKG-INFO +341 -0
- unforget_cli-0.1.0/unforget_cli.egg-info/SOURCES.txt +26 -0
- unforget_cli-0.1.0/unforget_cli.egg-info/dependency_links.txt +1 -0
- unforget_cli-0.1.0/unforget_cli.egg-info/entry_points.txt +2 -0
- unforget_cli-0.1.0/unforget_cli.egg-info/requires.txt +9 -0
- unforget_cli-0.1.0/unforget_cli.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2026 Aria Karimi
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: unforget-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A lightweight BYOK shell command suggestion utility.
|
|
5
|
+
Author: Aria Karimi
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/aria-karimi/unforget
|
|
8
|
+
Project-URL: Source, https://github.com/aria-karimi/unforget
|
|
9
|
+
Project-URL: Issues, https://github.com/aria-karimi/unforget/issues
|
|
10
|
+
Keywords: cli,shell,llm,byok,bash,zsh,fish,productivity,security
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: PyYAML>=6.0.1
|
|
26
|
+
Requires-Dist: rich>=13.7.0
|
|
27
|
+
Requires-Dist: litellm>=1.45.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
30
|
+
Provides-Extra: validation
|
|
31
|
+
Requires-Dist: pydantic>=2.8.0; extra == "validation"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# unforget
|
|
35
|
+
|
|
36
|
+
`unforget` is a lightweight BYOK shell assistant that suggests commands using local terminal context (filesystem, shell env, recent output/history) and your chosen LLM provider.
|
|
37
|
+
|
|
38
|
+
> **Distribution:** install from GitHub using `uv`.
|
|
39
|
+
|
|
40
|
+
## Prerequisites
|
|
41
|
+
- Python 3.10+
|
|
42
|
+
- Bash, Zsh, or Fish shell
|
|
43
|
+
- [uv](https://docs.astral.sh/uv/)
|
|
44
|
+
|
|
45
|
+
## Install (GitHub + uv)
|
|
46
|
+
|
|
47
|
+
### Primary install command
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
uv tool install "git+https://github.com/aria-karimi/unforget.git"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Manage install
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
uv tool install --reinstall "git+https://github.com/aria-karimi/unforget.git"
|
|
57
|
+
unforget uninstall # removes config, shell integration, and tool
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Note: Use `unforget uninstall` instead of `uv tool uninstall unforget` directly. The latter only removes the tool but leaves behind local config files (`~/.config/unforget/config.yaml`), shell integration blocks, and logs in your home directory.
|
|
61
|
+
|
|
62
|
+
## Quick start
|
|
63
|
+
|
|
64
|
+
1. Install using `uv` (see commands above).
|
|
65
|
+
2. Run setup:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
unforget setup
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
3. Reload your shell once to load the integration:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
exec "$SHELL"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
4. Request a suggestion:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
unforget ask "find all large files in this folder"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Setup runs an interactive provider/model/key wizard and a connection test. After setup succeeds, it prints reload guidance so the shell integration can be loaded.
|
|
84
|
+
|
|
85
|
+
## Command reference
|
|
86
|
+
|
|
87
|
+
### CLI commands
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
unforget setup # interactive provider/model/key setup + connection test
|
|
91
|
+
unforget ask "..." # request a shell suggestion
|
|
92
|
+
unforget ready # exit 0 only after a successful setup test
|
|
93
|
+
unforget consent # show disclosure and record consent
|
|
94
|
+
unforget cleanup # remove local config, managed shell block, and logs
|
|
95
|
+
unforget uninstall # confirmation prompt, cleanup, uv uninstall, then reload guidance
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Shell integration functions
|
|
99
|
+
|
|
100
|
+
Available after `unforget setup` succeeds and you reload the shell once:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
uf_hotkey_status # show active hotkey bindings in the current shell session
|
|
104
|
+
uf_bind_hotkey # re-bind hotkeys in the current shell session
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Shell behavior
|
|
108
|
+
|
|
109
|
+
Setup installs shell integration snippets in:
|
|
110
|
+
- Bash: `~/.bashrc`
|
|
111
|
+
- Zsh: `~/.zshrc`
|
|
112
|
+
- Fish: `~/.config/fish/config.fish`
|
|
113
|
+
|
|
114
|
+
Hotkey binding:
|
|
115
|
+
- Default: `Alt+u`, fallback: `Esc+u` (configurable via `UNFORGET_HOTKEY` env vars)
|
|
116
|
+
- When pressed, opens an `unforget>` prompt
|
|
117
|
+
- Injects suggestion into current command buffer (does not auto-run)
|
|
118
|
+
|
|
119
|
+
Prerequisites:
|
|
120
|
+
- Must run `unforget setup`, then reload your shell once, before `ask` or hotkey work
|
|
121
|
+
- First hotkey use prompts for consent before any spinner appears
|
|
122
|
+
|
|
123
|
+
During suggestion fetch:
|
|
124
|
+
- A short `unforget: thinking` spinner runs in-widget
|
|
125
|
+
- Press `Ctrl+C` to cancel the request and clear the spinner
|
|
126
|
+
|
|
127
|
+
## BYOK / API integration guide
|
|
128
|
+
|
|
129
|
+
`unforget` is BYOK: you choose provider/model and bring your own key.
|
|
130
|
+
|
|
131
|
+
### Built-in setup providers
|
|
132
|
+
|
|
133
|
+
`unforget setup` currently supports:
|
|
134
|
+
- Google
|
|
135
|
+
- OpenAI
|
|
136
|
+
- Anthropic
|
|
137
|
+
- Local (Ollama)
|
|
138
|
+
|
|
139
|
+
During setup, `unforget` tries to fetch available models for your provider and lets you pick from them.
|
|
140
|
+
If model fetch fails, setup asks for a custom litellm model string.
|
|
141
|
+
|
|
142
|
+
Config is written to:
|
|
143
|
+
|
|
144
|
+
`~/.config/unforget/config.yaml`
|
|
145
|
+
|
|
146
|
+
### API key methods
|
|
147
|
+
|
|
148
|
+
You can store either:
|
|
149
|
+
1. Environment variable name (**recommended**)
|
|
150
|
+
2. Plain-text key in config (fallback)
|
|
151
|
+
|
|
152
|
+
Example env vars:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
export GOOGLE_API_KEY="..."
|
|
156
|
+
export OPENAI_API_KEY="..."
|
|
157
|
+
export ANTHROPIC_API_KEY="..."
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Example config:
|
|
161
|
+
|
|
162
|
+
```yaml
|
|
163
|
+
api:
|
|
164
|
+
provider: "openai"
|
|
165
|
+
model: "openai/gpt-4.1-mini"
|
|
166
|
+
api_key: "OPENAI_API_KEY"
|
|
167
|
+
timeout_seconds: 60
|
|
168
|
+
max_output_tokens: 128
|
|
169
|
+
interface:
|
|
170
|
+
show_timing: false
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Default context profile
|
|
174
|
+
|
|
175
|
+
`unforget` defaults to a balanced context profile:
|
|
176
|
+
- `context.max_files: 30`
|
|
177
|
+
- `context.stdout_lines: 50`
|
|
178
|
+
- `context.history_limit: 10`
|
|
179
|
+
- `context.tier_tokens.vital: 120`
|
|
180
|
+
- `context.tier_tokens.environment: 160`
|
|
181
|
+
- `context.tier_tokens.filesystem: 240`
|
|
182
|
+
- `context.tier_tokens.stdout: 800`
|
|
183
|
+
- `context.tier_tokens.history: 160`
|
|
184
|
+
|
|
185
|
+
### Generic litellm model routing
|
|
186
|
+
|
|
187
|
+
Any `litellm` model string is supported. Examples:
|
|
188
|
+
|
|
189
|
+
```yaml
|
|
190
|
+
api:
|
|
191
|
+
model: "anthropic/claude-3-5-sonnet-latest"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
```yaml
|
|
195
|
+
api:
|
|
196
|
+
model: "gemini/gemini-1.5-flash"
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
```yaml
|
|
200
|
+
api:
|
|
201
|
+
model: "ollama/llama3"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Safety and consent
|
|
205
|
+
|
|
206
|
+
- On first `unforget ask`, you must accept the disclosure prompt before suggestions are returned.
|
|
207
|
+
- AI output is non-deterministic. Review every command before pressing Enter.
|
|
208
|
+
- Sensitive values are scrubbed from context before provider calls.
|
|
209
|
+
|
|
210
|
+
## Troubleshooting
|
|
211
|
+
|
|
212
|
+
### `unforget error: setup required`
|
|
213
|
+
|
|
214
|
+
`ask` and hotkey usage are blocked until setup finishes with a successful provider connection test.
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
unforget setup
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
After setup succeeds, run your command again:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
unforget ask "echo hello"
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### `unforget error: consent required`
|
|
227
|
+
|
|
228
|
+
Accept the disclosure once:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
unforget consent
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Or run `ask` again and accept the prompt:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
unforget ask "echo hello"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### LLM call fails or provider module is missing
|
|
241
|
+
|
|
242
|
+
Reinstall the tool:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
uv tool install --reinstall "git+https://github.com/aria-karimi/unforget.git"
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
If reinstall fails with hardlink/`Operation not permitted`:
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
uv tool install --reinstall --link-mode copy "git+https://github.com/aria-karimi/unforget.git"
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Optional persistent fix:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
export UV_LINK_MODE=copy
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
If provider dependencies are compiled from source on your system, install Rust:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
curl https://sh.rustup.rs -sSf | sh
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Hotkey/integration does not load
|
|
267
|
+
|
|
268
|
+
First, make sure you reloaded your shell after setup:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
exec "$SHELL"
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Then check active bindings:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
uf_hotkey_status
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
If bindings are missing, re-bind in the current shell session:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
uf_bind_hotkey
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
If you changed hotkey environment variables manually, reload once:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
export UNFORGET_HOTKEY="\\eu"
|
|
290
|
+
export UNFORGET_HOTKEY_FALLBACK="\\eu"
|
|
291
|
+
exec "$SHELL"
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
To cancel an in-flight hotkey request while the spinner is visible, press `Ctrl+C`.
|
|
295
|
+
|
|
296
|
+
### `unforget ask` feels slow
|
|
297
|
+
|
|
298
|
+
Use the same model when comparing direct API calls vs `unforget ask`.
|
|
299
|
+
|
|
300
|
+
Quick benchmark:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
bash -lc 'time unforget ask "echo hello"'
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Optional tuning:
|
|
307
|
+
|
|
308
|
+
```yaml
|
|
309
|
+
context:
|
|
310
|
+
max_files: 12
|
|
311
|
+
stdout_lines: 5
|
|
312
|
+
history_limit: 2
|
|
313
|
+
interface:
|
|
314
|
+
show_timing: true
|
|
315
|
+
api:
|
|
316
|
+
max_output_tokens: 96
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Uninstall and remove local config
|
|
320
|
+
|
|
321
|
+
Use the unified uninstall command:
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
unforget uninstall
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Behavior:
|
|
328
|
+
- prompts for confirmation (`y` or `yes` proceeds)
|
|
329
|
+
- removes local config (`~/.config/unforget/config.yaml`)
|
|
330
|
+
- removes managed shell integration blocks from rc files
|
|
331
|
+
- removes stdout logs
|
|
332
|
+
- runs `uv tool uninstall unforget` to remove the tool
|
|
333
|
+
- prints reload guidance on success
|
|
334
|
+
|
|
335
|
+
Manual fallback (if shell integration is not loaded):
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
unforget cleanup
|
|
339
|
+
uv tool uninstall unforget
|
|
340
|
+
exec "$SHELL"
|
|
341
|
+
```
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# unforget
|
|
2
|
+
|
|
3
|
+
`unforget` is a lightweight BYOK shell assistant that suggests commands using local terminal context (filesystem, shell env, recent output/history) and your chosen LLM provider.
|
|
4
|
+
|
|
5
|
+
> **Distribution:** install from GitHub using `uv`.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
- Python 3.10+
|
|
9
|
+
- Bash, Zsh, or Fish shell
|
|
10
|
+
- [uv](https://docs.astral.sh/uv/)
|
|
11
|
+
|
|
12
|
+
## Install (GitHub + uv)
|
|
13
|
+
|
|
14
|
+
### Primary install command
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
uv tool install "git+https://github.com/aria-karimi/unforget.git"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Manage install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv tool install --reinstall "git+https://github.com/aria-karimi/unforget.git"
|
|
24
|
+
unforget uninstall # removes config, shell integration, and tool
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Note: Use `unforget uninstall` instead of `uv tool uninstall unforget` directly. The latter only removes the tool but leaves behind local config files (`~/.config/unforget/config.yaml`), shell integration blocks, and logs in your home directory.
|
|
28
|
+
|
|
29
|
+
## Quick start
|
|
30
|
+
|
|
31
|
+
1. Install using `uv` (see commands above).
|
|
32
|
+
2. Run setup:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
unforget setup
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
3. Reload your shell once to load the integration:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
exec "$SHELL"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
4. Request a suggestion:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
unforget ask "find all large files in this folder"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Setup runs an interactive provider/model/key wizard and a connection test. After setup succeeds, it prints reload guidance so the shell integration can be loaded.
|
|
51
|
+
|
|
52
|
+
## Command reference
|
|
53
|
+
|
|
54
|
+
### CLI commands
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
unforget setup # interactive provider/model/key setup + connection test
|
|
58
|
+
unforget ask "..." # request a shell suggestion
|
|
59
|
+
unforget ready # exit 0 only after a successful setup test
|
|
60
|
+
unforget consent # show disclosure and record consent
|
|
61
|
+
unforget cleanup # remove local config, managed shell block, and logs
|
|
62
|
+
unforget uninstall # confirmation prompt, cleanup, uv uninstall, then reload guidance
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Shell integration functions
|
|
66
|
+
|
|
67
|
+
Available after `unforget setup` succeeds and you reload the shell once:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
uf_hotkey_status # show active hotkey bindings in the current shell session
|
|
71
|
+
uf_bind_hotkey # re-bind hotkeys in the current shell session
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Shell behavior
|
|
75
|
+
|
|
76
|
+
Setup installs shell integration snippets in:
|
|
77
|
+
- Bash: `~/.bashrc`
|
|
78
|
+
- Zsh: `~/.zshrc`
|
|
79
|
+
- Fish: `~/.config/fish/config.fish`
|
|
80
|
+
|
|
81
|
+
Hotkey binding:
|
|
82
|
+
- Default: `Alt+u`, fallback: `Esc+u` (configurable via `UNFORGET_HOTKEY` env vars)
|
|
83
|
+
- When pressed, opens an `unforget>` prompt
|
|
84
|
+
- Injects suggestion into current command buffer (does not auto-run)
|
|
85
|
+
|
|
86
|
+
Prerequisites:
|
|
87
|
+
- Must run `unforget setup`, then reload your shell once, before `ask` or hotkey work
|
|
88
|
+
- First hotkey use prompts for consent before any spinner appears
|
|
89
|
+
|
|
90
|
+
During suggestion fetch:
|
|
91
|
+
- A short `unforget: thinking` spinner runs in-widget
|
|
92
|
+
- Press `Ctrl+C` to cancel the request and clear the spinner
|
|
93
|
+
|
|
94
|
+
## BYOK / API integration guide
|
|
95
|
+
|
|
96
|
+
`unforget` is BYOK: you choose provider/model and bring your own key.
|
|
97
|
+
|
|
98
|
+
### Built-in setup providers
|
|
99
|
+
|
|
100
|
+
`unforget setup` currently supports:
|
|
101
|
+
- Google
|
|
102
|
+
- OpenAI
|
|
103
|
+
- Anthropic
|
|
104
|
+
- Local (Ollama)
|
|
105
|
+
|
|
106
|
+
During setup, `unforget` tries to fetch available models for your provider and lets you pick from them.
|
|
107
|
+
If model fetch fails, setup asks for a custom litellm model string.
|
|
108
|
+
|
|
109
|
+
Config is written to:
|
|
110
|
+
|
|
111
|
+
`~/.config/unforget/config.yaml`
|
|
112
|
+
|
|
113
|
+
### API key methods
|
|
114
|
+
|
|
115
|
+
You can store either:
|
|
116
|
+
1. Environment variable name (**recommended**)
|
|
117
|
+
2. Plain-text key in config (fallback)
|
|
118
|
+
|
|
119
|
+
Example env vars:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
export GOOGLE_API_KEY="..."
|
|
123
|
+
export OPENAI_API_KEY="..."
|
|
124
|
+
export ANTHROPIC_API_KEY="..."
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Example config:
|
|
128
|
+
|
|
129
|
+
```yaml
|
|
130
|
+
api:
|
|
131
|
+
provider: "openai"
|
|
132
|
+
model: "openai/gpt-4.1-mini"
|
|
133
|
+
api_key: "OPENAI_API_KEY"
|
|
134
|
+
timeout_seconds: 60
|
|
135
|
+
max_output_tokens: 128
|
|
136
|
+
interface:
|
|
137
|
+
show_timing: false
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Default context profile
|
|
141
|
+
|
|
142
|
+
`unforget` defaults to a balanced context profile:
|
|
143
|
+
- `context.max_files: 30`
|
|
144
|
+
- `context.stdout_lines: 50`
|
|
145
|
+
- `context.history_limit: 10`
|
|
146
|
+
- `context.tier_tokens.vital: 120`
|
|
147
|
+
- `context.tier_tokens.environment: 160`
|
|
148
|
+
- `context.tier_tokens.filesystem: 240`
|
|
149
|
+
- `context.tier_tokens.stdout: 800`
|
|
150
|
+
- `context.tier_tokens.history: 160`
|
|
151
|
+
|
|
152
|
+
### Generic litellm model routing
|
|
153
|
+
|
|
154
|
+
Any `litellm` model string is supported. Examples:
|
|
155
|
+
|
|
156
|
+
```yaml
|
|
157
|
+
api:
|
|
158
|
+
model: "anthropic/claude-3-5-sonnet-latest"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
```yaml
|
|
162
|
+
api:
|
|
163
|
+
model: "gemini/gemini-1.5-flash"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
167
|
+
api:
|
|
168
|
+
model: "ollama/llama3"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Safety and consent
|
|
172
|
+
|
|
173
|
+
- On first `unforget ask`, you must accept the disclosure prompt before suggestions are returned.
|
|
174
|
+
- AI output is non-deterministic. Review every command before pressing Enter.
|
|
175
|
+
- Sensitive values are scrubbed from context before provider calls.
|
|
176
|
+
|
|
177
|
+
## Troubleshooting
|
|
178
|
+
|
|
179
|
+
### `unforget error: setup required`
|
|
180
|
+
|
|
181
|
+
`ask` and hotkey usage are blocked until setup finishes with a successful provider connection test.
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
unforget setup
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
After setup succeeds, run your command again:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
unforget ask "echo hello"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### `unforget error: consent required`
|
|
194
|
+
|
|
195
|
+
Accept the disclosure once:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
unforget consent
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Or run `ask` again and accept the prompt:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
unforget ask "echo hello"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### LLM call fails or provider module is missing
|
|
208
|
+
|
|
209
|
+
Reinstall the tool:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
uv tool install --reinstall "git+https://github.com/aria-karimi/unforget.git"
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
If reinstall fails with hardlink/`Operation not permitted`:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
uv tool install --reinstall --link-mode copy "git+https://github.com/aria-karimi/unforget.git"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Optional persistent fix:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
export UV_LINK_MODE=copy
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
If provider dependencies are compiled from source on your system, install Rust:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
curl https://sh.rustup.rs -sSf | sh
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Hotkey/integration does not load
|
|
234
|
+
|
|
235
|
+
First, make sure you reloaded your shell after setup:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
exec "$SHELL"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Then check active bindings:
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
uf_hotkey_status
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
If bindings are missing, re-bind in the current shell session:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
uf_bind_hotkey
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
If you changed hotkey environment variables manually, reload once:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
export UNFORGET_HOTKEY="\\eu"
|
|
257
|
+
export UNFORGET_HOTKEY_FALLBACK="\\eu"
|
|
258
|
+
exec "$SHELL"
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
To cancel an in-flight hotkey request while the spinner is visible, press `Ctrl+C`.
|
|
262
|
+
|
|
263
|
+
### `unforget ask` feels slow
|
|
264
|
+
|
|
265
|
+
Use the same model when comparing direct API calls vs `unforget ask`.
|
|
266
|
+
|
|
267
|
+
Quick benchmark:
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
bash -lc 'time unforget ask "echo hello"'
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Optional tuning:
|
|
274
|
+
|
|
275
|
+
```yaml
|
|
276
|
+
context:
|
|
277
|
+
max_files: 12
|
|
278
|
+
stdout_lines: 5
|
|
279
|
+
history_limit: 2
|
|
280
|
+
interface:
|
|
281
|
+
show_timing: true
|
|
282
|
+
api:
|
|
283
|
+
max_output_tokens: 96
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Uninstall and remove local config
|
|
287
|
+
|
|
288
|
+
Use the unified uninstall command:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
unforget uninstall
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Behavior:
|
|
295
|
+
- prompts for confirmation (`y` or `yes` proceeds)
|
|
296
|
+
- removes local config (`~/.config/unforget/config.yaml`)
|
|
297
|
+
- removes managed shell integration blocks from rc files
|
|
298
|
+
- removes stdout logs
|
|
299
|
+
- runs `uv tool uninstall unforget` to remove the tool
|
|
300
|
+
- prints reload guidance on success
|
|
301
|
+
|
|
302
|
+
Manual fallback (if shell integration is not loaded):
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
unforget cleanup
|
|
306
|
+
uv tool uninstall unforget
|
|
307
|
+
exec "$SHELL"
|
|
308
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "unforget-cli"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A lightweight BYOK shell command suggestion utility."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "Aria Karimi" },
|
|
13
|
+
]
|
|
14
|
+
license = { text = "MIT" }
|
|
15
|
+
keywords = ["cli", "shell", "llm", "byok", "bash", "zsh", "fish", "productivity", "security"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Operating System :: POSIX :: Linux",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Software Development :: User Interfaces",
|
|
27
|
+
"Topic :: Utilities",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"PyYAML>=6.0.1",
|
|
31
|
+
"rich>=13.7.0",
|
|
32
|
+
"litellm>=1.45.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://github.com/aria-karimi/unforget"
|
|
37
|
+
Source = "https://github.com/aria-karimi/unforget"
|
|
38
|
+
Issues = "https://github.com/aria-karimi/unforget/issues"
|
|
39
|
+
|
|
40
|
+
[project.optional-dependencies]
|
|
41
|
+
dev = [
|
|
42
|
+
"pytest>=8.0.0",
|
|
43
|
+
]
|
|
44
|
+
validation = [
|
|
45
|
+
"pydantic>=2.8.0",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[project.scripts]
|
|
49
|
+
unforget = "unforget.cli:main"
|
|
50
|
+
|
|
51
|
+
[tool.setuptools]
|
|
52
|
+
packages = ["unforget", "unforget.core"]
|
|
53
|
+
|
|
54
|
+
[tool.setuptools.package-data]
|
|
55
|
+
unforget = ["integrations/*"]
|
|
56
|
+
|
|
57
|
+
[tool.pytest.ini_options]
|
|
58
|
+
testpaths = ["tests"]
|