@alphafox/cli 0.2.0 → 0.3.2
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 +42 -4
- package/dist/catalog/command-tree.d.ts +1 -0
- package/dist/catalog/command-tree.js +5 -3
- package/dist/catalog/validate-body.d.ts +22 -0
- package/dist/catalog/validate-body.js +98 -0
- package/dist/commands/request-body.d.ts +21 -0
- package/dist/commands/request-body.js +92 -0
- package/dist/commands/run.js +113 -10
- package/dist/engine-backtest/errors.d.ts +18 -0
- package/dist/engine-backtest/errors.js +26 -0
- package/dist/engine-backtest/fetch-runtime.d.ts +38 -0
- package/dist/engine-backtest/fetch-runtime.js +170 -0
- package/dist/engine-backtest/native-import.d.ts +1 -0
- package/dist/engine-backtest/native-import.js +10 -0
- package/dist/engine-backtest/parse-args.d.ts +6 -0
- package/dist/engine-backtest/parse-args.js +281 -0
- package/dist/engine-backtest/persist.d.ts +32 -0
- package/dist/engine-backtest/persist.js +94 -0
- package/dist/engine-backtest/replay-timeframe.d.ts +16 -0
- package/dist/engine-backtest/replay-timeframe.js +48 -0
- package/dist/engine-backtest/resolve-packages.d.ts +27 -0
- package/dist/engine-backtest/resolve-packages.js +288 -0
- package/dist/engine-backtest/run-command.d.ts +38 -0
- package/dist/engine-backtest/run-command.js +540 -0
- package/dist/engine-backtest/types.d.ts +249 -0
- package/dist/engine-backtest/types.js +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +16 -1
- package/dist/install/exec.d.ts +13 -0
- package/dist/install/exec.js +73 -0
- package/dist/install/package-root.d.ts +4 -0
- package/dist/install/package-root.js +59 -0
- package/dist/install/types.d.ts +69 -0
- package/dist/install/types.js +26 -0
- package/dist/install/wizard.d.ts +21 -0
- package/dist/install/wizard.js +332 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/.nojekyll +0 -0
- package/docs/alphafox-cli-installation-guide.md +105 -0
- package/docs/favicon.svg +4 -0
- package/docs/index.html +748 -0
- package/docs/logo/alphafox-mark.svg +4 -0
- package/docs/logo/alphafox-wordmark-black-en.svg +17 -0
- package/docs/logo/alphafox-wordmark-white-en.svg +16 -0
- package/docs/release-supply-chain.md +10 -2
- package/package.json +7 -2
- package/skills/account/SKILL.md +2 -2
- package/skills/admin/SKILL.md +2 -2
- package/skills/alphafox-shared/SKILL.md +22 -1
- package/skills/auth/SKILL.md +1 -1
- package/skills/engine-backtest/SKILL.md +71 -0
- package/skills/exchange/SKILL.md +2 -2
- package/skills/market/SKILL.md +1 -1
- package/skills/notification/SKILL.md +2 -2
- package/skills/strategy/SKILL.md +10 -2
- package/skills/trading/SKILL.md +6 -3
- package/vendor/backtest-runner/NOTICE.md +1 -0
- package/vendor/backtest-runner/README.md +97 -0
- package/vendor/backtest-runner/index.d.ts +423 -0
- package/vendor/backtest-runner/index.mjs +59 -0
- package/vendor/backtest-runner/lib/abortable.mjs +23 -0
- package/vendor/backtest-runner/lib/cache.mjs +159 -0
- package/vendor/backtest-runner/lib/coverage.mjs +238 -0
- package/vendor/backtest-runner/lib/encode.mjs +28 -0
- package/vendor/backtest-runner/lib/exchanges.mjs +143 -0
- package/vendor/backtest-runner/lib/proxy.mjs +78 -0
- package/vendor/backtest-runner/lib/scenario.mjs +66 -0
- package/vendor/backtest-runner/lib/series.mjs +370 -0
- package/vendor/backtest-runner/lib/tape-loader.mjs +614 -0
- package/vendor/backtest-runner/lib/timeframes.mjs +55 -0
- package/vendor/backtest-runner/package.json +13 -0
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseInstallArgs = parseInstallArgs;
|
|
4
|
+
exports.semverLessThan = semverLessThan;
|
|
5
|
+
exports.parseNpmListVersion = parseNpmListVersion;
|
|
6
|
+
exports.skillsListHasAlphafox = skillsListHasAlphafox;
|
|
7
|
+
exports.nextSteps = nextSteps;
|
|
8
|
+
exports.runInstallWizard = runInstallWizard;
|
|
9
|
+
exports.installHelpData = installHelpData;
|
|
10
|
+
exports.resolveLocalSkillsDir = resolveLocalSkillsDir;
|
|
11
|
+
const node_fs_1 = require("node:fs");
|
|
12
|
+
const node_path_1 = require("node:path");
|
|
13
|
+
const version_1 = require("../version");
|
|
14
|
+
const exec_1 = require("./exec");
|
|
15
|
+
const package_root_1 = require("./package-root");
|
|
16
|
+
const types_1 = require("./types");
|
|
17
|
+
const NPM_TIMEOUT_MS = 120_000;
|
|
18
|
+
const SKILLS_TIMEOUT_MS = 120_000;
|
|
19
|
+
function parseInstallArgs(args) {
|
|
20
|
+
let noAuth = false;
|
|
21
|
+
let help = false;
|
|
22
|
+
const unknown = [];
|
|
23
|
+
for (const arg of args) {
|
|
24
|
+
if (arg === "--no-auth") {
|
|
25
|
+
noAuth = true;
|
|
26
|
+
}
|
|
27
|
+
else if (arg === "--help" || arg === "-h") {
|
|
28
|
+
help = true;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
unknown.push(arg);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return { noAuth, help, unknown };
|
|
35
|
+
}
|
|
36
|
+
function semverLessThan(a, b) {
|
|
37
|
+
const pa = stripPrerelease(a).split(".").map((part) => Number(part) || 0);
|
|
38
|
+
const pb = stripPrerelease(b).split(".").map((part) => Number(part) || 0);
|
|
39
|
+
for (let i = 0; i < 3; i += 1) {
|
|
40
|
+
if ((pa[i] ?? 0) < (pb[i] ?? 0))
|
|
41
|
+
return true;
|
|
42
|
+
if ((pa[i] ?? 0) > (pb[i] ?? 0))
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
function parseNpmListVersion(output) {
|
|
48
|
+
const match = output.match(/@(\d+\.\d+\.\d+[^\s]*)/);
|
|
49
|
+
return match?.[1] ?? null;
|
|
50
|
+
}
|
|
51
|
+
function skillsListHasAlphafox(output) {
|
|
52
|
+
const prefix = types_1.SKILLS_NAME_PREFIX.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
53
|
+
return new RegExp(`(^|\\s)${prefix}[\\w-]+`, "m").test(output);
|
|
54
|
+
}
|
|
55
|
+
function nextSteps(input) {
|
|
56
|
+
const steps = [
|
|
57
|
+
"Restart the AI tool so newly installed Skills are loaded.",
|
|
58
|
+
];
|
|
59
|
+
if (input.auth.action === "skipped" || input.auth.action === "planned") {
|
|
60
|
+
steps.push("alphafox auth login --browser --format json --no-input", "alphafox auth login --no-wait --format json --no-input");
|
|
61
|
+
}
|
|
62
|
+
steps.push("alphafox doctor --format json --no-input", `Agent install guide: ${types_1.AGENT_INSTALL_GUIDE_BLOB_URL}`);
|
|
63
|
+
if (input.dryRun) {
|
|
64
|
+
steps.unshift("This was --dry-run; re-run without it to apply changes.");
|
|
65
|
+
}
|
|
66
|
+
return steps;
|
|
67
|
+
}
|
|
68
|
+
async function runInstallWizard(flags, env = process.env, runner = (0, exec_1.createDefaultInstallRunner)(env, defaultSearchDirs())) {
|
|
69
|
+
runner.log("Setting up Alphafox CLI...");
|
|
70
|
+
const installedVer = await readGloballyInstalledVersion(runner);
|
|
71
|
+
const latestVer = await readLatestVersion(runner);
|
|
72
|
+
const needsUpgrade = Boolean(installedVer) &&
|
|
73
|
+
Boolean(latestVer) &&
|
|
74
|
+
semverLessThan(installedVer, latestVer);
|
|
75
|
+
const cli = await stepInstallCli(flags, runner, {
|
|
76
|
+
installedVer,
|
|
77
|
+
latestVer,
|
|
78
|
+
needsUpgrade,
|
|
79
|
+
});
|
|
80
|
+
const skills = await stepInstallSkills(flags, runner);
|
|
81
|
+
const auth = await stepAuth(flags, runner);
|
|
82
|
+
return {
|
|
83
|
+
cli,
|
|
84
|
+
skills,
|
|
85
|
+
auth,
|
|
86
|
+
next: nextSteps({ auth, dryRun: flags.dryRun }),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function defaultSearchDirs() {
|
|
90
|
+
return [__dirname, process.cwd()];
|
|
91
|
+
}
|
|
92
|
+
function stripPrerelease(version) {
|
|
93
|
+
return version.replace(/-.*$/, "");
|
|
94
|
+
}
|
|
95
|
+
async function readGloballyInstalledVersion(runner) {
|
|
96
|
+
try {
|
|
97
|
+
const { stdout, stderr } = await runner.exec("npm", ["list", "-g", version_1.CLI_PACKAGE, "--depth=0"], { timeoutMs: 15_000 });
|
|
98
|
+
return parseNpmListVersion(`${stdout}\n${stderr}`);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function readLatestVersion(runner) {
|
|
105
|
+
try {
|
|
106
|
+
const { stdout } = await runner.exec("npm", ["view", version_1.CLI_PACKAGE, "version"], {
|
|
107
|
+
timeoutMs: 15_000,
|
|
108
|
+
});
|
|
109
|
+
const ver = stdout.trim();
|
|
110
|
+
return /^\d+\.\d+\.\d+/.test(ver) ? ver : null;
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function npmRootGlobal(runner) {
|
|
117
|
+
try {
|
|
118
|
+
const { stdout } = await runner.exec("npm", ["root", "-g"], {
|
|
119
|
+
timeoutMs: 15_000,
|
|
120
|
+
});
|
|
121
|
+
const root = stdout.trim();
|
|
122
|
+
return root.length > 0 ? root : null;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function npmPrefixGlobal(runner) {
|
|
129
|
+
try {
|
|
130
|
+
const { stdout } = await runner.exec("npm", ["prefix", "-g"], {
|
|
131
|
+
timeoutMs: 15_000,
|
|
132
|
+
});
|
|
133
|
+
const prefix = stdout.trim();
|
|
134
|
+
return prefix.length > 0 ? prefix : null;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async function stepInstallCli(flags, runner, versions) {
|
|
141
|
+
const { installedVer, latestVer, needsUpgrade } = versions;
|
|
142
|
+
if (installedVer && !needsUpgrade) {
|
|
143
|
+
runner.log(`Already installed (${installedVer}). Skipped`);
|
|
144
|
+
return {
|
|
145
|
+
action: flags.dryRun ? "planned" : "skipped",
|
|
146
|
+
version: installedVer,
|
|
147
|
+
latestVersion: latestVer ?? undefined,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
if (flags.dryRun) {
|
|
151
|
+
runner.log(needsUpgrade
|
|
152
|
+
? `Would upgrade ${version_1.CLI_PACKAGE} (${installedVer} → ${latestVer ?? "latest"})`
|
|
153
|
+
: `Would install ${version_1.CLI_PACKAGE} globally`);
|
|
154
|
+
return {
|
|
155
|
+
action: "planned",
|
|
156
|
+
previousVersion: installedVer ?? undefined,
|
|
157
|
+
latestVersion: latestVer ?? undefined,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
runner.log(needsUpgrade
|
|
161
|
+
? `Upgrading ${version_1.CLI_PACKAGE} (${installedVer} → ${latestVer})...`
|
|
162
|
+
: `Installing ${version_1.CLI_PACKAGE} globally...`);
|
|
163
|
+
try {
|
|
164
|
+
await runner.exec("npm", ["install", "-g", version_1.CLI_PACKAGE], {
|
|
165
|
+
timeoutMs: NPM_TIMEOUT_MS,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
throw new types_1.InstallError({
|
|
170
|
+
type: "install",
|
|
171
|
+
subtype: "npm_global_failed",
|
|
172
|
+
message: `Failed to install ${version_1.CLI_PACKAGE} globally.`,
|
|
173
|
+
hint: `npm install -g ${version_1.CLI_PACKAGE}`,
|
|
174
|
+
details: err instanceof Error ? err.message : String(err),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
const after = (await readGloballyInstalledVersion(runner)) ?? latestVer ?? version_1.CLI_VERSION;
|
|
178
|
+
runner.log(needsUpgrade ? `Upgraded to ${after}` : "Installed globally");
|
|
179
|
+
return {
|
|
180
|
+
action: needsUpgrade ? "upgraded" : "installed",
|
|
181
|
+
version: after,
|
|
182
|
+
previousVersion: installedVer ?? undefined,
|
|
183
|
+
latestVersion: latestVer ?? undefined,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
async function resolveSkillsSources(runner) {
|
|
187
|
+
const override = runner.env.ALPHAFOX_SKILLS_SOURCE?.trim();
|
|
188
|
+
if (override)
|
|
189
|
+
return [override];
|
|
190
|
+
const sources = [];
|
|
191
|
+
const npmRoot = await npmRootGlobal(runner);
|
|
192
|
+
if (npmRoot) {
|
|
193
|
+
const globalRoot = (0, package_root_1.globalPackageRoot)(npmRoot);
|
|
194
|
+
if ((0, package_root_1.packageHasSkills)(globalRoot))
|
|
195
|
+
sources.push(globalRoot);
|
|
196
|
+
}
|
|
197
|
+
const localRoot = (0, package_root_1.findAlphafoxPackageRoot)(runner.packageSearchDirs());
|
|
198
|
+
if (localRoot && !sources.includes(localRoot) && (0, package_root_1.packageHasSkills)(localRoot)) {
|
|
199
|
+
sources.push(localRoot);
|
|
200
|
+
}
|
|
201
|
+
sources.push(types_1.SKILLS_GITHUB_SOURCE);
|
|
202
|
+
return sources;
|
|
203
|
+
}
|
|
204
|
+
async function skillsAlreadyInstalled(runner) {
|
|
205
|
+
try {
|
|
206
|
+
const { stdout, stderr } = await runner.exec("npx", ["-y", "skills", "ls", "-g"], { timeoutMs: SKILLS_TIMEOUT_MS });
|
|
207
|
+
return skillsListHasAlphafox(`${stdout}\n${stderr}`);
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
async function stepInstallSkills(flags, runner) {
|
|
214
|
+
const sources = await resolveSkillsSources(runner);
|
|
215
|
+
const already = flags.dryRun ? false : await skillsAlreadyInstalled(runner);
|
|
216
|
+
if (already) {
|
|
217
|
+
runner.log("Skills already installed. Skipped");
|
|
218
|
+
return {
|
|
219
|
+
action: "skipped",
|
|
220
|
+
source: sources[0],
|
|
221
|
+
scope: "global",
|
|
222
|
+
alreadyPresent: true,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
if (flags.dryRun) {
|
|
226
|
+
runner.log(`Would install Skills from ${sources[0] ?? types_1.SKILLS_GITHUB_SOURCE}`);
|
|
227
|
+
return {
|
|
228
|
+
action: "planned",
|
|
229
|
+
source: sources[0] ?? types_1.SKILLS_GITHUB_SOURCE,
|
|
230
|
+
scope: "global",
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
runner.log("Installing AI Skills...");
|
|
234
|
+
let lastError;
|
|
235
|
+
for (const source of sources) {
|
|
236
|
+
try {
|
|
237
|
+
await runner.exec("npx", ["-y", "skills", "add", source, "-y", "-g"], { timeoutMs: SKILLS_TIMEOUT_MS });
|
|
238
|
+
runner.log(`Skills installed (${source})`);
|
|
239
|
+
return { action: "installed", source, scope: "global" };
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
lastError = err;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
throw new types_1.InstallError({
|
|
246
|
+
type: "install",
|
|
247
|
+
subtype: "skills_add_failed",
|
|
248
|
+
message: "Failed to install Agent Skills.",
|
|
249
|
+
hint: `npx skills add ${types_1.SKILLS_GITHUB_SOURCE} -y -g`,
|
|
250
|
+
details: lastError instanceof Error ? lastError.message : String(lastError),
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
async function resolveAlphafoxBin(runner) {
|
|
254
|
+
const prefix = await npmPrefixGlobal(runner);
|
|
255
|
+
if (prefix) {
|
|
256
|
+
const bin = (0, package_root_1.globalBinPath)(prefix);
|
|
257
|
+
if ((0, node_fs_1.existsSync)(bin))
|
|
258
|
+
return bin;
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
const { stdout } = await runner.exec(process.platform === "win32" ? "where" : "which", ["alphafox"], { timeoutMs: 10_000 });
|
|
262
|
+
const first = stdout.split(/\r?\n/)[0]?.trim();
|
|
263
|
+
return first || null;
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async function stepAuth(flags, runner) {
|
|
270
|
+
if (flags.noAuth) {
|
|
271
|
+
return { action: "skipped", reason: "no-auth" };
|
|
272
|
+
}
|
|
273
|
+
if (flags.noInput || !runner.isTty()) {
|
|
274
|
+
if (flags.dryRun) {
|
|
275
|
+
return { action: "planned", reason: "non-interactive" };
|
|
276
|
+
}
|
|
277
|
+
runner.log("To finish setup, run:\n alphafox auth login --browser\n alphafox auth login --no-wait --format json --no-input");
|
|
278
|
+
return { action: "skipped", reason: "non-interactive" };
|
|
279
|
+
}
|
|
280
|
+
if (flags.dryRun) {
|
|
281
|
+
runner.log("Would prompt for alphafox auth login --browser");
|
|
282
|
+
return { action: "planned", reason: "tty" };
|
|
283
|
+
}
|
|
284
|
+
const yes = await runner.confirm("Log in now so Agents can call the public Application API?");
|
|
285
|
+
if (!yes) {
|
|
286
|
+
runner.log("Skipped login. Run alphafox auth login later.");
|
|
287
|
+
return { action: "skipped", reason: "declined" };
|
|
288
|
+
}
|
|
289
|
+
const bin = await resolveAlphafoxBin(runner);
|
|
290
|
+
if (!bin) {
|
|
291
|
+
throw new types_1.InstallError({
|
|
292
|
+
type: "install",
|
|
293
|
+
subtype: "cli_bin_missing",
|
|
294
|
+
message: "alphafox binary not found after install.",
|
|
295
|
+
hint: "Ensure the npm global bin directory is on PATH, then run alphafox auth login --browser.",
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
await runner.execInherit(bin, ["auth", "login", "--browser"], {
|
|
300
|
+
timeoutMs: 10 * 60_000,
|
|
301
|
+
});
|
|
302
|
+
runner.log("Login complete");
|
|
303
|
+
return { action: "completed" };
|
|
304
|
+
}
|
|
305
|
+
catch (err) {
|
|
306
|
+
runner.log("Login failed. Run alphafox auth login --browser to retry.");
|
|
307
|
+
return {
|
|
308
|
+
action: "failed",
|
|
309
|
+
reason: err instanceof Error ? err.message : String(err),
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function installHelpData() {
|
|
314
|
+
return {
|
|
315
|
+
name: "install",
|
|
316
|
+
usage: [
|
|
317
|
+
"npx @alphafox/cli@latest install",
|
|
318
|
+
"alphafox install",
|
|
319
|
+
"alphafox install --no-auth",
|
|
320
|
+
"alphafox install --dry-run",
|
|
321
|
+
],
|
|
322
|
+
description: "Install @alphafox/cli globally and copy co-versioned Agent Skills into detected agents (Cursor, Claude Code, Codex, …) via npx skills add.",
|
|
323
|
+
agentGuide: types_1.AGENT_INSTALL_GUIDE_BLOB_URL,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
function resolveLocalSkillsDir(searchDirs) {
|
|
327
|
+
const root = (0, package_root_1.findAlphafoxPackageRoot)(searchDirs);
|
|
328
|
+
if (!root)
|
|
329
|
+
return null;
|
|
330
|
+
const skillsDir = (0, node_path_1.join)(root, "skills");
|
|
331
|
+
return (0, package_root_1.packageHasSkills)(root) ? skillsDir : null;
|
|
332
|
+
}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -3,6 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.CLI_CONTRACT_VERSION = exports.CLI_VERSION = exports.CLI_PACKAGE = exports.CLI_NAME = void 0;
|
|
4
4
|
exports.CLI_NAME = "alphafox";
|
|
5
5
|
exports.CLI_PACKAGE = "@alphafox/cli";
|
|
6
|
-
exports.CLI_VERSION = "0.2
|
|
6
|
+
exports.CLI_VERSION = "0.3.2";
|
|
7
7
|
var operations_1 = require("./catalog/operations");
|
|
8
8
|
Object.defineProperty(exports, "CLI_CONTRACT_VERSION", { enumerable: true, get: function () { return operations_1.CATALOG_VERSION; } });
|
package/docs/.nojekyll
ADDED
|
File without changes
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Alphafox CLI installation guide
|
|
2
|
+
|
|
3
|
+
The following steps are designed for AI Agents. Some steps require the user
|
|
4
|
+
to complete a browser or Device Flow approval. Always use
|
|
5
|
+
`--format json --no-input` when invoking the CLI. Never pass `--token`.
|
|
6
|
+
|
|
7
|
+
Raw copy of this file:
|
|
8
|
+
https://raw.githubusercontent.com/alphafoxai/alphafox-cli/main/docs/alphafox-cli-installation-guide.md
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
- Node.js 20+ (`npm` / `npx`)
|
|
13
|
+
|
|
14
|
+
## Step 1: Install the CLI and Agent Skills
|
|
15
|
+
|
|
16
|
+
Skills do **not** register with Cursor / Claude Code / Codex from
|
|
17
|
+
`npm install -g` alone. The second command is required.
|
|
18
|
+
|
|
19
|
+
```shell
|
|
20
|
+
# Install CLI
|
|
21
|
+
npm install -g @alphafox/cli
|
|
22
|
+
|
|
23
|
+
# Install CLI SKILL (required) — project-local, current workspace
|
|
24
|
+
npx -y skills add "$(npm root -g)/@alphafox/cli" -y
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
If the local package path fails (older tarball without `skills/`, or
|
|
28
|
+
`npm root -g` is wrong), fall back to the public GitHub source:
|
|
29
|
+
|
|
30
|
+
```shell
|
|
31
|
+
npx -y skills add alphafoxai/alphafox-cli -y
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
To install Skills for every project on this machine instead of the current
|
|
35
|
+
repo, add `-g`:
|
|
36
|
+
|
|
37
|
+
```shell
|
|
38
|
+
npx -y skills add "$(npm root -g)/@alphafox/cli" -y -g
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Do not invent a second catalog. Skills must stay co-versioned with the CLI
|
|
42
|
+
that was just installed.
|
|
43
|
+
|
|
44
|
+
## Step 2: Login
|
|
45
|
+
|
|
46
|
+
### Device Flow (headless / Agent)
|
|
47
|
+
|
|
48
|
+
1. Start login and extract `verification_uri` / `user_code` from the JSON
|
|
49
|
+
envelope. Send those to the user. Do not poll in a tight loop.
|
|
50
|
+
|
|
51
|
+
```shell
|
|
52
|
+
alphafox auth login --no-wait --format json --no-input
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
2. After the user approves, resume with the `device_code` from step 1:
|
|
56
|
+
|
|
57
|
+
```shell
|
|
58
|
+
alphafox auth login --device-code <device_code> --format json --no-input
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Browser loopback (human on this machine)
|
|
62
|
+
|
|
63
|
+
If the user is at a local desktop and can use a browser:
|
|
64
|
+
|
|
65
|
+
```shell
|
|
66
|
+
alphafox auth login --browser --format json --no-input
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The CLI binds `127.0.0.1` and opens the system browser. If the browser
|
|
70
|
+
cannot open, the error includes a copyable `authorizeUrl` — send that to
|
|
71
|
+
the user. Do not retry as Device Flow unless the operator is headless.
|
|
72
|
+
|
|
73
|
+
Default profile is `production`. Use `--profile staging|local` only when
|
|
74
|
+
the user explicitly asks.
|
|
75
|
+
|
|
76
|
+
## Step 3: Verify
|
|
77
|
+
|
|
78
|
+
```shell
|
|
79
|
+
alphafox doctor --format json --no-input
|
|
80
|
+
alphafox auth status --verify --format json --no-input
|
|
81
|
+
alphafox whoami --format json --no-input
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Parse the JSON envelope: `ok === true` means success. Errors land on
|
|
85
|
+
**stderr**. A 401 / expired session means re-run Step 2 — do not pass
|
|
86
|
+
`--token` and do not reuse a token from another profile.
|
|
87
|
+
|
|
88
|
+
## Step 4: Tell the user to restart
|
|
89
|
+
|
|
90
|
+
Ask the user to **restart the AI tool** so the new Skills are loaded.
|
|
91
|
+
Then they can ask the Agent to use Alphafox (auth, catalog, trading,
|
|
92
|
+
engine-backtest, …).
|
|
93
|
+
|
|
94
|
+
## Human wizard (do not run this from an Agent)
|
|
95
|
+
|
|
96
|
+
Humans who prefer an interactive terminal should run this instead of
|
|
97
|
+
stepping through the commands above:
|
|
98
|
+
|
|
99
|
+
```shell
|
|
100
|
+
npx @alphafox/cli@latest install
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
That wizard installs the CLI globally, runs `npx skills add … -y -g`,
|
|
104
|
+
and may prompt for `alphafox auth login --browser`. It is TTY-oriented.
|
|
105
|
+
Agents must follow Steps 1–4 in this document rather than the wizard.
|
package/docs/favicon.svg
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg width="880" height="1320" viewBox="560 400 880 1320" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M600 859.99V448.467C600 444.343 603.341 440.997 607.455 441.283C633.947 443.127 687.377 454.464 738.326 489.713C790.889 526.08 819.686 577.964 829.376 603.853C830.516 606.899 833.375 608.999 836.627 608.999H974.473C977.797 608.999 980.699 606.816 981.805 603.682C989.573 581.673 1012.28 537.164 1054.85 499.081C1097.95 460.53 1170.23 445.26 1207.73 441.629C1212.01 441.215 1215.61 444.632 1215.61 448.934V860.713C1215.61 864.837 1212.28 868.175 1208.15 868.278C1166.66 869.316 1082.4 878.881 1024.32 911.272C971.303 940.844 930.998 987.234 911.43 1015.2C907.935 1020.2 899.832 1019.72 896.775 1014.44C882.18 989.258 849.547 947.01 795.65 911.272C735.079 871.11 650.192 865.287 608.157 867.588C603.768 867.828 600 864.385 600 859.99Z" fill="#FF991F"/>
|
|
3
|
+
<path d="M600.58 1235.01L600.58 969.867C600.58 965.744 603.924 962.4 608.047 962.458C675.284 963.412 740.225 977.952 799.655 1043.32C866.429 1116.76 897.008 1187.09 1027.44 1187.09L1133.53 1187.09C1290.79 1187.09 1400 1305.96 1400 1452.22L1400 1676.91C1400 1684.08 1391.55 1686.6 1387.59 1680.62C1357.88 1635.76 1286.34 1537.49 1154.22 1537.49L897.008 1537.49C718.527 1537.49 600.58 1420.82 600.58 1235.01Z" fill="#FF991F"/>
|
|
4
|
+
</svg>
|