@jovan158/vantage
Version:
See and control what your coding agent does
47 lines (46 loc) • 2.27 kB
JavaScript
// `vantage policy [init]`: show the rules in effect, or create a starter set.
import fs from "node:fs";
import path from "node:path";
import { loadPolicy, needsEnforcement } from "../policy.js";
import { loadRules, policyFilePath, STARTER_POLICY } from "../rules.js";
import { log } from "./output.js";
export async function cmdPolicy(argv) {
const cwd = process.cwd();
const file = policyFilePath(cwd);
if (argv[0] === "init") {
if (fs.existsSync(file)) {
log(`${path.relative(cwd, file)} already exists — left unchanged`);
return 1;
}
fs.mkdirSync(path.dirname(file), { recursive: true });
fs.writeFileSync(file, JSON.stringify(STARTER_POLICY, null, 2) + "\n");
log(`created ${path.relative(cwd, file)} with recommended rules — edit it to fit your project`);
}
else if (argv[0]) {
log(`unknown policy command "${argv[0]}" (show | init)`);
return 1;
}
const color = (level) => (level === "deny" ? "\x1b[31m" : level === "ask" || level === "warn" ? "\x1b[33m" : "") + level + "\x1b[0m";
const policy = loadPolicy(cwd);
log("by action type — allow · warn (notice only) · ask (approval) · deny (blocked):");
for (const [type, level] of Object.entries(policy)) {
process.stdout.write(` ${type.padEnd(8)} ${color(level)}\n`);
}
const rules = loadRules(file);
for (const kind of ["file", "command"]) {
const list = rules.filter((r) => r.kind === kind);
if (!list.length)
continue;
log(`${kind} rules — override the action type when they match; the strictest match wins:`);
const width = Math.max(...list.map((r) => r.pattern.length));
for (const r of list)
process.stdout.write(` ${r.pattern.padEnd(width)} ${color(r.level)}\n`);
}
if (needsEnforcement(policy) || rules.some((r) => r.level === "ask" || r.level === "deny")) {
log("ask/deny are enforced through Claude Code's PreToolUse hook");
}
if (!rules.length)
log("no file or command rules yet — `vantage policy init` creates a starter set");
log("configure in .vantage/policy.json (VANTAGE_POLICY=\"shell:deny,network:ask\" overrides action types)");
return 0;
}