@eventmodelers/cli 1.0.3 → 1.0.4

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/cli.js CHANGED
@@ -1161,39 +1161,50 @@ function ensureMcpRegistered(projectDir, baseUrl) {
1161
1161
  // process spawns `claude` (true for `run --modeling`'s own spawn). It is NOT true
1162
1162
  // for an interactive session opened directly in the project right after
1163
1163
  // `init`/`init-config` — that `claude` process inherits the user's shell env,
1164
- // which never had a reason to already have this var set. Without a `.env` to
1165
- // resolve it from, `.mcp.json`'s `${EVENTMODELERS_TOKEN}` placeholder resolves to
1166
- // empty, the MCP server gets an empty x-token header, and the connection fails
1167
- // silently, until something happens to trigger the `connect` skill's own Step 3.5,
1168
- // which writes this same file. Do it here too so a fresh interactive session works
1169
- // without depending on that skill having run first.
1164
+ // which never had a reason to already have this var set.
1165
+ //
1166
+ // A plain `.env` file does NOT fix this Claude Code never sources one; per its
1167
+ // own docs, an unresolved `.mcp.json` placeholder is left as the literal
1168
+ // `${EVENTMODELERS_TOKEN}` text, which fails auth and falls back to an OAuth
1169
+ // flow the eventmodelers server can't actually satisfy for this client. The
1170
+ // only things Claude Code itself resolves `.mcp.json` placeholders against are
1171
+ // the inherited shell env and its own settings files' `env` block. `.claude/
1172
+ // settings.local.json` is the documented per-user, gitignored-by-convention
1173
+ // scope for exactly this — same idea as `.eventmodelers/config.json` already
1174
+ // holding the raw token, just in the one file Claude Code's own process env
1175
+ // actually consults before expanding `.mcp.json`.
1170
1176
  function ensureEnvToken(targetDir, token) {
1171
1177
  if (!token) return;
1172
- const envPath = join(targetDir, '.env');
1173
- const line = `EVENTMODELERS_TOKEN=${token}`;
1174
-
1175
- if (existsSync(envPath)) {
1176
- const content = readFileSync(envPath, 'utf-8');
1177
- if (/^EVENTMODELERS_TOKEN=/m.test(content)) {
1178
- const updated = content.replace(/^EVENTMODELERS_TOKEN=.*$/m, line);
1179
- if (updated !== content) writeFileSync(envPath, updated);
1180
- } else {
1181
- appendFileSync(envPath, `${content === '' || content.endsWith('\n') ? '' : '\n'}${line}\n`);
1178
+ const claudeDir = join(targetDir, '.claude');
1179
+ mkdirSync(claudeDir, { recursive: true });
1180
+ const settingsPath = join(claudeDir, 'settings.local.json');
1181
+
1182
+ let settings = {};
1183
+ if (existsSync(settingsPath)) {
1184
+ try {
1185
+ settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
1186
+ } catch {
1187
+ settings = {};
1182
1188
  }
1183
- } else {
1184
- writeFileSync(envPath, `${line}\n`);
1185
1189
  }
1186
1190
 
1191
+ settings.env = settings.env || {};
1192
+ settings.env.EVENTMODELERS_TOKEN = token;
1193
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
1194
+
1195
+ // settings.local.json is gitignored by Claude Code's own convention, but make
1196
+ // sure nothing here relies on that silently — it now holds a live secret.
1187
1197
  const gitignorePath = join(targetDir, '.gitignore');
1198
+ const entry = '.claude/settings.local.json';
1188
1199
  if (existsSync(gitignorePath)) {
1189
1200
  const content = readFileSync(gitignorePath, 'utf-8');
1190
- if (!content.split('\n').map((l) => l.trim()).includes('.env')) {
1191
- appendFileSync(gitignorePath, `${content === '' || content.endsWith('\n') ? '' : '\n'}.env\n`);
1201
+ if (!content.split('\n').map((l) => l.trim()).includes(entry)) {
1202
+ appendFileSync(gitignorePath, `${content === '' || content.endsWith('\n') ? '' : '\n'}${entry}\n`);
1192
1203
  }
1193
1204
  } else {
1194
- writeFileSync(gitignorePath, '.env\n');
1205
+ writeFileSync(gitignorePath, `${entry}\n`);
1195
1206
  }
1196
- console.log(' ✓ Wrote EVENTMODELERS_TOKEN to .env (gitignored)');
1207
+ console.log(' ✓ Wrote EVENTMODELERS_TOKEN to .claude/settings.local.json (gitignored)');
1197
1208
  }
1198
1209
 
1199
1210
  // `run --modeling`: modeling-kit's one and only runtime mode — there is no
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eventmodelers/cli",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Eventmodelers CLI — real-time Claude agent + skills for Claude Code, for any stack (Node, Supabase, Axon, Cratis, or modeling-only)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -150,7 +150,7 @@ Always run this step (not only when Step 3 ran) — it's idempotent and safe to
150
150
 
151
151
  The eventmodelers backend exposes the same board capabilities as an MCP server at `<BASE_URL>/mcp`, authenticated with the same `TOKEN` via an `x-token` header. Register it in the project's `.mcp.json` so Claude Code (or any other MCP-aware host) can connect and expose tools as `mcp__eventmodelers__<tool_name>`.
152
152
 
153
- **Do not put the raw token in `.mcp.json`** — that file is typically committed to share server config with the team. Instead reference an environment variable and keep the actual secret in a gitignored `.env` file:
153
+ **Do not put the raw token in `.mcp.json`** — that file is typically committed to share server config with the team. Instead reference an environment variable and set the actual secret in `.claude/settings.local.json`'s `env` block:
154
154
 
155
155
  1. Read the existing `.mcp.json` at the project root if present (it may already list other MCP servers, e.g. a browser-automation server used by `discover-storyboard` — merge into `mcpServers`, never replace the whole file). If absent, start from `{"mcpServers": {}}`.
156
156
  2. Add or update the `eventmodelers` entry:
@@ -165,8 +165,14 @@ The eventmodelers backend exposes the same board capabilities as an MCP server a
165
165
  }
166
166
  }
167
167
  ```
168
- 3. Ensure a project-root `.env` file contains `EVENTMODELERS_TOKEN=<TOKEN>` (append/update the line; create the file if missing).
169
- 4. Ensure `.env` is listed in `.gitignore` (same check-then-append pattern as Step 3 uses for `.eventmodelers/config.json`) — it holds the same secret and must never be committed.
168
+ 3. Read the existing `.claude/settings.local.json` if present and merge in — never clobber `permissions`/`enabledMcpjsonServers` or anything else already there. Ensure it has `EVENTMODELERS_TOKEN` set under `env` (create the file with just this key if it doesn't exist yet):
169
+ ```json
170
+ {
171
+ "env": { "EVENTMODELERS_TOKEN": "<TOKEN>" }
172
+ }
173
+ ```
174
+ A plain `.env` file does **not** work here — Claude Code never sources one, so a `${EVENTMODELERS_TOKEN}` placeholder in `.mcp.json` would be left unexpanded (sent as the literal `${EVENTMODELERS_TOKEN}` text), which fails auth and pushes the client into an OAuth flow the eventmodelers server can't satisfy for this client. `.claude/settings.local.json`'s `env` block — alongside the inherited shell environment — is the only thing Claude Code actually resolves `.mcp.json` placeholders against.
175
+ 4. Ensure `.claude/settings.local.json` is listed in `.gitignore` (same check-then-append pattern as Step 3 uses for `.eventmodelers/config.json`) — it now holds the same secret and must never be committed. (Gitignored by Claude Code's own convention already, but don't rely on that silently.)
170
176
 
171
177
  MCP tools only become visible to the current agent session after the host (re)connects to the server — a brand-new `.mcp.json` entry written mid-session may need the user to approve the new server or reconnect (e.g. Claude Code's `/mcp` command) before `mcp__eventmodelers__*` tools appear in the tool list. That's expected and not an error: tell the user once, then let every other skill fall back to curl automatically until the tools show up.
172
178
 
@@ -226,7 +232,7 @@ The `token` field is a secret. It is never logged or shown after initial confirm
226
232
 
227
233
  ## Security notes
228
234
 
229
- - The config file (`.eventmodelers/config.json`) and the `.env` file holding `EVENTMODELERS_TOKEN` are both workspace-local and gitignored — never commit either.
235
+ - The config file (`.eventmodelers/config.json`) and `.claude/settings.local.json` (holding `EVENTMODELERS_TOKEN` under `env`) are both workspace-local and gitignored — never commit either.
230
236
  - `.mcp.json` itself is safe to commit — it only ever contains the `${EVENTMODELERS_TOKEN}` placeholder, never the literal token.
231
237
  - The token grants write access to all boards in its organization — treat it like a password.
232
238
  - If a skill receives a `401`/`403` (curl) or an access-denied tool error (MCP) mid-session, re-invoke this skill to refresh the config before retrying.