dotdotdot-cli 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 +21 -0
- package/README.md +707 -0
- package/bin/dotdotdot.js +170 -0
- package/lib/colors.js +244 -0
- package/lib/config.js +224 -0
- package/lib/context.js +265 -0
- package/lib/executor.js +274 -0
- package/lib/index.js +16 -0
- package/lib/llm.js +471 -0
- package/lib/menu.js +100 -0
- package/lib/planner.js +169 -0
- package/lib/postinstall.js +20 -0
- package/lib/renderer.js +145 -0
- package/lib/safety.js +71 -0
- package/lib/session.js +165 -0
- package/lib/tokens.js +291 -0
- package/lib/ui.js +207 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,707 @@
|
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<br>
|
|
3
|
+
<code>...</code>
|
|
4
|
+
<br>
|
|
5
|
+
</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<code>npm install -g dotdotdot</code>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/dotdotdot"><img src="https://img.shields.io/npm/v/dotdotdot?color=blue&label=npm" alt="npm version" /></a>
|
|
13
|
+
<img src="https://img.shields.io/badge/dependencies-0-brightgreen" alt="zero dependencies" />
|
|
14
|
+
<img src="https://img.shields.io/badge/node-%3E%3D18-green" alt="node version" />
|
|
15
|
+
<img src="https://img.shields.io/badge/license-MIT-blue" alt="license" />
|
|
16
|
+
<img src="https://img.shields.io/badge/windows%20%7C%20macos%20%7C%20linux-supported-lightgrey" alt="platforms" />
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
<br>
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
You know what you want. You just don't know the command.
|
|
23
|
+
<br>
|
|
24
|
+
<code>...</code> takes plain English and gives you the exact terminal command for your OS, your shell, your setup. Execute it, copy it, or just look at it. Nothing runs without your say-so.
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
<br>
|
|
28
|
+
|
|
29
|
+
**Quick mode** — say it, get it
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
... show my public IP
|
|
33
|
+
... find all files over 100MB
|
|
34
|
+
... undo my last git commit
|
|
35
|
+
... what's eating my RAM
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
<p align="center">
|
|
39
|
+
<img src="demo/quick.gif" alt="dotdotdot quick mode demo" width="700" />
|
|
40
|
+
</p>
|
|
41
|
+
|
|
42
|
+
**Task mode** — chain steps together
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
... find all .tmp files then delete them
|
|
46
|
+
... check node version, scaffold a new app
|
|
47
|
+
... build the project then deploy to staging
|
|
48
|
+
... ping popular DNS and show the fastest
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
<p align="center">
|
|
52
|
+
<img src="demo/task.gif" alt="dotdotdot task mode demo" width="700" />
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
<br>
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Setup
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install -g dotdotdot
|
|
63
|
+
... -c # add your API key (you need at least one)
|
|
64
|
+
... show my disk usage
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
<details>
|
|
68
|
+
<summary><strong>Or use environment variables</strong></summary>
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
export DOT_OPENROUTER_KEY=sk-or-...
|
|
72
|
+
export DOT_ANTHROPIC_KEY=sk-ant-...
|
|
73
|
+
export DOT_OPENAI_KEY=sk-...
|
|
74
|
+
export DOT_GOOGLE_KEY=AIza...
|
|
75
|
+
export DOT_CUSTOM_KEY=sk-...
|
|
76
|
+
```
|
|
77
|
+
</details>
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Contents
|
|
82
|
+
|
|
83
|
+
- [How It Works](#how-it-works)
|
|
84
|
+
- [Quick Mode](#quick-mode)
|
|
85
|
+
- [Task Mode](#task-mode)
|
|
86
|
+
- [Examples](#examples)
|
|
87
|
+
- [Context Awareness](#context-awareness)
|
|
88
|
+
- [Session Memory](#session-memory)
|
|
89
|
+
- [Safety](#safety)
|
|
90
|
+
- [Providers](#providers)
|
|
91
|
+
- [Token Tracking & Cost](#token-tracking--cost)
|
|
92
|
+
- [Flags](#flags)
|
|
93
|
+
- [Config](#config)
|
|
94
|
+
- [Shell Aliases](#shell-aliases)
|
|
95
|
+
- [Why `...`](#why-)
|
|
96
|
+
- [Project Structure](#project-structure)
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## How It Works
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
you type something in plain english
|
|
104
|
+
↓
|
|
105
|
+
... gathers context ─── OS, shell, cwd, git, tools, project info
|
|
106
|
+
↓
|
|
107
|
+
sends it to your chosen LLM
|
|
108
|
+
↓
|
|
109
|
+
you get back a command (or a multi-step plan)
|
|
110
|
+
↓
|
|
111
|
+
you decide: execute ─ copy ─ skip
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
You always choose. `...` never runs anything behind your back.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Quick Mode
|
|
119
|
+
|
|
120
|
+
One request. One command. The right one.
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
... compress this folder into a zip
|
|
124
|
+
... show running docker containers
|
|
125
|
+
... make a new react project called my-app
|
|
126
|
+
... list all open ports
|
|
127
|
+
... what version of python do I have
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
You pick what happens:
|
|
131
|
+
|
|
132
|
+
| Key | Action |
|
|
133
|
+
|:---:|--------|
|
|
134
|
+
| **e** | Execute the command |
|
|
135
|
+
| **c** | Copy to clipboard |
|
|
136
|
+
| **i** | Insert (print to stdout) |
|
|
137
|
+
| **q** | Cancel |
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Task Mode
|
|
142
|
+
|
|
143
|
+
Chain actions with `-t`, or just use natural words like *"then"*, *"and"*, or commas.
|
|
144
|
+
`...` breaks it into steps, shows you the full plan, and runs them one at a time.
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
... find all .tmp files then delete them
|
|
148
|
+
... read my desktop files and propose a new organization
|
|
149
|
+
... locate project my-site, install deps, then start dev server
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Before anything executes, you see everything. You can:
|
|
153
|
+
- **Run all** at once
|
|
154
|
+
- Go **step by step**
|
|
155
|
+
- **Skip** or **abort** any step
|
|
156
|
+
- **Retry** if something fails
|
|
157
|
+
|
|
158
|
+
Dangerous steps always pause and ask first.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Examples
|
|
163
|
+
|
|
164
|
+
Real terminal sessions. Debug mode (`-d`) shows timing, provider, and token cost.
|
|
165
|
+
|
|
166
|
+
### Quick Mode
|
|
167
|
+
|
|
168
|
+
<table><tr><td><strong>List files in the current directory</strong></td></tr></table>
|
|
169
|
+
|
|
170
|
+
<details>
|
|
171
|
+
<summary>Session</summary>
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
$ ... -d list files
|
|
175
|
+
✔ ctx 688ms | openrouter/google/gemma-4-31b-it | mode: quick
|
|
176
|
+
✔ done
|
|
177
|
+
|
|
178
|
+
❯ Get-ChildItem -Path .
|
|
179
|
+
Lists all files and directories in the current working directory.
|
|
180
|
+
✔ Execute
|
|
181
|
+
|
|
182
|
+
Directory: C:\Users\you\Projects\my-app
|
|
183
|
+
|
|
184
|
+
Mode LastWriteTime Length Name
|
|
185
|
+
---- ------------- ------ ----
|
|
186
|
+
d----- 4/4/2026 4:22 PM src
|
|
187
|
+
d----- 4/4/2026 4:22 PM node_modules
|
|
188
|
+
-a---- 4/4/2026 3:17 PM 1157 package.json
|
|
189
|
+
-a---- 4/4/2026 5:38 PM 14098 README.md
|
|
190
|
+
|
|
191
|
+
tokens: 711 in 43 out (754 total) ~$0.000117
|
|
192
|
+
✔ exit 0
|
|
193
|
+
```
|
|
194
|
+
</details>
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
<table><tr><td><strong>What's my public IP address?</strong></td></tr></table>
|
|
199
|
+
|
|
200
|
+
<details>
|
|
201
|
+
<summary>Session</summary>
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
$ ... -d what is my public ip address
|
|
205
|
+
✔ ctx 209ms | openrouter/google/gemma-4-31b-it | mode: quick
|
|
206
|
+
✔ done
|
|
207
|
+
|
|
208
|
+
❯ (Invoke-RestMethod -Uri 'https://api.ipify.org').Trim()
|
|
209
|
+
Uses Invoke-RestMethod to query the ipify API and retrieve the public IP address.
|
|
210
|
+
✔ Execute
|
|
211
|
+
|
|
212
|
+
203.0.113.42
|
|
213
|
+
|
|
214
|
+
tokens: 715 in 57 out (772 total) ~$0.000123
|
|
215
|
+
✔ exit 0
|
|
216
|
+
```
|
|
217
|
+
</details>
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
<table><tr><td><strong>Show disk usage</strong></td></tr></table>
|
|
222
|
+
|
|
223
|
+
<details>
|
|
224
|
+
<summary>Session</summary>
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
$ ... -d show me the disk usage
|
|
228
|
+
✔ ctx 211ms | openrouter/google/gemma-4-31b-it | mode: quick
|
|
229
|
+
✔ done
|
|
230
|
+
|
|
231
|
+
❯ Get-PSDrive C | Select-Object Name, @{Name='Used(GB)';Expression={...}}, ...
|
|
232
|
+
Retrieves disk usage statistics for the C drive, converting bytes to
|
|
233
|
+
gigabytes and rounding to two decimal places.
|
|
234
|
+
✔ Execute
|
|
235
|
+
|
|
236
|
+
Name Used(GB) Free(GB) Total(GB)
|
|
237
|
+
---- -------- -------- ---------
|
|
238
|
+
C 256.36 218.36 474.72
|
|
239
|
+
|
|
240
|
+
tokens: 714 in 135 out (849 total) ~$0.000154
|
|
241
|
+
✔ exit 0
|
|
242
|
+
```
|
|
243
|
+
</details>
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
### Task Mode
|
|
248
|
+
|
|
249
|
+
<table><tr><td><strong>Find the fastest DNS provider</strong></td></tr></table>
|
|
250
|
+
|
|
251
|
+
<details>
|
|
252
|
+
<summary>Session</summary>
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
$ ... -d -t find the best dns provider by pinging popular ones and show me the fastest
|
|
256
|
+
✔ ctx 213ms | openrouter/google/gemma-4-31b-it | mode: task
|
|
257
|
+
✔ 1 steps planned | tokens: 837 in 256 out (1.1k total) ~$0.000220
|
|
258
|
+
Pings Google, Cloudflare, OpenDNS, and Quad9 to determine the fastest DNS provider.
|
|
259
|
+
|
|
260
|
+
─ 1. Ping DNS providers and sort by response time
|
|
261
|
+
$ $dns = @{ 'Google'='8.8.8.8'; 'Cloudflare'='1.1.1.1'; 'OpenDNS'=...
|
|
262
|
+
|
|
263
|
+
✔ Run
|
|
264
|
+
|
|
265
|
+
▶ 1/1 Ping DNS providers and sort by response time
|
|
266
|
+
$ $dns = @{ 'Google'='8.8.8.8'; 'Cloudflare'='1.1.1.1'; 'OpenDNS'='208.67.222.222'; ...
|
|
267
|
+
|
|
268
|
+
Provider IP AvgResponse
|
|
269
|
+
-------- -- -----------
|
|
270
|
+
Cloudflare 1.1.1.1 20
|
|
271
|
+
Quad9 9.9.9.9 35.5
|
|
272
|
+
OpenDNS 208.67.222.222 47.5
|
|
273
|
+
Google 8.8.8.8 80.5
|
|
274
|
+
|
|
275
|
+
✔ exit 0
|
|
276
|
+
✔ 1/1 done
|
|
277
|
+
```
|
|
278
|
+
</details>
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
<table><tr><td><strong>Check Node version, then scaffold a new project</strong></td></tr></table>
|
|
283
|
+
|
|
284
|
+
<details>
|
|
285
|
+
<summary>Session</summary>
|
|
286
|
+
|
|
287
|
+
```
|
|
288
|
+
$ ... -d check my node version, then create a new folder called test-app and initialize a new npm project in it
|
|
289
|
+
✔ ctx 214ms | openrouter/google/gemma-4-31b-it | mode: task
|
|
290
|
+
✔ 2 steps planned | tokens: 844 in 173 out (1.0k total) ~$0.000187
|
|
291
|
+
Checks the Node.js version and initializes a new npm project in 'test-app'.
|
|
292
|
+
|
|
293
|
+
─ 1. Check Node.js version
|
|
294
|
+
$ node -v
|
|
295
|
+
─ 2. Create folder and initialize npm project
|
|
296
|
+
$ New-Item -ItemType Directory -Name 'test-app'; Set-Location -Path 'test-app'; npm init -y
|
|
297
|
+
|
|
298
|
+
✔ Run
|
|
299
|
+
|
|
300
|
+
▶ 1/2 Check Node.js version
|
|
301
|
+
$ node -v
|
|
302
|
+
v22.0.0
|
|
303
|
+
✔ exit 0
|
|
304
|
+
|
|
305
|
+
▶ 2/2 Create folder and initialize npm project
|
|
306
|
+
$ New-Item -ItemType Directory -Name 'test-app'; Set-Location -Path 'test-app'; npm init -y
|
|
307
|
+
|
|
308
|
+
Wrote to C:\Users\you\Projects\test-app\package.json:
|
|
309
|
+
{
|
|
310
|
+
"name": "test-app",
|
|
311
|
+
"version": "1.0.0",
|
|
312
|
+
...
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
✔ exit 0
|
|
316
|
+
✔ 2/2 done
|
|
317
|
+
```
|
|
318
|
+
</details>
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
<table><tr><td><strong>System diagnostics with Claude — top CPU and memory hogs</strong></td></tr></table>
|
|
323
|
+
|
|
324
|
+
<details>
|
|
325
|
+
<summary>Session</summary>
|
|
326
|
+
|
|
327
|
+
```
|
|
328
|
+
$ ... -d -p claude show me the top 5 processes using the most CPU, then show the top 5 using the most memory
|
|
329
|
+
✔ ctx 209ms | anthropic/claude-haiku-4-5 | mode: task
|
|
330
|
+
✔ 2 steps planned | tokens: 869 in 287 out (1.2k total) ~$0.002304
|
|
331
|
+
Display top 5 CPU-consuming and top 5 memory-consuming processes.
|
|
332
|
+
|
|
333
|
+
─ 1. Get top 5 processes by CPU usage
|
|
334
|
+
$ Get-Process | Sort-Object -Property CPU -Descending | Select-Object -First 5 ...
|
|
335
|
+
─ 2. Get top 5 processes by memory usage
|
|
336
|
+
$ Get-Process | Sort-Object -Property WorkingSet -Descending | Select-Object -First 5 ...
|
|
337
|
+
|
|
338
|
+
✔ Run
|
|
339
|
+
|
|
340
|
+
▶ 1/2 Get top 5 processes by CPU usage
|
|
341
|
+
$ Get-Process | Sort-Object -Property CPU -Descending | Select-Object -First 5 ...
|
|
342
|
+
|
|
343
|
+
Name CPU MemoryMB
|
|
344
|
+
---- --- --------
|
|
345
|
+
Code 2519.78125 1118.19
|
|
346
|
+
Code 1688.984375 191.6
|
|
347
|
+
RemotePCViewerUI 1034.375 54.03
|
|
348
|
+
Code 582.546875 333.34
|
|
349
|
+
Cursor 559.28125 435.31
|
|
350
|
+
|
|
351
|
+
✔ exit 0
|
|
352
|
+
|
|
353
|
+
▶ 2/2 Get top 5 processes by memory usage
|
|
354
|
+
$ Get-Process | Sort-Object -Property WorkingSet -Descending | Select-Object -First 5 ...
|
|
355
|
+
|
|
356
|
+
Name MemoryMB CPU
|
|
357
|
+
---- -------- ---
|
|
358
|
+
Memory Compression 1654.66
|
|
359
|
+
Code 1117.14 2520.31
|
|
360
|
+
kilo 697.46 241.05
|
|
361
|
+
chrome 629.8 339.38
|
|
362
|
+
Cursor 435.32 559.28
|
|
363
|
+
|
|
364
|
+
✔ exit 0
|
|
365
|
+
✔ 2/2 done
|
|
366
|
+
```
|
|
367
|
+
</details>
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
<table><tr><td><strong>Git branch cleanup — find merged branches and delete stale ones</strong></td></tr></table>
|
|
372
|
+
|
|
373
|
+
<details>
|
|
374
|
+
<summary>Session</summary>
|
|
375
|
+
|
|
376
|
+
```
|
|
377
|
+
$ ... -d -p claude find all merged git branches, show them, then delete the stale ones
|
|
378
|
+
✔ ctx 48ms | anthropic/claude-haiku-4-5 | mode: task
|
|
379
|
+
✔ 3 steps planned | tokens: 853 in 397 out (1.3k total) ~$0.002838
|
|
380
|
+
Identify merged branches, list them with last commit info, then clean up.
|
|
381
|
+
|
|
382
|
+
─ 1. List all branches merged into main with last commit date
|
|
383
|
+
$ git for-each-ref --merged=main --format='%(refname:short) %(committerdate:short) ...
|
|
384
|
+
─ 2. Count how many stale branches will be removed
|
|
385
|
+
$ git branch --merged main | Select-String -NotMatch -Pattern '^\s*[*+]|^\s*(main|master)$' ...
|
|
386
|
+
! 3. Delete all merged branches except main/master
|
|
387
|
+
$ git branch --merged main | Select-String -NotMatch -Pattern '^\s*[*+]|^\s*(main|master)$' ...
|
|
388
|
+
|
|
389
|
+
✔ Run
|
|
390
|
+
|
|
391
|
+
▶ 1/3 List all branches merged into main with last commit date
|
|
392
|
+
$ git for-each-ref --merged=main --format='%(refname:short) %(committerdate:short) %(subject)' refs/heads/
|
|
393
|
+
|
|
394
|
+
feature/dark-mode 2024-08-12 feat: add dark mode toggle
|
|
395
|
+
fix/login-redirect 2024-11-03 fix: redirect loop on expired session
|
|
396
|
+
chore/deps-update 2025-01-19 chore: bump dependencies
|
|
397
|
+
feature/user-export 2025-03-28 feat: csv export for user data
|
|
398
|
+
|
|
399
|
+
▶ 2/3 Count how many stale branches will be removed
|
|
400
|
+
$ git branch --merged main | Select-String -NotMatch ... | Measure-Object
|
|
401
|
+
|
|
402
|
+
4
|
|
403
|
+
|
|
404
|
+
▶ 3/3 Delete all merged branches except main/master
|
|
405
|
+
$ git branch --merged main | Select-String -NotMatch ... | ForEach-Object { git branch -d $_.Trim() }
|
|
406
|
+
|
|
407
|
+
Deleted branch feature/dark-mode (was a3f291c).
|
|
408
|
+
Deleted branch fix/login-redirect (was 88d0e4f).
|
|
409
|
+
Deleted branch chore/deps-update (was c41b7a2).
|
|
410
|
+
Deleted branch feature/user-export (was 1f9d3bb).
|
|
411
|
+
|
|
412
|
+
✔ 3/3 done
|
|
413
|
+
```
|
|
414
|
+
</details>
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
<table><tr><td><strong>Check system uptime, then show free memory</strong></td></tr></table>
|
|
419
|
+
|
|
420
|
+
<details>
|
|
421
|
+
<summary>Session</summary>
|
|
422
|
+
|
|
423
|
+
```
|
|
424
|
+
$ ... -d show system uptime, then show free memory in GB
|
|
425
|
+
✔ ctx 208ms | openrouter/google/gemma-4-31b-it | mode: task
|
|
426
|
+
✔ 2 steps planned | tokens: 836 in 173 out (1.0k total) ~$0.000186
|
|
427
|
+
Retrieves system uptime and free physical memory in GB.
|
|
428
|
+
|
|
429
|
+
─ 1. Get system uptime
|
|
430
|
+
$ (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
|
|
431
|
+
─ 2. Get free memory in GB
|
|
432
|
+
$ (Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory / 1MB
|
|
433
|
+
|
|
434
|
+
✔ Run
|
|
435
|
+
|
|
436
|
+
▶ 1/2 Get system uptime
|
|
437
|
+
$ (Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime
|
|
438
|
+
|
|
439
|
+
Days : 0
|
|
440
|
+
Hours : 15
|
|
441
|
+
Minutes : 36
|
|
442
|
+
Seconds : 23
|
|
443
|
+
|
|
444
|
+
✔ exit 0
|
|
445
|
+
|
|
446
|
+
▶ 2/2 Get free memory in GB
|
|
447
|
+
$ (Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory / 1MB
|
|
448
|
+
|
|
449
|
+
3.65
|
|
450
|
+
✔ exit 0
|
|
451
|
+
✔ 2/2 done
|
|
452
|
+
```
|
|
453
|
+
</details>
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## Context Awareness
|
|
458
|
+
|
|
459
|
+
`...` isn't guessing. It knows where it's running.
|
|
460
|
+
|
|
461
|
+
| | What it detects |
|
|
462
|
+
|:---|:---|
|
|
463
|
+
| **OS** | Windows, macOS, Linux — auto-detected |
|
|
464
|
+
| **Shell** | PowerShell, CMD, Bash, Zsh, Fish |
|
|
465
|
+
| **Tools** | node, npm, python, git, docker, etc. |
|
|
466
|
+
| **Project** | package.json, Cargo.toml, pyproject.toml |
|
|
467
|
+
| **Git** | Branch, dirty status, remote |
|
|
468
|
+
| **Environment** | WSL, Docker, SSH, virtualenv |
|
|
469
|
+
| **History** | What you just ran (session memory) |
|
|
470
|
+
|
|
471
|
+
It won't suggest `brew` on Windows or `apt` on macOS. It adapts to you.
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## Session Memory
|
|
476
|
+
|
|
477
|
+
Follow-ups just work.
|
|
478
|
+
|
|
479
|
+
```
|
|
480
|
+
$ ... find all log files
|
|
481
|
+
❯ Get-ChildItem -Recurse -Filter *.log
|
|
482
|
+
|
|
483
|
+
$ ... now delete them
|
|
484
|
+
❯ Get-ChildItem -Recurse -Filter *.log | Remove-Item
|
|
485
|
+
|
|
486
|
+
$ ... actually undo that
|
|
487
|
+
❯ well...
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## Safety
|
|
493
|
+
|
|
494
|
+
Every command is checked for risk **before** it touches anything.
|
|
495
|
+
|
|
496
|
+
| | Risk | What happens |
|
|
497
|
+
|:---:|:---|:---|
|
|
498
|
+
| **low** | Read-only, harmless | Runs freely (auto-exec if enabled) |
|
|
499
|
+
| **medium** | Creates or modifies files | Runs with your OK |
|
|
500
|
+
| **high** | Destructive (`rm -rf`, `sudo`, `dd`, etc.) | Blocked in auto-mode. Always asks. |
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## Providers
|
|
505
|
+
|
|
506
|
+
Pick your LLM. Five providers out of the box. Switch on the fly with `-p`.
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
... -p claude explain this error
|
|
510
|
+
... -p gpt list my largest files
|
|
511
|
+
... -p gemini what does this cron do
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
| Provider | Default Model | Flag |
|
|
515
|
+
|:---------|:--------------|:-----|
|
|
516
|
+
| **OpenRouter** | `gemma-4-26b-a4b-it` | `-p router` |
|
|
517
|
+
| **Anthropic** | `claude-haiku-4-5` | `-p claude` |
|
|
518
|
+
| **OpenAI** | `gpt-4o-mini` | `-p gpt` |
|
|
519
|
+
| **Google Gemini** | `gemini-2.0-flash` | `-p gemini` |
|
|
520
|
+
| **Custom** | *(you set it)* | `-p custom` |
|
|
521
|
+
|
|
522
|
+
**Custom** works with any OpenAI-compatible API — LM Studio, Ollama, vLLM, Together, etc.
|
|
523
|
+
|
|
524
|
+
Change models anytime: `... -c`
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
## Token Tracking & Cost
|
|
529
|
+
|
|
530
|
+
Every request shows token count and cost inline:
|
|
531
|
+
|
|
532
|
+
```
|
|
533
|
+
tokens: 1.3k in 93 out (1.4k total) ~$0.000203
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
Check cumulative usage with `... -u`:
|
|
537
|
+
|
|
538
|
+
```
|
|
539
|
+
● ● ● dotdotdot
|
|
540
|
+
|
|
541
|
+
Totals
|
|
542
|
+
────────────────────────────────────────────
|
|
543
|
+
Requests 9
|
|
544
|
+
Input 12.3k tokens
|
|
545
|
+
Output 763 tokens
|
|
546
|
+
Combined 13.1k tokens
|
|
547
|
+
Cost $0.001696
|
|
548
|
+
|
|
549
|
+
Per Request
|
|
550
|
+
────────────────────────────────────────────
|
|
551
|
+
Input 1.4k
|
|
552
|
+
Output 85
|
|
553
|
+
Combined 1.5k
|
|
554
|
+
Cost $0.000188
|
|
555
|
+
|
|
556
|
+
Recent
|
|
557
|
+
────────────────────────────────────────────
|
|
558
|
+
04/04 18:32 1.1k tokens $0.000220 gemma-4-31b-it
|
|
559
|
+
04/04 18:35 1.0k tokens $0.000187 gemma-4-31b-it
|
|
560
|
+
04/04 18:41 1.2k tokens $0.002304 claude-haiku-4-5
|
|
561
|
+
|
|
562
|
+
tracking since 4/1/2026
|
|
563
|
+
|
|
564
|
+
❯ Exit q
|
|
565
|
+
Reset usage r
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Reset from the menu, or directly: `... --reset-usage`
|
|
569
|
+
|
|
570
|
+
<details>
|
|
571
|
+
<summary><strong>Custom pricing</strong></summary>
|
|
572
|
+
|
|
573
|
+
`...` ships with pricing for all default models. For custom models, set pricing during `... -c`:
|
|
574
|
+
|
|
575
|
+
```
|
|
576
|
+
❯ Price $/1M input enter to skip (current: 0.10):
|
|
577
|
+
❯ Price $/1M output enter to skip (current: 0.10):
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
Custom pricing overrides built-in defaults.
|
|
581
|
+
</details>
|
|
582
|
+
|
|
583
|
+
---
|
|
584
|
+
|
|
585
|
+
## Flags
|
|
586
|
+
|
|
587
|
+
| Flag | What it does |
|
|
588
|
+
|:-----|:-------------|
|
|
589
|
+
| `-t` `--task` | Force task mode |
|
|
590
|
+
| `-p` `--provider` `<name>` | Switch provider for this request |
|
|
591
|
+
| `-u` `--usage` | Token usage and cost stats |
|
|
592
|
+
| `-c` `--config` | View and edit config |
|
|
593
|
+
| `-d` `--debug` | Timing, provider info, debug log path |
|
|
594
|
+
| `-v` `--version` | Print version |
|
|
595
|
+
| `-h` `--help` | Help |
|
|
596
|
+
| `--clear` | Clear session history (fresh start, keeps OS/shell context) |
|
|
597
|
+
| `--reset-usage` | Clear all token tracking data |
|
|
598
|
+
|
|
599
|
+
---
|
|
600
|
+
|
|
601
|
+
## Config
|
|
602
|
+
|
|
603
|
+
Everything lives in `~/.dotdotdot/config.json`:
|
|
604
|
+
|
|
605
|
+
```bash
|
|
606
|
+
... -c # view config, then exit or edit
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
```json
|
|
610
|
+
{
|
|
611
|
+
"provider": "openrouter",
|
|
612
|
+
"autoExec": false,
|
|
613
|
+
"providers": {
|
|
614
|
+
"openrouter": { "apiKey": "sk-or-...", "model": "google/gemma-4-26b-a4b-it" },
|
|
615
|
+
"anthropic": { "apiKey": "sk-ant-...", "model": "claude-haiku-4-5-20251001" },
|
|
616
|
+
"custom": { "apiKey": "sk-...", "model": "my-model", "apiUrl": "https://..." }
|
|
617
|
+
},
|
|
618
|
+
"pricing": {
|
|
619
|
+
"my-model": { "input": 1.00, "output": 3.00 }
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
---
|
|
625
|
+
|
|
626
|
+
## Shell Aliases
|
|
627
|
+
|
|
628
|
+
`...` works as a command in most shells. If yours doesn't like it, use `dotdotdot` instead:
|
|
629
|
+
|
|
630
|
+
<details>
|
|
631
|
+
<summary><strong>PowerShell</strong></summary>
|
|
632
|
+
|
|
633
|
+
```powershell
|
|
634
|
+
# Add to $PROFILE
|
|
635
|
+
function ... { dotdotdot @args }
|
|
636
|
+
```
|
|
637
|
+
</details>
|
|
638
|
+
|
|
639
|
+
<details>
|
|
640
|
+
<summary><strong>Bash / Zsh</strong></summary>
|
|
641
|
+
|
|
642
|
+
```bash
|
|
643
|
+
# Add to ~/.bashrc or ~/.zshrc
|
|
644
|
+
alias ...='dotdotdot'
|
|
645
|
+
```
|
|
646
|
+
</details>
|
|
647
|
+
|
|
648
|
+
<details>
|
|
649
|
+
<summary><strong>Fish</strong></summary>
|
|
650
|
+
|
|
651
|
+
```fish
|
|
652
|
+
# Add to ~/.config/fish/config.fish
|
|
653
|
+
alias ... 'dotdotdot'
|
|
654
|
+
```
|
|
655
|
+
</details>
|
|
656
|
+
|
|
657
|
+
---
|
|
658
|
+
|
|
659
|
+
## Why `...`
|
|
660
|
+
|
|
661
|
+
Nobody should have to memorize:
|
|
662
|
+
|
|
663
|
+
- `tar -xvzf` vs `tar -xvf` — seriously, which one
|
|
664
|
+
- every `docker` flag combo
|
|
665
|
+
- `ffmpeg` syntax — literally impossible
|
|
666
|
+
- PowerShell's `Select-String` vs `grep` vs `findstr`
|
|
667
|
+
- 47 ways to check disk usage across 3 operating systems
|
|
668
|
+
- `find` syntax differences between macOS and Linux
|
|
669
|
+
|
|
670
|
+
**You know what you want. `...` knows how to say it.**
|
|
671
|
+
|
|
672
|
+
---
|
|
673
|
+
|
|
674
|
+
## Project Structure
|
|
675
|
+
|
|
676
|
+
```
|
|
677
|
+
bin/
|
|
678
|
+
dotdotdot.js CLI entry point & arg parser
|
|
679
|
+
lib/
|
|
680
|
+
colors.js Zero-dep ANSI color system
|
|
681
|
+
config.js Multi-provider config management
|
|
682
|
+
context.js OS, shell, git, tools detection
|
|
683
|
+
executor.js Command runner & error recovery
|
|
684
|
+
index.js Public API exports
|
|
685
|
+
llm.js 5 LLM providers, 2 prompt modes
|
|
686
|
+
menu.js Keyboard-driven selection menus
|
|
687
|
+
planner.js Multi-step task orchestrator
|
|
688
|
+
postinstall.js Post-install welcome message
|
|
689
|
+
renderer.js Spinners, boxes, step indicators
|
|
690
|
+
safety.js Command risk analysis engine
|
|
691
|
+
session.js Session history & follow-ups
|
|
692
|
+
tokens.js Token usage tracking & cost estimates
|
|
693
|
+
ui.js Help screen, config view, setup wizard
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
---
|
|
697
|
+
|
|
698
|
+
<p align="center">
|
|
699
|
+
<strong>Zero dependencies.</strong> Nothing to break, nothing to conflict.<br>
|
|
700
|
+
<strong>Cross-platform.</strong> Windows, macOS, Linux — detects your shell and adapts.<br>
|
|
701
|
+
<strong>Transparent.</strong> You always see the command before it runs.<br>
|
|
702
|
+
<strong>Safe.</strong> Dangerous commands are flagged and blocked in auto-mode.
|
|
703
|
+
</p>
|
|
704
|
+
|
|
705
|
+
<p align="center">
|
|
706
|
+
MIT — do whatever you want with it.
|
|
707
|
+
</p>
|