AgentCLIHub Development Notes 3: Per-CLI Model, Reasoning, and Permission Settings

AI-generated conceptual illustration of per-CLI settings.
This article explains the code at fixed commit 46dfca2. It does not report runtime testing or performance measurements in an actual environment.
Bringing several AI CLIs into one window makes it tempting to reduce their settings to a handful of shared options. Yet the values and launch options behind familiar names such as “model” and “permissions” differ. Agent CLI Hub shares the UI structure while keeping each CLI's setting values and their meanings separate.
1. How a shared input field creates invalid combinations
A model alias selected for Claude cannot be assumed to be valid when passed directly to Codex. Overwriting a shared model value every time the user switches CLIs also creates the problem of restoring the previous settings when they switch back.
Settings has separate fields for ClaudeModel, CodexModel, and AntigravityModel. Reasoning effort and executable paths are also stored separately. CliProfile provides the field names and values that belong to its CLI, and reads only that CLI's fields when building a command line.
LastBackend, which remembers the most recently selected CLI, determines the initial selection in the new-conversation dialog. It is not a global switch that changes every open tab to a different CLI. Users can open different CLIs in the same window and use the options saved for each one. Settings fields, Per-CLI settings references
2. The UI and save-time validation read the same catalog
Maintaining the settings UI's choices separately from the C# allowlists can leave one side out of date. A value might be selectable in the UI but cleared when saved, or accepted for storage even though the CLI does not support it.
Agent CLI Hub brings model, reasoning-effort, and permission options together in CliCatalog. ForUi passes display names, settings keys, choices, and model-specific reasoning levels to the UI. The web UI uses this data to build a settings card for each CLI.
The save logic uses ClampModel, ClampEffort, and ClampPermission from the same catalog. It does not validate only the currently selected CLI. Instead, it normalizes each CLI's values against the appropriate criteria. Settings for a CLI that is not currently in use may become actual launch arguments for the next conversation.
Filtering choices in the UI and validating stored values in the host serve different purposes. The former guides the user's choices; the latter determines whether an incoming value is accepted as a launch setting. Keeping the criteria for both stages in one place reduces the chance of divergence during maintenance. Catalog and UI data, Save-time validation
3. First determine whether the model list is complete
Whether validation should unconditionally clear values that are absent from a list depends on how complete that list is. Claude's list of model aliases is there to help with input. Because users can also enter a full model name directly, a value is not removed simply because it is missing from the list. The UI accordingly uses a text field with suggested entries.
For Codex, the catalog reads model identifiers and supported_reasoning_levels from models_cache.json. It collects entries marked for display and removes duplicate identifiers. When this implementation obtains a list, it treats that list as the validation criteria and presents a select box in the UI. If the cache is absent or unreadable, the UI switches to a form that allows direct input.
Before reusing cached data, the code compares both the modification time and the file path. If the configuration home changes but the two files have the same modification time, a cache that compares only timestamps could return the model list from the previous home. This is why the path is compared as well.
This design reduces the need to keep adding model names to the application's source code. It also depends on the contents and format of the cache. The mere presence of a cache cannot establish that it contains the provider's latest complete model list or the models available to every account. It is important to understand the extent to which the implementation uses that list for validation. Determining model-list completeness, Reading the Codex cache
4. Choose reasoning effort together with the model
Codex's reasoning-effort choices come from the list reported for each model. When a model is specified, the catalog uses that model's entries. Otherwise, it combines the entries from the models in the cache. It then sorts them in the application's defined display order. This is why the reasoning-effort choices are rebuilt when the model changes.
If the cache cannot be read, the code uses a predefined fallback list. In this path, support for each individual model has not been verified against the cache. The existence of a fallback list should not be interpreted as a guarantee that every combination is compatible.
Antigravity reads model IDs and display names through a separate agy models command. It parses the two output columns, filters out duplicates and entries containing control characters, and imposes a 15-second query timeout. The UI also retains an option for direct input. The catalog has a shared shape, while the method of obtaining model lists remains specific to each CLI. Selecting reasoning effort, Querying Antigravity models
5. Preserve the distinct dimensions of permissions
Claude's settings use options corresponding to --permission-mode. Codex keeps sandboxing (-s) and approval (-a) as separate settings. Antigravity also defines its own permission choices separately.
Combining these under generic labels such as “normal” and “automatic” can obscure the actual scope and approval policy being applied. Preserving the provider's separate dimensions even in a unified UI allows users to compare their chosen values with the launch flags. Offering a permission option does not make settings that broaden access a recommendation. The choice should first fit the scope of the task and its approval requirements.
Permission values are validated when saved and checked again when the command line is built. Settings from an older version or a manually edited file may still contain values that are no longer in the list. Models and reasoning effort are validated during saving, but at this reference commit the Claude and Codex command-line builders do not revalidate every setting in the same way. The scope of revalidation needs to be distinguished precisely. Permission catalog, Building launch commands
6. Empty values and when changes take effect are part of a setting's meaning
An empty model, reasoning-effort, or permission value means that the corresponding option is not added to the command line. The UI labels this “CLI default.” This differs from a default that forces every CLI to use the same model or approval policy.
Saving settings also does not change the startup arguments of tabs that are already running. TerminalHost reads the settings when it starts a process, and the UI and logs explain that changes apply to conversations opened afterward.
There is also compatibility logic for reading the old shared model and reasoning-effort fields. It migrates them into the new fields for the previously selected CLI, while giving priority to any values already present in those new fields. When expanding the set of settings, the migration must preserve which CLI the user's earlier choices belonged to and what those choices meant. When settings take effect, Migrating existing settings
Key takeaways
- Keep each CLI's setting values and permission semantics separate, even within a shared UI.
- Use the same catalog for UI choices and save-time validation.
- Distinguish a list's completeness from the fallback path used when discovery fails.
- Explain empty values, migration of earlier settings, and the point at which changes take effect for the next process so that settings behave predictably.
Reviewed sources at a fixed commit
Reference: Full repository snapshot at 46dfca2
Previous: Development Notes 2: Finding Installed CLIs on Windows
댓글
댓글 쓰기