Skip to content

Replace env vars and conf file with config.json#1464

Draft
jeremyfowers wants to merge 14 commits intomainfrom
1457-replace-confd-and-env-vars-with-configjson
Draft

Replace env vars and conf file with config.json#1464
jeremyfowers wants to merge 14 commits intomainfrom
1457-replace-confd-and-env-vars-with-configjson

Conversation

@jeremyfowers
Copy link
Copy Markdown
Member

@jeremyfowers jeremyfowers commented Mar 26, 2026

Summary

  • Replace the mix of environment variables, lemonade.conf, and CLI arguments with a single config.json file in the lemonade home directory
  • lemond now takes exactly 3 CLI args: [home_dir] [--port PORT] [--host HOST]
  • config.json is auto-created with defaults on first run; there is no auto-migration — users migrate manually via lemonade config set
  • lemonade config displays the current configuration; lemonade config set key=value updates it (e.g. lemonade config set llamacpp-backend=rocm port=8123)
  • GUI apps and the CLI manage configuration at runtime via /internal/set (nested JSON) and /internal/config (GET), which persist changes to config.json
  • Backend-specific settings are nested under their backend name (llamacpp, sdcpp, etc.) with meaningful defaults ("auto" for backends, "builtin" for binary paths)
  • config.json is hardened with thread-safe read/write, atomic saves (write-to-temp + rename), corruption recovery (auto-recreate from defaults), and schema versioning
  • Legacy lemonade-server shim stays backwards-compatible by translating old CLI args into /internal/set calls
  • LEMONADE_API_KEY, LEMONADE_CI_MODE, and HF_TOKEN remain as environment variables

Test plan

  • cmake --build --preset default compiles cleanly
  • lemond /tmp/test creates config.json with correct nested structure and defaults
  • lemond --port 9000 persists port override to config.json
  • lemonade config displays current configuration
  • lemonade config set llamacpp-backend=vulkan updates config via /internal/set
  • curl localhost:8000/internal/config returns full nested config
  • lemonade-server serve --log-level debug --llamacpp vulkan still works via legacy shim
  • python test/server_cli.py passes
  • python test/server_endpoints.py passes
  • Windows MSI install + CI tests pass

Replace the mix of environment variables, lemonade.conf, and CLI arguments
that configured lemond with a single config.json file in the lemonade home
directory. This makes configuration manageable by GUI apps at runtime via
the /internal/set endpoint, and gives users a single source of truth.

Key changes:
- lemond now takes 3 CLI args: [home_dir] [--port] [--host]
- config.json is auto-created with defaults on first run
- Backend settings nested under their backend name (llamacpp, sdcpp, etc.)
- Meaningful defaults: "auto" for backends, "builtin" for binary paths
- /internal/set persists changes to config.json on disk
- Auto-migration from env vars and /etc/lemonade/lemonade.conf on first run
- Legacy shim (lemonade-server) stays backwards-compatible by translating
  old CLI args into /internal/set calls after spawning lemond
- LEMONADE_API_KEY, LEMONADE_CI_MODE, HF_TOKEN stay as env vars

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jeremyfowers jeremyfowers linked an issue Mar 26, 2026 that may be closed by this pull request
Merge origin/main (super-resolution, issue templates, system-info fix,
recipes fix) and resolve the recipe_options.cpp conflict by keeping the
branch's OPTION_TO_CLI_FLAG structure.

Add value validation to RuntimeConfig that was lost when replacing CLI
args with config.json:

- Backend selection (llamacpp, whispercpp, sdcpp) validated dynamically
  against SystemInfo::get_supported_backends() at both set time and use
  time via a single validate_backend_choice() helper
- Binary path overrides (*_bin) validated via validate_bin_path(): must
  be "builtin" or an existing filesystem path
- Numeric options (steps, width, height, cfg_scale) validated for
  positive values
- Centralize config-section/recipe name mapping
  (config_section_to_recipe / recipe_to_config_section) to eliminate
  duplicate hand-rolled conversions in backend_utils.cpp

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jeremyfowers jeremyfowers self-assigned this Mar 26, 2026
jeremyfowers and others added 4 commits March 27, 2026 11:12
…versioning

- Fix ::tolower UB by using unsigned char lambda instead of bare ::tolower
- Replace std::mutex with std::shared_mutex for concurrent load/save safety
- Use RAII scoped lock blocks instead of manual unlock in error paths
- Back up corrupt config.json as .corrupted before falling back to defaults
- Clean up stale .tmp files from interrupted saves
- Add config_version field for future schema migration
- Add bounds validation for config_version (>= 1)
- Quote PowerShell argument for paths with spaces in MSI installer action
- Remove low-value section dividers and obvious comments

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a `config` command with `view` and `set` subcommands to the lemonade CLI
for reading and modifying server configuration via /internal/config and
/internal/set endpoints.

- `config view` displays a formatted table with key=value syntax that maps
  directly to `config set` arguments
- `config set` accepts key=value positional args (e.g., `port=8123
  llamacpp-backend=rocm`) and dynamically determines top-level vs nested keys
  by querying the server's config structure
- Update legacy shim (lemonade-server) to delegate config changes through
  `lemonade config set` instead of direct HTTP calls to /internal/set

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ault

- Remove ConfigFile::migrate() and all supporting code (env_to_config_key,
  read_conf_file, parse_env_value) — users migrate manually via
  `lemonade config set`
- Remove migrate() calls from lemond and tray startup
- Make `lemonade config` default to displaying config (previously required
  `lemonade config view` subcommand); `lemonade config set` unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@lemonade-sdk lemonade-sdk deleted a comment from github-actions bot Mar 27, 2026
jfowers and others added 4 commits March 27, 2026 14:49
Merge main which includes PR #1453 (direct-run log streaming fix) and
PR #1466 (openSUSE Tumbleweed support). Resolve conflicts by adapting
the dual-sink logging (console + file when not under systemd) to use
config.json-based RuntimeConfig instead of the old CLI config struct.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- LEMONADE_CACHE_DIR env var sets the lemonade home dir (checked after
  explicit CLI arg, before platform defaults)
- Default models_dir in config.json is now "auto", which resolves
  HF_HUB_CACHE → HF_HOME/hub → platform default per the HF spec
- Explicit models_dir paths in config.json still override env vars

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix Windows build: use runtime_config->host()/port() instead of removed
  config struct in tray/main.cpp shutdown block
- Fix Linux distro builds: remove --log-level CLI arg (no longer supported);
  instead have LEMONADE_CI_MODE auto-set log level to debug in RuntimeConfig
- Fix test /internal/set format: send nested backend objects (e.g.
  {"llamacpp": {"backend": "metal"}}) instead of flat keys (llamacpp_backend)
- Remove redundant "Set debug logging" CI steps now that LEMONADE_CI_MODE
  handles it automatically

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On main, lemonade-router resolved its home dir via get_cache_dir()
($HOME/.cache/lemonade). The positional arg was overriding that to
a different path. Remove it so lemond uses the same default resolution.

Also document valid env vars for the conf.d drop-in and note that
server settings now live in config.json.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@lemonade-sdk lemonade-sdk deleted a comment from github-actions bot Mar 27, 2026
jfowers and others added 4 commits March 27, 2026 16:13
- Use std::atomic for global RuntimeConfig pointer for thread safety
- Document set-once-at-startup invariant for g_home_dir/g_models_dir
- Move stale .tmp cleanup from shared_lock to unique_lock in ConfigFile
- Fix docs: models_dir default is "auto", not a hardcoded path
- Fix docs: migration is manual via `lemonade config set`, not automatic
- Log when --port/--host CLI overrides are persisted to config.json
- Quote Windows cmd_line args in legacy shim to handle paths with spaces

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace ambiguous hyphen-based key syntax (llamacpp-backend=rocm) with
unambiguous dot notation (llamacpp.backend=rocm) for `lemonade config set`.
Hyphens were doing double duty as both word separators and section
separators, causing parsing bugs for keys like cfg-scale.

- config set/view now uses section.field for nested keys (e.g., sdcpp.steps)
- Top-level keys shown as JSON names (e.g., log_level, no_broadcast)
- Removed server round-trip from config set (no longer needs to fetch
  config to determine key nesting)
- lemonade-web-app discovers port from running server via lemonade status

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

Replace confd and env vars with config.json

2 participants