enigma-cli 1.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/LICENSE +202 -0
- package/README.md +87 -0
- package/assets/memory/AGENTS.md +270 -0
- package/assets/memory/CLAUDE.md +270 -0
- package/assets/skills/backend-policy/SKILL.md +84 -0
- package/assets/skills/backend-policy/skill.json +8 -0
- package/assets/skills/ciphera-style-policy/SKILL.md +136 -0
- package/assets/skills/ciphera-style-policy/skill.json +8 -0
- package/assets/skills/code-review-policy/SKILL.md +68 -0
- package/assets/skills/code-review-policy/skill.json +8 -0
- package/assets/skills/core-engineering-policy/SKILL.md +277 -0
- package/assets/skills/core-engineering-policy/skill.json +8 -0
- package/assets/skills/database-expert/SKILL.md +224 -0
- package/assets/skills/database-expert/skill.json +8 -0
- package/assets/skills/debugging-policy/SKILL.md +59 -0
- package/assets/skills/debugging-policy/skill.json +8 -0
- package/assets/skills/dependency-policy/SKILL.md +61 -0
- package/assets/skills/dependency-policy/skill.json +8 -0
- package/assets/skills/frontend-policy/SKILL.md +117 -0
- package/assets/skills/frontend-policy/skill.json +8 -0
- package/assets/skills/git-policy/SKILL.md +192 -0
- package/assets/skills/git-policy/skill.json +8 -0
- package/assets/skills/security-policy/SKILL.md +86 -0
- package/assets/skills/security-policy/skill.json +8 -0
- package/assets/skills/testing-policy/SKILL.md +76 -0
- package/assets/skills/testing-policy/skill.json +8 -0
- package/assets/skills/validation-policy/SKILL.md +77 -0
- package/assets/skills/validation-policy/skill.json +8 -0
- package/dist/enigma.js +1068 -0
- package/dist/guard.js +153 -0
- package/package.json +65 -0
package/dist/guard.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/guard.ts
|
|
4
|
+
import { readFileSync, statSync } from "fs";
|
|
5
|
+
import { execFileSync } from "child_process";
|
|
6
|
+
import { basename, extname, dirname, join } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
var LARGE_FILE_BYTES = 5 * 1024 * 1024;
|
|
9
|
+
var ENV_ALLOWED = /(example|sample|template)/i;
|
|
10
|
+
var isForbiddenEnv = (base) => /^\.env(\..+)?$/.test(base) && !ENV_ALLOWED.test(base);
|
|
11
|
+
var BLOCK_DIRS = [
|
|
12
|
+
/(^|\/)node_modules\//,
|
|
13
|
+
/(^|\/)bower_components\//,
|
|
14
|
+
/(^|\/)\.pnp(\/|$)/,
|
|
15
|
+
/(^|\/)__pycache__\//,
|
|
16
|
+
/(^|\/)\.venv\//,
|
|
17
|
+
/(^|\/)venv\//,
|
|
18
|
+
/(^|\/)\.mypy_cache\//,
|
|
19
|
+
/(^|\/)\.pytest_cache\//,
|
|
20
|
+
/(^|\/)\.gradle\//
|
|
21
|
+
];
|
|
22
|
+
var WARN_DIRS = [
|
|
23
|
+
/(^|\/)dist\//,
|
|
24
|
+
/(^|\/)build\//,
|
|
25
|
+
/(^|\/)out\//,
|
|
26
|
+
/(^|\/)\.next\//,
|
|
27
|
+
/(^|\/)\.nuxt\//,
|
|
28
|
+
/(^|\/)\.svelte-kit\//,
|
|
29
|
+
/(^|\/)\.turbo\//,
|
|
30
|
+
/(^|\/)coverage\//
|
|
31
|
+
];
|
|
32
|
+
var WARN_FILES = [/\.log$/i, /(^|\/)\.DS_Store$/, /(^|\/)Thumbs\.db$/i];
|
|
33
|
+
var SECRET_SKIP_EXT = /* @__PURE__ */ new Set([
|
|
34
|
+
".png",
|
|
35
|
+
".jpg",
|
|
36
|
+
".jpeg",
|
|
37
|
+
".gif",
|
|
38
|
+
".webp",
|
|
39
|
+
".ico",
|
|
40
|
+
".pdf",
|
|
41
|
+
".zip",
|
|
42
|
+
".gz",
|
|
43
|
+
".woff",
|
|
44
|
+
".woff2",
|
|
45
|
+
".ttf",
|
|
46
|
+
".eot",
|
|
47
|
+
".mp4",
|
|
48
|
+
".mov",
|
|
49
|
+
".lock"
|
|
50
|
+
]);
|
|
51
|
+
var SECRET_PATTERNS = [
|
|
52
|
+
["AWS access key id", /\bAKIA[0-9A-Z]{16}\b/],
|
|
53
|
+
["GitHub token", /\bgh[pousr]_[A-Za-z0-9]{36,}\b/],
|
|
54
|
+
["OpenAI API key", /\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/],
|
|
55
|
+
["Anthropic API key", /\bsk-ant-[A-Za-z0-9_-]{20,}\b/],
|
|
56
|
+
["Slack token", /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/],
|
|
57
|
+
["Google API key", /\bAIza[0-9A-Za-z_-]{35}\b/],
|
|
58
|
+
["Stripe secret key", /\bsk_live_[0-9A-Za-z]{24,}\b/],
|
|
59
|
+
["Private key block", /-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/],
|
|
60
|
+
["Generic bearer secret", /\b(?:secret|token|api[_-]?key|passwd|password)\s*[:=]\s*["'][A-Za-z0-9_\-./+]{16,}["']/i]
|
|
61
|
+
];
|
|
62
|
+
var SECRET_SKIP_PATH = [/(^|\/)node_modules\//, /(^|\/)\.git\//, /package-lock\.json$/, /guard\.[mc]?js$/];
|
|
63
|
+
var SELF_DIR = dirname(fileURLToPath(import.meta.url));
|
|
64
|
+
function loadConfig() {
|
|
65
|
+
const defaults = { secrets: true, envFiles: true, depDirs: true, generatedDirs: true, junkFiles: true, largeFiles: true };
|
|
66
|
+
try {
|
|
67
|
+
const raw = JSON.parse(readFileSync(join(SELF_DIR, "enigma-guard.json"), "utf8"));
|
|
68
|
+
return { ...defaults, ...raw };
|
|
69
|
+
} catch {
|
|
70
|
+
return defaults;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function gitFiles(all) {
|
|
74
|
+
const out = execFileSync("git", all ? ["ls-files"] : ["diff", "--cached", "--name-only", "--diff-filter=ACM"], { encoding: "utf8" });
|
|
75
|
+
return out.split("\n").map((s) => s.trim()).filter(Boolean);
|
|
76
|
+
}
|
|
77
|
+
function scanSecrets(file, blocks) {
|
|
78
|
+
if (SECRET_SKIP_PATH.some((re) => re.test(file))) return;
|
|
79
|
+
if (SECRET_SKIP_EXT.has(extname(file).toLowerCase())) return;
|
|
80
|
+
let text;
|
|
81
|
+
try {
|
|
82
|
+
text = readFileSync(file, "utf8");
|
|
83
|
+
} catch {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (text.includes("\0")) return;
|
|
87
|
+
text.split("\n").forEach((line, i) => {
|
|
88
|
+
for (const [label, re] of SECRET_PATTERNS) {
|
|
89
|
+
if (re.test(line)) blocks.push(`${file}:${i + 1} [secret: ${label}]`);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function runGuard({ all = false } = {}) {
|
|
94
|
+
const cfg = loadConfig();
|
|
95
|
+
let files;
|
|
96
|
+
try {
|
|
97
|
+
files = gitFiles(all);
|
|
98
|
+
} catch {
|
|
99
|
+
return { ok: true, blocks: [], warns: [], notRepo: true };
|
|
100
|
+
}
|
|
101
|
+
const blocks = [];
|
|
102
|
+
const warns = [];
|
|
103
|
+
for (const file of files) {
|
|
104
|
+
const base = basename(file);
|
|
105
|
+
if (cfg.envFiles && isForbiddenEnv(base)) {
|
|
106
|
+
blocks.push(`${file} [env file with secrets - commit .env.example/.template instead]`);
|
|
107
|
+
}
|
|
108
|
+
if (cfg.depDirs && BLOCK_DIRS.some((re) => re.test(file))) {
|
|
109
|
+
blocks.push(`${file} [dependency/cache dir - must not be committed]`);
|
|
110
|
+
} else if (cfg.generatedDirs && WARN_DIRS.some((re) => re.test(file))) {
|
|
111
|
+
warns.push(`${file} [looks generated - confirm you really want it tracked]`);
|
|
112
|
+
}
|
|
113
|
+
if (cfg.junkFiles && WARN_FILES.some((re) => re.test(file))) warns.push(`${file} [log / OS junk file]`);
|
|
114
|
+
if (cfg.largeFiles) {
|
|
115
|
+
try {
|
|
116
|
+
if (statSync(file).size > LARGE_FILE_BYTES) warns.push(`${file} [larger than 5 MB]`);
|
|
117
|
+
} catch {
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (cfg.secrets) scanSecrets(file, blocks);
|
|
121
|
+
}
|
|
122
|
+
return { ok: blocks.length === 0, blocks, warns, count: files.length, all };
|
|
123
|
+
}
|
|
124
|
+
function runGuardCli(all) {
|
|
125
|
+
const r = runGuard({ all });
|
|
126
|
+
if (r.notRepo) {
|
|
127
|
+
console.error("enigma-guard: not a git repository; nothing to check.");
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
if (r.warns.length) {
|
|
131
|
+
console.error(`enigma-guard: ${r.warns.length} warning(s):`);
|
|
132
|
+
for (const w of r.warns) console.error(` ! ${w}`);
|
|
133
|
+
}
|
|
134
|
+
if (r.blocks.length) {
|
|
135
|
+
console.error(`
|
|
136
|
+
enigma-guard: BLOCKED - ${r.blocks.length} problem(s) must be fixed before committing:`);
|
|
137
|
+
for (const b of r.blocks) console.error(` x ${b}`);
|
|
138
|
+
console.error("\nFix the above (move secrets to env/secret manager, gitignore generated paths).");
|
|
139
|
+
console.error("To bypass intentionally for one commit: git commit --no-verify");
|
|
140
|
+
return 1;
|
|
141
|
+
}
|
|
142
|
+
console.log(`enigma-guard: ${r.count} ${r.all ? "tracked" : "staged"} file(s) checked, no blocking problems.`);
|
|
143
|
+
return 0;
|
|
144
|
+
}
|
|
145
|
+
var guardEntry = process.argv[1] ?? "";
|
|
146
|
+
var isGuardEntry = /(^|[\\/])guard\.[mc]?[jt]s$/.test(guardEntry);
|
|
147
|
+
if (isGuardEntry && fileURLToPath(import.meta.url) === guardEntry) {
|
|
148
|
+
process.exit(runGuardCli(process.argv.includes("--all")));
|
|
149
|
+
}
|
|
150
|
+
export {
|
|
151
|
+
runGuard,
|
|
152
|
+
runGuardCli
|
|
153
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "enigma-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Everything you need to work with a coding agent: install shared policy skills for Claude Code, OpenAI Codex and opencode, and set up portable git security hooks.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"enigma": "dist/enigma.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"enigma": "tsx src/bin/enigma.ts",
|
|
11
|
+
"build": "tsup",
|
|
12
|
+
"dev": "tsup --watch",
|
|
13
|
+
"typecheck": "tsc --noEmit",
|
|
14
|
+
"seal": "tsx src/bin/enigma.ts seal",
|
|
15
|
+
"check": "tsx src/bin/enigma.ts check",
|
|
16
|
+
"guard": "tsx src/guard.ts --all",
|
|
17
|
+
"verify": "npm run typecheck && npm run check && npm run guard",
|
|
18
|
+
"prepublishOnly": "npm run verify && npm run build"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"assets",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@clack/prompts": "^0.7.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^22.0.0",
|
|
34
|
+
"tsup": "^8.0.0",
|
|
35
|
+
"tsx": "^4.0.0",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"ai",
|
|
40
|
+
"agent",
|
|
41
|
+
"claude-code",
|
|
42
|
+
"codex",
|
|
43
|
+
"opencode",
|
|
44
|
+
"skills",
|
|
45
|
+
"agents.md",
|
|
46
|
+
"git-hooks",
|
|
47
|
+
"secrets",
|
|
48
|
+
"cli"
|
|
49
|
+
],
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/FJRG2007/enigma.git",
|
|
53
|
+
"directory": "packages/enigma-cli"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/FJRG2007/enigma#readme",
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/FJRG2007/enigma/issues"
|
|
58
|
+
},
|
|
59
|
+
"author": "FJRG2007 <fjrg2007@tpeoficial.com>",
|
|
60
|
+
"license": "Apache-2.0",
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public",
|
|
63
|
+
"provenance": true
|
|
64
|
+
}
|
|
65
|
+
}
|