Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions crates/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,9 @@ nemo-relay run --agent codex --dry-run

Project config lives at `./.nemo-relay/config.toml`; user config lives at
`~/.config/nemo-relay/config.toml` or `$XDG_CONFIG_HOME/nemo-relay/config.toml`.
The project layer overrides system config, and the user layer overrides the
project layer.
Runtime files layer from lowest to highest precedence as explicit-or-user,
nearest project, then system. An explicit `--config` replaces the ambient user
file without suppressing project or system configuration.

Set up agent entries in the top-level config with:

Expand All @@ -174,8 +175,9 @@ Unix) and reject authorization headers; use the corresponding environment
variables or a user config for credentials.

When the top-level CLI receives `--config path/to/config.toml`, the config
editor uses that exact file. An explicit `config edit --user`, `--project`, or
`--global` flag overrides the inherited target.
editor uses that exact file as its user target, so the default editor and
`config edit --user` both open it. Use `--project` or `--global` to edit the
other active layers.

Observability exporters are configured through the plugin config. Edit the user
plugin config with:
Expand All @@ -186,8 +188,9 @@ nemo-relay plugins edit

When the top-level CLI receives `--plugin-config-path`, the editor uses that
exact file. Otherwise, `--config path/to/config.toml` makes the editor use the
sibling `path/to/plugins.toml`, matching runtime selection. An explicit
`--user`, `--project`, or `--global` editor flag overrides the inherited target.
sibling `path/to/plugins.toml`, matching runtime selection. The explicit file
replaces the user layer, so `--user` keeps that inherited target.
`--project` and `--global` edit the other active layers.

The top-level editor menu contains one entry per supported built-in, followed by
the dynamic plugin references in the selected physical `plugins.toml`. Dynamic
Expand All @@ -202,6 +205,12 @@ The canonical plugin file is `plugins.toml`; user config lives at
not store credentials there. The editor rejects schema-declared secret values
in global plugin configuration.

Runtime plugin files layer from lowest to highest precedence as
explicit-or-user, nearest project, then system. An explicit
`--plugin-config-path`, or a `plugins.toml` beside `--config`, replaces the
ambient XDG user file without suppressing project or system policy. Missing
files are skipped, and symlink aliases to one physical file are loaded once.

Minimal ATIF example:

```toml
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/commands/configure/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ fn resolve_edit_target(
explicit_path: Option<PathBuf>,
) -> Result<(TargetScope, PathBuf), CliError> {
let scope = TargetScope::from(command);
let path = if command.user || command.project || command.global {
let path = if command.project || command.global {
target_path(scope)?
} else {
match explicit_path {
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/commands/configure/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub(crate) enum ConfigSubcommand {
.multiple(false)
))]
pub(crate) struct ConfigEditCommand {
/// Edit the user config at `$XDG_CONFIG_HOME/nemo-relay/config.toml`.
/// Edit explicit `--config`, otherwise `$XDG_CONFIG_HOME/nemo-relay/config.toml`.
#[arg(long)]
pub(crate) user: bool,
/// Edit the nearest project config at `.nemo-relay/config.toml`.
Expand Down
7 changes: 4 additions & 3 deletions crates/cli/src/commands/configure/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ pub(crate) fn plugins_edit_command_for_scope(
scope: ConfigScope,
explicit_path: Option<PathBuf>,
) -> PluginsEditRequest {
let scope = match scope {
ConfigScope::Project | ConfigScope::Both => ConfigurationScope::Project,
ConfigScope::Global => ConfigurationScope::User,
let scope = match (&explicit_path, scope) {
(Some(_), _) => ConfigurationScope::User,
(None, ConfigScope::Project | ConfigScope::Both) => ConfigurationScope::Project,
(None, ConfigScope::Global) => ConfigurationScope::User,
};
PluginsEditRequest {
scope,
Expand Down
6 changes: 5 additions & 1 deletion crates/cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,12 @@ async fn run_default(
// `nemo-relay config` remains the reconfiguration path.
if runtime_args.requested_daemon_mode() {
let resolved = runtime_configuration::resolve_server_config(&runtime_args)?;
let dynamic_plugins = crate::plugins::lifecycle::active_dynamic_plugin_components(
let explicit_plugin_config = crate::configuration::explicit_plugin_config_path(
runtime_args.config.as_ref(),
runtime_args.plugin_config_path.as_ref(),
);
let dynamic_plugins = crate::plugins::lifecycle::active_dynamic_plugin_components(
explicit_plugin_config.as_ref(),
&resolved,
)?;
let managed_bootstrap = runtime_configuration::managed_bootstrap_identity(
Expand Down
13 changes: 7 additions & 6 deletions crates/cli/src/commands/plugins/subcommands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl PluginsSubcommand {
.multiple(false)
))]
pub(crate) struct PluginsScopeArgs {
/// Edit the user config at `$XDG_CONFIG_HOME/nemo-relay/plugins.toml`.
/// Edit the selected low layer: an explicit plugin target, or the XDG user config.
#[arg(long)]
pub(crate) user: bool,
/// Edit the nearest project config at `.nemo-relay/plugins.toml`.
Expand Down Expand Up @@ -169,11 +169,12 @@ impl PluginsEditCommand {
explicit_path: Option<PathBuf>,
) -> crate::plugins::PluginsEditRequest {
let scope = self.scope.into();
let explicit_path = if matches!(scope, crate::plugins::ConfigurationScope::Default) {
explicit_path
} else {
None
};
let explicit_path = matches!(
scope,
crate::plugins::ConfigurationScope::Default | crate::plugins::ConfigurationScope::User
)
.then_some(explicit_path)
.flatten();
crate::plugins::PluginsEditRequest {
explicit_path,
scope,
Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/commands/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use clap::Args;

#[derive(Debug, Clone, Default, Args)]
pub(crate) struct ServerArgs {
/// Path to an explicit config file (disables auto-discovery of workspace/global/system)
/// Path replacing the user config layer; project and system config still apply
#[arg(long)]
pub(super) config: Option<PathBuf>,
/// Address for the gateway to listen on in daemon mode (default 127.0.0.1:4040)
Expand Down
Loading
Loading