envibe 0.2.2 → 0.2.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/index.js +70 -44
- package/dist/index.js +53 -27
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -15498,6 +15498,27 @@ var $stringify = publicApi.stringify;
|
|
|
15498
15498
|
var $visit = visit.visit;
|
|
15499
15499
|
var $visitAsync = visit.visitAsync;
|
|
15500
15500
|
|
|
15501
|
+
// src/utils/file.ts
|
|
15502
|
+
import { readFile, writeFile, access } from "node:fs/promises";
|
|
15503
|
+
function createFile(path) {
|
|
15504
|
+
return {
|
|
15505
|
+
async exists() {
|
|
15506
|
+
try {
|
|
15507
|
+
await access(path);
|
|
15508
|
+
return true;
|
|
15509
|
+
} catch {
|
|
15510
|
+
return false;
|
|
15511
|
+
}
|
|
15512
|
+
},
|
|
15513
|
+
async text() {
|
|
15514
|
+
return readFile(path, "utf-8");
|
|
15515
|
+
}
|
|
15516
|
+
};
|
|
15517
|
+
}
|
|
15518
|
+
async function write(path, content) {
|
|
15519
|
+
await writeFile(path, content, "utf-8");
|
|
15520
|
+
}
|
|
15521
|
+
|
|
15501
15522
|
// src/core/manifest.ts
|
|
15502
15523
|
var MANIFEST_VERSION = 1;
|
|
15503
15524
|
var MANIFEST_FILENAME = ".env.manifest.yaml";
|
|
@@ -15524,12 +15545,12 @@ function parseManifest(content) {
|
|
|
15524
15545
|
throw new Error(`Invalid manifest: variable "${key}" must be an object`);
|
|
15525
15546
|
}
|
|
15526
15547
|
const config = value;
|
|
15527
|
-
const
|
|
15528
|
-
if (!
|
|
15529
|
-
throw new Error(`Invalid manifest: variable "${key}" has invalid access level "${
|
|
15548
|
+
const access2 = config.access;
|
|
15549
|
+
if (!access2 || !isValidAccessLevel(access2)) {
|
|
15550
|
+
throw new Error(`Invalid manifest: variable "${key}" has invalid access level "${access2}". ` + `Valid levels: ${Object.values(AccessLevel).join(", ")}`);
|
|
15530
15551
|
}
|
|
15531
15552
|
variables[key] = {
|
|
15532
|
-
access,
|
|
15553
|
+
access: access2,
|
|
15533
15554
|
description: config.description,
|
|
15534
15555
|
default: config.default,
|
|
15535
15556
|
required: config.required,
|
|
@@ -15570,7 +15591,7 @@ function getManifestFilename() {
|
|
|
15570
15591
|
}
|
|
15571
15592
|
async function loadManifest(directory = ".") {
|
|
15572
15593
|
const path = `${directory}/${MANIFEST_FILENAME}`;
|
|
15573
|
-
const file =
|
|
15594
|
+
const file = createFile(path);
|
|
15574
15595
|
if (!await file.exists()) {
|
|
15575
15596
|
throw new Error(`Manifest not found: ${path}`);
|
|
15576
15597
|
}
|
|
@@ -15580,7 +15601,7 @@ async function loadManifest(directory = ".") {
|
|
|
15580
15601
|
async function saveManifest(manifest, directory = ".") {
|
|
15581
15602
|
const path = `${directory}/${MANIFEST_FILENAME}`;
|
|
15582
15603
|
const content = serializeManifest(manifest);
|
|
15583
|
-
await
|
|
15604
|
+
await write(path, content);
|
|
15584
15605
|
}
|
|
15585
15606
|
// src/core/patterns.ts
|
|
15586
15607
|
var CLASSIFICATION_PATTERNS = [
|
|
@@ -15824,11 +15845,11 @@ function getDisplayValue(key, value, config) {
|
|
|
15824
15845
|
return `<${key}>`;
|
|
15825
15846
|
}
|
|
15826
15847
|
}
|
|
15827
|
-
function canModify(
|
|
15828
|
-
return
|
|
15848
|
+
function canModify(access2) {
|
|
15849
|
+
return access2 === "full" /* FULL */;
|
|
15829
15850
|
}
|
|
15830
|
-
function canSee(
|
|
15831
|
-
return
|
|
15851
|
+
function canSee(access2) {
|
|
15852
|
+
return access2 !== "hidden" /* HIDDEN */;
|
|
15832
15853
|
}
|
|
15833
15854
|
function filterForAI(env, manifest) {
|
|
15834
15855
|
const result = [];
|
|
@@ -15952,7 +15973,7 @@ function parseEnvContent(content) {
|
|
|
15952
15973
|
return result;
|
|
15953
15974
|
}
|
|
15954
15975
|
async function loadEnvFile(path = ENV_FILENAME) {
|
|
15955
|
-
const file =
|
|
15976
|
+
const file = createFile(path);
|
|
15956
15977
|
if (!await file.exists()) {
|
|
15957
15978
|
return { variables: {}, raw: "" };
|
|
15958
15979
|
}
|
|
@@ -15961,7 +15982,7 @@ async function loadEnvFile(path = ENV_FILENAME) {
|
|
|
15961
15982
|
return { variables, raw };
|
|
15962
15983
|
}
|
|
15963
15984
|
async function updateEnvVariable(key, value, path = ENV_FILENAME) {
|
|
15964
|
-
const file =
|
|
15985
|
+
const file = createFile(path);
|
|
15965
15986
|
let content = "";
|
|
15966
15987
|
if (await file.exists()) {
|
|
15967
15988
|
content = await file.text();
|
|
@@ -15993,7 +16014,7 @@ async function updateEnvVariable(key, value, path = ENV_FILENAME) {
|
|
|
15993
16014
|
lines.push("");
|
|
15994
16015
|
}
|
|
15995
16016
|
}
|
|
15996
|
-
await
|
|
16017
|
+
await write(path, lines.join(`
|
|
15997
16018
|
`));
|
|
15998
16019
|
}
|
|
15999
16020
|
function getAIEnvFilename() {
|
|
@@ -16003,14 +16024,14 @@ function escapeRegex(str) {
|
|
|
16003
16024
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
16004
16025
|
}
|
|
16005
16026
|
async function envFileExists(path = ENV_FILENAME) {
|
|
16006
|
-
const file =
|
|
16027
|
+
const file = createFile(path);
|
|
16007
16028
|
return file.exists();
|
|
16008
16029
|
}
|
|
16009
16030
|
|
|
16010
16031
|
// src/cli/commands/init.ts
|
|
16011
16032
|
var initCommand = new Command("init").description("Initialize .env.manifest.yaml from existing .env file").option("-f, --force", "Overwrite existing manifest").option("-e, --env <path>", "Path to .env file", ".env").action(async (options) => {
|
|
16012
16033
|
const manifestPath = getManifestFilename();
|
|
16013
|
-
const manifestFile =
|
|
16034
|
+
const manifestFile = createFile(manifestPath);
|
|
16014
16035
|
if (await manifestFile.exists() && !options.force) {
|
|
16015
16036
|
console.error(`Error: ${manifestPath} already exists. Use --force to overwrite.`);
|
|
16016
16037
|
process.exit(1);
|
|
@@ -16038,15 +16059,15 @@ var initCommand = new Command("init").description("Initialize .env.manifest.yaml
|
|
|
16038
16059
|
console.log("------------------------");
|
|
16039
16060
|
const byAccess = {};
|
|
16040
16061
|
for (const [key, config] of Object.entries(classified)) {
|
|
16041
|
-
const
|
|
16042
|
-
if (!byAccess[
|
|
16043
|
-
byAccess[
|
|
16062
|
+
const access2 = config.access;
|
|
16063
|
+
if (!byAccess[access2]) {
|
|
16064
|
+
byAccess[access2] = [];
|
|
16044
16065
|
}
|
|
16045
|
-
byAccess[
|
|
16066
|
+
byAccess[access2].push(key);
|
|
16046
16067
|
}
|
|
16047
|
-
for (const [
|
|
16068
|
+
for (const [access2, vars] of Object.entries(byAccess)) {
|
|
16048
16069
|
console.log(`
|
|
16049
|
-
[${
|
|
16070
|
+
[${access2}] (${vars.length} variables):`);
|
|
16050
16071
|
for (const v of vars.slice(0, 5)) {
|
|
16051
16072
|
console.log(` - ${v}`);
|
|
16052
16073
|
}
|
|
@@ -16074,7 +16095,7 @@ var generateCommand = new Command("generate").description("Generate AI-safe .env
|
|
|
16074
16095
|
console.log(content);
|
|
16075
16096
|
return;
|
|
16076
16097
|
}
|
|
16077
|
-
await
|
|
16098
|
+
await write(options.output, content);
|
|
16078
16099
|
console.log(`Generated ${options.output} with ${filtered.length} variables`);
|
|
16079
16100
|
const counts = {};
|
|
16080
16101
|
for (const v of filtered) {
|
|
@@ -16082,8 +16103,8 @@ var generateCommand = new Command("generate").description("Generate AI-safe .env
|
|
|
16082
16103
|
}
|
|
16083
16104
|
console.log(`
|
|
16084
16105
|
Access level summary:`);
|
|
16085
|
-
for (const [
|
|
16086
|
-
console.log(` ${
|
|
16106
|
+
for (const [access2, count] of Object.entries(counts)) {
|
|
16107
|
+
console.log(` ${access2}: ${count}`);
|
|
16087
16108
|
}
|
|
16088
16109
|
} catch (error) {
|
|
16089
16110
|
if (error instanceof Error && error.message.includes("not found")) {
|
|
@@ -16128,10 +16149,10 @@ var viewCommand = new Command("view").description("Display environment variables
|
|
|
16128
16149
|
for (const key of Array.from(allKeys).sort()) {
|
|
16129
16150
|
const config = manifest2.variables[key];
|
|
16130
16151
|
const value = env[key];
|
|
16131
|
-
const
|
|
16152
|
+
const access2 = config?.access ?? "unclassified";
|
|
16132
16153
|
const isSet = value !== undefined;
|
|
16133
16154
|
let displayValue;
|
|
16134
|
-
if (
|
|
16155
|
+
if (access2 === "hidden" /* HIDDEN */) {
|
|
16135
16156
|
displayValue = "***HIDDEN***";
|
|
16136
16157
|
} else if (!isSet) {
|
|
16137
16158
|
displayValue = "(not set)";
|
|
@@ -16139,7 +16160,7 @@ var viewCommand = new Command("view").description("Display environment variables
|
|
|
16139
16160
|
displayValue = value;
|
|
16140
16161
|
}
|
|
16141
16162
|
console.log(`${key}=${displayValue}`);
|
|
16142
|
-
console.log(` Access: ${
|
|
16163
|
+
console.log(` Access: ${access2}`);
|
|
16143
16164
|
if (config?.description) {
|
|
16144
16165
|
console.log(` Description: ${config.description}`);
|
|
16145
16166
|
}
|
|
@@ -16188,7 +16209,7 @@ To bypass access control, use --force (not recommended)`);
|
|
|
16188
16209
|
const { variables: env } = await loadEnvFile(options.env);
|
|
16189
16210
|
const filtered = filterForAI(env, manifest2);
|
|
16190
16211
|
const content = generateAIEnvContent(filtered);
|
|
16191
|
-
await
|
|
16212
|
+
await write(getAIEnvFilename(), content);
|
|
16192
16213
|
console.log(`Updated ${getAIEnvFilename()}`);
|
|
16193
16214
|
}
|
|
16194
16215
|
} catch (error) {
|
|
@@ -16279,6 +16300,7 @@ Summary: ${errors2.length} errors, ${warnings.length} warnings`);
|
|
|
16279
16300
|
import * as readline from "readline";
|
|
16280
16301
|
|
|
16281
16302
|
// src/utils/claude-settings.ts
|
|
16303
|
+
import { readdir, mkdir } from "node:fs/promises";
|
|
16282
16304
|
var CLAUDE_DIR = ".claude";
|
|
16283
16305
|
var CLAUDE_SETTINGS_FILE = ".claude/settings.json";
|
|
16284
16306
|
var SAFE_ENV_FILES = [
|
|
@@ -16314,13 +16336,17 @@ var ALLOW_RULES = [
|
|
|
16314
16336
|
"Read(./.env.example)"
|
|
16315
16337
|
];
|
|
16316
16338
|
async function discoverEnvFiles() {
|
|
16317
|
-
const glob = new Bun.Glob(".env*");
|
|
16318
16339
|
const files = [];
|
|
16319
|
-
|
|
16320
|
-
|
|
16321
|
-
|
|
16340
|
+
try {
|
|
16341
|
+
const entries = await readdir(".", { withFileTypes: true });
|
|
16342
|
+
for (const entry of entries) {
|
|
16343
|
+
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
16344
|
+
if (!SAFE_ENV_FILES.includes(entry.name)) {
|
|
16345
|
+
files.push(entry.name);
|
|
16346
|
+
}
|
|
16347
|
+
}
|
|
16322
16348
|
}
|
|
16323
|
-
}
|
|
16349
|
+
} catch {}
|
|
16324
16350
|
return files;
|
|
16325
16351
|
}
|
|
16326
16352
|
function generateDenyRulesForFile(filename) {
|
|
@@ -16336,9 +16362,9 @@ function generateDenyRulesForFile(filename) {
|
|
|
16336
16362
|
}
|
|
16337
16363
|
async function configureClaudeSettings(silent = false) {
|
|
16338
16364
|
try {
|
|
16339
|
-
await
|
|
16365
|
+
await mkdir(CLAUDE_DIR, { recursive: true });
|
|
16340
16366
|
} catch {}
|
|
16341
|
-
const settingsFile =
|
|
16367
|
+
const settingsFile = createFile(CLAUDE_SETTINGS_FILE);
|
|
16342
16368
|
let settings = {};
|
|
16343
16369
|
if (await settingsFile.exists()) {
|
|
16344
16370
|
try {
|
|
@@ -16387,7 +16413,7 @@ async function configureClaudeSettings(silent = false) {
|
|
|
16387
16413
|
command: "npx",
|
|
16388
16414
|
args: ["envibe", "mcp"]
|
|
16389
16415
|
};
|
|
16390
|
-
await
|
|
16416
|
+
await write(CLAUDE_SETTINGS_FILE, JSON.stringify(settings, null, 2) + `
|
|
16391
16417
|
`);
|
|
16392
16418
|
if (!silent) {
|
|
16393
16419
|
const changes = [];
|
|
@@ -16522,7 +16548,7 @@ var setupCommand = new Command("setup").description("Full setup: init manifest,
|
|
|
16522
16548
|
console.log(`Setting up envibe...
|
|
16523
16549
|
`);
|
|
16524
16550
|
const manifestPath = getManifestFilename();
|
|
16525
|
-
const manifestFile =
|
|
16551
|
+
const manifestFile = createFile(manifestPath);
|
|
16526
16552
|
let manifest2;
|
|
16527
16553
|
let sourceFile = null;
|
|
16528
16554
|
if (await manifestFile.exists()) {
|
|
@@ -16568,7 +16594,7 @@ var setupCommand = new Command("setup").description("Full setup: init manifest,
|
|
|
16568
16594
|
}
|
|
16569
16595
|
const filtered = filterForAI(env, manifest2);
|
|
16570
16596
|
const content = generateAIEnvContent(filtered);
|
|
16571
|
-
await
|
|
16597
|
+
await write(getAIEnvFilename(), content);
|
|
16572
16598
|
console.log(` Generated with ${filtered.length} AI-visible variables`);
|
|
16573
16599
|
if (options.skipGitignore) {
|
|
16574
16600
|
console.log("[3/4] Skipped .gitignore configuration");
|
|
@@ -16590,7 +16616,7 @@ Setup complete! Next steps:`);
|
|
|
16590
16616
|
console.log(" 4. AI will read .env.ai and use MCP tools (secrets protected)");
|
|
16591
16617
|
});
|
|
16592
16618
|
async function configureGitignore() {
|
|
16593
|
-
const gitignoreFile =
|
|
16619
|
+
const gitignoreFile = createFile(GITIGNORE_FILE);
|
|
16594
16620
|
let content = "";
|
|
16595
16621
|
if (await gitignoreFile.exists()) {
|
|
16596
16622
|
content = await gitignoreFile.text();
|
|
@@ -16615,7 +16641,7 @@ async function configureGitignore() {
|
|
|
16615
16641
|
`) + `
|
|
16616
16642
|
`;
|
|
16617
16643
|
const newContent = content.trimEnd() + addition;
|
|
16618
|
-
await
|
|
16644
|
+
await write(GITIGNORE_FILE, newContent);
|
|
16619
16645
|
console.log(` Added ${newPatterns.length} patterns`);
|
|
16620
16646
|
}
|
|
16621
16647
|
|
|
@@ -22906,7 +22932,7 @@ var FALLBACK_MANIFEST2 = {
|
|
|
22906
22932
|
}
|
|
22907
22933
|
};
|
|
22908
22934
|
async function ensureSetup() {
|
|
22909
|
-
const manifestFile =
|
|
22935
|
+
const manifestFile = createFile(getManifestFilename());
|
|
22910
22936
|
if (await manifestFile.exists()) {
|
|
22911
22937
|
return loadManifest();
|
|
22912
22938
|
}
|
|
@@ -22941,7 +22967,7 @@ async function ensureSetup() {
|
|
|
22941
22967
|
}
|
|
22942
22968
|
const filtered = filterForAI(env, manifest2);
|
|
22943
22969
|
const content = generateAIEnvContent(filtered);
|
|
22944
|
-
await
|
|
22970
|
+
await write(getAIEnvFilename(), content);
|
|
22945
22971
|
await configureClaudeSettings(true);
|
|
22946
22972
|
return manifest2;
|
|
22947
22973
|
}
|
|
@@ -23127,7 +23153,7 @@ async function startMCPServer() {
|
|
|
23127
23153
|
const { variables: updatedEnv } = await loadEnvFile();
|
|
23128
23154
|
const filtered = filterForAI(updatedEnv, manifest2);
|
|
23129
23155
|
const content = generateAIEnvContent(filtered);
|
|
23130
|
-
await
|
|
23156
|
+
await write(getAIEnvFilename(), content);
|
|
23131
23157
|
return {
|
|
23132
23158
|
content: [
|
|
23133
23159
|
{
|
|
@@ -23279,7 +23305,7 @@ async function startMCPServer() {
|
|
|
23279
23305
|
switch (uri) {
|
|
23280
23306
|
case "env://manifest": {
|
|
23281
23307
|
await ensureSetup();
|
|
23282
|
-
const manifestFile =
|
|
23308
|
+
const manifestFile = createFile(getManifestFilename());
|
|
23283
23309
|
const content = await manifestFile.text();
|
|
23284
23310
|
return {
|
|
23285
23311
|
contents: [
|
package/dist/index.js
CHANGED
|
@@ -13447,6 +13447,27 @@ var $stringify = publicApi.stringify;
|
|
|
13447
13447
|
var $visit = visit.visit;
|
|
13448
13448
|
var $visitAsync = visit.visitAsync;
|
|
13449
13449
|
|
|
13450
|
+
// src/utils/file.ts
|
|
13451
|
+
import { readFile, writeFile, access } from "node:fs/promises";
|
|
13452
|
+
function createFile(path) {
|
|
13453
|
+
return {
|
|
13454
|
+
async exists() {
|
|
13455
|
+
try {
|
|
13456
|
+
await access(path);
|
|
13457
|
+
return true;
|
|
13458
|
+
} catch {
|
|
13459
|
+
return false;
|
|
13460
|
+
}
|
|
13461
|
+
},
|
|
13462
|
+
async text() {
|
|
13463
|
+
return readFile(path, "utf-8");
|
|
13464
|
+
}
|
|
13465
|
+
};
|
|
13466
|
+
}
|
|
13467
|
+
async function write(path, content) {
|
|
13468
|
+
await writeFile(path, content, "utf-8");
|
|
13469
|
+
}
|
|
13470
|
+
|
|
13450
13471
|
// src/core/manifest.ts
|
|
13451
13472
|
var MANIFEST_VERSION = 1;
|
|
13452
13473
|
var MANIFEST_FILENAME = ".env.manifest.yaml";
|
|
@@ -13473,12 +13494,12 @@ function parseManifest(content) {
|
|
|
13473
13494
|
throw new Error(`Invalid manifest: variable "${key}" must be an object`);
|
|
13474
13495
|
}
|
|
13475
13496
|
const config = value;
|
|
13476
|
-
const
|
|
13477
|
-
if (!
|
|
13478
|
-
throw new Error(`Invalid manifest: variable "${key}" has invalid access level "${
|
|
13497
|
+
const access2 = config.access;
|
|
13498
|
+
if (!access2 || !isValidAccessLevel(access2)) {
|
|
13499
|
+
throw new Error(`Invalid manifest: variable "${key}" has invalid access level "${access2}". ` + `Valid levels: ${Object.values(AccessLevel).join(", ")}`);
|
|
13479
13500
|
}
|
|
13480
13501
|
variables[key] = {
|
|
13481
|
-
access,
|
|
13502
|
+
access: access2,
|
|
13482
13503
|
description: config.description,
|
|
13483
13504
|
default: config.default,
|
|
13484
13505
|
required: config.required,
|
|
@@ -13531,7 +13552,7 @@ function getManifestFilename() {
|
|
|
13531
13552
|
}
|
|
13532
13553
|
async function loadManifest(directory = ".") {
|
|
13533
13554
|
const path = `${directory}/${MANIFEST_FILENAME}`;
|
|
13534
|
-
const file =
|
|
13555
|
+
const file = createFile(path);
|
|
13535
13556
|
if (!await file.exists()) {
|
|
13536
13557
|
throw new Error(`Manifest not found: ${path}`);
|
|
13537
13558
|
}
|
|
@@ -13541,7 +13562,7 @@ async function loadManifest(directory = ".") {
|
|
|
13541
13562
|
async function saveManifest(manifest, directory = ".") {
|
|
13542
13563
|
const path = `${directory}/${MANIFEST_FILENAME}`;
|
|
13543
13564
|
const content = serializeManifest(manifest);
|
|
13544
|
-
await
|
|
13565
|
+
await write(path, content);
|
|
13545
13566
|
}
|
|
13546
13567
|
// src/core/patterns.ts
|
|
13547
13568
|
var CLASSIFICATION_PATTERNS = [
|
|
@@ -13785,11 +13806,11 @@ function getDisplayValue(key, value, config) {
|
|
|
13785
13806
|
return `<${key}>`;
|
|
13786
13807
|
}
|
|
13787
13808
|
}
|
|
13788
|
-
function canModify(
|
|
13789
|
-
return
|
|
13809
|
+
function canModify(access2) {
|
|
13810
|
+
return access2 === "full" /* FULL */;
|
|
13790
13811
|
}
|
|
13791
|
-
function canSee(
|
|
13792
|
-
return
|
|
13812
|
+
function canSee(access2) {
|
|
13813
|
+
return access2 !== "hidden" /* HIDDEN */;
|
|
13793
13814
|
}
|
|
13794
13815
|
function filterForAI(env, manifest) {
|
|
13795
13816
|
const result = [];
|
|
@@ -13929,7 +13950,7 @@ function serializeEnv(env) {
|
|
|
13929
13950
|
`;
|
|
13930
13951
|
}
|
|
13931
13952
|
async function loadEnvFile(path = ENV_FILENAME) {
|
|
13932
|
-
const file =
|
|
13953
|
+
const file = createFile(path);
|
|
13933
13954
|
if (!await file.exists()) {
|
|
13934
13955
|
return { variables: {}, raw: "" };
|
|
13935
13956
|
}
|
|
@@ -13939,10 +13960,10 @@ async function loadEnvFile(path = ENV_FILENAME) {
|
|
|
13939
13960
|
}
|
|
13940
13961
|
async function saveEnvFile(env, path = ENV_FILENAME) {
|
|
13941
13962
|
const content = serializeEnv(env);
|
|
13942
|
-
await
|
|
13963
|
+
await write(path, content);
|
|
13943
13964
|
}
|
|
13944
13965
|
async function updateEnvVariable(key, value, path = ENV_FILENAME) {
|
|
13945
|
-
const file =
|
|
13966
|
+
const file = createFile(path);
|
|
13946
13967
|
let content = "";
|
|
13947
13968
|
if (await file.exists()) {
|
|
13948
13969
|
content = await file.text();
|
|
@@ -13974,7 +13995,7 @@ async function updateEnvVariable(key, value, path = ENV_FILENAME) {
|
|
|
13974
13995
|
lines.push("");
|
|
13975
13996
|
}
|
|
13976
13997
|
}
|
|
13977
|
-
await
|
|
13998
|
+
await write(path, lines.join(`
|
|
13978
13999
|
`));
|
|
13979
14000
|
}
|
|
13980
14001
|
function getEnvFilename() {
|
|
@@ -13987,7 +14008,7 @@ function escapeRegex(str) {
|
|
|
13987
14008
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13988
14009
|
}
|
|
13989
14010
|
async function envFileExists(path = ENV_FILENAME) {
|
|
13990
|
-
const file =
|
|
14011
|
+
const file = createFile(path);
|
|
13991
14012
|
return file.exists();
|
|
13992
14013
|
}
|
|
13993
14014
|
async function getEnvVariableNames(path = ENV_FILENAME) {
|
|
@@ -13995,6 +14016,7 @@ async function getEnvVariableNames(path = ENV_FILENAME) {
|
|
|
13995
14016
|
return Object.keys(variables);
|
|
13996
14017
|
}
|
|
13997
14018
|
// src/utils/claude-settings.ts
|
|
14019
|
+
import { readdir, mkdir } from "node:fs/promises";
|
|
13998
14020
|
var CLAUDE_DIR = ".claude";
|
|
13999
14021
|
var CLAUDE_SETTINGS_FILE = ".claude/settings.json";
|
|
14000
14022
|
var SAFE_ENV_FILES = [
|
|
@@ -14030,13 +14052,17 @@ var ALLOW_RULES = [
|
|
|
14030
14052
|
"Read(./.env.example)"
|
|
14031
14053
|
];
|
|
14032
14054
|
async function discoverEnvFiles() {
|
|
14033
|
-
const glob = new Bun.Glob(".env*");
|
|
14034
14055
|
const files = [];
|
|
14035
|
-
|
|
14036
|
-
|
|
14037
|
-
|
|
14056
|
+
try {
|
|
14057
|
+
const entries = await readdir(".", { withFileTypes: true });
|
|
14058
|
+
for (const entry of entries) {
|
|
14059
|
+
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
14060
|
+
if (!SAFE_ENV_FILES.includes(entry.name)) {
|
|
14061
|
+
files.push(entry.name);
|
|
14062
|
+
}
|
|
14063
|
+
}
|
|
14038
14064
|
}
|
|
14039
|
-
}
|
|
14065
|
+
} catch {}
|
|
14040
14066
|
return files;
|
|
14041
14067
|
}
|
|
14042
14068
|
function generateDenyRulesForFile(filename) {
|
|
@@ -14052,9 +14078,9 @@ function generateDenyRulesForFile(filename) {
|
|
|
14052
14078
|
}
|
|
14053
14079
|
async function configureClaudeSettings(silent = false) {
|
|
14054
14080
|
try {
|
|
14055
|
-
await
|
|
14081
|
+
await mkdir(CLAUDE_DIR, { recursive: true });
|
|
14056
14082
|
} catch {}
|
|
14057
|
-
const settingsFile =
|
|
14083
|
+
const settingsFile = createFile(CLAUDE_SETTINGS_FILE);
|
|
14058
14084
|
let settings = {};
|
|
14059
14085
|
if (await settingsFile.exists()) {
|
|
14060
14086
|
try {
|
|
@@ -14103,7 +14129,7 @@ async function configureClaudeSettings(silent = false) {
|
|
|
14103
14129
|
command: "npx",
|
|
14104
14130
|
args: ["envibe", "mcp"]
|
|
14105
14131
|
};
|
|
14106
|
-
await
|
|
14132
|
+
await write(CLAUDE_SETTINGS_FILE, JSON.stringify(settings, null, 2) + `
|
|
14107
14133
|
`);
|
|
14108
14134
|
if (!silent) {
|
|
14109
14135
|
const changes = [];
|
|
@@ -20415,7 +20441,7 @@ var FALLBACK_MANIFEST = {
|
|
|
20415
20441
|
}
|
|
20416
20442
|
};
|
|
20417
20443
|
async function ensureSetup() {
|
|
20418
|
-
const manifestFile =
|
|
20444
|
+
const manifestFile = createFile(getManifestFilename());
|
|
20419
20445
|
if (await manifestFile.exists()) {
|
|
20420
20446
|
return loadManifest();
|
|
20421
20447
|
}
|
|
@@ -20450,7 +20476,7 @@ async function ensureSetup() {
|
|
|
20450
20476
|
}
|
|
20451
20477
|
const filtered = filterForAI(env, manifest2);
|
|
20452
20478
|
const content = generateAIEnvContent(filtered);
|
|
20453
|
-
await
|
|
20479
|
+
await write(getAIEnvFilename(), content);
|
|
20454
20480
|
await configureClaudeSettings(true);
|
|
20455
20481
|
return manifest2;
|
|
20456
20482
|
}
|
|
@@ -20636,7 +20662,7 @@ async function startMCPServer() {
|
|
|
20636
20662
|
const { variables: updatedEnv } = await loadEnvFile();
|
|
20637
20663
|
const filtered = filterForAI(updatedEnv, manifest2);
|
|
20638
20664
|
const content = generateAIEnvContent(filtered);
|
|
20639
|
-
await
|
|
20665
|
+
await write(getAIEnvFilename(), content);
|
|
20640
20666
|
return {
|
|
20641
20667
|
content: [
|
|
20642
20668
|
{
|
|
@@ -20788,7 +20814,7 @@ async function startMCPServer() {
|
|
|
20788
20814
|
switch (uri) {
|
|
20789
20815
|
case "env://manifest": {
|
|
20790
20816
|
await ensureSetup();
|
|
20791
|
-
const manifestFile =
|
|
20817
|
+
const manifestFile = createFile(getManifestFilename());
|
|
20792
20818
|
const content = await manifestFile.text();
|
|
20793
20819
|
return {
|
|
20794
20820
|
contents: [
|