@funnycode/myclaude 0.1.36 → 0.1.37
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/myclaude.js +82 -120
- package/dist/myclaude.mjs +82 -120
- package/package.json +2 -1
- package/seed/known_marketplaces.json +10 -0
- package/seed/marketplaces/ecc/.claude-plugin/marketplace.json +29 -0
package/dist/myclaude.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// MACRO - build-time constants (injected by build.ts)
|
|
5
5
|
// MACRO injected by build script
|
|
6
6
|
globalThis.MACRO = {
|
|
7
|
-
VERSION: "0.1.
|
|
8
|
-
BUILD_TIME: "2026-06-23T13:
|
|
7
|
+
VERSION: "0.1.37",
|
|
8
|
+
BUILD_TIME: "2026-06-23T13:46:09.406Z",
|
|
9
9
|
PACKAGE_URL: "@funnycode/myclaude",
|
|
10
10
|
NATIVE_PACKAGE_URL: "@funnycode/myclaude",
|
|
11
11
|
VERSION_CHANGELOG: '',
|
|
@@ -554538,6 +554538,52 @@ var init_codegraphCheck = __esm(() => {
|
|
|
554538
554538
|
init_execFileNoThrow();
|
|
554539
554539
|
});
|
|
554540
554540
|
|
|
554541
|
+
// src/plugins/bundled/eccMarketplace.ts
|
|
554542
|
+
async function ensureEccMarketplaceRegistered() {
|
|
554543
|
+
try {
|
|
554544
|
+
const changed = await registerSeedMarketplaces();
|
|
554545
|
+
logForDebugging(changed ? "ECC seed marketplace registered" : "ECC marketplace already registered, skipped");
|
|
554546
|
+
return true;
|
|
554547
|
+
} catch (error49) {
|
|
554548
|
+
logForDebugging(`Failed to register ECC marketplace: ${error49}`, {
|
|
554549
|
+
level: "warn"
|
|
554550
|
+
});
|
|
554551
|
+
return false;
|
|
554552
|
+
}
|
|
554553
|
+
}
|
|
554554
|
+
var init_eccMarketplace = __esm(() => {
|
|
554555
|
+
init_debug();
|
|
554556
|
+
init_marketplaceManager();
|
|
554557
|
+
});
|
|
554558
|
+
|
|
554559
|
+
// src/plugins/bundled/index.ts
|
|
554560
|
+
function initBuiltinPlugins() {
|
|
554561
|
+
registerBuiltinPlugin({
|
|
554562
|
+
name: "codegraph",
|
|
554563
|
+
description: "Semantic code intelligence — surgical context, fewer tool calls",
|
|
554564
|
+
version: "1.0.0",
|
|
554565
|
+
defaultEnabled: false,
|
|
554566
|
+
isAvailable: () => {
|
|
554567
|
+
isCodeGraphInstalled().catch(() => {});
|
|
554568
|
+
return false;
|
|
554569
|
+
},
|
|
554570
|
+
mcpServers: {
|
|
554571
|
+
codegraph: {
|
|
554572
|
+
command: "codegraph",
|
|
554573
|
+
args: ["mcp"]
|
|
554574
|
+
}
|
|
554575
|
+
}
|
|
554576
|
+
});
|
|
554577
|
+
}
|
|
554578
|
+
async function initSeedMarketplaces() {
|
|
554579
|
+
await ensureEccMarketplaceRegistered();
|
|
554580
|
+
}
|
|
554581
|
+
var init_bundled = __esm(() => {
|
|
554582
|
+
init_builtinPlugins();
|
|
554583
|
+
init_codegraphCheck();
|
|
554584
|
+
init_eccMarketplace();
|
|
554585
|
+
});
|
|
554586
|
+
|
|
554541
554587
|
// src/services/plugins/pluginCliCommands.ts
|
|
554542
554588
|
function handlePluginCommandError(error49, command8, plugin2) {
|
|
554543
554589
|
logError2(error49);
|
|
@@ -554698,96 +554744,6 @@ var init_pluginCliCommands = __esm(() => {
|
|
|
554698
554744
|
init_pluginOperations();
|
|
554699
554745
|
});
|
|
554700
554746
|
|
|
554701
|
-
// src/plugins/bundled/eccMarketplace.ts
|
|
554702
|
-
import { join as join150 } from "path";
|
|
554703
|
-
import { readFile as readFile51 } from "fs/promises";
|
|
554704
|
-
async function ensureEccMarketplaceRegistered() {
|
|
554705
|
-
try {
|
|
554706
|
-
const result = await addMarketplaceSource({
|
|
554707
|
-
source: "git",
|
|
554708
|
-
url: ECC_MARKETPLACE_URL
|
|
554709
|
-
});
|
|
554710
|
-
const eccName = result.name;
|
|
554711
|
-
logForDebugging(`ECC marketplace registered as '${eccName}' (materialized: ${!result.alreadyMaterialized})`);
|
|
554712
|
-
await installEccPlugins(eccName);
|
|
554713
|
-
return true;
|
|
554714
|
-
} catch (error49) {
|
|
554715
|
-
logForDebugging(`Failed to register ECC marketplace: ${error49}`, {
|
|
554716
|
-
level: "warn"
|
|
554717
|
-
});
|
|
554718
|
-
return false;
|
|
554719
|
-
}
|
|
554720
|
-
}
|
|
554721
|
-
async function installEccPlugins(marketplaceName) {
|
|
554722
|
-
try {
|
|
554723
|
-
const cacheDir = getMarketplacesCacheDir();
|
|
554724
|
-
const marketplaceDir = join150(cacheDir, marketplaceName);
|
|
554725
|
-
const marketplaceJsonPath = join150(marketplaceDir, ".claude-plugin", "marketplace.json");
|
|
554726
|
-
let marketplaceData;
|
|
554727
|
-
try {
|
|
554728
|
-
const content = await readFile51(marketplaceJsonPath, "utf-8");
|
|
554729
|
-
marketplaceData = JSON.parse(content);
|
|
554730
|
-
} catch {
|
|
554731
|
-
logForDebugging("ECC marketplace.json not found yet, skipping auto-install");
|
|
554732
|
-
return;
|
|
554733
|
-
}
|
|
554734
|
-
const plugins = marketplaceData?.plugins ?? [];
|
|
554735
|
-
if (plugins.length === 0) {
|
|
554736
|
-
logForDebugging("No plugins found in ECC marketplace");
|
|
554737
|
-
return;
|
|
554738
|
-
}
|
|
554739
|
-
let installed = 0;
|
|
554740
|
-
for (const plugin2 of plugins) {
|
|
554741
|
-
try {
|
|
554742
|
-
const pluginId = `${plugin2.name}@${marketplaceName}`;
|
|
554743
|
-
await installPlugin(pluginId, "user");
|
|
554744
|
-
installed++;
|
|
554745
|
-
} catch (pluginError) {
|
|
554746
|
-
logForDebugging(`Failed to auto-install ECC plugin '${plugin2.name}': ${pluginError}`, { level: "warn" });
|
|
554747
|
-
}
|
|
554748
|
-
}
|
|
554749
|
-
logForDebugging(`Auto-installed ${installed}/${plugins.length} ECC plugins`);
|
|
554750
|
-
} catch (error49) {
|
|
554751
|
-
logForDebugging(`Failed to auto-install ECC plugins: ${error49}`, {
|
|
554752
|
-
level: "warn"
|
|
554753
|
-
});
|
|
554754
|
-
}
|
|
554755
|
-
}
|
|
554756
|
-
var ECC_MARKETPLACE_URL = "https://github.com/affaan-m/ECC.git";
|
|
554757
|
-
var init_eccMarketplace = __esm(() => {
|
|
554758
|
-
init_debug();
|
|
554759
|
-
init_marketplaceManager();
|
|
554760
|
-
init_pluginCliCommands();
|
|
554761
|
-
});
|
|
554762
|
-
|
|
554763
|
-
// src/plugins/bundled/index.ts
|
|
554764
|
-
function initBuiltinPlugins() {
|
|
554765
|
-
registerBuiltinPlugin({
|
|
554766
|
-
name: "codegraph",
|
|
554767
|
-
description: "Semantic code intelligence — surgical context, fewer tool calls",
|
|
554768
|
-
version: "1.0.0",
|
|
554769
|
-
defaultEnabled: false,
|
|
554770
|
-
isAvailable: () => {
|
|
554771
|
-
isCodeGraphInstalled().catch(() => {});
|
|
554772
|
-
return false;
|
|
554773
|
-
},
|
|
554774
|
-
mcpServers: {
|
|
554775
|
-
codegraph: {
|
|
554776
|
-
command: "codegraph",
|
|
554777
|
-
args: ["mcp"]
|
|
554778
|
-
}
|
|
554779
|
-
}
|
|
554780
|
-
});
|
|
554781
|
-
}
|
|
554782
|
-
async function initSeedMarketplaces() {
|
|
554783
|
-
await ensureEccMarketplaceRegistered();
|
|
554784
|
-
}
|
|
554785
|
-
var init_bundled = __esm(() => {
|
|
554786
|
-
init_builtinPlugins();
|
|
554787
|
-
init_codegraphCheck();
|
|
554788
|
-
init_eccMarketplace();
|
|
554789
|
-
});
|
|
554790
|
-
|
|
554791
554747
|
// src/skills/bundled/batch.ts
|
|
554792
554748
|
function buildPrompt(instruction) {
|
|
554793
554749
|
return `# Batch: Parallel Work Orchestration
|
|
@@ -557433,12 +557389,12 @@ var init_createDirectConnectSession = __esm(() => {
|
|
|
557433
557389
|
});
|
|
557434
557390
|
|
|
557435
557391
|
// src/utils/errorLogSink.ts
|
|
557436
|
-
import { dirname as dirname64, join as
|
|
557392
|
+
import { dirname as dirname64, join as join150 } from "path";
|
|
557437
557393
|
function getErrorsPath() {
|
|
557438
|
-
return
|
|
557394
|
+
return join150(CACHE_PATHS.errors(), DATE + ".jsonl");
|
|
557439
557395
|
}
|
|
557440
557396
|
function getMCPLogsPath(serverName) {
|
|
557441
|
-
return
|
|
557397
|
+
return join150(CACHE_PATHS.mcpLogs(serverName), DATE + ".jsonl");
|
|
557442
557398
|
}
|
|
557443
557399
|
function createJsonlWriter(options) {
|
|
557444
557400
|
const writer = createBufferedWriter(options);
|
|
@@ -557781,7 +557737,7 @@ var init_sessionMemory = __esm(() => {
|
|
|
557781
557737
|
// src/utils/iTermBackup.ts
|
|
557782
557738
|
import { copyFile as copyFile12, stat as stat49 } from "fs/promises";
|
|
557783
557739
|
import { homedir as homedir39 } from "os";
|
|
557784
|
-
import { join as
|
|
557740
|
+
import { join as join151 } from "path";
|
|
557785
557741
|
function markITerm2SetupComplete() {
|
|
557786
557742
|
saveGlobalConfig((current) => ({
|
|
557787
557743
|
...current,
|
|
@@ -557796,7 +557752,7 @@ function getIterm2RecoveryInfo() {
|
|
|
557796
557752
|
};
|
|
557797
557753
|
}
|
|
557798
557754
|
function getITerm2PlistPath() {
|
|
557799
|
-
return
|
|
557755
|
+
return join151(homedir39(), "Library", "Preferences", "com.googlecode.iterm2.plist");
|
|
557800
557756
|
}
|
|
557801
557757
|
async function checkAndRestoreITerm2Backup() {
|
|
557802
557758
|
const { inProgress, backupPath } = getIterm2RecoveryInfo();
|
|
@@ -561161,7 +561117,7 @@ var init_idleTimeout = __esm(() => {
|
|
|
561161
561117
|
// src/bridge/inboundAttachments.ts
|
|
561162
561118
|
import { randomUUID as randomUUID48 } from "crypto";
|
|
561163
561119
|
import { mkdir as mkdir42, writeFile as writeFile46 } from "fs/promises";
|
|
561164
|
-
import { basename as basename58, join as
|
|
561120
|
+
import { basename as basename58, join as join152 } from "path";
|
|
561165
561121
|
function debug3(msg) {
|
|
561166
561122
|
logForDebugging(`[bridge:inbound-attach] ${msg}`);
|
|
561167
561123
|
}
|
|
@@ -561177,7 +561133,7 @@ function sanitizeFileName(name) {
|
|
|
561177
561133
|
return base2 || "attachment";
|
|
561178
561134
|
}
|
|
561179
561135
|
function uploadsDir() {
|
|
561180
|
-
return
|
|
561136
|
+
return join152(getClaudeConfigHomeDir(), "uploads", getSessionId());
|
|
561181
561137
|
}
|
|
561182
561138
|
async function resolveOne(att) {
|
|
561183
561139
|
const token = getBridgeAccessToken();
|
|
@@ -561206,7 +561162,7 @@ async function resolveOne(att) {
|
|
|
561206
561162
|
const safeName = sanitizeFileName(att.file_name);
|
|
561207
561163
|
const prefix = (att.file_uuid.slice(0, 8) || randomUUID48().slice(0, 8)).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
561208
561164
|
const dir = uploadsDir();
|
|
561209
|
-
const outPath =
|
|
561165
|
+
const outPath = join152(dir, `${prefix}-${safeName}`);
|
|
561210
561166
|
try {
|
|
561211
561167
|
await mkdir42(dir, { recursive: true });
|
|
561212
561168
|
await writeFile46(outPath, data);
|
|
@@ -561305,11 +561261,11 @@ var init_sessionUrl = __esm(() => {
|
|
|
561305
561261
|
});
|
|
561306
561262
|
|
|
561307
561263
|
// src/utils/plugins/zipCacheAdapters.ts
|
|
561308
|
-
import { readFile as
|
|
561309
|
-
import { join as
|
|
561264
|
+
import { readFile as readFile51 } from "fs/promises";
|
|
561265
|
+
import { join as join153 } from "path";
|
|
561310
561266
|
async function readZipCacheKnownMarketplaces() {
|
|
561311
561267
|
try {
|
|
561312
|
-
const content = await
|
|
561268
|
+
const content = await readFile51(getZipCacheKnownMarketplacesPath(), "utf-8");
|
|
561313
561269
|
const parsed = KnownMarketplacesFileSchema().safeParse(jsonParse(content));
|
|
561314
561270
|
if (!parsed.success) {
|
|
561315
561271
|
logForDebugging(`Invalid known_marketplaces.json in zip cache: ${parsed.error.message}`, { level: "error" });
|
|
@@ -561331,18 +561287,18 @@ async function saveMarketplaceJsonToZipCache(marketplaceName, installLocation) {
|
|
|
561331
561287
|
const content = await readMarketplaceJsonContent(installLocation);
|
|
561332
561288
|
if (content !== null) {
|
|
561333
561289
|
const relPath = getMarketplaceJsonRelativePath(marketplaceName);
|
|
561334
|
-
await atomicWriteToZipCache(
|
|
561290
|
+
await atomicWriteToZipCache(join153(zipCachePath, relPath), content);
|
|
561335
561291
|
}
|
|
561336
561292
|
}
|
|
561337
561293
|
async function readMarketplaceJsonContent(dir) {
|
|
561338
561294
|
const candidates = [
|
|
561339
|
-
|
|
561340
|
-
|
|
561295
|
+
join153(dir, ".claude-plugin", "marketplace.json"),
|
|
561296
|
+
join153(dir, "marketplace.json"),
|
|
561341
561297
|
dir
|
|
561342
561298
|
];
|
|
561343
561299
|
for (const candidate of candidates) {
|
|
561344
561300
|
try {
|
|
561345
|
-
return await
|
|
561301
|
+
return await readFile51(candidate, "utf-8");
|
|
561346
561302
|
} catch {}
|
|
561347
561303
|
}
|
|
561348
561304
|
return null;
|
|
@@ -561795,10 +561751,10 @@ __export(exports_bridgePointer, {
|
|
|
561795
561751
|
clearBridgePointer: () => clearBridgePointer,
|
|
561796
561752
|
BRIDGE_POINTER_TTL_MS: () => BRIDGE_POINTER_TTL_MS
|
|
561797
561753
|
});
|
|
561798
|
-
import { mkdir as mkdir43, readFile as
|
|
561799
|
-
import { dirname as dirname65, join as
|
|
561754
|
+
import { mkdir as mkdir43, readFile as readFile52, stat as stat50, unlink as unlink22, writeFile as writeFile47 } from "fs/promises";
|
|
561755
|
+
import { dirname as dirname65, join as join154 } from "path";
|
|
561800
561756
|
function getBridgePointerPath(dir) {
|
|
561801
|
-
return
|
|
561757
|
+
return join154(getProjectsDir(), sanitizePath2(dir), "bridge-pointer.json");
|
|
561802
561758
|
}
|
|
561803
561759
|
async function writeBridgePointer(dir, pointer) {
|
|
561804
561760
|
const path24 = getBridgePointerPath(dir);
|
|
@@ -561816,7 +561772,7 @@ async function readBridgePointer(dir) {
|
|
|
561816
561772
|
let mtimeMs;
|
|
561817
561773
|
try {
|
|
561818
561774
|
mtimeMs = (await stat50(path24)).mtimeMs;
|
|
561819
|
-
raw = await
|
|
561775
|
+
raw = await readFile52(path24, "utf8");
|
|
561820
561776
|
} catch {
|
|
561821
561777
|
return null;
|
|
561822
561778
|
}
|
|
@@ -563805,7 +563761,7 @@ __export(exports_print, {
|
|
|
563805
563761
|
createCanUseToolWithPermissionPrompt: () => createCanUseToolWithPermissionPrompt,
|
|
563806
563762
|
canBatchWith: () => canBatchWith
|
|
563807
563763
|
});
|
|
563808
|
-
import { readFile as
|
|
563764
|
+
import { readFile as readFile53, stat as stat51 } from "fs/promises";
|
|
563809
563765
|
import { dirname as dirname66 } from "path";
|
|
563810
563766
|
import { cwd as cwd2 } from "process";
|
|
563811
563767
|
import { randomUUID as randomUUID51 } from "crypto";
|
|
@@ -565155,7 +565111,7 @@ ${m2.text}
|
|
|
565155
565111
|
const normalizedPath = expandPath(message.request.path);
|
|
565156
565112
|
const diskMtime = Math.floor((await stat51(normalizedPath)).mtimeMs);
|
|
565157
565113
|
if (diskMtime <= message.request.mtime) {
|
|
565158
|
-
const raw = await
|
|
565114
|
+
const raw = await readFile53(normalizedPath, "utf-8");
|
|
565159
565115
|
const content = (raw.charCodeAt(0) === 65279 ? raw.slice(1) : raw).replaceAll(`\r
|
|
565160
565116
|
`, `
|
|
565161
565117
|
`);
|
|
@@ -567733,16 +567689,16 @@ __export(exports_claudeDesktop, {
|
|
|
567733
567689
|
readClaudeDesktopMcpServers: () => readClaudeDesktopMcpServers,
|
|
567734
567690
|
getClaudeDesktopConfigPath: () => getClaudeDesktopConfigPath
|
|
567735
567691
|
});
|
|
567736
|
-
import { readdir as readdir30, readFile as
|
|
567692
|
+
import { readdir as readdir30, readFile as readFile54, stat as stat52 } from "fs/promises";
|
|
567737
567693
|
import { homedir as homedir40 } from "os";
|
|
567738
|
-
import { join as
|
|
567694
|
+
import { join as join155 } from "path";
|
|
567739
567695
|
async function getClaudeDesktopConfigPath() {
|
|
567740
567696
|
const platform6 = getPlatform();
|
|
567741
567697
|
if (!SUPPORTED_PLATFORMS.includes(platform6)) {
|
|
567742
567698
|
throw new Error(`Unsupported platform: ${platform6} - Claude Desktop integration only works on macOS and WSL.`);
|
|
567743
567699
|
}
|
|
567744
567700
|
if (platform6 === "macos") {
|
|
567745
|
-
return
|
|
567701
|
+
return join155(homedir40(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
567746
567702
|
}
|
|
567747
567703
|
const windowsHome = process.env.USERPROFILE ? process.env.USERPROFILE.replace(/\\/g, "/") : null;
|
|
567748
567704
|
if (windowsHome) {
|
|
@@ -567761,7 +567717,7 @@ async function getClaudeDesktopConfigPath() {
|
|
|
567761
567717
|
if (user.name === "Public" || user.name === "Default" || user.name === "Default User" || user.name === "All Users") {
|
|
567762
567718
|
continue;
|
|
567763
567719
|
}
|
|
567764
|
-
const potentialConfigPath =
|
|
567720
|
+
const potentialConfigPath = join155(usersDir, user.name, "AppData", "Roaming", "Claude", "claude_desktop_config.json");
|
|
567765
567721
|
try {
|
|
567766
567722
|
await stat52(potentialConfigPath);
|
|
567767
567723
|
return potentialConfigPath;
|
|
@@ -567781,7 +567737,7 @@ async function readClaudeDesktopMcpServers() {
|
|
|
567781
567737
|
const configPath = await getClaudeDesktopConfigPath();
|
|
567782
567738
|
let configContent;
|
|
567783
567739
|
try {
|
|
567784
|
-
configContent = await
|
|
567740
|
+
configContent = await readFile54(configPath, { encoding: "utf8" });
|
|
567785
567741
|
} catch (e) {
|
|
567786
567742
|
const code = getErrnoCode(e);
|
|
567787
567743
|
if (code === "ENOENT") {
|
|
@@ -568670,12 +568626,12 @@ __export(exports_install, {
|
|
|
568670
568626
|
install: () => install
|
|
568671
568627
|
});
|
|
568672
568628
|
import { homedir as homedir41 } from "node:os";
|
|
568673
|
-
import { join as
|
|
568629
|
+
import { join as join156 } from "node:path";
|
|
568674
568630
|
function getInstallationPath2() {
|
|
568675
568631
|
const isWindows2 = env4.platform === "win32";
|
|
568676
568632
|
const homeDir = homedir41();
|
|
568677
568633
|
if (isWindows2) {
|
|
568678
|
-
const windowsPath =
|
|
568634
|
+
const windowsPath = join156(homeDir, ".local", "bin", "claude.exe");
|
|
568679
568635
|
return windowsPath.replace(/\//g, "\\");
|
|
568680
568636
|
}
|
|
568681
568637
|
return "~/.local/bin/claude";
|
|
@@ -572037,6 +571993,10 @@ var init_main3 = __esm(() => {
|
|
|
572037
571993
|
}
|
|
572038
571994
|
});
|
|
572039
571995
|
|
|
571996
|
+
// src/entrypoints/cli.tsx
|
|
571997
|
+
import { join as join157 } from "path";
|
|
571998
|
+
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
571999
|
+
|
|
572040
572000
|
// src/utils/envCompat.ts
|
|
572041
572001
|
var ENV_ALIASES = {
|
|
572042
572002
|
MYCLAUDE_MODEL: "CLAUDE_CODE_MODEL",
|
|
@@ -572098,6 +572058,8 @@ function applyEnvAliases() {
|
|
|
572098
572058
|
}
|
|
572099
572059
|
|
|
572100
572060
|
// src/entrypoints/cli.tsx
|
|
572061
|
+
var __dirname3 = join157(fileURLToPath9(import.meta.url), "..");
|
|
572062
|
+
process.env.CLAUDE_CODE_PLUGIN_SEED_DIR = join157(__dirname3, "../../seed");
|
|
572101
572063
|
applyEnvAliases();
|
|
572102
572064
|
process.env.COREPACK_ENABLE_AUTO_PIN = "0";
|
|
572103
572065
|
if (process.env.CLAUDE_CODE_REMOTE === "true") {
|
package/dist/myclaude.mjs
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// MACRO - build-time constants (injected by build.ts)
|
|
5
5
|
// MACRO injected by build script
|
|
6
6
|
globalThis.MACRO = {
|
|
7
|
-
VERSION: "0.1.
|
|
8
|
-
BUILD_TIME: "2026-06-23T13:
|
|
7
|
+
VERSION: "0.1.37",
|
|
8
|
+
BUILD_TIME: "2026-06-23T13:46:09.406Z",
|
|
9
9
|
PACKAGE_URL: "@funnycode/myclaude",
|
|
10
10
|
NATIVE_PACKAGE_URL: "@funnycode/myclaude",
|
|
11
11
|
VERSION_CHANGELOG: '',
|
|
@@ -554538,6 +554538,52 @@ var init_codegraphCheck = __esm(() => {
|
|
|
554538
554538
|
init_execFileNoThrow();
|
|
554539
554539
|
});
|
|
554540
554540
|
|
|
554541
|
+
// src/plugins/bundled/eccMarketplace.ts
|
|
554542
|
+
async function ensureEccMarketplaceRegistered() {
|
|
554543
|
+
try {
|
|
554544
|
+
const changed = await registerSeedMarketplaces();
|
|
554545
|
+
logForDebugging(changed ? "ECC seed marketplace registered" : "ECC marketplace already registered, skipped");
|
|
554546
|
+
return true;
|
|
554547
|
+
} catch (error49) {
|
|
554548
|
+
logForDebugging(`Failed to register ECC marketplace: ${error49}`, {
|
|
554549
|
+
level: "warn"
|
|
554550
|
+
});
|
|
554551
|
+
return false;
|
|
554552
|
+
}
|
|
554553
|
+
}
|
|
554554
|
+
var init_eccMarketplace = __esm(() => {
|
|
554555
|
+
init_debug();
|
|
554556
|
+
init_marketplaceManager();
|
|
554557
|
+
});
|
|
554558
|
+
|
|
554559
|
+
// src/plugins/bundled/index.ts
|
|
554560
|
+
function initBuiltinPlugins() {
|
|
554561
|
+
registerBuiltinPlugin({
|
|
554562
|
+
name: "codegraph",
|
|
554563
|
+
description: "Semantic code intelligence — surgical context, fewer tool calls",
|
|
554564
|
+
version: "1.0.0",
|
|
554565
|
+
defaultEnabled: false,
|
|
554566
|
+
isAvailable: () => {
|
|
554567
|
+
isCodeGraphInstalled().catch(() => {});
|
|
554568
|
+
return false;
|
|
554569
|
+
},
|
|
554570
|
+
mcpServers: {
|
|
554571
|
+
codegraph: {
|
|
554572
|
+
command: "codegraph",
|
|
554573
|
+
args: ["mcp"]
|
|
554574
|
+
}
|
|
554575
|
+
}
|
|
554576
|
+
});
|
|
554577
|
+
}
|
|
554578
|
+
async function initSeedMarketplaces() {
|
|
554579
|
+
await ensureEccMarketplaceRegistered();
|
|
554580
|
+
}
|
|
554581
|
+
var init_bundled = __esm(() => {
|
|
554582
|
+
init_builtinPlugins();
|
|
554583
|
+
init_codegraphCheck();
|
|
554584
|
+
init_eccMarketplace();
|
|
554585
|
+
});
|
|
554586
|
+
|
|
554541
554587
|
// src/services/plugins/pluginCliCommands.ts
|
|
554542
554588
|
function handlePluginCommandError(error49, command8, plugin2) {
|
|
554543
554589
|
logError2(error49);
|
|
@@ -554698,96 +554744,6 @@ var init_pluginCliCommands = __esm(() => {
|
|
|
554698
554744
|
init_pluginOperations();
|
|
554699
554745
|
});
|
|
554700
554746
|
|
|
554701
|
-
// src/plugins/bundled/eccMarketplace.ts
|
|
554702
|
-
import { join as join150 } from "path";
|
|
554703
|
-
import { readFile as readFile51 } from "fs/promises";
|
|
554704
|
-
async function ensureEccMarketplaceRegistered() {
|
|
554705
|
-
try {
|
|
554706
|
-
const result = await addMarketplaceSource({
|
|
554707
|
-
source: "git",
|
|
554708
|
-
url: ECC_MARKETPLACE_URL
|
|
554709
|
-
});
|
|
554710
|
-
const eccName = result.name;
|
|
554711
|
-
logForDebugging(`ECC marketplace registered as '${eccName}' (materialized: ${!result.alreadyMaterialized})`);
|
|
554712
|
-
await installEccPlugins(eccName);
|
|
554713
|
-
return true;
|
|
554714
|
-
} catch (error49) {
|
|
554715
|
-
logForDebugging(`Failed to register ECC marketplace: ${error49}`, {
|
|
554716
|
-
level: "warn"
|
|
554717
|
-
});
|
|
554718
|
-
return false;
|
|
554719
|
-
}
|
|
554720
|
-
}
|
|
554721
|
-
async function installEccPlugins(marketplaceName) {
|
|
554722
|
-
try {
|
|
554723
|
-
const cacheDir = getMarketplacesCacheDir();
|
|
554724
|
-
const marketplaceDir = join150(cacheDir, marketplaceName);
|
|
554725
|
-
const marketplaceJsonPath = join150(marketplaceDir, ".claude-plugin", "marketplace.json");
|
|
554726
|
-
let marketplaceData;
|
|
554727
|
-
try {
|
|
554728
|
-
const content = await readFile51(marketplaceJsonPath, "utf-8");
|
|
554729
|
-
marketplaceData = JSON.parse(content);
|
|
554730
|
-
} catch {
|
|
554731
|
-
logForDebugging("ECC marketplace.json not found yet, skipping auto-install");
|
|
554732
|
-
return;
|
|
554733
|
-
}
|
|
554734
|
-
const plugins = marketplaceData?.plugins ?? [];
|
|
554735
|
-
if (plugins.length === 0) {
|
|
554736
|
-
logForDebugging("No plugins found in ECC marketplace");
|
|
554737
|
-
return;
|
|
554738
|
-
}
|
|
554739
|
-
let installed = 0;
|
|
554740
|
-
for (const plugin2 of plugins) {
|
|
554741
|
-
try {
|
|
554742
|
-
const pluginId = `${plugin2.name}@${marketplaceName}`;
|
|
554743
|
-
await installPlugin(pluginId, "user");
|
|
554744
|
-
installed++;
|
|
554745
|
-
} catch (pluginError) {
|
|
554746
|
-
logForDebugging(`Failed to auto-install ECC plugin '${plugin2.name}': ${pluginError}`, { level: "warn" });
|
|
554747
|
-
}
|
|
554748
|
-
}
|
|
554749
|
-
logForDebugging(`Auto-installed ${installed}/${plugins.length} ECC plugins`);
|
|
554750
|
-
} catch (error49) {
|
|
554751
|
-
logForDebugging(`Failed to auto-install ECC plugins: ${error49}`, {
|
|
554752
|
-
level: "warn"
|
|
554753
|
-
});
|
|
554754
|
-
}
|
|
554755
|
-
}
|
|
554756
|
-
var ECC_MARKETPLACE_URL = "https://github.com/affaan-m/ECC.git";
|
|
554757
|
-
var init_eccMarketplace = __esm(() => {
|
|
554758
|
-
init_debug();
|
|
554759
|
-
init_marketplaceManager();
|
|
554760
|
-
init_pluginCliCommands();
|
|
554761
|
-
});
|
|
554762
|
-
|
|
554763
|
-
// src/plugins/bundled/index.ts
|
|
554764
|
-
function initBuiltinPlugins() {
|
|
554765
|
-
registerBuiltinPlugin({
|
|
554766
|
-
name: "codegraph",
|
|
554767
|
-
description: "Semantic code intelligence — surgical context, fewer tool calls",
|
|
554768
|
-
version: "1.0.0",
|
|
554769
|
-
defaultEnabled: false,
|
|
554770
|
-
isAvailable: () => {
|
|
554771
|
-
isCodeGraphInstalled().catch(() => {});
|
|
554772
|
-
return false;
|
|
554773
|
-
},
|
|
554774
|
-
mcpServers: {
|
|
554775
|
-
codegraph: {
|
|
554776
|
-
command: "codegraph",
|
|
554777
|
-
args: ["mcp"]
|
|
554778
|
-
}
|
|
554779
|
-
}
|
|
554780
|
-
});
|
|
554781
|
-
}
|
|
554782
|
-
async function initSeedMarketplaces() {
|
|
554783
|
-
await ensureEccMarketplaceRegistered();
|
|
554784
|
-
}
|
|
554785
|
-
var init_bundled = __esm(() => {
|
|
554786
|
-
init_builtinPlugins();
|
|
554787
|
-
init_codegraphCheck();
|
|
554788
|
-
init_eccMarketplace();
|
|
554789
|
-
});
|
|
554790
|
-
|
|
554791
554747
|
// src/skills/bundled/batch.ts
|
|
554792
554748
|
function buildPrompt(instruction) {
|
|
554793
554749
|
return `# Batch: Parallel Work Orchestration
|
|
@@ -557433,12 +557389,12 @@ var init_createDirectConnectSession = __esm(() => {
|
|
|
557433
557389
|
});
|
|
557434
557390
|
|
|
557435
557391
|
// src/utils/errorLogSink.ts
|
|
557436
|
-
import { dirname as dirname64, join as
|
|
557392
|
+
import { dirname as dirname64, join as join150 } from "path";
|
|
557437
557393
|
function getErrorsPath() {
|
|
557438
|
-
return
|
|
557394
|
+
return join150(CACHE_PATHS.errors(), DATE + ".jsonl");
|
|
557439
557395
|
}
|
|
557440
557396
|
function getMCPLogsPath(serverName) {
|
|
557441
|
-
return
|
|
557397
|
+
return join150(CACHE_PATHS.mcpLogs(serverName), DATE + ".jsonl");
|
|
557442
557398
|
}
|
|
557443
557399
|
function createJsonlWriter(options) {
|
|
557444
557400
|
const writer = createBufferedWriter(options);
|
|
@@ -557781,7 +557737,7 @@ var init_sessionMemory = __esm(() => {
|
|
|
557781
557737
|
// src/utils/iTermBackup.ts
|
|
557782
557738
|
import { copyFile as copyFile12, stat as stat49 } from "fs/promises";
|
|
557783
557739
|
import { homedir as homedir39 } from "os";
|
|
557784
|
-
import { join as
|
|
557740
|
+
import { join as join151 } from "path";
|
|
557785
557741
|
function markITerm2SetupComplete() {
|
|
557786
557742
|
saveGlobalConfig((current) => ({
|
|
557787
557743
|
...current,
|
|
@@ -557796,7 +557752,7 @@ function getIterm2RecoveryInfo() {
|
|
|
557796
557752
|
};
|
|
557797
557753
|
}
|
|
557798
557754
|
function getITerm2PlistPath() {
|
|
557799
|
-
return
|
|
557755
|
+
return join151(homedir39(), "Library", "Preferences", "com.googlecode.iterm2.plist");
|
|
557800
557756
|
}
|
|
557801
557757
|
async function checkAndRestoreITerm2Backup() {
|
|
557802
557758
|
const { inProgress, backupPath } = getIterm2RecoveryInfo();
|
|
@@ -561161,7 +561117,7 @@ var init_idleTimeout = __esm(() => {
|
|
|
561161
561117
|
// src/bridge/inboundAttachments.ts
|
|
561162
561118
|
import { randomUUID as randomUUID48 } from "crypto";
|
|
561163
561119
|
import { mkdir as mkdir42, writeFile as writeFile46 } from "fs/promises";
|
|
561164
|
-
import { basename as basename58, join as
|
|
561120
|
+
import { basename as basename58, join as join152 } from "path";
|
|
561165
561121
|
function debug3(msg) {
|
|
561166
561122
|
logForDebugging(`[bridge:inbound-attach] ${msg}`);
|
|
561167
561123
|
}
|
|
@@ -561177,7 +561133,7 @@ function sanitizeFileName(name) {
|
|
|
561177
561133
|
return base2 || "attachment";
|
|
561178
561134
|
}
|
|
561179
561135
|
function uploadsDir() {
|
|
561180
|
-
return
|
|
561136
|
+
return join152(getClaudeConfigHomeDir(), "uploads", getSessionId());
|
|
561181
561137
|
}
|
|
561182
561138
|
async function resolveOne(att) {
|
|
561183
561139
|
const token = getBridgeAccessToken();
|
|
@@ -561206,7 +561162,7 @@ async function resolveOne(att) {
|
|
|
561206
561162
|
const safeName = sanitizeFileName(att.file_name);
|
|
561207
561163
|
const prefix = (att.file_uuid.slice(0, 8) || randomUUID48().slice(0, 8)).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
561208
561164
|
const dir = uploadsDir();
|
|
561209
|
-
const outPath =
|
|
561165
|
+
const outPath = join152(dir, `${prefix}-${safeName}`);
|
|
561210
561166
|
try {
|
|
561211
561167
|
await mkdir42(dir, { recursive: true });
|
|
561212
561168
|
await writeFile46(outPath, data);
|
|
@@ -561305,11 +561261,11 @@ var init_sessionUrl = __esm(() => {
|
|
|
561305
561261
|
});
|
|
561306
561262
|
|
|
561307
561263
|
// src/utils/plugins/zipCacheAdapters.ts
|
|
561308
|
-
import { readFile as
|
|
561309
|
-
import { join as
|
|
561264
|
+
import { readFile as readFile51 } from "fs/promises";
|
|
561265
|
+
import { join as join153 } from "path";
|
|
561310
561266
|
async function readZipCacheKnownMarketplaces() {
|
|
561311
561267
|
try {
|
|
561312
|
-
const content = await
|
|
561268
|
+
const content = await readFile51(getZipCacheKnownMarketplacesPath(), "utf-8");
|
|
561313
561269
|
const parsed = KnownMarketplacesFileSchema().safeParse(jsonParse(content));
|
|
561314
561270
|
if (!parsed.success) {
|
|
561315
561271
|
logForDebugging(`Invalid known_marketplaces.json in zip cache: ${parsed.error.message}`, { level: "error" });
|
|
@@ -561331,18 +561287,18 @@ async function saveMarketplaceJsonToZipCache(marketplaceName, installLocation) {
|
|
|
561331
561287
|
const content = await readMarketplaceJsonContent(installLocation);
|
|
561332
561288
|
if (content !== null) {
|
|
561333
561289
|
const relPath = getMarketplaceJsonRelativePath(marketplaceName);
|
|
561334
|
-
await atomicWriteToZipCache(
|
|
561290
|
+
await atomicWriteToZipCache(join153(zipCachePath, relPath), content);
|
|
561335
561291
|
}
|
|
561336
561292
|
}
|
|
561337
561293
|
async function readMarketplaceJsonContent(dir) {
|
|
561338
561294
|
const candidates = [
|
|
561339
|
-
|
|
561340
|
-
|
|
561295
|
+
join153(dir, ".claude-plugin", "marketplace.json"),
|
|
561296
|
+
join153(dir, "marketplace.json"),
|
|
561341
561297
|
dir
|
|
561342
561298
|
];
|
|
561343
561299
|
for (const candidate of candidates) {
|
|
561344
561300
|
try {
|
|
561345
|
-
return await
|
|
561301
|
+
return await readFile51(candidate, "utf-8");
|
|
561346
561302
|
} catch {}
|
|
561347
561303
|
}
|
|
561348
561304
|
return null;
|
|
@@ -561795,10 +561751,10 @@ __export(exports_bridgePointer, {
|
|
|
561795
561751
|
clearBridgePointer: () => clearBridgePointer,
|
|
561796
561752
|
BRIDGE_POINTER_TTL_MS: () => BRIDGE_POINTER_TTL_MS
|
|
561797
561753
|
});
|
|
561798
|
-
import { mkdir as mkdir43, readFile as
|
|
561799
|
-
import { dirname as dirname65, join as
|
|
561754
|
+
import { mkdir as mkdir43, readFile as readFile52, stat as stat50, unlink as unlink22, writeFile as writeFile47 } from "fs/promises";
|
|
561755
|
+
import { dirname as dirname65, join as join154 } from "path";
|
|
561800
561756
|
function getBridgePointerPath(dir) {
|
|
561801
|
-
return
|
|
561757
|
+
return join154(getProjectsDir(), sanitizePath2(dir), "bridge-pointer.json");
|
|
561802
561758
|
}
|
|
561803
561759
|
async function writeBridgePointer(dir, pointer) {
|
|
561804
561760
|
const path24 = getBridgePointerPath(dir);
|
|
@@ -561816,7 +561772,7 @@ async function readBridgePointer(dir) {
|
|
|
561816
561772
|
let mtimeMs;
|
|
561817
561773
|
try {
|
|
561818
561774
|
mtimeMs = (await stat50(path24)).mtimeMs;
|
|
561819
|
-
raw = await
|
|
561775
|
+
raw = await readFile52(path24, "utf8");
|
|
561820
561776
|
} catch {
|
|
561821
561777
|
return null;
|
|
561822
561778
|
}
|
|
@@ -563805,7 +563761,7 @@ __export(exports_print, {
|
|
|
563805
563761
|
createCanUseToolWithPermissionPrompt: () => createCanUseToolWithPermissionPrompt,
|
|
563806
563762
|
canBatchWith: () => canBatchWith
|
|
563807
563763
|
});
|
|
563808
|
-
import { readFile as
|
|
563764
|
+
import { readFile as readFile53, stat as stat51 } from "fs/promises";
|
|
563809
563765
|
import { dirname as dirname66 } from "path";
|
|
563810
563766
|
import { cwd as cwd2 } from "process";
|
|
563811
563767
|
import { randomUUID as randomUUID51 } from "crypto";
|
|
@@ -565155,7 +565111,7 @@ ${m2.text}
|
|
|
565155
565111
|
const normalizedPath = expandPath(message.request.path);
|
|
565156
565112
|
const diskMtime = Math.floor((await stat51(normalizedPath)).mtimeMs);
|
|
565157
565113
|
if (diskMtime <= message.request.mtime) {
|
|
565158
|
-
const raw = await
|
|
565114
|
+
const raw = await readFile53(normalizedPath, "utf-8");
|
|
565159
565115
|
const content = (raw.charCodeAt(0) === 65279 ? raw.slice(1) : raw).replaceAll(`\r
|
|
565160
565116
|
`, `
|
|
565161
565117
|
`);
|
|
@@ -567733,16 +567689,16 @@ __export(exports_claudeDesktop, {
|
|
|
567733
567689
|
readClaudeDesktopMcpServers: () => readClaudeDesktopMcpServers,
|
|
567734
567690
|
getClaudeDesktopConfigPath: () => getClaudeDesktopConfigPath
|
|
567735
567691
|
});
|
|
567736
|
-
import { readdir as readdir30, readFile as
|
|
567692
|
+
import { readdir as readdir30, readFile as readFile54, stat as stat52 } from "fs/promises";
|
|
567737
567693
|
import { homedir as homedir40 } from "os";
|
|
567738
|
-
import { join as
|
|
567694
|
+
import { join as join155 } from "path";
|
|
567739
567695
|
async function getClaudeDesktopConfigPath() {
|
|
567740
567696
|
const platform6 = getPlatform();
|
|
567741
567697
|
if (!SUPPORTED_PLATFORMS.includes(platform6)) {
|
|
567742
567698
|
throw new Error(`Unsupported platform: ${platform6} - Claude Desktop integration only works on macOS and WSL.`);
|
|
567743
567699
|
}
|
|
567744
567700
|
if (platform6 === "macos") {
|
|
567745
|
-
return
|
|
567701
|
+
return join155(homedir40(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
567746
567702
|
}
|
|
567747
567703
|
const windowsHome = process.env.USERPROFILE ? process.env.USERPROFILE.replace(/\\/g, "/") : null;
|
|
567748
567704
|
if (windowsHome) {
|
|
@@ -567761,7 +567717,7 @@ async function getClaudeDesktopConfigPath() {
|
|
|
567761
567717
|
if (user.name === "Public" || user.name === "Default" || user.name === "Default User" || user.name === "All Users") {
|
|
567762
567718
|
continue;
|
|
567763
567719
|
}
|
|
567764
|
-
const potentialConfigPath =
|
|
567720
|
+
const potentialConfigPath = join155(usersDir, user.name, "AppData", "Roaming", "Claude", "claude_desktop_config.json");
|
|
567765
567721
|
try {
|
|
567766
567722
|
await stat52(potentialConfigPath);
|
|
567767
567723
|
return potentialConfigPath;
|
|
@@ -567781,7 +567737,7 @@ async function readClaudeDesktopMcpServers() {
|
|
|
567781
567737
|
const configPath = await getClaudeDesktopConfigPath();
|
|
567782
567738
|
let configContent;
|
|
567783
567739
|
try {
|
|
567784
|
-
configContent = await
|
|
567740
|
+
configContent = await readFile54(configPath, { encoding: "utf8" });
|
|
567785
567741
|
} catch (e) {
|
|
567786
567742
|
const code = getErrnoCode(e);
|
|
567787
567743
|
if (code === "ENOENT") {
|
|
@@ -568670,12 +568626,12 @@ __export(exports_install, {
|
|
|
568670
568626
|
install: () => install
|
|
568671
568627
|
});
|
|
568672
568628
|
import { homedir as homedir41 } from "node:os";
|
|
568673
|
-
import { join as
|
|
568629
|
+
import { join as join156 } from "node:path";
|
|
568674
568630
|
function getInstallationPath2() {
|
|
568675
568631
|
const isWindows2 = env4.platform === "win32";
|
|
568676
568632
|
const homeDir = homedir41();
|
|
568677
568633
|
if (isWindows2) {
|
|
568678
|
-
const windowsPath =
|
|
568634
|
+
const windowsPath = join156(homeDir, ".local", "bin", "claude.exe");
|
|
568679
568635
|
return windowsPath.replace(/\//g, "\\");
|
|
568680
568636
|
}
|
|
568681
568637
|
return "~/.local/bin/claude";
|
|
@@ -572037,6 +571993,10 @@ var init_main3 = __esm(() => {
|
|
|
572037
571993
|
}
|
|
572038
571994
|
});
|
|
572039
571995
|
|
|
571996
|
+
// src/entrypoints/cli.tsx
|
|
571997
|
+
import { join as join157 } from "path";
|
|
571998
|
+
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
571999
|
+
|
|
572040
572000
|
// src/utils/envCompat.ts
|
|
572041
572001
|
var ENV_ALIASES = {
|
|
572042
572002
|
MYCLAUDE_MODEL: "CLAUDE_CODE_MODEL",
|
|
@@ -572098,6 +572058,8 @@ function applyEnvAliases() {
|
|
|
572098
572058
|
}
|
|
572099
572059
|
|
|
572100
572060
|
// src/entrypoints/cli.tsx
|
|
572061
|
+
var __dirname3 = join157(fileURLToPath9(import.meta.url), "..");
|
|
572062
|
+
process.env.CLAUDE_CODE_PLUGIN_SEED_DIR = join157(__dirname3, "../../seed");
|
|
572101
572063
|
applyEnvAliases();
|
|
572102
572064
|
process.env.COREPACK_ENABLE_AUTO_PIN = "0";
|
|
572103
572065
|
if (process.env.CLAUDE_CODE_REMOTE === "true") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funnycode/myclaude",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.37",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "An open-source AI coding assistant in your terminal - powered by Claude",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"files": [
|
|
32
32
|
"dist/",
|
|
33
|
+
"seed/",
|
|
33
34
|
"bin/",
|
|
34
35
|
"LICENSE",
|
|
35
36
|
"README.md",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ecc",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "Affaan Mustafa",
|
|
5
|
+
"email": "me@affaanmustafa.com"
|
|
6
|
+
},
|
|
7
|
+
"metadata": {
|
|
8
|
+
"description": "Harness-native ECC skills, hooks, rules, MCP conventions, and operator workflows"
|
|
9
|
+
},
|
|
10
|
+
"plugins": [
|
|
11
|
+
{
|
|
12
|
+
"name": "ecc",
|
|
13
|
+
"source": "./",
|
|
14
|
+
"description": "Harness-native ECC operator layer - 67 agents, 271 skills, 92 legacy command shims, reusable hooks, rules, selective install profiles, and production-ready workflows for Claude Code, Codex, OpenCode, Cursor, and related agent harnesses",
|
|
15
|
+
"version": "2.0.0",
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "Affaan Mustafa",
|
|
18
|
+
"email": "me@affaanmustafa.com"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://ecc.tools",
|
|
21
|
+
"repository": "https://github.com/affaan-m/ECC",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"keywords": ["agents", "skills", "hooks", "commands", "tdd", "code-review", "security", "best-practices"],
|
|
24
|
+
"category": "workflow",
|
|
25
|
+
"tags": ["agents", "skills", "hooks", "commands", "tdd", "code-review", "security", "best-practices"],
|
|
26
|
+
"strict": false
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|