Skip to content

Implement improved launch subcommand#1454

Merged
bitgamma merged 34 commits intomainfrom
sawansri/launch-improvements
Apr 1, 2026
Merged

Implement improved launch subcommand#1454
bitgamma merged 34 commits intomainfrom
sawansri/launch-improvements

Conversation

@sawansri
Copy link
Copy Markdown
Collaborator

@sawansri sawansri commented Mar 25, 2026

Resolves #1331

Implements the launch workflow as described in this comment

List of changes:

  1. adds remote recipe workflow to import subcommand
  2. adds model list before run and launch subcommands, user can select model from list vs having to type out model name
  3. combines 1+2 into a singular workflow for launch that provides an easy to use and seamless experience with agents like claude code and codex
  4. adds back async model loading, loading agent before the model is loaded onto the backend. This makes the whole launch experience a lot more frictionless, the user can start typing out their prompt while their model is being loaded
  5. refactors agent_launcher for modularity (fcns for different agents)
  6. enables the use of API keys with --api-key (key would previously not propagate past load, messages would return 401)
image

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Lemonade CLI’s launch workflow and related UX, including modularizing agent launching, adding interactive model selection, and introducing remote recipe import support (with new CLI tests and docs updates).

Changes:

  • Added interactive model selection utilities and remote recipe import implementation (GitHub recipes browsing/downloading).
  • Updated run, import, and launch subcommands to support prompting/remote flows and async model loading during launch.
  • Expanded CLI integration tests and updated CLI documentation/man page to reflect new behaviors.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
test/server_cli2.py Adds env-overridable CLI runner + new tests for import/run/launch workflows using stubbed binaries.
src/cpp/include/lemon_cli/recipe_import.h Declares recipe import + JSON normalization APIs.
src/cpp/include/lemon_cli/model_selection.h Declares interactive model selection + yes/no prompt helpers.
src/cpp/include/lemon_cli/agent_launcher.h Extends agent config builder to accept an API key.
src/cpp/cli/recipe_import.cpp Implements remote recipe browsing via GitHub API + local JSON import normalization.
src/cpp/cli/model_selection.cpp Implements interactive model selection via /api/v1/models.
src/cpp/cli/main.cpp Wires new import/run/launch flows, adds async background load for launch, new flags.
src/cpp/cli/agent_launcher.cpp Refactors agent configuration logic; adds default API key constant and per-agent setup.
src/cpp/cli/CMakeLists.txt Adds new compilation units + http_client dependency for CLI build.
docs/man/man1/lemonade.1 Updates high-level command descriptions for import/launch.
docs/lemonade-cli.md Documents new import/launch options and examples.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@sawansri sawansri marked this pull request as ready for review March 26, 2026 03:54
@sawansri sawansri requested a review from jeremyfowers March 26, 2026 20:20
@jeremyfowers jeremyfowers added this to the Release v10.1.0 milestone Mar 26, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@sawansri sawansri force-pushed the sawansri/launch-improvements branch from d417ee4 to 6b365c7 Compare March 28, 2026 01:16
sawansri added 15 commits March 29, 2026 23:51
…st of fetched models

Signed-off-by: Sawan Srivastava <sawan1210@gmail.com>
Signed-off-by: Sawan Srivastava <sawan1210@gmail.com>
Signed-off-by: Sawan Srivastava <sawan1210@gmail.com>
Signed-off-by: Sawan Srivastava <sawan1210@gmail.com>
Signed-off-by: Sawan Srivastava <sawan1210@gmail.com>
Signed-off-by: Sawan Srivastava <sawan1210@gmail.com>
Signed-off-by: Sawan Srivastava <sawan1210@gmail.com>
Signed-off-by: Sawan Srivastava <sawan1210@gmail.com>
Signed-off-by: Sawan Srivastava <sawan1210@gmail.com>
Signed-off-by: Sawan Srivastava <sawan1210@gmail.com>
@sawansri sawansri force-pushed the sawansri/launch-improvements branch from 6b365c7 to 96b8a04 Compare March 30, 2026 07:13
@sawansri
Copy link
Copy Markdown
Collaborator Author

@jeremyfowers implemented your suggestions! Please test them out and let me know if you have any more inputs.

@jeremyfowers
Copy link
Copy Markdown
Member

@claude review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

Claude finished @jeremyfowers's task in 2m 46s —— View job


Code Review

  • Gather context
  • Read changed files
  • Analysis complete

Overall this is a solid PR — the modularization, async loading, API key propagation, and test coverage are all good additions. Most of the previous reviewer concerns appear already addressed. Here are the remaining issues I found, from most to least important.


Open reviewer note: Collapse the two-level recipe menu

jeremyfowers' remaining comment (the only unresolved one) is spot on. The prompt_launch_recipe_first state machine in model_selection.cpp:115-357 has a RecipeDirectories state (pick a folder) then a RecipeFiles state (pick a file inside it). This produces a redundant click for the common single-directory case:

Select a recipe directory to import and use with Claude:
  0) Browse downloaded models
  1) claude-code
Enter number: 1         ← unnecessary step when there's only one directory
Select a recipe from 'claude-code' to import and use with Claude:
  ...

A flat list (all files with directory prefix, if there are ever multiple directories) would be cleaner and match jeremyfowers' suggestion. Fix this →


Bug: prompt_recommended_catalog only shows not-downloaded models, returns error when all are downloaded

model_selection.cpp:371-377:

if ((for_launch && is_recommended_for_launch(model)) ||
    (!for_launch && is_recommended_for_run(model))) {
    if (!model.downloaded) {          // ← filters out already-downloaded models
        recommended_models.push_back(&model);
    }
}

Then at model_selection.cpp:379-384:

if (recommended_models.empty()) {
    LOG(ERROR, "ModelSelector")
        << "No recommended models available. Try 'lemonade list' or 'lemonade pull <MODEL>'."
        << std::endl;
    return false;
}

If a user has already downloaded all the recommended models, run (with no model arg) → option 0 "Browse recommended models" will show an empty list and fail with a confusing error. The fix is to show all recommended models with a [downloaded]/[not-downloaded] label, and let the user pick any of them.


Bug: file_is_executable doesn't check execute permission

agent_launcher.cpp:47-55:

bool file_is_executable(const std::string& candidate) {
    ...
    return fs::exists(p, ec) && fs::is_regular_file(p, ec);
    //                         ↑ only checks it's a regular file, not that it's executable
}

On Linux/macOS this can return true for a non-executable file (e.g., a regular .txt file). The exec will then fail with a less-helpful error. On POSIX you can use access(path.c_str(), X_OK) instead.


Minor: prompt_launch_recipe_first re-fetches recipe directories on every back-navigation

model_selection.cpp:135-186: The RecipeDirectories state calls list_remote_recipe_directories on every loop iteration. When the user navigates back from RecipeFilesRecipeDirectories, it makes another GitHub API call. The directory list should be fetched once and cached in a local variable before the loop.


Minor: Test numbering conflict between Import and Load tests

test/server_cli2.py has two sets of tests with overlapping prefix numbers:

  • Import: test_060_import_json_file, test_061_import_malformed_json, …
  • Load: test_060_load_with_ctx_size, test_061_load_with_save_options

Python's unittest will sort these alphabetically by full name (import comes before load, so the ordering will actually be correct by chance), but the duplicate prefix numbers are confusing. Consider renumbering load tests to test_070_* (shifting the current 070 unload tests to test_080_* and delete to test_090_*).


Minor: CLIHelpDocsConsistencyTests not included in run_cli_client_tests()

test/server_cli2.py:929-950: run_cli_client_tests() only adds PersistentServerCLIClientTests to the suite. CLIHelpDocsConsistencyTests.test_900_launch_use_recipe_docs_match_help_text won't run when calling python test/server_cli2.py (though it would run with python -m unittest). Add it to the loader in run_cli_client_tests().


Resolved: Previous copilot/reviewer issues

  • resolved_api_key is correctly used for ANTHROPIC_AUTH_TOKEN and LEMONADE_API_KEY in agent_launcher.cpp:104-106
  • build_server_base_url now calls normalize_server_host for wildcard address normalization (agent_launcher.cpp:71-79)
  • AgentLauncher log tag fixed to ModelSelector in model_selection.cpp:86
  • ✅ Dead for_launch flag in the run branch is no longer present
  • ✅ Stale duplicate dispatch chain in main.cpp is not present
  • --use-recipe help strings and docs now correctly describe the skip-import behavior

@sawansri
Copy link
Copy Markdown
Collaborator Author

Not sure why web app compilation is failing. Builds fine locally.

image

@jeremyfowers
Copy link
Copy Markdown
Member

CI fixed on main and pushed to this branch

@jeremyfowers jeremyfowers requested a review from bitgamma April 1, 2026 15:49
Copy link
Copy Markdown
Member

@jeremyfowers jeremyfowers left a comment

Choose a reason for hiding this comment

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

Love this @sawansri! Thanks for doing those rounds of feedback with me. The getting started experience is now ultra smooth for new users!

Let's get @bitgamma's review before merging.

Copy link
Copy Markdown
Member

@bitgamma bitgamma left a comment

Choose a reason for hiding this comment

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

works very well! this might make try out claude as an agent 😄

@bitgamma bitgamma added this pull request to the merge queue Apr 1, 2026
Merged via the queue into main with commit 524f469 Apr 1, 2026
60 checks passed
@bitgamma bitgamma deleted the sawansri/launch-improvements branch April 1, 2026 16:42
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.

Launch command followup: UI/UX

4 participants