engram-harness 0.1.1 → 0.1.3
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/dist/cli.js +45 -69
- package/package.json +6 -5
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
// @bun
|
|
1
|
+
#!/usr/bin/env node
|
|
3
2
|
import { createRequire } from "node:module";
|
|
4
3
|
var __create = Object.create;
|
|
5
4
|
var __getProtoOf = Object.getPrototypeOf;
|
|
@@ -12029,42 +12028,9 @@ function skillCreate(name) {
|
|
|
12029
12028
|
console.log(" 3. Run 'engram skill index' to register the skill");
|
|
12030
12029
|
}
|
|
12031
12030
|
|
|
12032
|
-
// src/commands/skill-index.ts
|
|
12033
|
-
import { readdirSync as readdirSync3, existsSync as existsSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
12034
|
-
import { join as join5 } from "path";
|
|
12035
|
-
function skillIndex2() {
|
|
12036
|
-
const skillsDir = join5(process.env.HOME || "", ".claude", "skills");
|
|
12037
|
-
if (!existsSync5(skillsDir)) {
|
|
12038
|
-
console.error(" No skills directory found at ~/.claude/skills/");
|
|
12039
|
-
process.exit(1);
|
|
12040
|
-
}
|
|
12041
|
-
const entries = [];
|
|
12042
|
-
const dirs = readdirSync3(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
12043
|
-
for (const dir of dirs) {
|
|
12044
|
-
const skillMdPath = join5(skillsDir, dir.name, "SKILL.md");
|
|
12045
|
-
if (!existsSync5(skillMdPath))
|
|
12046
|
-
continue;
|
|
12047
|
-
const metadata = parseSkillFrontmatter(skillMdPath);
|
|
12048
|
-
if (!metadata)
|
|
12049
|
-
continue;
|
|
12050
|
-
entries.push({
|
|
12051
|
-
name: metadata.name,
|
|
12052
|
-
description: metadata.description,
|
|
12053
|
-
triggers: extractUseWhen(metadata.description),
|
|
12054
|
-
path: skillMdPath
|
|
12055
|
-
});
|
|
12056
|
-
}
|
|
12057
|
-
const indexPath = join5(skillsDir, "skill-index.json");
|
|
12058
|
-
writeFileSync4(indexPath, JSON.stringify(entries, null, 2));
|
|
12059
|
-
console.log(` Indexed ${entries.length} skills -> ${indexPath}`);
|
|
12060
|
-
for (const entry of entries) {
|
|
12061
|
-
console.log(` ${entry.name}: ${entry.triggers.length} triggers`);
|
|
12062
|
-
}
|
|
12063
|
-
}
|
|
12064
|
-
|
|
12065
12031
|
// src/commands/bundle.ts
|
|
12066
|
-
import { mkdirSync as mkdirSync3, writeFileSync as
|
|
12067
|
-
import { join as
|
|
12032
|
+
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
12033
|
+
import { join as join6 } from "path";
|
|
12068
12034
|
|
|
12069
12035
|
// src/lib/instructions.ts
|
|
12070
12036
|
function renderInstructionsMd(config) {
|
|
@@ -12169,20 +12135,20 @@ Core rules:
|
|
|
12169
12135
|
}
|
|
12170
12136
|
|
|
12171
12137
|
// src/lib/flatten-skill.ts
|
|
12172
|
-
import { readFileSync as readFileSync4, readdirSync as
|
|
12173
|
-
import { join as
|
|
12138
|
+
import { readFileSync as readFileSync4, readdirSync as readdirSync3, existsSync as existsSync5 } from "fs";
|
|
12139
|
+
import { join as join5 } from "path";
|
|
12174
12140
|
function flattenSkill(skillDir) {
|
|
12175
|
-
const skillMdPath =
|
|
12176
|
-
if (!
|
|
12141
|
+
const skillMdPath = join5(skillDir, "SKILL.md");
|
|
12142
|
+
if (!existsSync5(skillMdPath)) {
|
|
12177
12143
|
return null;
|
|
12178
12144
|
}
|
|
12179
12145
|
let content = readFileSync4(skillMdPath, "utf-8");
|
|
12180
12146
|
content = content.replace(/^---\n[\s\S]*?\n---\n*/, "");
|
|
12181
|
-
const workflowsDir =
|
|
12182
|
-
if (
|
|
12183
|
-
const workflows =
|
|
12147
|
+
const workflowsDir = join5(skillDir, "Workflows");
|
|
12148
|
+
if (existsSync5(workflowsDir)) {
|
|
12149
|
+
const workflows = readdirSync3(workflowsDir).filter((f) => f.endsWith(".md")).sort();
|
|
12184
12150
|
for (const file of workflows) {
|
|
12185
|
-
const workflowContent = readFileSync4(
|
|
12151
|
+
const workflowContent = readFileSync4(join5(workflowsDir, file), "utf-8");
|
|
12186
12152
|
const name = file.replace(".md", "");
|
|
12187
12153
|
content += `
|
|
12188
12154
|
---
|
|
@@ -12196,13 +12162,13 @@ ${workflowContent.trim()}
|
|
|
12196
12162
|
return content.trim();
|
|
12197
12163
|
}
|
|
12198
12164
|
function flattenAllSkills(skillsDir) {
|
|
12199
|
-
if (!
|
|
12165
|
+
if (!existsSync5(skillsDir)) {
|
|
12200
12166
|
return [];
|
|
12201
12167
|
}
|
|
12202
12168
|
const results = [];
|
|
12203
|
-
const dirs =
|
|
12169
|
+
const dirs = readdirSync3(skillsDir, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
12204
12170
|
for (const dir of dirs) {
|
|
12205
|
-
const content = flattenSkill(
|
|
12171
|
+
const content = flattenSkill(join5(skillsDir, dir.name));
|
|
12206
12172
|
if (content) {
|
|
12207
12173
|
results.push({ name: dir.name, content });
|
|
12208
12174
|
}
|
|
@@ -12257,22 +12223,22 @@ async function bundle(options) {
|
|
|
12257
12223
|
console.log("");
|
|
12258
12224
|
console.log(" Generating bundle...");
|
|
12259
12225
|
console.log("");
|
|
12260
|
-
const skillsOutputDir =
|
|
12226
|
+
const skillsOutputDir = join6(outputDir, "skills");
|
|
12261
12227
|
mkdirSync3(skillsOutputDir, { recursive: true });
|
|
12262
12228
|
const instructions = renderInstructionsMd(config);
|
|
12263
|
-
|
|
12229
|
+
writeFileSync4(join6(outputDir, "INSTRUCTIONS.md"), instructions);
|
|
12264
12230
|
const context = renderContextMd(config);
|
|
12265
|
-
|
|
12266
|
-
const sourceSkillsDir =
|
|
12231
|
+
writeFileSync4(join6(outputDir, "context.md"), context);
|
|
12232
|
+
const sourceSkillsDir = join6(frameworkRoot2, "skills");
|
|
12267
12233
|
const skills = flattenAllSkills(sourceSkillsDir);
|
|
12268
12234
|
for (const skill of skills) {
|
|
12269
|
-
|
|
12235
|
+
writeFileSync4(join6(skillsOutputDir, `${skill.name}.md`), skill.content);
|
|
12270
12236
|
}
|
|
12271
12237
|
const memoryStarter = renderMemoryStarter(config);
|
|
12272
|
-
|
|
12238
|
+
writeFileSync4(join6(outputDir, "memory-starter.md"), memoryStarter);
|
|
12273
12239
|
const chatGptInstructions = renderChatGPTInstructions(config);
|
|
12274
12240
|
const setup = renderSetupMd(config, skills.length, chatGptInstructions);
|
|
12275
|
-
|
|
12241
|
+
writeFileSync4(join6(outputDir, "SETUP.md"), setup);
|
|
12276
12242
|
console.log(` Bundle generated at: ${outputDir}/`);
|
|
12277
12243
|
console.log("");
|
|
12278
12244
|
console.log(" Contents:");
|
|
@@ -34222,19 +34188,19 @@ class StdioServerTransport {
|
|
|
34222
34188
|
}
|
|
34223
34189
|
|
|
34224
34190
|
// src/commands/serve.ts
|
|
34225
|
-
import { readFileSync as readFileSync5, writeFileSync as
|
|
34226
|
-
import { join as
|
|
34191
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync4 } from "fs";
|
|
34192
|
+
import { join as join7 } from "path";
|
|
34227
34193
|
import { homedir as homedir2 } from "os";
|
|
34228
|
-
var ENGRAM_HOME =
|
|
34229
|
-
var MEMORY_DIR =
|
|
34194
|
+
var ENGRAM_HOME = join7(homedir2(), ".engram");
|
|
34195
|
+
var MEMORY_DIR = join7(ENGRAM_HOME, "memory");
|
|
34230
34196
|
var VALID_CATEGORIES = ["context", "learnings", "preferences"];
|
|
34231
34197
|
function ensureMemoryDir() {
|
|
34232
|
-
if (!
|
|
34198
|
+
if (!existsSync7(MEMORY_DIR)) {
|
|
34233
34199
|
mkdirSync4(MEMORY_DIR, { recursive: true });
|
|
34234
34200
|
}
|
|
34235
34201
|
for (const category of VALID_CATEGORIES) {
|
|
34236
|
-
const filePath =
|
|
34237
|
-
if (!
|
|
34202
|
+
const filePath = join7(MEMORY_DIR, `${category}.md`);
|
|
34203
|
+
if (!existsSync7(filePath)) {
|
|
34238
34204
|
const headers = {
|
|
34239
34205
|
context: `# Context
|
|
34240
34206
|
|
|
@@ -34249,28 +34215,28 @@ function ensureMemoryDir() {
|
|
|
34249
34215
|
*User preferences and working style.*
|
|
34250
34216
|
`
|
|
34251
34217
|
};
|
|
34252
|
-
|
|
34218
|
+
writeFileSync5(filePath, headers[category]);
|
|
34253
34219
|
}
|
|
34254
34220
|
}
|
|
34255
34221
|
}
|
|
34256
34222
|
function getCategoryPath(category) {
|
|
34257
|
-
return
|
|
34223
|
+
return join7(MEMORY_DIR, `${category}.md`);
|
|
34258
34224
|
}
|
|
34259
34225
|
function readCategory(category) {
|
|
34260
34226
|
const filePath = getCategoryPath(category);
|
|
34261
|
-
if (!
|
|
34227
|
+
if (!existsSync7(filePath)) {
|
|
34262
34228
|
return "";
|
|
34263
34229
|
}
|
|
34264
34230
|
return readFileSync5(filePath, "utf-8");
|
|
34265
34231
|
}
|
|
34266
34232
|
function appendToCategory(category, content) {
|
|
34267
34233
|
const filePath = getCategoryPath(category);
|
|
34268
|
-
const existing =
|
|
34234
|
+
const existing = existsSync7(filePath) ? readFileSync5(filePath, "utf-8") : "";
|
|
34269
34235
|
const timestamp = new Date().toISOString().split("T")[0];
|
|
34270
34236
|
const entry = `
|
|
34271
34237
|
- [${timestamp}] ${content}
|
|
34272
34238
|
`;
|
|
34273
|
-
|
|
34239
|
+
writeFileSync5(filePath, existing + entry);
|
|
34274
34240
|
}
|
|
34275
34241
|
async function serve() {
|
|
34276
34242
|
ensureMemoryDir();
|
|
@@ -34337,12 +34303,22 @@ ${matches.join(`
|
|
|
34337
34303
|
}
|
|
34338
34304
|
|
|
34339
34305
|
// src/cli.ts
|
|
34306
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
34307
|
+
import { join as join8 } from "path";
|
|
34308
|
+
function getVersion() {
|
|
34309
|
+
try {
|
|
34310
|
+
const pkg = JSON.parse(readFileSync6(join8(getFrameworkRoot(), "package.json"), "utf-8"));
|
|
34311
|
+
return pkg.version || "0.0.0";
|
|
34312
|
+
} catch {
|
|
34313
|
+
return "0.1.2";
|
|
34314
|
+
}
|
|
34315
|
+
}
|
|
34340
34316
|
var program2 = new Command;
|
|
34341
|
-
program2.name("engram").description("Engram
|
|
34317
|
+
program2.name("engram").description("Engram — Personal AI Infrastructure").version(getVersion());
|
|
34342
34318
|
program2.command("init").description("Initialize AI infrastructure in ~/.claude/").action(init);
|
|
34343
34319
|
program2.command("bundle").description("Generate a portable AI setup package for Claude Projects or ChatGPT").option("-o, --output <dir>", "Output directory", "./engram-bundle").option("--for <name>", "Pre-fill user name").action(bundle);
|
|
34344
34320
|
program2.command("serve").description("Start MCP memory server for Claude Desktop").action(serve);
|
|
34345
34321
|
var skill = program2.command("skill").description("Manage skills");
|
|
34346
34322
|
skill.command("create <name>").description("Create a new skill scaffold").action(skillCreate);
|
|
34347
|
-
skill.command("index").description("Regenerate skill-index.json").action(
|
|
34323
|
+
skill.command("index").description("Regenerate skill-index.json").action(skillIndex);
|
|
34348
34324
|
program2.parse();
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "engram-harness",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Engram — The AI Harness for Everyone. Personal AI infrastructure that turns any model into your AI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"engram": "
|
|
7
|
+
"engram": "dist/cli.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"build": "bun build src/cli.ts --outdir dist --target node && bun run build:hooks",
|
|
11
|
-
"build:cli": "bun build src/cli.ts --outdir dist --target node",
|
|
10
|
+
"build": "bun build src/cli.ts --outdir dist --target node && bun run build:fix-shebang && bun run build:hooks",
|
|
11
|
+
"build:cli": "bun build src/cli.ts --outdir dist --target node && bun run build:fix-shebang",
|
|
12
|
+
"build:fix-shebang": "node -e \"const f=require('fs');const p='dist/cli.js';let c=f.readFileSync(p,'utf-8');c=c.replace(/^#!.*\\n/,'#!/usr/bin/env node\\n');f.writeFileSync(p,c);f.chmodSync(p,0o755)\"",
|
|
12
13
|
"build:hooks": "bun run scripts/build-hooks.ts",
|
|
13
14
|
"dev": "bun run src/cli.ts",
|
|
14
15
|
"typecheck": "tsc --noEmit"
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
"license": "MIT",
|
|
39
40
|
"repository": {
|
|
40
41
|
"type": "git",
|
|
41
|
-
"url": "https://github.com/Percival-Labs/engram"
|
|
42
|
+
"url": "git+https://github.com/Percival-Labs/engram.git"
|
|
42
43
|
},
|
|
43
44
|
"keywords": [
|
|
44
45
|
"ai",
|