@jovan158/vantage
Version:
See and control what your coding agent does
91 lines (90 loc) • 4.12 kB
JavaScript
// vantage — see and control what your coding agent does.
//
// The entry point: parses the command and hands over to src/commands/. Its
// own path is what Claude Code starts for the approval hook, so it is passed
// to the commands that register or check that hook.
import { fileURLToPath } from "node:url";
import { knownAgents } from "./agents/index.js";
import { banner, bannerForStdout } from "./banner.js";
import { log } from "./commands/output.js";
import { cmdRun } from "./commands/run.js";
import { cmdWatch } from "./commands/watch.js";
import { cmdHook } from "./commands/hook.js";
import { cmdReview, cmdDiscard } from "./commands/review.js";
import { cmdSessions, cmdReplay, cmdHarvest } from "./commands/sessions.js";
import { cmdStats } from "./commands/stats.js";
import { cmdSearch } from "./commands/search.js";
import { cmdDoctor } from "./commands/doctor.js";
import { cmdPolicy } from "./commands/policy.js";
import { cmdPricing } from "./commands/pricing.js";
import { cmdMemory } from "./commands/memory.js";
import { cmdDemo } from "./commands/demo.js";
const ENTRY = fileURLToPath(import.meta.url);
// The logo heads the help when it is asked for; after a mistyped command
// the help follows the error, plain.
function printHelp(withLogo = true) {
const head = withLogo ? bannerForStdout() : banner({ art: false, color: false });
process.stdout.write(`${head}\n\n` +
`Usage:\n` +
` vantage run [--isolate] [--no-memory] [--max-cost <usd>] [--max-quota <percent>]\n` +
` <agent> [-- <agent args...>]\n` +
` vantage watch [sessionId]\n` +
` vantage sessions [prune [--older-than 30d] [--all] [--yes]]\n` +
` vantage stats [--days N]\n` +
` vantage search <text> [--files | --commands]\n` +
` vantage replay <sessionId>\n` +
` vantage harvest [sessionId]\n` +
` vantage review <sessionId> [--patch]\n` +
` vantage discard <sessionId>\n` +
` vantage memory <init|show|add <category> <text>>\n` +
` vantage policy [init]\n` +
` vantage pricing [show|update|check] [anthropic|openai|google]\n` +
` vantage doctor [agent]\n` +
` vantage demo\n` +
` vantage --help\n\n` +
`Agents: ${knownAgents().join(", ")}\n\n` +
`--isolate runs the agent in a dedicated git worktree/branch so your\n` +
`working tree is untouched; review or discard the changes afterwards.\n` +
`Project memory under .vantage/memory/ is injected into the agent unless\n` +
`--no-memory is given.\n\n` +
`--max-cost 2 / --max-quota 80 set a budget: once the session's estimated\n` +
`cost reaches $2, or a subscription quota window 80%, every action needs\n` +
`your approval. Also settable as VANTAGE_MAX_COST / VANTAGE_MAX_QUOTA.\n\n` +
`VANTAGE_AGENT_PATH=<path> starts the agent from that executable instead of\n` +
`looking it up on PATH.\n\n` +
`Prices come from Anthropic's, OpenAI's and Google's official lists: a copy\n` +
`ships with vantage, and \`vantage pricing update\` fetches the current ones.\n` +
`Nothing is fetched unless you run that command.\n`);
}
const COMMANDS = {
run: (argv) => cmdRun(argv, ENTRY),
watch: cmdWatch,
sessions: cmdSessions,
stats: cmdStats,
search: cmdSearch,
replay: cmdReplay,
harvest: cmdHarvest,
review: cmdReview,
discard: cmdDiscard,
memory: cmdMemory,
policy: cmdPolicy,
pricing: cmdPricing,
hook: (argv) => cmdHook(argv),
doctor: (argv) => cmdDoctor(argv, ENTRY),
demo: () => cmdDemo(),
};
async function main() {
const [cmd, ...rest] = process.argv.slice(2);
if (cmd === undefined || cmd === "-h" || cmd === "--help" || cmd === "help") {
printHelp();
process.exit(0);
}
const run = Object.hasOwn(COMMANDS, cmd) ? COMMANDS[cmd] : undefined;
if (!run) {
log(`unknown command "${cmd}"`);
printHelp(false);
process.exit(1);
}
process.exit(await run(rest));
}
void main();