@envseal/cli 0.1.3 → 0.1.5

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.
Files changed (39) hide show
  1. package/dist/bin.js +3 -3
  2. package/dist/cli-utils.d.ts +1 -0
  3. package/dist/cli-utils.js +8 -5
  4. package/dist/commands/doctor.js +26 -10
  5. package/dist/commands/init.js +70 -42
  6. package/dist/commands/revoke.d.ts +1 -1
  7. package/dist/commands/revoke.js +40 -2
  8. package/dist/exit-codes.js +2 -0
  9. package/dist/host-wiring/agents-md-content.d.ts +9 -0
  10. package/dist/host-wiring/agents-md-content.js +73 -0
  11. package/dist/host-wiring/agents-md.d.ts +20 -0
  12. package/dist/host-wiring/agents-md.js +50 -0
  13. package/dist/host-wiring/aider-conf.d.ts +8 -0
  14. package/dist/host-wiring/aider-conf.js +37 -0
  15. package/dist/host-wiring/aider.d.ts +14 -0
  16. package/dist/host-wiring/aider.js +90 -0
  17. package/dist/host-wiring/apply.d.ts +22 -0
  18. package/dist/host-wiring/apply.js +165 -0
  19. package/dist/host-wiring/codex.d.ts +8 -0
  20. package/dist/host-wiring/codex.js +57 -0
  21. package/dist/host-wiring/continue.d.ts +9 -0
  22. package/dist/host-wiring/continue.js +54 -0
  23. package/dist/host-wiring/copilot.d.ts +10 -0
  24. package/dist/host-wiring/copilot.js +99 -0
  25. package/dist/host-wiring/cursor-rules.d.ts +9 -0
  26. package/dist/host-wiring/cursor-rules.js +31 -0
  27. package/dist/host-wiring/cursor.d.ts +31 -0
  28. package/dist/host-wiring/cursor.js +39 -0
  29. package/dist/host-wiring/goose.d.ts +16 -0
  30. package/dist/host-wiring/goose.js +57 -0
  31. package/dist/host-wiring/inspect.d.ts +24 -0
  32. package/dist/host-wiring/inspect.js +102 -0
  33. package/dist/host-wiring/mcp.d.ts +55 -0
  34. package/dist/host-wiring/mcp.js +238 -0
  35. package/dist/host-wiring/zed.d.ts +10 -0
  36. package/dist/host-wiring/zed.js +97 -0
  37. package/dist/host.d.ts +28 -0
  38. package/dist/host.js +131 -16
  39. package/package.json +8 -8
package/dist/host.js CHANGED
@@ -1,6 +1,23 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { homedir } from 'node:os';
4
+ /** Host ids `init --host` accepts. `openhands` is Layer 1 only. */
5
+ export const KNOWN_HOST_IDS = [
6
+ 'claude-code',
7
+ 'cursor',
8
+ 'continue',
9
+ 'aider',
10
+ 'windsurf',
11
+ 'cline',
12
+ 'zed',
13
+ 'codex',
14
+ 'jetbrains',
15
+ 'goose',
16
+ 'copilot',
17
+ 'generic',
18
+ 'unknown',
19
+ 'openhands',
20
+ ];
4
21
  /**
5
22
  * Detect the host environment from marker files and env vars.
6
23
  * Tier A: protocol + interception hooks (Claude Code)
@@ -60,6 +77,110 @@ function envsealHooksInstalled(root) {
60
77
  */
61
78
  const TIER_B_ADVICE = 'Tier B host with protocol + advisory guardrails only. Shell-command leaks are possible; prefer the keychain sink so .env holds only references.';
62
79
  const TIER_C_ADVICE = 'Tier C host with protocol only. No interception hooks available; prefer the keychain sink so .env holds only references.';
80
+ const AIDER_CONF_PATTERNS = ['aider', '.aider'];
81
+ export function aiderMarkerExists(root) {
82
+ return AIDER_CONF_PATTERNS.some((pattern) => existsSync(join(root, `${pattern}.conf.yml`)) ||
83
+ existsSync(join(root, `${pattern}.conf.yaml`)) ||
84
+ existsSync(join(root, `${pattern}.conf.json`)));
85
+ }
86
+ export function copilotSettingsExist(root) {
87
+ const vscodeSettings = join(root, '.vscode', 'settings.json');
88
+ try {
89
+ return existsSync(vscodeSettings) && /copilot/i.test(readFileSync(vscodeSettings, 'utf8'));
90
+ }
91
+ catch {
92
+ return false;
93
+ }
94
+ }
95
+ /**
96
+ * Every project-local host marker in this repo. Used by `init` so a dual-host
97
+ * tree (`.cursor/` + `.claude/`) gets both configs. Does not include AGENTS.md
98
+ * (Layer 1 is always applied) and does not scan `$HOME`.
99
+ */
100
+ export function collectProjectHostIds(root) {
101
+ const ids = [];
102
+ if (existsSync(join(root, '.claude')))
103
+ ids.push('claude-code');
104
+ if (existsSync(join(root, '.cursor')))
105
+ ids.push('cursor');
106
+ if (existsSync(join(root, '.continue')))
107
+ ids.push('continue');
108
+ if (aiderMarkerExists(root))
109
+ ids.push('aider');
110
+ if (existsSync(join(root, '.windsurf')))
111
+ ids.push('windsurf');
112
+ if (existsSync(join(root, '.cline')))
113
+ ids.push('cline');
114
+ if (existsSync(join(root, '.zed')))
115
+ ids.push('zed');
116
+ if (existsSync(join(root, '.codex')))
117
+ ids.push('codex');
118
+ if (existsSync(join(root, '.idea')))
119
+ ids.push('jetbrains');
120
+ if (existsSync(join(root, 'goose.config.yaml')) || existsSync(join(root, '.goose'))) {
121
+ ids.push('goose');
122
+ }
123
+ if (copilotSettingsExist(root))
124
+ ids.push('copilot');
125
+ return ids;
126
+ }
127
+ /**
128
+ * This-process host only. Used by `init` when the project has no markers.
129
+ * Never treats a global `~/.cursor` / `~/.codex` install as this project.
130
+ */
131
+ export function detectProcessHostId() {
132
+ if (process.env.CLAUDECODE)
133
+ return 'claude-code';
134
+ if (process.env.CURSOR_WORKSPACE || process.env.CURSOR_VERSION)
135
+ return 'cursor';
136
+ if (process.env.CLINE_ROOT)
137
+ return 'cline';
138
+ if (process.env.ZED_EDITOR)
139
+ return 'zed';
140
+ if (process.env.CODEX_ROOT)
141
+ return 'codex';
142
+ if (process.env.GOOSE_ROOT)
143
+ return 'goose';
144
+ return undefined;
145
+ }
146
+ export function parseHostOverride(raw) {
147
+ const ids = raw
148
+ .split(',')
149
+ .map((s) => s.trim())
150
+ .filter((s) => s.length > 0);
151
+ if (ids.length === 0) {
152
+ return { error: `unknown --host '${raw}'. Valid values: ${KNOWN_HOST_IDS.join(', ')}.` };
153
+ }
154
+ const unknown = ids.filter((id) => !KNOWN_HOST_IDS.includes(id));
155
+ if (unknown.length > 0) {
156
+ return {
157
+ error: `unknown --host '${unknown.join(', ')}'. Valid values: ${KNOWN_HOST_IDS.join(', ')}.`,
158
+ };
159
+ }
160
+ return ids;
161
+ }
162
+ /**
163
+ * Which hosts `init` should write Layer 2 config for.
164
+ * `--host` is an escape hatch (comma-separated ok). Never crawls `$HOME`.
165
+ */
166
+ export function resolveInitHostIds(root, hostOverride) {
167
+ if (hostOverride !== undefined) {
168
+ const parsed = parseHostOverride(hostOverride);
169
+ if ('error' in parsed) {
170
+ return { ids: [], source: 'flag', error: parsed.error };
171
+ }
172
+ return { ids: parsed, source: 'flag' };
173
+ }
174
+ const project = collectProjectHostIds(root);
175
+ if (project.length > 0) {
176
+ return { ids: project, source: 'project' };
177
+ }
178
+ const processId = detectProcessHostId();
179
+ if (processId !== undefined) {
180
+ return { ids: [processId], source: 'process' };
181
+ }
182
+ return { ids: [], source: 'none' };
183
+ }
63
184
  export function detectHost(root) {
64
185
  /* ---------------- Pass 1: project-local evidence ---------------- */
65
186
  // Claude Code. Detecting the HOST is not the same as detecting the PROTECTION:
@@ -105,11 +226,7 @@ export function detectHost(root) {
105
226
  };
106
227
  }
107
228
  // Tier C: Aider (project-local config forms).
108
- const aiderConfPatterns = ['aider', '.aider'];
109
- const aiderMarkerExists = aiderConfPatterns.some((pattern) => existsSync(join(root, `${pattern}.conf.yml`)) ||
110
- existsSync(join(root, `${pattern}.conf.yaml`)) ||
111
- existsSync(join(root, `${pattern}.conf.json`)));
112
- if (aiderMarkerExists) {
229
+ if (aiderMarkerExists(root)) {
113
230
  return {
114
231
  id: 'aider',
115
232
  name: 'Aider',
@@ -178,16 +295,7 @@ export function detectHost(root) {
178
295
  // directory, so the honest marker is Copilot settings inside
179
296
  // .vscode/settings.json — a bare .vscode/ proves nothing, every VS Code
180
297
  // project has one.
181
- const vscodeSettings = join(root, '.vscode', 'settings.json');
182
- let copilotSettings = false;
183
- try {
184
- copilotSettings =
185
- existsSync(vscodeSettings) && /copilot/i.test(readFileSync(vscodeSettings, 'utf8'));
186
- }
187
- catch {
188
- // Unreadable settings are not evidence of Copilot.
189
- }
190
- if (copilotSettings) {
298
+ if (copilotSettingsExist(root)) {
191
299
  return {
192
300
  id: 'copilot',
193
301
  name: 'GitHub Copilot',
@@ -207,7 +315,14 @@ export function detectHost(root) {
207
315
  };
208
316
  }
209
317
  /* ------------- Pass 2: environment / global-home evidence -------------
210
- * Reached ONLY when the project carries no marker of its own. */
318
+ * Reached ONLY when the project carries no marker of its own.
319
+ *
320
+ * Process env (CLAUDECODE, CURSOR_*, …) names the host running *this*
321
+ * command. `$HOME` markers are labeling only — never a reason for `init`
322
+ * to write files. `~/.codex/` is intentionally not treated as Codex (see
323
+ * tests): a global install is not this project. `~/.codeium/windsurf`,
324
+ * `~/.cline`, `~/.config/zed` lump to Generic Agent, not a named host.
325
+ * `~/.continue/config.yaml` alone is Unknown, matching Continue docs. */
211
326
  if (process.env.CLAUDECODE) {
212
327
  return {
213
328
  id: 'claude-code',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@envseal/cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.js",
@@ -23,13 +23,13 @@
23
23
  "provenance": true
24
24
  },
25
25
  "dependencies": {
26
- "@envseal/core": "0.1.3",
27
- "@envseal/prompters": "0.1.3",
28
- "@envseal/protocol": "0.1.3",
29
- "@envseal/registry": "0.1.3",
30
- "@envseal/detector": "0.1.3",
31
- "@envseal/mcp-server": "0.1.3",
32
- "@envseal/http-server": "0.1.3"
26
+ "@envseal/protocol": "0.1.5",
27
+ "@envseal/core": "0.1.5",
28
+ "@envseal/registry": "0.1.5",
29
+ "@envseal/detector": "0.1.5",
30
+ "@envseal/mcp-server": "0.1.5",
31
+ "@envseal/http-server": "0.1.5",
32
+ "@envseal/prompters": "0.1.5"
33
33
  },
34
34
  "repository": {
35
35
  "type": "git",