@darkrei08/setup-ai 3.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/README.md +114 -0
- package/bin/setup-ai.mjs +191 -0
- package/package.json +45 -0
- package/setup-ai.ps1 +418 -0
- package/setup-ai.sh +1091 -0
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# setup-ai
|
|
2
|
+
|
|
3
|
+
Cross-OS installer for an AI coding toolchain. One command bootstraps
|
|
4
|
+
[pi](https://pi.dev), [Codex](https://github.com/openai/codex),
|
|
5
|
+
[Antigravity](https://antigravity.google), [opencode](https://opencode.ai),
|
|
6
|
+
[herdr](https://herdr.dev), [gentle-ai](https://github.com/Gentleman-Programming/gentle-ai),
|
|
7
|
+
[Engram](https://github.com/Gentleman-Programming/engram) memory, and the
|
|
8
|
+
[Engineering Excellence](https://github.com/micio86dev/Engineering-Excellence)
|
|
9
|
+
skill — each via its **official, current** method for your OS.
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# no install needed — runs the launcher once, then discards it
|
|
15
|
+
npx github:darkrei08/setup-ai
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
or, once published to npm:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @darkrei08/setup-ai # interactive module menu
|
|
22
|
+
npx @darkrei08/setup-ai --only pi,codex,opencode
|
|
23
|
+
npx @darkrei08/setup-ai --all # everything incl. optional GUI apps
|
|
24
|
+
npm i -g @darkrei08/setup-ai && setup-ai # global command
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The launcher (`bin/setup-ai.mjs`, zero dependencies) detects your OS and runs
|
|
28
|
+
the right script: `setup-ai.ps1` on Windows (via `pwsh`), `setup-ai.sh` on
|
|
29
|
+
macOS/Linux (via `bash`). With no selection flag on an interactive terminal it
|
|
30
|
+
opens an arrow-key **multi-select menu** (↑/↓ move · Space toggle · `a` all ·
|
|
31
|
+
Enter confirm); on a non-interactive shell it installs the core set.
|
|
32
|
+
|
|
33
|
+
### npm vs npx
|
|
34
|
+
|
|
35
|
+
| | `npm` | `npx` |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| Role | **installs / manages** packages | **executes** a package's binary |
|
|
38
|
+
| Persistence | keeps it installed (`node_modules` / `-g`) | fetches, runs, discards |
|
|
39
|
+
| Here | `npm i -g @darkrei08/setup-ai` (permanent `setup-ai`) | `npx @darkrei08/setup-ai` (one-shot) |
|
|
40
|
+
|
|
41
|
+
For a one-time installer, `npx` is ideal — nothing is left behind.
|
|
42
|
+
|
|
43
|
+
## Install matrix (official methods)
|
|
44
|
+
|
|
45
|
+
| Tool | binary | macOS | Linux | Windows |
|
|
46
|
+
|---|---|---|---|---|
|
|
47
|
+
| Antigravity | `agy` | `curl -fsSL https://antigravity.google/cli/install.sh \| bash` | same | `irm https://antigravity.google/cli/install.ps1 \| iex` |
|
|
48
|
+
| Codex | `codex` | `brew install --cask codex` | `curl -fsSL https://chatgpt.com/codex/install.sh \| sh` | `irm https://chatgpt.com/codex/install.ps1 \| iex` |
|
|
49
|
+
| pi | `pi` | `curl -fsSL https://pi.dev/install.sh \| sh` | same | `irm https://pi.dev/install.ps1 \| iex` |
|
|
50
|
+
| herdr | `herdr` | `brew install herdr` | `curl -fsSL https://herdr.dev/install.sh \| sh` | `irm https://herdr.dev/install.ps1 \| iex` |
|
|
51
|
+
| Go | `go` | `brew install go` | distro pkg | `winget install -e --id GoLang.Go` |
|
|
52
|
+
| gentle-ai | `gentle-ai` | `brew install gentleman-programming/tap/gentle-ai` | `curl -fsSL .../scripts/install.sh \| bash` | `go install github.com/gentleman-programming/gentle-ai/v2/cmd/gentle-ai@latest` |
|
|
53
|
+
| Engram | `engram` | `brew install gentleman-programming/tap/engram` | `go install github.com/Gentleman-Programming/engram/cmd/engram@latest` | same (go install) |
|
|
54
|
+
| opencode | `opencode` | `brew install anomalyco/tap/opencode` | `curl -fsSL https://opencode.ai/install \| bash` | `npm i -g opencode-ai` |
|
|
55
|
+
| cockpit-tools *(opt-in GUI)* | app | `brew install --cask cockpit-tools` | `.deb`/`.rpm`/`.AppImage` | `.msi` |
|
|
56
|
+
| Engineering Excellence | skill | `npx skills@latest add micio86dev/Engineering-Excellence --agent <agent>` | same | same |
|
|
57
|
+
|
|
58
|
+
## Modules
|
|
59
|
+
|
|
60
|
+
Run `--list` to see them. Core modules install by default; optional ones
|
|
61
|
+
(GUI apps) only via `--all` or an explicit `--only`.
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
base node bun pi go dotenv ee pi-workflows herdr gentle-ai engram codex antigravity opencode [cockpit]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- **dotenv** is Linux-only (it runs vekexasia/dotenv's apt/pacman `setup_env.sh`).
|
|
68
|
+
- **ee** installs the Engineering Excellence skill for every detected agent
|
|
69
|
+
(pi, claude, gemini, cursor, antigravity) via `npx skills add`.
|
|
70
|
+
|
|
71
|
+
## Engram in pi (the gotcha)
|
|
72
|
+
|
|
73
|
+
`gentle-engram` is an **in-process pi extension** that auto-starts `engram serve`.
|
|
74
|
+
It therefore needs the **Engram Go binary on `PATH`** — if it's missing, the
|
|
75
|
+
extension loads but silently does nothing (the "engram doesn't work in pi"
|
|
76
|
+
symptom). The `engram` module installs the binary first, then:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pi install npm:gentle-engram
|
|
80
|
+
pi install npm:pi-mcp-adapter # optional MCP gateway
|
|
81
|
+
pi-engram init
|
|
82
|
+
# then RESTART pi, and verify:
|
|
83
|
+
# mem_current_project mem_doctor engram tui
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
MCP is only an optional gateway — the primary path for pi is the in-process
|
|
87
|
+
extension, so don't rely on the MCP-only choice.
|
|
88
|
+
|
|
89
|
+
## OpenCode Go inside pi
|
|
90
|
+
|
|
91
|
+
An OpenCode Go subscription is reusable in pi (no lock-in). After
|
|
92
|
+
`opencode auth login`, add a custom provider in pi:
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
pi.registerProvider("opencode-go", {
|
|
96
|
+
baseUrl: "https://opencode.ai/zen/v1",
|
|
97
|
+
apiKey: "$OPENCODE_API_KEY",
|
|
98
|
+
authHeader: true,
|
|
99
|
+
api: "openai-completions",
|
|
100
|
+
models: [ /* your Go plan model ids */ ],
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
or run `/provider add` in pi. Docs: <https://pi.dev/docs/latest/custom-provider>.
|
|
105
|
+
|
|
106
|
+
## Logs
|
|
107
|
+
|
|
108
|
+
Each run writes `logs/setup_<runid>.log` (human), `.jsonl` (structured), and an
|
|
109
|
+
`engineering-report_<runid>.md`.
|
|
110
|
+
|
|
111
|
+
## License
|
|
112
|
+
|
|
113
|
+
MIT (this installer). Installed tools keep their own licenses — note
|
|
114
|
+
cockpit-tools is CC BY-NC-SA 4.0 (non-commercial).
|
package/bin/setup-ai.mjs
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ============================================================================
|
|
3
|
+
// AI Dev Suite — cross-OS launcher
|
|
4
|
+
//
|
|
5
|
+
// Detects the OS and runs the right installer script:
|
|
6
|
+
// win32 -> setup-ai.ps1 (via pwsh, falling back to powershell)
|
|
7
|
+
// darwin / linux -> setup-ai.sh (via bash)
|
|
8
|
+
//
|
|
9
|
+
// With no selection flag on an interactive terminal it shows a gentle-ai-style
|
|
10
|
+
// arrow-key multi-select menu, then passes the chosen modules to the platform
|
|
11
|
+
// script as --only. Zero runtime dependencies.
|
|
12
|
+
//
|
|
13
|
+
// Usage:
|
|
14
|
+
// npx @darkrei08/setup-ai # interactive menu (or core if no TTY)
|
|
15
|
+
// npx @darkrei08/setup-ai --all
|
|
16
|
+
// npx @darkrei08/setup-ai --only pi,codex,opencode
|
|
17
|
+
// npx @darkrei08/setup-ai --yes # core set, no prompt
|
|
18
|
+
// npx @darkrei08/setup-ai --list | --help
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
import { spawn } from "node:child_process";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
import { dirname, join } from "node:path";
|
|
24
|
+
import process from "node:process";
|
|
25
|
+
|
|
26
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const PKG_ROOT = join(__dirname, "..");
|
|
28
|
+
|
|
29
|
+
// Canonical module list (mirrors the registries in setup-ai.sh / setup-ai.ps1).
|
|
30
|
+
// core:false => optional (unchecked by default in the menu).
|
|
31
|
+
const MODULES = [
|
|
32
|
+
{ name: "base", core: true, desc: "System dev tools (git, gh, python, neovim, ...)" },
|
|
33
|
+
{ name: "node", core: true, desc: "Node.js + npm@latest" },
|
|
34
|
+
{ name: "bun", core: true, desc: "Bun runtime" },
|
|
35
|
+
{ name: "pi", core: true, desc: "pi.dev coding agent CLI" },
|
|
36
|
+
{ name: "go", core: true, desc: "Go toolchain" },
|
|
37
|
+
{ name: "dotenv", core: true, desc: "vekexasia/dotenv dotfiles (Linux only)" },
|
|
38
|
+
{ name: "ee", core: true, desc: "Engineering Excellence skill (all agents)" },
|
|
39
|
+
{ name: "pi-workflows", core: true, desc: "pi-extensible-workflows resolution fix" },
|
|
40
|
+
{ name: "herdr", core: true, desc: "herdr terminal multiplexer" },
|
|
41
|
+
{ name: "gentle-ai", core: true, desc: "gentle-ai / gga + gentle-pi package" },
|
|
42
|
+
{ name: "engram", core: true, desc: "Engram persistent memory for pi" },
|
|
43
|
+
{ name: "codex", core: true, desc: "OpenAI Codex CLI" },
|
|
44
|
+
{ name: "antigravity", core: true, desc: "Google Antigravity CLI (agy)" },
|
|
45
|
+
{ name: "opencode", core: true, desc: "opencode agent CLI" },
|
|
46
|
+
{ name: "cockpit", core: false, desc: "cockpit-tools desktop GUI (optional)" },
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
// dotenv is Linux-only; drop it from the Windows menu.
|
|
50
|
+
const isWin = process.platform === "win32";
|
|
51
|
+
const menuModules = MODULES.filter((m) => !(isWin && m.name === "dotenv"));
|
|
52
|
+
|
|
53
|
+
const argv = process.argv.slice(2);
|
|
54
|
+
const has = (f) => argv.includes(f);
|
|
55
|
+
const getVal = (f) => {
|
|
56
|
+
const i = argv.indexOf(f);
|
|
57
|
+
if (i >= 0 && argv[i + 1]) return argv[i + 1];
|
|
58
|
+
const eq = argv.find((a) => a.startsWith(f + "="));
|
|
59
|
+
return eq ? eq.split("=").slice(1).join("=") : null;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
function runScript(passArgs) {
|
|
63
|
+
let cmd, cmdArgs;
|
|
64
|
+
if (isWin) {
|
|
65
|
+
const ps1 = join(PKG_ROOT, "setup-ai.ps1");
|
|
66
|
+
const psExe = process.env.SETUP_AI_PWSH || "pwsh";
|
|
67
|
+
cmdArgs = ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", ps1, ...passArgs];
|
|
68
|
+
cmd = psExe;
|
|
69
|
+
} else {
|
|
70
|
+
const sh = join(PKG_ROOT, "setup-ai.sh");
|
|
71
|
+
cmd = "bash";
|
|
72
|
+
cmdArgs = [sh, ...passArgs];
|
|
73
|
+
}
|
|
74
|
+
const child = spawn(cmd, cmdArgs, { stdio: "inherit" });
|
|
75
|
+
child.on("error", (err) => {
|
|
76
|
+
if (isWin && cmd === "pwsh") {
|
|
77
|
+
// Fall back to Windows PowerShell 5.
|
|
78
|
+
const ps1 = join(PKG_ROOT, "setup-ai.ps1");
|
|
79
|
+
const fb = spawn("powershell", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", ps1, ...passArgs], { stdio: "inherit" });
|
|
80
|
+
fb.on("exit", (c) => process.exit(c ?? 0));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
console.error(`Failed to launch installer: ${err.message}`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
});
|
|
86
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Translate a chosen module list into the platform script's flag.
|
|
90
|
+
function toScriptArgs(mode, csv) {
|
|
91
|
+
if (isWin) {
|
|
92
|
+
if (mode === "all") return ["-All"];
|
|
93
|
+
if (mode === "only") return ["-Only", csv];
|
|
94
|
+
if (mode === "yes") return ["-Yes"];
|
|
95
|
+
if (mode === "list") return ["-List"];
|
|
96
|
+
if (mode === "help") return ["-Help"];
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
if (mode === "all") return ["--all"];
|
|
100
|
+
if (mode === "only") return ["--only", csv];
|
|
101
|
+
if (mode === "yes") return ["--yes"];
|
|
102
|
+
if (mode === "list") return ["--list"];
|
|
103
|
+
if (mode === "help") return ["--help"];
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ---- interactive multi-select (gentle-ai style) ---------------------------
|
|
108
|
+
function interactiveMenu() {
|
|
109
|
+
return new Promise((resolve) => {
|
|
110
|
+
const items = menuModules.map((m) => ({ ...m, checked: m.core }));
|
|
111
|
+
let cursor = 0;
|
|
112
|
+
const out = process.stdout;
|
|
113
|
+
|
|
114
|
+
const render = (first) => {
|
|
115
|
+
if (!first) out.write(`\x1b[${items.length + 3}A`); // move up to redraw
|
|
116
|
+
out.write("\x1b[0J"); // clear below
|
|
117
|
+
out.write("\x1b[1mAI Dev Suite — select modules\x1b[0m (↑/↓ move · Space toggle · a all · Enter confirm · q quit)\n\n");
|
|
118
|
+
items.forEach((it, i) => {
|
|
119
|
+
const pointer = i === cursor ? "\x1b[36m>\x1b[0m " : " ";
|
|
120
|
+
const box = it.checked ? "\x1b[32m[x]\x1b[0m" : "[ ]";
|
|
121
|
+
const tag = it.core ? "" : " \x1b[33m(optional)\x1b[0m";
|
|
122
|
+
out.write(`${pointer}${box} ${it.name.padEnd(14)} ${it.desc}${tag}\n`);
|
|
123
|
+
});
|
|
124
|
+
out.write("\n");
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const stdin = process.stdin;
|
|
128
|
+
stdin.setRawMode(true);
|
|
129
|
+
stdin.resume();
|
|
130
|
+
stdin.setEncoding("utf8");
|
|
131
|
+
render(true);
|
|
132
|
+
|
|
133
|
+
const cleanup = () => {
|
|
134
|
+
stdin.setRawMode(false);
|
|
135
|
+
stdin.pause();
|
|
136
|
+
stdin.removeListener("data", onData);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const onData = (key) => {
|
|
140
|
+
if (key === "\x03" || key === "q") { // ctrl-c / q
|
|
141
|
+
cleanup();
|
|
142
|
+
out.write("\nAborted.\n");
|
|
143
|
+
process.exit(130);
|
|
144
|
+
} else if (key === "\x1b[A" || key === "k") {
|
|
145
|
+
cursor = (cursor - 1 + items.length) % items.length; render();
|
|
146
|
+
} else if (key === "\x1b[B" || key === "j") {
|
|
147
|
+
cursor = (cursor + 1) % items.length; render();
|
|
148
|
+
} else if (key === " ") {
|
|
149
|
+
items[cursor].checked = !items[cursor].checked; render();
|
|
150
|
+
} else if (key === "a") {
|
|
151
|
+
const allOn = items.every((i) => i.checked);
|
|
152
|
+
items.forEach((i) => (i.checked = !allOn)); render();
|
|
153
|
+
} else if (key === "\r" || key === "\n") {
|
|
154
|
+
cleanup();
|
|
155
|
+
resolve(items.filter((i) => i.checked).map((i) => i.name));
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
stdin.on("data", onData);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ---- numbered fallback (no TTY) -------------------------------------------
|
|
163
|
+
function defaultSelection() {
|
|
164
|
+
return menuModules.filter((m) => m.core).map((m) => m.name);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function main() {
|
|
168
|
+
if (has("--help") || has("-h")) return runScript(toScriptArgs("help"));
|
|
169
|
+
if (has("--list")) return runScript(toScriptArgs("list"));
|
|
170
|
+
if (has("--all")) return runScript(toScriptArgs("all"));
|
|
171
|
+
|
|
172
|
+
const only = getVal("--only");
|
|
173
|
+
if (only) return runScript(toScriptArgs("only", only));
|
|
174
|
+
|
|
175
|
+
if (has("--yes") || has("-y")) return runScript(toScriptArgs("yes"));
|
|
176
|
+
|
|
177
|
+
// No selection flag: interactive menu if we have a TTY, else core defaults.
|
|
178
|
+
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
179
|
+
const chosen = await interactiveMenu();
|
|
180
|
+
if (!chosen.length) {
|
|
181
|
+
console.log("Nothing selected — exiting.");
|
|
182
|
+
process.exit(0);
|
|
183
|
+
}
|
|
184
|
+
return runScript(toScriptArgs("only", chosen.join(",")));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
console.log("No TTY detected — installing the core module set. Use --only/--all to customize.");
|
|
188
|
+
return runScript(toScriptArgs("only", defaultSelection().join(",")));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@darkrei08/setup-ai",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Cross-OS installer for an AI coding toolchain (pi, codex, antigravity, opencode, herdr, gentle-ai, engram, Engineering Excellence) with an interactive module menu.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"setup-ai": "bin/setup-ai.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/setup-ai.mjs",
|
|
11
|
+
"setup-ai.sh",
|
|
12
|
+
"setup-ai.ps1",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18"
|
|
17
|
+
},
|
|
18
|
+
"os": [
|
|
19
|
+
"darwin",
|
|
20
|
+
"linux",
|
|
21
|
+
"win32"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"list": "node bin/setup-ai.mjs --list"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"ai",
|
|
28
|
+
"cli",
|
|
29
|
+
"installer",
|
|
30
|
+
"pi",
|
|
31
|
+
"codex",
|
|
32
|
+
"opencode",
|
|
33
|
+
"antigravity",
|
|
34
|
+
"gentle-ai",
|
|
35
|
+
"engram",
|
|
36
|
+
"engineering-excellence",
|
|
37
|
+
"setup"
|
|
38
|
+
],
|
|
39
|
+
"author": "darkrei08",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/darkrei08/setup-ai.git"
|
|
44
|
+
}
|
|
45
|
+
}
|