make-laten 1.0.1 → 1.1.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/dist/cli/index.js +532 -262
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +532 -262
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.js +352 -69
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +352 -69
- package/dist/index.mjs.map +1 -1
- package/dist/mcp/server.js +402 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/server.mjs +379 -0
- package/dist/mcp/server.mjs.map +1 -0
- package/package.json +12 -5
- package/shell/init.sh +62 -0
package/dist/cli/index.mjs
CHANGED
|
@@ -915,260 +915,310 @@ async function fetchCommand(url, options) {
|
|
|
915
915
|
}
|
|
916
916
|
}
|
|
917
917
|
|
|
918
|
-
// src/adapter/
|
|
919
|
-
import { exec as exec3 } from "child_process";
|
|
920
|
-
import { promisify as promisify3 } from "util";
|
|
918
|
+
// src/adapter/installer.ts
|
|
921
919
|
import fs2 from "fs/promises";
|
|
922
920
|
import path from "path";
|
|
921
|
+
import { exec as exec3 } from "child_process";
|
|
922
|
+
import { promisify as promisify3 } from "util";
|
|
923
|
+
var execAsync3 = promisify3(exec3);
|
|
924
|
+
var RULES_CONTENT = `
|
|
925
|
+
# make-laten efficiency rules
|
|
923
926
|
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
"cursor": { type: "rules", rulesFile: ".cursorrules" },
|
|
930
|
-
"windsurf": { type: "rules", rulesFile: ".windsurfrules" },
|
|
931
|
-
"cline": { type: "rules", rulesFile: ".clinerules" },
|
|
932
|
-
"copilot": { type: "rules", rulesFile: ".github/copilot-instructions.md" }
|
|
933
|
-
};
|
|
927
|
+
## Token Optimization
|
|
928
|
+
- When reading files, use \`make-laten read <file>\` for compressed output
|
|
929
|
+
- When searching code, use \`make-laten grep <pattern>\` for grouped results
|
|
930
|
+
- When checking git, use \`make-laten git diff\` for condensed output
|
|
931
|
+
- When fetching web, use \`make-laten fetch <url>\` for compressed content
|
|
934
932
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
933
|
+
## Quick Commands
|
|
934
|
+
- \`mread <file>\` \u2014 alias for make-laten read
|
|
935
|
+
- \`mgrep <pattern>\` \u2014 alias for make-laten grep
|
|
936
|
+
- \`mdiff\` \u2014 alias for make-laten git diff
|
|
937
|
+
- \`msearch <query>\` \u2014 alias for make-laten search
|
|
938
|
+
- \`mfetch <url>\` \u2014 alias for make-laten fetch
|
|
939
|
+
`;
|
|
940
|
+
function getHome() {
|
|
941
|
+
return process.env.HOME || process.env.USERPROFILE || "";
|
|
942
|
+
}
|
|
943
|
+
async function commandExists(cmd) {
|
|
944
|
+
try {
|
|
945
|
+
await execAsync3(`which ${cmd}`, { timeout: 3e3 });
|
|
946
|
+
return true;
|
|
947
|
+
} catch {
|
|
948
|
+
return false;
|
|
947
949
|
}
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
950
|
+
}
|
|
951
|
+
var agents = [
|
|
952
|
+
{
|
|
953
|
+
name: "terminal (shell aliases)",
|
|
954
|
+
detected: async () => true,
|
|
955
|
+
install: async () => {
|
|
956
|
+
const shellInit = await execAsync3("echo $SHELL").then((r) => r.stdout.trim());
|
|
957
|
+
const rcFile = shellInit.includes("zsh") ? ".zshrc" : ".bashrc";
|
|
958
|
+
const rcPath = path.join(getHome(), rcFile);
|
|
959
|
+
const marker = "make-laten shell";
|
|
960
|
+
let existing = "";
|
|
955
961
|
try {
|
|
956
|
-
|
|
957
|
-
const version = stdout.trim().split("\n")[0];
|
|
958
|
-
const agentPath = await this.getAgentPath(name);
|
|
959
|
-
return { name, type, path: agentPath, version, detected: true };
|
|
962
|
+
existing = await fs2.readFile(rcPath, "utf-8");
|
|
960
963
|
} catch {
|
|
961
|
-
return null;
|
|
962
964
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
965
|
+
if (!existing.includes(marker)) {
|
|
966
|
+
const npmRoot = await execAsync3("npm root -g").then((r) => r.stdout.trim());
|
|
967
|
+
const initScript = `
|
|
968
|
+
# make-laten shell integration
|
|
969
|
+
source ${npmRoot}/make-laten/shell/init.sh
|
|
970
|
+
`;
|
|
971
|
+
await fs2.appendFile(rcPath, initScript);
|
|
972
|
+
}
|
|
973
|
+
},
|
|
974
|
+
uninstall: async () => {
|
|
975
|
+
const shellInit = await execAsync3("echo $SHELL").then((r) => r.stdout.trim());
|
|
976
|
+
const rcFile = shellInit.includes("zsh") ? ".zshrc" : ".bashrc";
|
|
977
|
+
const rcPath = path.join(getHome(), rcFile);
|
|
978
|
+
try {
|
|
979
|
+
let content = await fs2.readFile(rcPath, "utf-8");
|
|
980
|
+
content = content.replace(/\n# make-laten shell integration\nsource .*\/make-laten\/shell\/init\.sh\n/g, "");
|
|
981
|
+
await fs2.writeFile(rcPath, content);
|
|
982
|
+
} catch {
|
|
973
983
|
}
|
|
974
984
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
};
|
|
984
|
-
return paths[name] || path.join(home, `.${name}`);
|
|
985
|
-
}
|
|
986
|
-
async hasCommand(cmd) {
|
|
987
|
-
try {
|
|
988
|
-
await execAsync3(`which ${cmd}`, { timeout: 3e3 });
|
|
989
|
-
return true;
|
|
990
|
-
} catch {
|
|
991
|
-
return false;
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
};
|
|
995
|
-
|
|
996
|
-
// src/adapter/hook.ts
|
|
997
|
-
import fs3 from "fs/promises";
|
|
998
|
-
import path2 from "path";
|
|
999
|
-
var HookAdapter = class {
|
|
1000
|
-
name;
|
|
1001
|
-
version = "1.0.0";
|
|
1002
|
-
type = "hook";
|
|
1003
|
-
hooks = {};
|
|
1004
|
-
constructor(name) {
|
|
1005
|
-
this.name = name;
|
|
1006
|
-
}
|
|
1007
|
-
format(input) {
|
|
1008
|
-
const { content, context } = input;
|
|
1009
|
-
const parts = [];
|
|
1010
|
-
if (context?.filePath) {
|
|
1011
|
-
parts.push(`**File:** \`${context.filePath}\``);
|
|
1012
|
-
}
|
|
1013
|
-
parts.push(content);
|
|
1014
|
-
return {
|
|
1015
|
-
output: parts.join("\n\n"),
|
|
1016
|
-
format: this.name,
|
|
1017
|
-
metadata: { filePath: context?.filePath, timestamp: Date.now() }
|
|
1018
|
-
};
|
|
1019
|
-
}
|
|
1020
|
-
parse(output) {
|
|
1021
|
-
return { content: output, parsed: true };
|
|
1022
|
-
}
|
|
1023
|
-
setHooks(hooks) {
|
|
1024
|
-
this.hooks = hooks;
|
|
1025
|
-
}
|
|
1026
|
-
async intercept(toolCall) {
|
|
1027
|
-
if (this.hooks.preToolUse) {
|
|
1028
|
-
return this.hooks.preToolUse(toolCall);
|
|
1029
|
-
}
|
|
1030
|
-
return toolCall;
|
|
1031
|
-
}
|
|
1032
|
-
async postProcess(result) {
|
|
1033
|
-
if (this.hooks.postToolUse) {
|
|
1034
|
-
return this.hooks.postToolUse(result);
|
|
1035
|
-
}
|
|
1036
|
-
return result;
|
|
1037
|
-
}
|
|
1038
|
-
async install(agentPath) {
|
|
1039
|
-
const hooksDir = path2.join(agentPath, "hooks");
|
|
1040
|
-
await fs3.mkdir(hooksDir, { recursive: true });
|
|
1041
|
-
const preToolHook = `#!/usr/bin/env node
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
name: "claude-code",
|
|
988
|
+
detected: async () => commandExists("claude"),
|
|
989
|
+
install: async () => {
|
|
990
|
+
const hooksDir = path.join(getHome(), ".claude", "hooks");
|
|
991
|
+
await fs2.mkdir(hooksDir, { recursive: true });
|
|
992
|
+
const preHook = `#!/usr/bin/env node
|
|
1042
993
|
const { readFileSync } = require('fs');
|
|
1043
994
|
const input = JSON.parse(readFileSync('/dev/stdin', 'utf-8'));
|
|
1044
|
-
|
|
1045
995
|
if (input.tool === 'Read' || input.tool === 'Bash') {
|
|
1046
996
|
process.env.MAKE_LATEN_INTERCEPT = '1';
|
|
1047
997
|
}
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
`;
|
|
1051
|
-
const postToolHook = `#!/usr/bin/env node
|
|
998
|
+
process.stdout.write(JSON.stringify(input));`;
|
|
999
|
+
const postHook = `#!/usr/bin/env node
|
|
1052
1000
|
const { readFileSync } = require('fs');
|
|
1053
1001
|
const input = JSON.parse(readFileSync('/dev/stdin', 'utf-8'));
|
|
1054
|
-
|
|
1055
1002
|
if (input.output && input.output.length > 10000) {
|
|
1056
1003
|
input.output = input.output.slice(0, 10000) + '\\n... (truncated by make-laten)';
|
|
1057
1004
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1005
|
+
process.stdout.write(JSON.stringify(input));`;
|
|
1006
|
+
await fs2.writeFile(path.join(hooksDir, "pre-tool-use.js"), preHook);
|
|
1007
|
+
await fs2.writeFile(path.join(hooksDir, "post-tool-use.js"), postHook);
|
|
1008
|
+
},
|
|
1009
|
+
uninstall: async () => {
|
|
1010
|
+
const hooksDir = path.join(getHome(), ".claude", "hooks");
|
|
1011
|
+
try {
|
|
1012
|
+
await fs2.rm(path.join(hooksDir, "pre-tool-use.js"), { force: true });
|
|
1013
|
+
} catch {
|
|
1014
|
+
}
|
|
1015
|
+
try {
|
|
1016
|
+
await fs2.rm(path.join(hooksDir, "post-tool-use.js"), { force: true });
|
|
1017
|
+
} catch {
|
|
1018
|
+
}
|
|
1070
1019
|
}
|
|
1071
|
-
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
name: "cursor",
|
|
1023
|
+
detected: async () => {
|
|
1024
|
+
try {
|
|
1025
|
+
await fs2.access(path.join(getHome(), ".cursor"));
|
|
1026
|
+
return true;
|
|
1027
|
+
} catch {
|
|
1028
|
+
return false;
|
|
1029
|
+
}
|
|
1030
|
+
},
|
|
1031
|
+
install: async () => {
|
|
1032
|
+
const rulesDir = path.join(getHome(), ".cursor", "rules");
|
|
1033
|
+
await fs2.mkdir(rulesDir, { recursive: true });
|
|
1034
|
+
const ruleFile = path.join(rulesDir, "make-laten.mdc");
|
|
1035
|
+
const content = `---
|
|
1036
|
+
description: make-laten efficiency rules
|
|
1037
|
+
globs:
|
|
1038
|
+
---
|
|
1039
|
+
${RULES_CONTENT}`;
|
|
1040
|
+
await fs2.writeFile(ruleFile, content);
|
|
1041
|
+
},
|
|
1042
|
+
uninstall: async () => {
|
|
1043
|
+
try {
|
|
1044
|
+
await fs2.rm(path.join(getHome(), ".cursor", "rules", "make-laten.mdc"), { force: true });
|
|
1045
|
+
} catch {
|
|
1046
|
+
}
|
|
1078
1047
|
}
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
##
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
var RulesAdapter = class {
|
|
1103
|
-
name;
|
|
1104
|
-
version = "1.0.0";
|
|
1105
|
-
type = "rules";
|
|
1106
|
-
constructor(agentName) {
|
|
1107
|
-
this.name = agentName;
|
|
1108
|
-
}
|
|
1109
|
-
format(input) {
|
|
1110
|
-
return {
|
|
1111
|
-
output: input.content,
|
|
1112
|
-
format: "markdown",
|
|
1113
|
-
metadata: { agent: this.name, timestamp: Date.now() }
|
|
1114
|
-
};
|
|
1115
|
-
}
|
|
1116
|
-
parse(output) {
|
|
1117
|
-
return { content: output };
|
|
1118
|
-
}
|
|
1119
|
-
async install(agentPath) {
|
|
1120
|
-
const config = AGENT_CONFIGS[this.name];
|
|
1121
|
-
if (!config?.rulesFile) {
|
|
1122
|
-
throw new Error(`No rules file configured for ${this.name}`);
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
name: "codex",
|
|
1051
|
+
detected: async () => commandExists("codex"),
|
|
1052
|
+
install: async () => {
|
|
1053
|
+
const agentsMd = path.join(process.cwd(), "AGENTS.md");
|
|
1054
|
+
let existing = "";
|
|
1055
|
+
try {
|
|
1056
|
+
existing = await fs2.readFile(agentsMd, "utf-8");
|
|
1057
|
+
} catch {
|
|
1058
|
+
}
|
|
1059
|
+
if (!existing.includes("make-laten")) {
|
|
1060
|
+
const content = existing + "\n\n## make-laten Integration\n" + RULES_CONTENT;
|
|
1061
|
+
await fs2.writeFile(agentsMd, content);
|
|
1062
|
+
}
|
|
1063
|
+
},
|
|
1064
|
+
uninstall: async () => {
|
|
1065
|
+
try {
|
|
1066
|
+
let content = await fs2.readFile(path.join(process.cwd(), "AGENTS.md"), "utf-8");
|
|
1067
|
+
content = content.replace(/\n## make-laten Integration[\s\S]*$/, "");
|
|
1068
|
+
await fs2.writeFile(path.join(process.cwd(), "AGENTS.md"), content.trim() + "\n");
|
|
1069
|
+
} catch {
|
|
1070
|
+
}
|
|
1123
1071
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1072
|
+
},
|
|
1073
|
+
{
|
|
1074
|
+
name: "windsurf",
|
|
1075
|
+
detected: async () => {
|
|
1076
|
+
try {
|
|
1077
|
+
await fs2.access(path.join(process.cwd(), ".windsurf"));
|
|
1078
|
+
return true;
|
|
1079
|
+
} catch {
|
|
1080
|
+
try {
|
|
1081
|
+
await fs2.access(path.join(getHome(), ".windsurf"));
|
|
1082
|
+
return true;
|
|
1083
|
+
} catch {
|
|
1084
|
+
return false;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
},
|
|
1088
|
+
install: async () => {
|
|
1089
|
+
const rulesPath = path.join(process.cwd(), ".windsurfrules");
|
|
1090
|
+
let existing = "";
|
|
1091
|
+
try {
|
|
1092
|
+
existing = await fs2.readFile(rulesPath, "utf-8");
|
|
1093
|
+
} catch {
|
|
1094
|
+
}
|
|
1095
|
+
if (!existing.includes("make-laten")) {
|
|
1096
|
+
await fs2.writeFile(rulesPath, existing + "\n\n" + RULES_CONTENT);
|
|
1097
|
+
}
|
|
1098
|
+
},
|
|
1099
|
+
uninstall: async () => {
|
|
1100
|
+
try {
|
|
1101
|
+
let content = await fs2.readFile(path.join(process.cwd(), ".windsurfrules"), "utf-8");
|
|
1102
|
+
content = content.replace(/\n# make-laten efficiency rules[\s\S]*$/, "");
|
|
1103
|
+
await fs2.writeFile(path.join(process.cwd(), ".windsurfrules"), content.trim() + "\n");
|
|
1104
|
+
} catch {
|
|
1105
|
+
}
|
|
1128
1106
|
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1107
|
+
},
|
|
1108
|
+
{
|
|
1109
|
+
name: "cline",
|
|
1110
|
+
detected: async () => {
|
|
1111
|
+
try {
|
|
1112
|
+
await fs2.access(path.join(process.cwd(), ".clinerules"));
|
|
1113
|
+
return true;
|
|
1114
|
+
} catch {
|
|
1115
|
+
try {
|
|
1116
|
+
await fs2.access(path.join(getHome(), ".cline"));
|
|
1117
|
+
return true;
|
|
1118
|
+
} catch {
|
|
1119
|
+
return false;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
},
|
|
1123
|
+
install: async () => {
|
|
1124
|
+
const rulesPath = path.join(process.cwd(), ".clinerules");
|
|
1125
|
+
let existing = "";
|
|
1126
|
+
try {
|
|
1127
|
+
existing = await fs2.readFile(rulesPath, "utf-8");
|
|
1128
|
+
} catch {
|
|
1129
|
+
}
|
|
1130
|
+
if (!existing.includes("make-laten")) {
|
|
1131
|
+
await fs2.writeFile(rulesPath, existing + "\n\n" + RULES_CONTENT);
|
|
1132
|
+
}
|
|
1133
|
+
},
|
|
1134
|
+
uninstall: async () => {
|
|
1135
|
+
try {
|
|
1136
|
+
let content = await fs2.readFile(path.join(process.cwd(), ".clinerules"), "utf-8");
|
|
1137
|
+
content = content.replace(/\n# make-laten efficiency rules[\s\S]*$/, "");
|
|
1138
|
+
await fs2.writeFile(path.join(process.cwd(), ".clinerules"), content.trim() + "\n");
|
|
1139
|
+
} catch {
|
|
1144
1140
|
}
|
|
1145
|
-
} catch {
|
|
1146
1141
|
}
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1142
|
+
},
|
|
1143
|
+
{
|
|
1144
|
+
name: "copilot",
|
|
1145
|
+
detected: async () => {
|
|
1146
|
+
try {
|
|
1147
|
+
await fs2.access(path.join(process.cwd(), ".github"));
|
|
1148
|
+
return true;
|
|
1149
|
+
} catch {
|
|
1150
|
+
return false;
|
|
1151
|
+
}
|
|
1152
|
+
},
|
|
1153
|
+
install: async () => {
|
|
1154
|
+
const dir = path.join(process.cwd(), ".github");
|
|
1155
|
+
await fs2.mkdir(dir, { recursive: true });
|
|
1156
|
+
const instructionsPath = path.join(dir, "copilot-instructions.md");
|
|
1157
|
+
let existing = "";
|
|
1158
|
+
try {
|
|
1159
|
+
existing = await fs2.readFile(instructionsPath, "utf-8");
|
|
1160
|
+
} catch {
|
|
1161
|
+
}
|
|
1162
|
+
if (!existing.includes("make-laten")) {
|
|
1163
|
+
await fs2.writeFile(instructionsPath, existing + "\n\n## make-laten Efficiency\n" + RULES_CONTENT);
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
uninstall: async () => {
|
|
1167
|
+
try {
|
|
1168
|
+
let content = await fs2.readFile(path.join(process.cwd(), ".github", "copilot-instructions.md"), "utf-8");
|
|
1169
|
+
content = content.replace(/\n## make-laten Efficiency[\s\S]*$/, "");
|
|
1170
|
+
await fs2.writeFile(path.join(process.cwd(), ".github", "copilot-instructions.md"), content.trim() + "\n");
|
|
1171
|
+
} catch {
|
|
1172
|
+
}
|
|
1156
1173
|
}
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1174
|
+
},
|
|
1175
|
+
{
|
|
1176
|
+
name: "opencode",
|
|
1177
|
+
detected: async () => {
|
|
1178
|
+
try {
|
|
1179
|
+
await fs2.access(path.join(getHome(), ".config", "opencode"));
|
|
1180
|
+
return true;
|
|
1181
|
+
} catch {
|
|
1182
|
+
return false;
|
|
1183
|
+
}
|
|
1184
|
+
},
|
|
1185
|
+
install: async () => {
|
|
1186
|
+
const skillsDir = path.join(getHome(), ".config", "opencode", "skills", "make-laten");
|
|
1187
|
+
await fs2.mkdir(skillsDir, { recursive: true });
|
|
1188
|
+
const npmRoot = await execAsync3("npm root -g").then((r) => r.stdout.trim());
|
|
1189
|
+
const skillSrc = path.join(npmRoot, "make-laten", "skills", "SKILL.md");
|
|
1190
|
+
try {
|
|
1191
|
+
const skillContent = await fs2.readFile(skillSrc, "utf-8");
|
|
1192
|
+
await fs2.writeFile(path.join(skillsDir, "SKILL.md"), skillContent);
|
|
1193
|
+
} catch {
|
|
1194
|
+
await fs2.writeFile(path.join(skillsDir, "SKILL.md"), `---
|
|
1195
|
+
name: make-laten
|
|
1196
|
+
description: Token optimization toolkit
|
|
1197
|
+
---
|
|
1159
1198
|
|
|
1160
|
-
|
|
1199
|
+
# make-laten Skill
|
|
1200
|
+
|
|
1201
|
+
Use make-laten CLI commands for all file/code/git operations.
|
|
1202
|
+
`);
|
|
1203
|
+
}
|
|
1204
|
+
},
|
|
1205
|
+
uninstall: async () => {
|
|
1206
|
+
try {
|
|
1207
|
+
await fs2.rm(path.join(getHome(), ".config", "opencode", "skills", "make-laten"), { recursive: true, force: true });
|
|
1208
|
+
} catch {
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
];
|
|
1161
1213
|
var Installer = class {
|
|
1162
|
-
detector = new AgentDetector();
|
|
1163
1214
|
async install() {
|
|
1164
|
-
const agents = await this.detector.detectAgents();
|
|
1165
1215
|
const installed = [];
|
|
1166
1216
|
const skipped = [];
|
|
1167
1217
|
for (const agent of agents) {
|
|
1168
1218
|
try {
|
|
1169
|
-
const
|
|
1170
|
-
if (
|
|
1171
|
-
await
|
|
1219
|
+
const detected = await agent.detected();
|
|
1220
|
+
if (detected) {
|
|
1221
|
+
await agent.install();
|
|
1172
1222
|
installed.push(agent.name);
|
|
1173
1223
|
} else {
|
|
1174
1224
|
skipped.push(agent.name);
|
|
@@ -1180,36 +1230,27 @@ var Installer = class {
|
|
|
1180
1230
|
return { installed, skipped };
|
|
1181
1231
|
}
|
|
1182
1232
|
async uninstall() {
|
|
1183
|
-
const agents = await this.detector.detectAgents();
|
|
1184
1233
|
const removed = [];
|
|
1185
1234
|
for (const agent of agents) {
|
|
1186
1235
|
try {
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
await adapter.uninstall(agent.path);
|
|
1190
|
-
removed.push(agent.name);
|
|
1191
|
-
}
|
|
1236
|
+
await agent.uninstall();
|
|
1237
|
+
removed.push(agent.name);
|
|
1192
1238
|
} catch {
|
|
1193
1239
|
}
|
|
1194
1240
|
}
|
|
1195
1241
|
return { removed };
|
|
1196
1242
|
}
|
|
1197
1243
|
async status() {
|
|
1198
|
-
const
|
|
1244
|
+
const result = [];
|
|
1199
1245
|
for (const agent of agents) {
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
agent.detected
|
|
1246
|
+
try {
|
|
1247
|
+
const detected = await agent.detected();
|
|
1248
|
+
result.push({ name: agent.name, detected, installed: false });
|
|
1249
|
+
} catch {
|
|
1250
|
+
result.push({ name: agent.name, detected: false, installed: false });
|
|
1203
1251
|
}
|
|
1204
1252
|
}
|
|
1205
|
-
return
|
|
1206
|
-
}
|
|
1207
|
-
createAdapter(agent) {
|
|
1208
|
-
const config = AGENT_CONFIGS[agent.name];
|
|
1209
|
-
if (config?.type === "rules") {
|
|
1210
|
-
return new RulesAdapter(agent.name);
|
|
1211
|
-
}
|
|
1212
|
-
return new HookAdapter(agent.name);
|
|
1253
|
+
return result;
|
|
1213
1254
|
}
|
|
1214
1255
|
};
|
|
1215
1256
|
|
|
@@ -1217,20 +1258,17 @@ var Installer = class {
|
|
|
1217
1258
|
async function installCommand(options) {
|
|
1218
1259
|
const installer = new Installer();
|
|
1219
1260
|
if (options.status) {
|
|
1220
|
-
console.log("Detecting
|
|
1221
|
-
const
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
for (const agent of agents) {
|
|
1227
|
-
const status = agent.detected ? "\u2713 installed" : "\u25CB detected";
|
|
1228
|
-
console.log(` ${status} ${agent.name} (${agent.type})${agent.version ? ` v${agent.version}` : ""}`);
|
|
1261
|
+
console.log("Detecting platforms...\n");
|
|
1262
|
+
const status = await installer.status();
|
|
1263
|
+
for (const s of status) {
|
|
1264
|
+
const icon = s.detected ? "\u2713" : "\u25CB";
|
|
1265
|
+
const label = s.detected ? "detected" : "not found";
|
|
1266
|
+
console.log(` ${icon} ${s.name} (${label})`);
|
|
1229
1267
|
}
|
|
1230
1268
|
return;
|
|
1231
1269
|
}
|
|
1232
1270
|
if (options.uninstall) {
|
|
1233
|
-
console.log("Uninstalling make-laten
|
|
1271
|
+
console.log("Uninstalling make-laten from all platforms...\n");
|
|
1234
1272
|
const { removed } = await installer.uninstall();
|
|
1235
1273
|
if (removed.length === 0) {
|
|
1236
1274
|
console.log("Nothing to uninstall.");
|
|
@@ -1239,31 +1277,262 @@ async function installCommand(options) {
|
|
|
1239
1277
|
for (const name of removed) {
|
|
1240
1278
|
console.log(` \u2713 removed from ${name}`);
|
|
1241
1279
|
}
|
|
1280
|
+
console.log(`
|
|
1281
|
+
Done! Removed from ${removed.length} platform(s).`);
|
|
1242
1282
|
return;
|
|
1243
1283
|
}
|
|
1244
|
-
console.log("Installing make-laten
|
|
1284
|
+
console.log("Installing make-laten across all platforms...\n");
|
|
1245
1285
|
const { installed, skipped } = await installer.install();
|
|
1246
|
-
if (installed.length === 0 && skipped.length === 0) {
|
|
1247
|
-
console.log("No supported agents detected.");
|
|
1248
|
-
console.log("make-laten CLI works standalone \u2014 use commands directly:");
|
|
1249
|
-
console.log(" make-laten read <file>");
|
|
1250
|
-
console.log(" make-laten grep <pattern>");
|
|
1251
|
-
console.log(" make-laten git diff");
|
|
1252
|
-
return;
|
|
1253
|
-
}
|
|
1254
1286
|
for (const name of installed) {
|
|
1255
|
-
console.log(` \u2713 ${name}
|
|
1287
|
+
console.log(` \u2713 ${name}`);
|
|
1256
1288
|
}
|
|
1257
1289
|
for (const name of skipped) {
|
|
1258
|
-
console.log(` \u25CB ${name}
|
|
1290
|
+
console.log(` \u25CB ${name} (not detected)`);
|
|
1259
1291
|
}
|
|
1260
1292
|
console.log(`
|
|
1261
|
-
Done! Configured for ${installed.length}
|
|
1293
|
+
Done! Configured for ${installed.length} platform(s).`);
|
|
1294
|
+
console.log("\nAvailable commands (terminal):");
|
|
1295
|
+
console.log(" mread <file> compressed file read");
|
|
1296
|
+
console.log(" mgrep <pattern> grouped grep results");
|
|
1297
|
+
console.log(" mdiff compressed git diff");
|
|
1298
|
+
console.log(" mstatus git status summary");
|
|
1299
|
+
console.log(" msearch <query> web search");
|
|
1300
|
+
console.log(" mfetch <url> web fetch + compress");
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
// src/cli/commands/init.ts
|
|
1304
|
+
import { exec as exec4 } from "child_process";
|
|
1305
|
+
import { promisify as promisify4 } from "util";
|
|
1306
|
+
import fs3 from "fs/promises";
|
|
1307
|
+
import path2 from "path";
|
|
1308
|
+
import readline from "readline";
|
|
1309
|
+
var execAsync4 = promisify4(exec4);
|
|
1310
|
+
function getHome2() {
|
|
1311
|
+
return process.env.HOME || process.env.USERPROFILE || "";
|
|
1312
|
+
}
|
|
1313
|
+
async function commandExists2(cmd) {
|
|
1314
|
+
try {
|
|
1315
|
+
await execAsync4(`which ${cmd}`, { timeout: 3e3 });
|
|
1316
|
+
return true;
|
|
1317
|
+
} catch {
|
|
1318
|
+
return false;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
async function directoryExists(dirPath) {
|
|
1322
|
+
try {
|
|
1323
|
+
await fs3.access(dirPath);
|
|
1324
|
+
return true;
|
|
1325
|
+
} catch {
|
|
1326
|
+
return false;
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
async function detectAllAgents() {
|
|
1330
|
+
const home = getHome2();
|
|
1331
|
+
const agents2 = [];
|
|
1332
|
+
const claudeConfig = path2.join(home, ".claude", "mcp.json");
|
|
1333
|
+
const claudeDir = path2.join(home, ".claude");
|
|
1334
|
+
agents2.push({
|
|
1335
|
+
name: "Claude Code",
|
|
1336
|
+
detected: await commandExists2("claude") || await directoryExists(claudeDir),
|
|
1337
|
+
configPath: claudeConfig,
|
|
1338
|
+
mcpConfig: {
|
|
1339
|
+
mcpServers: {
|
|
1340
|
+
"make-laten": { command: "npx", args: ["-y", "make-laten-mcp", "server"] }
|
|
1341
|
+
}
|
|
1342
|
+
},
|
|
1343
|
+
version: await commandExists2("claude") ? await execAsync4("claude --version", { timeout: 3e3 }).then((r) => r.stdout.trim().split("\n")[0]).catch(() => "unknown") : void 0
|
|
1344
|
+
});
|
|
1345
|
+
const cursorMcp = path2.join(home, ".cursor", "mcp.json");
|
|
1346
|
+
const cursorDir = path2.join(home, ".cursor");
|
|
1347
|
+
agents2.push({
|
|
1348
|
+
name: "Cursor",
|
|
1349
|
+
detected: await directoryExists(cursorDir),
|
|
1350
|
+
configPath: cursorMcp,
|
|
1351
|
+
mcpConfig: {
|
|
1352
|
+
mcpServers: {
|
|
1353
|
+
"make-laten": { command: "npx", args: ["-y", "make-laten-mcp", "server"] }
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
});
|
|
1357
|
+
const codexMcp = path2.join(home, ".codex", "config.json");
|
|
1358
|
+
const codexDir = path2.join(home, ".codex");
|
|
1359
|
+
agents2.push({
|
|
1360
|
+
name: "Codex",
|
|
1361
|
+
detected: await commandExists2("codex") || await directoryExists(codexDir),
|
|
1362
|
+
configPath: codexMcp,
|
|
1363
|
+
mcpConfig: {
|
|
1364
|
+
mcpServers: {
|
|
1365
|
+
"make-laten": { command: "npx", args: ["-y", "make-laten-mcp", "server"] }
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
});
|
|
1369
|
+
const windsurfMcp = path2.join(home, ".codeium", "windsurf", "mcp_config.json");
|
|
1370
|
+
const windsurfDir = path2.join(home, ".codeium", "windsurf");
|
|
1371
|
+
agents2.push({
|
|
1372
|
+
name: "Windsurf",
|
|
1373
|
+
detected: await directoryExists(windsurfDir),
|
|
1374
|
+
configPath: windsurfMcp,
|
|
1375
|
+
mcpConfig: {
|
|
1376
|
+
mcpServers: {
|
|
1377
|
+
"make-laten": { command: "npx", args: ["-y", "make-laten-mcp", "server"] }
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
});
|
|
1381
|
+
const openCodeConfig = path2.join(home, ".config", "opencode", "opencode.json");
|
|
1382
|
+
const openCodeDir = path2.join(home, ".config", "opencode");
|
|
1383
|
+
agents2.push({
|
|
1384
|
+
name: "OpenCode",
|
|
1385
|
+
detected: await directoryExists(openCodeDir),
|
|
1386
|
+
configPath: openCodeConfig,
|
|
1387
|
+
mcpConfig: {
|
|
1388
|
+
mcpServers: {
|
|
1389
|
+
"make-laten": { command: "npx", args: ["-y", "make-laten-mcp", "server"] }
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
});
|
|
1393
|
+
const clineDir = path2.join(home, ".cline");
|
|
1394
|
+
const clineMcp = path2.join(home, ".cline", "mcp_settings.json");
|
|
1395
|
+
agents2.push({
|
|
1396
|
+
name: "Cline",
|
|
1397
|
+
detected: await directoryExists(clineDir),
|
|
1398
|
+
configPath: clineMcp,
|
|
1399
|
+
mcpConfig: {
|
|
1400
|
+
mcpServers: {
|
|
1401
|
+
"make-laten": { command: "npx", args: ["-y", "make-laten-mcp", "server"] }
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
});
|
|
1405
|
+
const vscodeDir = path2.join(home, "Library", "Application Support", "Code", "User", "globalStorage");
|
|
1406
|
+
agents2.push({
|
|
1407
|
+
name: "GitHub Copilot (VS Code)",
|
|
1408
|
+
detected: await directoryExists(vscodeDir),
|
|
1409
|
+
configPath: "",
|
|
1410
|
+
mcpConfig: {}
|
|
1411
|
+
});
|
|
1412
|
+
const geminiDir = path2.join(home, ".gemini");
|
|
1413
|
+
agents2.push({
|
|
1414
|
+
name: "Gemini CLI",
|
|
1415
|
+
detected: await commandExists2("gemini") || await directoryExists(geminiDir),
|
|
1416
|
+
configPath: path2.join(home, ".gemini", "settings.json"),
|
|
1417
|
+
mcpConfig: {
|
|
1418
|
+
mcpServers: {
|
|
1419
|
+
"make-laten": { command: "npx", args: ["-y", "make-laten-mcp", "server"] }
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
return agents2;
|
|
1424
|
+
}
|
|
1425
|
+
async function writeMCPConfig(agent) {
|
|
1426
|
+
try {
|
|
1427
|
+
const dir = path2.dirname(agent.configPath);
|
|
1428
|
+
await fs3.mkdir(dir, { recursive: true });
|
|
1429
|
+
let existing = {};
|
|
1430
|
+
try {
|
|
1431
|
+
const raw = await fs3.readFile(agent.configPath, "utf-8");
|
|
1432
|
+
existing = JSON.parse(raw);
|
|
1433
|
+
} catch {
|
|
1434
|
+
}
|
|
1435
|
+
const merged = {
|
|
1436
|
+
...existing,
|
|
1437
|
+
mcpServers: {
|
|
1438
|
+
...existing.mcpServers || {},
|
|
1439
|
+
...agent.mcpConfig.mcpServers
|
|
1440
|
+
}
|
|
1441
|
+
};
|
|
1442
|
+
await fs3.writeFile(agent.configPath, JSON.stringify(merged, null, 2));
|
|
1443
|
+
return true;
|
|
1444
|
+
} catch {
|
|
1445
|
+
return false;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
function askQuestion(rl, question) {
|
|
1449
|
+
return new Promise((resolve) => rl.question(question, resolve));
|
|
1450
|
+
}
|
|
1451
|
+
async function initCommand(options) {
|
|
1452
|
+
console.log("");
|
|
1453
|
+
console.log(" make-laten setup wizard");
|
|
1454
|
+
console.log(" ======================");
|
|
1455
|
+
console.log("");
|
|
1456
|
+
const agents2 = await detectAllAgents();
|
|
1457
|
+
const detected = agents2.filter((a) => a.detected);
|
|
1458
|
+
const notDetected = agents2.filter((a) => !a.detected);
|
|
1459
|
+
console.log(" Detected agents:");
|
|
1460
|
+
for (const agent of detected) {
|
|
1461
|
+
const ver = agent.version ? ` v${agent.version}` : "";
|
|
1462
|
+
console.log(` \u2713 ${agent.name}${ver}`);
|
|
1463
|
+
}
|
|
1464
|
+
if (notDetected.length > 0) {
|
|
1465
|
+
console.log("");
|
|
1466
|
+
console.log(" Not detected (skipped):");
|
|
1467
|
+
for (const agent of notDetected) {
|
|
1468
|
+
console.log(` \u25CB ${agent.name}`);
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
console.log("");
|
|
1472
|
+
if (options.all) {
|
|
1473
|
+
for (const agent of detected) {
|
|
1474
|
+
const success = await writeMCPConfig(agent);
|
|
1475
|
+
if (success) {
|
|
1476
|
+
console.log(` \u2713 ${agent.name} \u2192 MCP configured`);
|
|
1477
|
+
} else {
|
|
1478
|
+
console.log(` \u2717 ${agent.name} \u2192 failed`);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
} else if (options.project) {
|
|
1482
|
+
const cwd = process.cwd();
|
|
1483
|
+
const mcpConfig = {
|
|
1484
|
+
mcpServers: {
|
|
1485
|
+
"make-laten": { command: "npx", args: ["-y", "make-laten-mcp", "server"] }
|
|
1486
|
+
}
|
|
1487
|
+
};
|
|
1488
|
+
const configPath = path2.join(cwd, ".mcp.json");
|
|
1489
|
+
let existing = {};
|
|
1490
|
+
try {
|
|
1491
|
+
const raw = await fs3.readFile(configPath, "utf-8");
|
|
1492
|
+
existing = JSON.parse(raw);
|
|
1493
|
+
} catch {
|
|
1494
|
+
}
|
|
1495
|
+
const merged = {
|
|
1496
|
+
...existing,
|
|
1497
|
+
mcpServers: {
|
|
1498
|
+
...existing.mcpServers || {},
|
|
1499
|
+
...mcpConfig.mcpServers
|
|
1500
|
+
}
|
|
1501
|
+
};
|
|
1502
|
+
await fs3.writeFile(configPath, JSON.stringify(merged, null, 2));
|
|
1503
|
+
console.log(` \u2713 .mcp.json created in ${cwd}`);
|
|
1504
|
+
} else {
|
|
1505
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1506
|
+
for (const agent of detected) {
|
|
1507
|
+
const answer = await askQuestion(rl, ` Configure ${agent.name}? (Y/n) `);
|
|
1508
|
+
if (answer.toLowerCase() !== "n") {
|
|
1509
|
+
const success = await writeMCPConfig(agent);
|
|
1510
|
+
if (success) {
|
|
1511
|
+
console.log(` \u2713 ${agent.name} \u2192 MCP configured`);
|
|
1512
|
+
} else {
|
|
1513
|
+
console.log(` \u2717 ${agent.name} \u2192 failed`);
|
|
1514
|
+
}
|
|
1515
|
+
} else {
|
|
1516
|
+
console.log(` \u25CB ${agent.name} \u2192 skipped`);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
rl.close();
|
|
1520
|
+
}
|
|
1521
|
+
console.log("");
|
|
1522
|
+
console.log(" Setup complete!");
|
|
1523
|
+
console.log("");
|
|
1524
|
+
console.log(" make-laten provides:");
|
|
1525
|
+
console.log(" \u2022 MCP server \u2192 auto-compress for all AI agents");
|
|
1526
|
+
console.log(" \u2022 CLI commands \u2192 mread, mgrep, mdiff, msearch, mfetch");
|
|
1527
|
+
console.log(" \u2022 Shell aliases \u2192 auto-load in new terminals");
|
|
1528
|
+
console.log("");
|
|
1529
|
+
console.log(" Restart your agent to activate MCP tools.");
|
|
1530
|
+
console.log("");
|
|
1262
1531
|
}
|
|
1263
1532
|
|
|
1264
1533
|
// src/cli/index.ts
|
|
1265
1534
|
var program = new Command();
|
|
1266
|
-
program.name("make-laten").description("Universal efficiency
|
|
1535
|
+
program.name("make-laten").description("Universal efficiency toolkit for AI coding agents").version("1.0.3");
|
|
1267
1536
|
program.command("read").description("Compressed file read").argument("<file>", "File path").action(readCommand);
|
|
1268
1537
|
program.command("grep").description("Compressed grep with file grouping").argument("<pattern>", "Search pattern").argument("[directory]", "Directory to search", ".").option("-i, --ignore <ext>", "File extension to ignore").action(grepCommand);
|
|
1269
1538
|
var gitCmd = program.command("git").description("Git operations");
|
|
@@ -1274,6 +1543,7 @@ cacheCmd.command("stats").description("Show cache statistics").action(cacheStats
|
|
|
1274
1543
|
cacheCmd.command("clear").description("Clear cache").action(cacheClearCommand);
|
|
1275
1544
|
program.command("search").description("Search the web").argument("<query>", "Search query").option("-b, --backend <backend>", "Search backend").option("-m, --max <n>", "Max results", "5").action(searchCommand);
|
|
1276
1545
|
program.command("fetch").description("Fetch and compress web content").argument("<url>", "URL to fetch").option("--no-compress", "Disable compression").option("--no-extract", "Disable semantic extraction").action(fetchCommand);
|
|
1277
|
-
program.command("install").description("Install make-laten
|
|
1546
|
+
program.command("install").description("Install make-laten across all detected platforms").option("-u, --uninstall", "Remove adapters").option("-s, --status", "Show installation status").action(installCommand);
|
|
1547
|
+
program.command("init").description("Interactive setup wizard \u2014 detect agents & configure MCP").option("-a, --all", "Configure all detected agents (no prompts)").option("-p, --project", "Create .mcp.json in current directory only").action(initCommand);
|
|
1278
1548
|
program.parse();
|
|
1279
1549
|
//# sourceMappingURL=index.mjs.map
|