Skip to content

feat(cli)!: migrate command-line parsing to usage-rs - #3030

Merged
kixelated merged 7 commits into
devfrom
codex/usage-rs-spike
Aug 26, 2026
Merged

feat(cli)!: migrate command-line parsing to usage-rs#3030
kixelated merged 7 commits into
devfrom
codex/usage-rs-spike

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Summary

  • Replace direct Clap usage across the Rust binaries and examples with usage-rs, including native completion endpoints, strict unknown and duplicate argument handling, and typed adapters for custom values.
  • Preserve moq-cli's repeated stage syntax while delegating each stage's parsing, validation, help, specification, and completions to Usage.
  • Merge relay and benchmark configuration in the order CLI > TOML > environment > built-in defaults, including canonical handling of legacy TOML aliases.
  • Materialize effective defaults instead of representing known defaults with Option, backed by a reusable human-readable moq_tokio::Duration type.
  • Accept AAC as a valid playback selection while continuing to reject unsupported VP8 and VP9 video selections.

Public API changes

  • Breaking: moq_tokio::connect::Config::{race,resolution_delay,timeout} now use concrete moq_tokio::Duration values instead of optional standard durations.
  • Breaking: moq_tokio::connection::Backoff::{initial,multiplier,max,timeout} and GoawayConfig::{redirect,handover} now expose concrete defaulted values.
  • Breaking: moq_tokio::quic::Config::{idle_timeout,keep_alive}, unix::Config::allow, and websocket::Config::{enabled,delay} now expose concrete defaulted values.
  • Additive: moq_tokio::Duration provides human-readable parsing, display, serde, conversion, and comparison support.
  • moq-ffi, libmoq, and moq-gst only adapt their internal construction to these changes. Their published ABI and wrapper surfaces are unchanged, so bindings and binding documentation were not regenerated.

Wire behavior changes

  • None. Protocol negotiation, framing, and peer-visible transport behavior are unchanged.

Documentation

  • Document the relay's CLI, TOML, environment, and default precedence.
  • Existing moq-cli examples remain valid because canonical command and flag spellings are unchanged.

Test plan

  • MOQ_STRICT=1 nix develop --command just fix
  • MOQ_STRICT=1 nix develop --command just check
  • MOQ_STRICT=1 nix develop --command just test (3,472 Rust tests passed, 2 skipped; 52 Python tests passed)
  • git diff --check
  • Audit for remaining direct Clap dependencies and attributes

(Written by GPT-5)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f7b4dad4c8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-relay/src/config.rs Outdated
Comment on lines +147 to +148
let mut config = Config::parse_from(&argv)
.map_err(|err| anyhow::anyhow!(usage::render_failure(Config::spec(), &argv, &err)))?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exit successfully for help and version requests

When moq-relay is invoked with --help or --version, Usage returns its Help or Version control-flow error here, but this converts every parser result into anyhow::Error; main then returns it and exits as a failure instead of printing the requested output and exiting 0. The identical conversion in rs/moq-bench/src/config.rs has the same regression. Handle these Usage variants as successful exits, as the custom moq-cli parser does, before wrapping genuine parse failures.

Useful? React with 👍 / 👎.

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think Usage is a positive direction for these binaries, but I found three regressions that should be fixed before landing, in addition to the existing moq-relay / moq-bench help-exit finding.

  1. [P1] moq prints no help or version output. In rs/moq-cli/src/args.rs::parse_error, Help, HelpAll, and Version are classified as successful control flow, but their message is still built with usage::render_failure. Usage 6.3 explicitly renders those variants as an empty string because callers must handle them first. ParseError::exit therefore exits 0 after printing nothing for moq --help, stage help, and moq --version. These variants need their actual help page or version response rendered before conversion, with subprocess tests pinning stdout and status.

  2. [P2] Completion endpoints are bypassed by the custom entry points. #[usage(completion)] installs the __complete_word__ interception in the generated Cli::parse() method. Invocation::parse calls try_parse_from instead, while relay and bench call their own parse_and_merge paths, so all three feed completion requests into the ordinary grammar and reject them. Call completion_request before custom parsing, or expose an upstream process-entry helper that custom loaders can reuse. For moq, the completion route also needs to account for the repeated stage grammar after --, since the root Usage spec models only the first stage.

  3. [P2] The old command aliases become visible. Clap's #[command(alias = "publish")] and subscribe aliases were hidden. For Usage subcommands, alias is advertised in help and completions; alias_hidden is the hidden spelling. The migrated attributes on Command::{Import, Export} therefore reintroduce the old names into the published surface. Use alias_hidden to preserve the existing canonical import / export interface.

Two design concerns are worth resolving while this is still a spike:

  • Relay and bench now implement layer provenance indirectly through serialize, TOML overlay, deserialize, update_from, alias normalization, and manual has_long_flag exceptions. Usage's settings/config layer records explicit CLI presence directly and is a better owner for CLI > TOML > env > defaults; otherwise each new default-true boolean needs another parser-specific exception.
  • The accepted MoQ versions moved from Version::names() to four literal choices(...) lists across connect/listen and legacy/current flags. A new protocol version can now parse via FromStr but remain unavailable through these CLIs until every copy is updated. Please restore a single source of truth, or at least add a spec regression test comparing every version flag's choices with Version::names().

(Written by GPT-5)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 70e6e8365a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-cli/src/args.rs Outdated
// against a grammar that also carries the process-wide flags a stage refuses.
// Narrowing that needs the request's own line and cursor rewritten to the last
// stage, which is not done here.
if let Some(reply) = Cli::completion_request(args.get(1..).unwrap_or_default()) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Route later-stage completions through the stage grammar

When completion is requested with the cursor after a -- stage separator, this always invokes completion against the root Cli grammar. As the preceding comment acknowledges, that grammar includes process-wide flags which are rejected in later stages and does not model the active repeated stage, so shell completion can suggest invalid global flags or omit the applicable endpoint options. Rewrite the completion request to the active chunk and complete it against Stage when the cursor is in a later stage.

Useful? React with 👍 / 👎.

@kixelated
kixelated force-pushed the codex/usage-rs-spike branch from 70e6e83 to 2e70524 Compare August 25, 2026 21:01
kixelated added a commit that referenced this pull request Aug 25, 2026
… the cursor is in

Both findings from the Codex review on #3030.

moq-relay and moq-bench turned a help or version request into an `anyhow`
error, which renders as an empty string and exits non-zero: `moq-relay --help`
printed nothing and failed. moq-cli had the same bug and its own fix, so the
rendering now lives in `moq_tokio::cli::answer` and all three share it. A real
failure still comes back as an error, so a caller parsing synthetic args keeps
its Result.

Fixing that exposed what the missing output had hidden: Usage names a spec after
the type that declares it unless told otherwise, where clap used the binary
name. Both binaries called themselves `config` in every usage line, version
string, and completion. They now declare their own names, with a test.

Completion answered a later `--` stage against the root grammar, which carries
the process-wide flags a stage refuses. Both request shapes normalize to a word
list first -- elvish sends one, everything else sends a line and cursor that
Usage's own splitter turns into the same thing -- so the active chunk is found
without taking apart shell input by hand. A cursor sitting on the separator
itself stays with the root, since that is typing `--` rather than being past it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 171405d557

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if let Some(file) = config.file.clone() {
config = toml::from_str(&std::fs::read_to_string(file)?)?;
config.update_from(&args);
let mut merged = toml::Value::try_from(&config)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve non-TOML environment fields across the merge

When a relay uses a positional TOML file together with an environment-backed field marked #[serde(skip)], such as MOQ_AUTH_PUBLIC_SUBSCRIBE or deprecated variables like MOQ_CLIENT_CONNECT, this serialization drops the value before merged.try_into() reconstructs the config. Because update_from reapplies only explicit argv, the current auth setting is ignored and deprecated settings evade resolve() instead of being refused, allowing the relay to start with unintended defaults. Preserve these fields outside the serde round trip or otherwise retain the environment layer.

AGENTS.md reference: AGENTS.md:L121-L123

Useful? React with 👍 / 👎.

Comment thread rs/moq-boy/src/main.rs
Comment on lines +45 to +47
#[derive(usage::Cli, Clone)]
#[usage(unknown_flags = "error", args_override_self = false)]
#[usage(completion)]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Name each remaining root command

Usage derives the command name from the Rust type unless name or bin is specified, so moq-boy --help now renders usage for config; the same omission makes moq-bench-host --help and --version identify the binary as args, and affects the clock example similarly. Add explicit binary names to these root parsers so their public help, version output, and completion specifications refer to the invoked tools.

Useful? React with 👍 / 👎.

kixelated added a commit that referenced this pull request Aug 25, 2026
Usage takes a spec's program name from the type that declares it unless told
otherwise, where clap used the binary name. moq-boy and the clock example
rendered `Usage: config`, and moq-bench-host identified itself as `args`, in
help, `--version`, and the completions their specs describe.

Found by the Codex review on #3030, after the same defect surfaced in moq-relay
and moq-bench once their help stopped printing an empty string.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kixelated added a commit that referenced this pull request Aug 26, 2026
…ironment

`update_from` re-parses the CLI over the merged config so explicit flags win, and
fills a declared default or an environment value only where the standing value is
still empty. Emptiness is a property of the type: a bare `bool` reads empty when
it is `false`, so TOML saying `false` is refilled from the environment and the
file loses. `stats.enabled` and `cluster.lan.enabled` were `Option<bool>` before
the Usage migration materialized them; they are again, with the default resolved
in code.

Every other bare boolean under a Usage derive was checked: the two remaining are
a resolved-output struct and moq-bench-host, neither of which merges a file.
Scalars are safe, because a plain value always reads as present.

`Vec<T>` has the same hazard -- an empty list reads absent -- for about fifteen
env-bound list fields. That predates this migration and is unchanged here, so it
is tracked in #3051 along with the question of whether the environment should
outrank the file at all, which is what most tools do and what this repo does not.

rs/CLAUDE.md claimed every shape but `bool` was safe, which is wrong for `Vec`,
and doc/bin/relay/config.md presented the precedence as a decision when it is an
artifact of parse-then-overlay. Both now say what is true.

Found by the Codex review on #3030.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73993f4f58

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +174 to +177
if answer.is_question() {
answer.exit();
}
anyhow::bail!("{}", answer.message());

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the parser's usage-error exit status

For an invalid moq-relay invocation, this converts Answer::Failure into an anyhow::Error; because main returns that error, Rust terminates with status 1 rather than the parser's documented status 2. The same path exists in rs/moq-bench/src/config.rs, so scripts can no longer distinguish malformed command lines from runtime failures. Keep synthetic parsing fallible for tests, but have the process-facing load() path print and exit through Answer::exit() for parser failures.

Useful? React with 👍 / 👎.

kixelated added a commit that referenced this pull request Aug 26, 2026
… the cursor is in

Both findings from the Codex review on #3030.

moq-relay and moq-bench turned a help or version request into an `anyhow`
error, which renders as an empty string and exits non-zero: `moq-relay --help`
printed nothing and failed. moq-cli had the same bug and its own fix, so the
rendering now lives in `moq_tokio::cli::answer` and all three share it. A real
failure still comes back as an error, so a caller parsing synthetic args keeps
its Result.

Fixing that exposed what the missing output had hidden: Usage names a spec after
the type that declares it unless told otherwise, where clap used the binary
name. Both binaries called themselves `config` in every usage line, version
string, and completion. They now declare their own names, with a test.

Completion answered a later `--` stage against the root grammar, which carries
the process-wide flags a stage refuses. Both request shapes normalize to a word
list first -- elvish sends one, everything else sends a line and cursor that
Usage's own splitter turns into the same thing -- so the active chunk is found
without taking apart shell input by hand. A cursor sitting on the separator
itself stays with the root, since that is typing `--` rather than being past it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kixelated added a commit that referenced this pull request Aug 26, 2026
Usage takes a spec's program name from the type that declares it unless told
otherwise, where clap used the binary name. moq-boy and the clock example
rendered `Usage: config`, and moq-bench-host identified itself as `args`, in
help, `--version`, and the completions their specs describe.

Found by the Codex review on #3030, after the same defect surfaced in moq-relay
and moq-bench once their help stopped printing an empty string.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kixelated added a commit that referenced this pull request Aug 26, 2026
…ironment

`update_from` re-parses the CLI over the merged config so explicit flags win, and
fills a declared default or an environment value only where the standing value is
still empty. Emptiness is a property of the type: a bare `bool` reads empty when
it is `false`, so TOML saying `false` is refilled from the environment and the
file loses. `stats.enabled` and `cluster.lan.enabled` were `Option<bool>` before
the Usage migration materialized them; they are again, with the default resolved
in code.

Every other bare boolean under a Usage derive was checked: the two remaining are
a resolved-output struct and moq-bench-host, neither of which merges a file.
Scalars are safe, because a plain value always reads as present.

`Vec<T>` has the same hazard -- an empty list reads absent -- for about fifteen
env-bound list fields. That predates this migration and is unchanged here, so it
is tracked in #3051 along with the question of whether the environment should
outrank the file at all, which is what most tools do and what this repo does not.

rs/CLAUDE.md claimed every shape but `bool` was safe, which is wrong for `Vec`,
and doc/bin/relay/config.md presented the precedence as a decision when it is an
artifact of parse-then-overlay. Both now say what is true.

Found by the Codex review on #3030.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
kixelated added a commit that referenced this pull request Aug 26, 2026
`cluster.lan` is only a field under `cluster-lan`, so the new regression test
broke a build with that feature off. The stats half still runs there.

Three doc comments also claimed every non-boolean plain value reads as present.
An empty `Vec<T>` does not, which is the defect #3051 tracks.

Found by the Codex review on #3030.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@kixelated
kixelated force-pushed the codex/usage-rs-spike branch from 73993f4 to ba5e2db Compare August 26, 2026 03:05
kixelated and others added 7 commits August 25, 2026 20:07
Co-Authored-By: GPT-5 <noreply@openai.com>
…-true bools TOML-overridable

Six fixes on top of the Usage migration, all found by reading Usage's own
semantics against what the migrated attributes assume.

Help and version printed nothing. `usage::render_failure` renders `Error::Help`,
`HelpAll`, and `Version` as an empty string, because they are questions rather
than failures and a caller is expected to take them first; the generated
`parse()` does exactly that. moq-cli parses each `--`-separated stage itself, so
it never reaches that code and exited 0 having printed nothing for `moq --help`,
stage help, and `moq --version`. `parse_error` now renders the page through
`usage::help::page` and builds the version line from the spec. `MissingArgsHelp`
keeps clap's contract of the short page on stderr with status 2.

Completion endpoints were unreachable. `#[usage(completion)]` installs the
`__complete_word__` interception in the generated `parse()`, which none of the
three binaries use: moq-cli splits on `--` first, and relay and bench load
through `parse_and_merge`. Every completion request therefore reached the
ordinary grammar and was refused. Each entry point now calls
`completion_request` before parsing. A cursor inside a later moq-cli stage still
completes against the root grammar, which also offers the process-wide flags a
stage refuses; narrowing that needs the request's own line and cursor rewritten
to the last stage, and is noted where it would go.

A default-true `bool` was refilled over its TOML value. `update_from` fills a
declared default only where the standing value is still empty, and a bare `bool`
reading `false` is what Usage counts as empty, so `default = "true"` won every
merge. That was patched by scanning argv for the three flags it affects, which
left the next such field unguarded. `runtime.pin`, `web.ws`, and
`connect.websocket.enabled` are `Option<bool>` again with the default resolved in
code, and both copies of `has_long_flag` are gone. Every other shape was already
safe: a plain value always reads as present, so the rest of the migration's move
off `Option` stands.

`web.ws` was a bare `bool` on dev too, so this fixes a latent clobber there
rather than only restoring parity.

The old `publish` / `subscribe` spellings became visible. Usage advertises an
`alias` in help and completions where clap hid it; `alias_hidden` is the quiet
one. They parse as before and no longer appear on the published surface.

The accepted MoQ versions are four `choices(...)` literals, so a new draft can
parse through `FromStr` while staying unreachable from the command line. A test
walks the spec and holds every `*-version` flag to `Version::names()` as a set.

rs/CLAUDE.md carried the new merge rule without its one exception, and still
described a hidden flag as a plain `alias`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… the cursor is in

Both findings from the Codex review on #3030.

moq-relay and moq-bench turned a help or version request into an `anyhow`
error, which renders as an empty string and exits non-zero: `moq-relay --help`
printed nothing and failed. moq-cli had the same bug and its own fix, so the
rendering now lives in `moq_tokio::cli::answer` and all three share it. A real
failure still comes back as an error, so a caller parsing synthetic args keeps
its Result.

Fixing that exposed what the missing output had hidden: Usage names a spec after
the type that declares it unless told otherwise, where clap used the binary
name. Both binaries called themselves `config` in every usage line, version
string, and completion. They now declare their own names, with a test.

Completion answered a later `--` stage against the root grammar, which carries
the process-wide flags a stage refuses. Both request shapes normalize to a word
list first -- elvish sends one, everything else sends a line and cursor that
Usage's own splitter turns into the same thing -- so the active chunk is found
without taking apart shell input by hand. A cursor sitting on the separator
itself stays with the root, since that is typing `--` rather than being past it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Usage takes a spec's program name from the type that declares it unless told
otherwise, where clap used the binary name. moq-boy and the clock example
rendered `Usage: config`, and moq-bench-host identified itself as `args`, in
help, `--version`, and the completions their specs describe.

Found by the Codex review on #3030, after the same defect surfaced in moq-relay
and moq-bench once their help stopped printing an empty string.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ironment

`update_from` re-parses the CLI over the merged config so explicit flags win, and
fills a declared default or an environment value only where the standing value is
still empty. Emptiness is a property of the type: a bare `bool` reads empty when
it is `false`, so TOML saying `false` is refilled from the environment and the
file loses. `stats.enabled` and `cluster.lan.enabled` were `Option<bool>` before
the Usage migration materialized them; they are again, with the default resolved
in code.

Every other bare boolean under a Usage derive was checked: the two remaining are
a resolved-output struct and moq-bench-host, neither of which merges a file.
Scalars are safe, because a plain value always reads as present.

`Vec<T>` has the same hazard -- an empty list reads absent -- for about fifteen
env-bound list fields. That predates this migration and is unchanged here, so it
is tracked in #3051 along with the question of whether the environment should
outrank the file at all, which is what most tools do and what this repo does not.

rs/CLAUDE.md claimed every shape but `bool` was safe, which is wrong for `Vec`,
and doc/bin/relay/config.md presented the precedence as a decision when it is an
artifact of parse-then-overlay. Both now say what is true.

Found by the Codex review on #3030.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`cluster.lan` is only a field under `cluster-lan`, so the new regression test
broke a build with that feature off. The stats half still runs there.

Three doc comments also claimed every non-boolean plain value reads as present.
An empty `Vec<T>` does not, which is the defect #3051 tracks.

Found by the Codex review on #3030.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
dev moved the sink's config into `connect_config` / `quic_config` while this
branch made `quic::Config::{idle_timeout,keep_alive}` concrete. The properties
stay optional, so assigning one through is no longer a no-op when it is unset:
it would override the default with whatever `Option` resolved to. Assign only
what the caller actually set.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ba5e2dba78

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rs/moq-cli/src/rtc.rs

/// Public UDP address(es) advertised as ICE host candidates (repeatable).
#[arg(long, requires = "rtc-listen")]
#[usage(long, requires = "rtc-listen")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Point the ICE-address requirement at --listen

When an RTC listener supplies --public-addr, this constraint still references Clap's internal rtc-listen ID instead of the Usage flag spelling. Unlike the corrected udp_bind constraint immediately above, it therefore cannot recognize the actual --listen argument as satisfying the requirement, so valid listeners that advertise a public ICE address are rejected. Change this target to --listen as well.

Useful? React with 👍 / 👎.

@kixelated
kixelated force-pushed the codex/usage-rs-spike branch from ba5e2db to 6b19d24 Compare August 26, 2026 03:28
@kixelated
kixelated enabled auto-merge (squash) August 26, 2026 03:29
@kixelated
kixelated merged commit 7a22ced into dev Aug 26, 2026
5 checks passed
@kixelated
kixelated deleted the codex/usage-rs-spike branch August 26, 2026 03:45
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.

1 participant