Skip to content

feat(ramen): write first-run config to global, not project-local#98

Open
vigneshshanmugam wants to merge 2 commits intodevfrom
feat/global-ramen-config
Open

feat(ramen): write first-run config to global, not project-local#98
vigneshshanmugam wants to merge 2 commits intodevfrom
feat/global-ramen-config

Conversation

@vigneshshanmugam
Copy link
Copy Markdown
Member

@vigneshshanmugam vigneshshanmugam commented May 9, 2026

What does this PR do?

Today, the first time a user starts ramen in any directory, the setup dialog writes provider, model, mcp.eab, and permission.eab_* into <cwd>/elastic_ramen.json. Users running ramen across many directories had to redo setup each time, and ended up with stale elastic_ramen.json files polluting every project.

This change moves first-run setup, profile switches, and reset to write the same fields to ~/.config/elastic-ramen/elastic_ramen.json (global). The config loader already supported a global file at the same precedence layer; nothing in the merge order changes.

Why it's safe:

  • Elastic auth profiles (~/.config/elastic/config.yaml) are already global.
  • Sessions are already isolated globally by profile (feat(ramen): isolate sessions by Elastic profile #84).
  • Project-local elastic_ramen.json still wins via merge precedence, so a user who explicitly sets provider/model in a project file keeps that override.

Migration:

  • When global is written, provider and model are stripped from any leftover project-local elastic_ramen.json{,c} and .elastic-ramen/elastic_ramen.json{,c} so global stays the single source of truth.
  • .jsonc files are edited via `jsonc-parser`'s `modify` + `applyEdits` so user comments and untouched keys survive intact.
  • Other top-level keys (e.g. `agents`, custom config) in project-local files are preserved.

Other changes:

  • `Config.globalConfigFile` is now exported so `auth.ts` can reuse the same path-resolution logic instead of duplicating it.
  • `auth.dir()` switched from `os.homedir()` to `Global.Path.home` so `OPENCODE_TEST_HOME` actually isolates auth state in tests. Zero behavior change in production.
  • Pre-existing typecheck errors (introduced in feat(ramen): per-connector context limits for Kibana models #95) in `src/provider/provider.ts` and `src/util/model-label.ts` are fixed in a separate commit so the pre-push hook passes. Those are unrelated to the config move but were blocking the PR.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

🤖 Generated with Claude Code

vigneshshanmugam and others added 2 commits May 8, 2026 18:10
First-run setup, profile switches, and reset now write provider, model,
mcp.eab, and permission.eab_* to ~/.config/elastic-ramen/elastic_ramen.json
instead of <cwd>/elastic_ramen.json. Users no longer redo setup in every
directory, and per-project config bloat goes away. Project-local
elastic_ramen.json still wins via merge precedence for users who want
per-project overrides.

Stale provider/model in any project-local elastic_ramen.json{,c} or
.elastic-ramen/elastic_ramen.json{,c} is stripped on next save/switch
to keep global as the single source of truth. .jsonc files are edited
through jsonc-parser so comments and untouched keys survive intact.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Two pre-existing typecheck errors blocked the pre-push hook:

- model-label.ts ProviderEntry.models lacked api?: { id?: string },
  failing the M extends { api?: { id?: string } } constraint of
  KibanaGateway.resolveKibanaModel.

- provider.ts:1247 reassigned info from KibanaGateway.resolveKibanaModel
  (which returns M | undefined) to a let-binding inferred as Model.
  Annotate info as Model | undefined so the union is acceptable.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left one inline comment for a correctness issue that should be addressed before merge.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

})
if (text === undefined) return undefined
if (!text.trim()) return {}
const data = parseJsonc(text)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

readConfigFile says it "throws on malformed content", but parseJsonc(text) is called without an errors array, so syntax errors are not surfaced here. That means malformed config can be treated as an object and then rewritten by patchConfigFile, which can silently drop unrelated user keys.

Concrete scenario: a user has a global elastic_ramen.jsonc with a trailing syntax mistake in an unrelated section; a later save/setCurrent runs writeGlobalConfig, reads via this function, and writes back patched content instead of failing fast.

Please parse with an errors array (like Config.parseConfig) and throw when errors.length > 0 before proceeding with patch/write.

Copy link
Copy Markdown
Contributor

@flash1293 flash1293 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, works as expected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Default elastic-ramen.json config to global location on first run

2 participants