@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 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 · qwen2.5:7b |
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 · qwen2.5:7b
101
- ? [Model B] openrouter-free · llama-3.1-8b:free
102
- ? [Model C] groq · llama-3.1-8b-instant
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`**. Install it globally with:
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
- 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.
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
- // Also match when invoked via `tsx` where argv may be a .ts source file.
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 and --yolo set the agent mode and are stripped
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.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": { "node": ">=20" },
17
- "keywords": ["llm", "cli", "ai", "router", "ollama", "openrouter", "free"],
18
- "author": "Heman Subedi <hemansubedi66@gmail.com>",
19
- "license": "MIT",
20
- "homepage": "https://github.com/hemansubedi10/aether",
21
- "repository": {
22
- "type": "git",
23
- "url": "https://github.com/hemansubedi10/aether.git"
24
- },
25
- "dependencies": {},
26
- "devDependencies": {
27
- "typescript": "^7.0.0",
28
- "tsx": "^4.0.0",
29
- "@types/node": "^22.0.0"
30
- },
31
- "publishConfig": {
32
- "access": "public"
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
- function isMainModule(): boolean {
183
- // Robust across tsx/Node and Windows path formatting.
184
- const self = import.meta.url.replace(/\/$/g, "");
185
- const argv1 = "file://" + path.resolve(process.argv[1] ?? "");
186
- if (self === argv1) return true;
187
- // Also match when invoked via `tsx` where argv may be a .ts source file.
188
- try {
189
- const selfPath = new URL(self).pathname;
190
- const argvPath = path.resolve(process.argv[1] ?? "");
191
- const norm = (p: string) => p.toLowerCase().replace(/\\/g, "/").replace(/^\//, "");
192
- if (norm(selfPath) === norm(argvPath)) return true;
193
- } catch {
194
- // ignore
195
- }
196
- return false;
197
- }
198
-
199
- if (isMainModule()) {
200
- // Parse CLI flags: --plan and --yolo set the agent mode and are stripped
201
- // from the prompt args.
202
- let modeFlag: string | null = null;
203
- const promptArgs: string[] = [];
204
- for (const arg of process.argv.slice(2)) {
205
- if (arg === "--plan") {
206
- modeFlag = "plan";
207
- } else if (arg === "--yolo") {
208
- modeFlag = "yolo";
209
- } else {
210
- promptArgs.push(arg);
211
- }
212
- }
213
- const prompt = promptArgs.join(" ").trim();
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();