@hemansubedi/aether-ai 1.0.0 → 1.0.1
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/README.md +41 -28
- package/dist/index.js +52 -4
- package/package.json +44 -34
- package/src/index.ts +80 -34
package/README.md
CHANGED
|
@@ -43,6 +43,36 @@ Aether is a TypeScript CLI agent that turns your terminal into an autonomous cod
|
|
|
43
43
|
|
|
44
44
|
Aether installs like KiloCode and runs like Claude Code. One line, no setup beyond Node.js 20+.
|
|
45
45
|
|
|
46
|
+
### CLI flags
|
|
47
|
+
|
|
48
|
+
`aether-ai` understands standard flags before the prompt:
|
|
49
|
+
|
|
50
|
+
| Flag | Description |
|
|
51
|
+
|------|-------------|
|
|
52
|
+
| `-v`, `--version` | Print the version (`aether-ai 1.0.0`) and exit |
|
|
53
|
+
| `-h`, `--help` | Print the help text (same as `/help`) and exit |
|
|
54
|
+
| `--plan` | Start in plan mode (step-by-step approval) |
|
|
55
|
+
| `--yolo` | Start in yolo mode (autonomous execution) |
|
|
56
|
+
| `--no-stream` | Disable streaming output in one-shot mode |
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
$ aether-ai --version
|
|
60
|
+
aether-ai 1.0.0
|
|
61
|
+
|
|
62
|
+
$ aether-ai --help
|
|
63
|
+
Aether - the free, unlimited, multi-provider LLM CLI
|
|
64
|
+
|
|
65
|
+
Usage: aether-ai [options] [prompt]
|
|
66
|
+
|
|
67
|
+
Options:
|
|
68
|
+
-h, --help Show this help text and exit
|
|
69
|
+
-v, --version Print the version and exit
|
|
70
|
+
--plan Run in plan mode (step-by-step approval)
|
|
71
|
+
--yolo Run in yolo mode (autonomous execution)
|
|
72
|
+
--no-stream Disable streaming output in one-shot mode
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Flags are parsed from `process.argv` before the remaining args are treated as the prompt, so `aether-ai --yolo "fix the tests"` runs the prompt in yolo mode.
|
|
46
76
|
### Install
|
|
47
77
|
|
|
48
78
|
| Platform | Command |
|
|
@@ -72,7 +102,7 @@ $ npx tsx src/index.ts
|
|
|
72
102
|
|
|
73
103
|
+- Aether --------------------------------------------------+
|
|
74
104
|
| |
|
|
75
|
-
| ollama-local
|
|
105
|
+
| ollama-local · qwen2.5:7b |
|
|
76
106
|
| |
|
|
77
107
|
| ? Build a REST API in Node.js with CRUD endpoints |
|
|
78
108
|
| |
|
|
@@ -97,16 +127,16 @@ $ npx tsx src/index.ts /arena
|
|
|
97
127
|
|
|
98
128
|
? Prompt: write a hello world server
|
|
99
129
|
? Running 3 models in parallel...
|
|
100
|
-
? [Model A] ollama-local
|
|
101
|
-
? [Model B] openrouter-free
|
|
102
|
-
? [Model C] groq
|
|
130
|
+
? [Model A] ollama-local · qwen2.5:7b
|
|
131
|
+
? [Model B] openrouter-free · llama-3.1-8b:free
|
|
132
|
+
? [Model C] groq · llama-3.1-8b-instant
|
|
103
133
|
? Voting...
|
|
104
134
|
? Winner: Model A (Elo +12)
|
|
105
135
|
|
|
106
136
|
ELO LEADERBOARD
|
|
107
|
-
1. Model A 1240
|
|
108
|
-
2. Model B 1215
|
|
109
|
-
3. Model C 1142
|
|
137
|
+
1. Model A 1240 ââââââââââââ
|
|
138
|
+
2. Model B 1215 ââââââââââ
|
|
139
|
+
3. Model C 1142 ââââââââ
|
|
110
140
|
```
|
|
111
141
|
|
|
112
142
|
Session stats:
|
|
@@ -353,6 +383,7 @@ Add in local-first Ollama (priority 1, zero cost), zero-install one-shot mode (`
|
|
|
353
383
|
[MIT License](LICENSE) -- built by [Hemansubedi10](https://github.com/hemansubedi10).
|
|
354
384
|
|
|
355
385
|
Full docs: [docs/aether.md](docs/aether.md) | [INSTALL.md](INSTALL.md) | [Report an issue](https://github.com/hemansubedi10/aether/issues)
|
|
386
|
+
|
|
356
387
|
## Install via npm
|
|
357
388
|
|
|
358
389
|
```bash
|
|
@@ -360,31 +391,13 @@ npm install -g aether-ai
|
|
|
360
391
|
aether-ai "your prompt"
|
|
361
392
|
```
|
|
362
393
|
|
|
363
|
-
The package is published on npm: [npmjs.com/package/aether](https://www.npmjs.com/package/aether-ai).
|
|
364
|
-
|
|
365
|
-
## Install
|
|
366
|
-
|
|
367
|
-
Install the Aether CLI globally:
|
|
368
|
-
|
|
369
|
-
bash
|
|
370
|
-
npm install -g aether-ai
|
|
371
|
-
|
|
372
|
-
|
|
394
|
+
The package is published on npm: [npmjs.com/package/aether-ai](https://www.npmjs.com/package/aether-ai).
|
|
373
395
|
|
|
374
396
|
## Publishing
|
|
375
397
|
|
|
376
|
-
Aether is published on npm as **`aether-ai`**.
|
|
377
|
-
|
|
378
|
-
```bash
|
|
379
|
-
npm install -g aether-ai
|
|
380
|
-
aether-ai "your prompt"
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
Package page: [npmjs.com/package/aether-ai](https://www.npmjs.com/package/aether-ai).
|
|
384
|
-
|
|
385
|
-
### Trusted Publishing (OIDC � no token needed)
|
|
398
|
+
Aether is published on npm as **`aether-ai`**. New versions are published automatically by a GitHub Actions workflow using npm **Trusted Publishing**. There is no npm token to manage — GitHub Actions authenticates to npm via OpenID Connect.
|
|
386
399
|
|
|
387
|
-
|
|
400
|
+
### Trusted Publishing (OIDC - no token needed)
|
|
388
401
|
|
|
389
402
|
To release a new version:
|
|
390
403
|
|
package/dist/index.js
CHANGED
|
@@ -169,13 +169,49 @@ import { GitTool } from "./git.js";
|
|
|
169
169
|
import { Checkpoint } from "./checkpoint.js";
|
|
170
170
|
import { Skills } from "./skills.js";
|
|
171
171
|
// CLI entrypoint
|
|
172
|
+
const VERSION = "1.0.0";
|
|
173
|
+
function getHelpText() {
|
|
174
|
+
const lines = [];
|
|
175
|
+
lines.push("Aether - the free, unlimited, multi-provider LLM CLI");
|
|
176
|
+
lines.push("");
|
|
177
|
+
lines.push("Usage: aether-ai [options] [prompt]");
|
|
178
|
+
lines.push("");
|
|
179
|
+
lines.push("Options:");
|
|
180
|
+
lines.push(" -h, --help Show this help text and exit");
|
|
181
|
+
lines.push(" -v, --version Print the version and exit");
|
|
182
|
+
lines.push(" --plan Run in plan mode (step-by-step approval)");
|
|
183
|
+
lines.push(" --yolo Run in yolo mode (autonomous execution)");
|
|
184
|
+
lines.push(" --no-stream Disable streaming output in one-shot mode");
|
|
185
|
+
lines.push("");
|
|
186
|
+
lines.push("Commands (prefix a prompt with /):");
|
|
187
|
+
lines.push(" /help Show all available commands");
|
|
188
|
+
lines.push(" /model <name> Switch the active model");
|
|
189
|
+
lines.push(" /provider <name> Switch the active provider");
|
|
190
|
+
lines.push(" /models List all available models across providers");
|
|
191
|
+
lines.push(" /providers Show provider health status");
|
|
192
|
+
lines.push(" /combo ... Manage named provider/model combos");
|
|
193
|
+
lines.push(" /session ... Manage sessions");
|
|
194
|
+
lines.push(" /arena Enter arena mode (compare models)");
|
|
195
|
+
lines.push(" /cost Show token usage and estimated cost summary");
|
|
196
|
+
lines.push(" /stats Show session stats, cost summary, and provider health");
|
|
197
|
+
lines.push(" /skills List available custom skills");
|
|
198
|
+
lines.push(" /connect ... Connect an API key for a provider");
|
|
199
|
+
lines.push(" /exit Exit the TUI");
|
|
200
|
+
lines.push("");
|
|
201
|
+
lines.push("When no prompt is given, Aether starts an interactive TUI.");
|
|
202
|
+
return lines.join("\n");
|
|
203
|
+
}
|
|
172
204
|
function isMainModule() {
|
|
173
|
-
// Robust across tsx/Node and Windows path formatting.
|
|
205
|
+
// Robust across tsx/Node and Windows path formatting. The compiled bin is
|
|
206
|
+
// dist/index.js; tsx may also hand us src/index.ts directly.
|
|
174
207
|
const self = import.meta.url.replace(/\/$/g, "");
|
|
175
208
|
const argv1 = "file://" + path.resolve(process.argv[1] ?? "");
|
|
176
209
|
if (self === argv1)
|
|
177
210
|
return true;
|
|
178
|
-
|
|
211
|
+
const binNames = ["dist/index.js", "src/index.ts"];
|
|
212
|
+
if (binNames.includes(path.basename(process.argv[1] ?? "")))
|
|
213
|
+
return true;
|
|
214
|
+
// Also match when invoked via tsx where argv may be a .ts source file.
|
|
179
215
|
try {
|
|
180
216
|
const selfPath = new URL(self).pathname;
|
|
181
217
|
const argvPath = path.resolve(process.argv[1] ?? "");
|
|
@@ -189,9 +225,10 @@ function isMainModule() {
|
|
|
189
225
|
return false;
|
|
190
226
|
}
|
|
191
227
|
if (isMainModule()) {
|
|
192
|
-
// Parse CLI flags: --plan
|
|
193
|
-
// from the prompt args.
|
|
228
|
+
// Parse CLI flags: --plan, --yolo, --no-stream, --version and --help are
|
|
229
|
+
// consumed here and stripped from the prompt args.
|
|
194
230
|
let modeFlag = null;
|
|
231
|
+
let noStream = false;
|
|
195
232
|
const promptArgs = [];
|
|
196
233
|
for (const arg of process.argv.slice(2)) {
|
|
197
234
|
if (arg === "--plan") {
|
|
@@ -200,6 +237,17 @@ if (isMainModule()) {
|
|
|
200
237
|
else if (arg === "--yolo") {
|
|
201
238
|
modeFlag = "yolo";
|
|
202
239
|
}
|
|
240
|
+
else if (arg === "--no-stream") {
|
|
241
|
+
noStream = true;
|
|
242
|
+
}
|
|
243
|
+
else if (arg === "--version" || arg === "-v") {
|
|
244
|
+
process.stdout.write("aether-ai " + VERSION + "\n");
|
|
245
|
+
process.exit(0);
|
|
246
|
+
}
|
|
247
|
+
else if (arg === "--help" || arg === "-h") {
|
|
248
|
+
process.stdout.write(getHelpText() + "\n");
|
|
249
|
+
process.exit(0);
|
|
250
|
+
}
|
|
203
251
|
else {
|
|
204
252
|
promptArgs.push(arg);
|
|
205
253
|
}
|
package/package.json
CHANGED
|
@@ -1,34 +1,44 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@hemansubedi/aether-ai",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "The Aether CLI: the free, unlimited, multi-provider LLM CLI - install like KiloCode, run like Claude Code.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "dist/index.js",
|
|
7
|
-
"bin": {
|
|
8
|
-
"aether-ai": "dist/index.js",
|
|
9
|
-
"aether-ai-server": "dist/server.js"
|
|
10
|
-
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsc",
|
|
13
|
-
"start": "node dist/index.js",
|
|
14
|
-
"dev": "tsx src/index.ts"
|
|
15
|
-
},
|
|
16
|
-
"engines": {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@hemansubedi/aether-ai",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "The Aether CLI: the free, unlimited, multi-provider LLM CLI - install like KiloCode, run like Claude Code.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"aether-ai": "dist/index.js",
|
|
9
|
+
"aether-ai-server": "dist/server.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"dev": "tsx src/index.ts"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=20"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"llm",
|
|
21
|
+
"cli",
|
|
22
|
+
"ai",
|
|
23
|
+
"router",
|
|
24
|
+
"ollama",
|
|
25
|
+
"openrouter",
|
|
26
|
+
"free"
|
|
27
|
+
],
|
|
28
|
+
"author": "Heman Subedi <hemansubedi66@gmail.com>",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"homepage": "https://github.com/hemansubedi10/aether",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/hemansubedi10/aether.git"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"typescript": "^7.0.0",
|
|
38
|
+
"tsx": "^4.0.0",
|
|
39
|
+
"@types/node": "^22.0.0"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -178,40 +178,86 @@ import { GitTool } from "./git.js";
|
|
|
178
178
|
import { Checkpoint } from "./checkpoint.js";
|
|
179
179
|
import { Skills } from "./skills.js";
|
|
180
180
|
|
|
181
|
-
// CLI entrypoint
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
181
|
+
// CLI entrypoint
|
|
182
|
+
const VERSION = "1.0.0";
|
|
183
|
+
|
|
184
|
+
function getHelpText() {
|
|
185
|
+
const lines = [];
|
|
186
|
+
lines.push("Aether - the free, unlimited, multi-provider LLM CLI");
|
|
187
|
+
lines.push("");
|
|
188
|
+
lines.push("Usage: aether-ai [options] [prompt]");
|
|
189
|
+
lines.push("");
|
|
190
|
+
lines.push("Options:");
|
|
191
|
+
lines.push(" -h, --help Show this help text and exit");
|
|
192
|
+
lines.push(" -v, --version Print the version and exit");
|
|
193
|
+
lines.push(" --plan Run in plan mode (step-by-step approval)");
|
|
194
|
+
lines.push(" --yolo Run in yolo mode (autonomous execution)");
|
|
195
|
+
lines.push(" --no-stream Disable streaming output in one-shot mode");
|
|
196
|
+
lines.push("");
|
|
197
|
+
lines.push("Commands (prefix a prompt with /):");
|
|
198
|
+
lines.push(" /help Show all available commands");
|
|
199
|
+
lines.push(" /model <name> Switch the active model");
|
|
200
|
+
lines.push(" /provider <name> Switch the active provider");
|
|
201
|
+
lines.push(" /models List all available models across providers");
|
|
202
|
+
lines.push(" /providers Show provider health status");
|
|
203
|
+
lines.push(" /combo ... Manage named provider/model combos");
|
|
204
|
+
lines.push(" /session ... Manage sessions");
|
|
205
|
+
lines.push(" /arena Enter arena mode (compare models)");
|
|
206
|
+
lines.push(" /cost Show token usage and estimated cost summary");
|
|
207
|
+
lines.push(" /stats Show session stats, cost summary, and provider health");
|
|
208
|
+
lines.push(" /skills List available custom skills");
|
|
209
|
+
lines.push(" /connect ... Connect an API key for a provider");
|
|
210
|
+
lines.push(" /exit Exit the TUI");
|
|
211
|
+
lines.push("");
|
|
212
|
+
lines.push("When no prompt is given, Aether starts an interactive TUI.");
|
|
213
|
+
return lines.join("\n");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function isMainModule() {
|
|
217
|
+
// Robust across tsx/Node and Windows path formatting. The compiled bin is
|
|
218
|
+
// dist/index.js; tsx may also hand us src/index.ts directly.
|
|
219
|
+
const self = import.meta.url.replace(/\/$/g, "");
|
|
220
|
+
const argv1 = "file://" + path.resolve(process.argv[1] ?? "");
|
|
221
|
+
if (self === argv1) return true;
|
|
222
|
+
const binNames = ["dist/index.js", "src/index.ts"];
|
|
223
|
+
if (binNames.includes(path.basename(process.argv[1] ?? ""))) return true;
|
|
224
|
+
// Also match when invoked via tsx where argv may be a .ts source file.
|
|
225
|
+
try {
|
|
226
|
+
const selfPath = new URL(self).pathname;
|
|
227
|
+
const argvPath = path.resolve(process.argv[1] ?? "");
|
|
228
|
+
const norm = (p: string) => p.toLowerCase().replace(/\\/g, "/").replace(/^\//, "");
|
|
229
|
+
if (norm(selfPath) === norm(argvPath)) return true;
|
|
230
|
+
} catch {
|
|
231
|
+
// ignore
|
|
232
|
+
}
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (isMainModule()) {
|
|
237
|
+
// Parse CLI flags: --plan, --yolo, --no-stream, --version and --help are
|
|
238
|
+
// consumed here and stripped from the prompt args.
|
|
239
|
+
let modeFlag = null;
|
|
240
|
+
let noStream = false;
|
|
241
|
+
const promptArgs = [];
|
|
242
|
+
for (const arg of process.argv.slice(2)) {
|
|
243
|
+
if (arg === "--plan") {
|
|
244
|
+
modeFlag = "plan";
|
|
245
|
+
} else if (arg === "--yolo") {
|
|
246
|
+
modeFlag = "yolo";
|
|
247
|
+
} else if (arg === "--no-stream") {
|
|
248
|
+
noStream = true;
|
|
249
|
+
} else if (arg === "--version" || arg === "-v") {
|
|
250
|
+
process.stdout.write("aether-ai " + VERSION + "\n");
|
|
251
|
+
process.exit(0);
|
|
252
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
253
|
+
process.stdout.write(getHelpText() + "\n");
|
|
254
|
+
process.exit(0);
|
|
255
|
+
} else {
|
|
256
|
+
promptArgs.push(arg);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const prompt = promptArgs.join(" ").trim();
|
|
260
|
+
|
|
215
261
|
if (!prompt) {
|
|
216
262
|
// Interactive TUI mode.
|
|
217
263
|
const { tui } = createTUIContext();
|