# schemaui-cli Usage Guide
`schemaui-cli` is the official command-line wrapper around the `schemaui`
library. It accepts JSON Schema + config snapshots, defaults to the interactive
TUI when no mode subcommand is provided, and also exposes explicit `completion`,
`tui`, `web`, `tui-snapshot`, and `web-snapshot` subcommands. This guide mirrors
the actual code in `schemaui-cli/src/main.rs` so the behaviour stays
predictable.
## 1. Install & Run
### From source
```bash
cargo run -p schemaui-cli -- tui --schema ./schema.json --config ./config.yaml
```
### Install as a binary
The installed binary is always named `schemaui`, so the normal entry point is
`schemaui -c ./config.json`.
Choose one of the supported channels:
#### Cargo (`cargo install`)
Build from crates.io with Cargo.
```bash
cargo install schemaui-cli
```
#### Cargo binstall
Fetch prebuilt GitHub release binaries through cargo-binstall.
```bash
cargo binstall schemaui-cli
```
#### Homebrew
Install from the repository tap on macOS or Linux.
```bash
brew install YuniqueUnic/schemaui/schemaui
```
#### Scoop
Install on Windows from the repository-hosted Scoop manifest.
```bash
scoop install https://raw.githubusercontent.com/YuniqueUnic/schemaui/main/packaging/scoop/schemaui-cli.json
```
#### Direct download
Download the matching archive from
`https://github.com/YuniqueUnic/schemaui/releases/latest`, extract `schemaui` /
`schemaui.exe`, and place it on your `PATH`.
#### winget manifests
Use the versioned manifests in `packaging/winget` with
`winget install --manifest <dir>`, or submit them upstream to the community
repository.
```bash
schemaui --help
```
If you omit a mode subcommand, `schemaui` falls back to the TUI flow, so the
following invocations are equivalent:
```bash
schemaui --schema ./schema.json
schemaui tui --schema ./schema.json
```
### Shell completion
`schemaui-cli` now ships an `argh`-backed completion generator:
```bash
schemaui completion bash > ~/.local/share/bash-completion/completions/schemaui
schemaui completion zsh > ~/.zfunc/_schemaui
schemaui completion fish > ~/.config/fish/completions/schemaui.fish
schemaui completion nushell > ~/.config/nushell/completions/schemaui.nu
```
Supported shells are `bash`, `zsh`, `fish`, and `nushell`. PowerShell is not
listed yet because upstream `argh_complete` does not currently ship a PowerShell
generator.
## 2. Execution Flow
```
┌────────┐ args┌───────────────┐ schema/config ┌──────────────┐ result ┌────────────┐
│ argh ├────▶│ InputSource ├──────────────▶│ SchemaUI ├──────▶│ io::output │
└────┬───┘ └─────────┬─────┘ │ (library) │ └────┬───────┘
│ diagnostics │ format hint └─────┬────────┘ │ writes
┌────▼─────────┐ │ DocumentFormat │ validator ▼ files/stdout
│Diagnostic │◀────────┘ (extension or default) │
│Collector │ ▼
└──────────────┘ Interactive UI
```
Key components:
- **`schema_source`** – resolves explicit `--schema`, config-file declarations,
remote/local schema loading, and final fallback inference in one place.
- **`FormatHint`** – inspects extensions and ensures disabled formats are
rejected before parsing.
- **`DiagnosticCollector`** – aggregates every input/output issue and aborts
early if anything is wrong.
- **`completion`** – renders shell completion scripts from the same command
graph used for runtime parsing.
- **`SchemaUI`** – same runtime used by library consumers; the CLI only wires up
arguments.
## 3. Input Modes
| `-s, --schema <SPEC>` | Local path, `file://`, `http(s)://`, literal JSON/YAML/TOML, or `-` for stdin. | Explicit schema wins over any declaration found inside `--config`. |
| `-c, --config <SPEC>` | Same loading semantics as `--schema`. | Optional; if `--schema` is omitted the CLI tries config declarations before inferring. |
Constraints enforced by code:
- `stdin` can only be consumed once, so `--schema -` and `--config -` cannot be
combined.
- Resolution priority is: `--schema` > config declaration > inferred schema.
- Relative local declarations are resolved against the config file's directory.
For inline/stdin config payloads, relative paths are resolved against the
current working directory.
- HTTP(S) schema loading is controlled by the `schemaui-cli` `remote-schema`
feature, which is enabled by default for the CLI. Local paths and `file://`
URLs always work, and the `schemaui` library crate keeps remote schema loading
disabled by default. The library crate defaults to `tui + json`, while the CLI
defaults to the convenience-oriented feature set.
- `json`, `yaml`, and `toml` are all real feature gates. Keep at least one of
them enabled; disabling all three fails the build with a clear error.
### Config schema auto-detection
When only `--config` is provided, `schemaui-cli` scans the config for a schema
hint before falling back to `schema_from_data_value`.
Supported declarations:
- **JSON**: root `$schema`
- **TOML**: `#:schema https://example.com/schema.json`
- **YAML**: `# yaml-language-server: $schema=...`
- **YAML fallback**: `# @schema ...`
JSON declarations are treated as metadata, so the root `$schema` key is removed
from the in-memory defaults before validation/output.
## 4. Output & Persistence
- `-o, --output <DEST>` is repeatable; pass `-` to include stdout alongside
files. Extensions (`.json`, `.yaml`, `.toml`) drive `DocumentFormat`.
- When no destination is set, the CLI writes to stdout. Pass
`--temp-file <PATH>` if you explicitly want a fallback file instead.
- `--no-pretty` toggles compact serialization; pretty output is the default.
- `--force`/`--yes` allows overwriting existing files. Without the flag the CLI
refuses to run when a destination already exists.
Internally this is powered by `io::output::OutputOptions` so embedding projects
can reuse the exact same serialization logic.
## 5. Argument Reference
| `-o, --output <DEST>` | Append destinations (`-` writes to stdout). | `build_output_options` |
| `--title <TEXT>` | Overrides the active UI header title. | `SchemaUI::with_title` |
| `--description <TEXT>` | Overrides the active UI header description. | `SchemaUI::with_description` |
| `--temp-file <PATH>` | Write to this file when no `--output` is given. | `build_output_options` |
| `--no-temp-file` | Compatibility no-op; stdout is already the default. | `build_output_options` |
| `--no-pretty` | Emit compact JSON/TOML/YAML. | `OutputOptions::with_pretty(false)` |
| `--force`, `--yes` | Allow overwriting files. | `ensure_output_paths_available` |
## 6. Usage Examples
### Schema + config + dual outputs
```bash
schemaui tui \
--schema ./schema.json \
--config ./config.yaml \
-o - \
-o ./edited.toml
```
### Config only (schema inferred)
```bash
### Config only with schema declaration
```bash
schemaui web --config ./config.yaml
```
```yaml
# yaml-language-server: $schema=./schema.json
name: api
port: 8080
```
### Explicit schema override beats the file header
```bash
schemaui \
--schema https://example.com/runtime.schema.json \
--config ./config.toml
```
### Inline schema to avoid double-stdin
```bash
schemaui tui \
--schema '{"type":"object","properties":{"host":{"type":"string"}}}' \
--config ./config.json -o -
```
### Generate a completion script
```bash
schemaui completion bash
```
## 7. Diagnostics & Errors
- **Aggregated reporting** – `DiagnosticCollector` stores every input/output
issue (conflicting stdin, disabled format, existing files) and prints them as
a numbered list before exiting with a non-zero code.
- **Format inference** – `resolve_format_hint` warns when an extension requires
a disabled feature (e.g., `.yaml` without the `yaml` feature). The CLI stops
immediately instead of failing later during serialization.
- **Runtime errors** – everything else bubbles through `color-eyre`, so stack
traces include context like `failed to parse config as yaml` or
`failed to compile JSON schema`.
## 8. Library Interop
The CLI is a thin wrapper over `SchemaUI`:
```rust
let mut ui = if let Some(defaults) = config_value {
SchemaUI::new(defaults).with_schema(schema)
} else {
SchemaUI::from_schema(schema)
};
if let Some(title) = cli.title.as_ref() {
ui = ui.with_title(title.clone());
}
let value = ui.run_tui()?;
if let Some(options) = output_settings.as_ref() {
options.write(&value)?;
}
```
This means embedding projects can reproduce the CLI flow verbatim or replace the
front-end entirely (e.g., build a custom CLI or GUI) while reusing the same I/O
and validation pipeline.
## 9. Feature Flags
| `json` | Enables JSON parsing/serialization and JSON format probes. |
| `yaml` | Adds YAML parsing/serialization via `serde_yaml`. |
| `toml` | Adds TOML parsing/serialization via `toml`. |
| `web` | Enables the browser UI subcommands and the embedded HTTP runtime. |
| `full` | Convenience feature: enables `json`, `yaml`, `toml`, and `web`. |
| `remote-schema` | Enables HTTP(S) schema loading through `reqwest`. |
| default (`full` + `remote-schema`) | Matches the convenience-oriented CLI build shipped to end users. |
`DocumentFormat::available_formats()` obeys the same feature matrix, so both the
CLI and host applications automatically reflect build-time capabilities. At
least one of `json`, `yaml`, or `toml` must remain enabled.
## 10. Operational Tips
- Pass one stream as literal text (a non-existent path is treated inline) when
both schema and config would otherwise require stdin; the executable only
reads stdin once.
- Prefer explicit extensions for outputs—format inference uses the first file’s
suffix, and mismatches across files are rejected.
- Combine `-o -` with file outputs to tee the result into CI logs while still
writing to disk.
## 11. Web Mode
When built with the `web` feature (enabled by default), `schemaui-cli` exposes a
`web` subcommand that proxies the library's browser UI helpers:
```bash
schemaui web \
--schema ./schema.json \
--config ./defaults.json \
--host 127.0.0.1 --port 0 \
-o -
```
The command reuses the same schema/config pipeline as the TUI flow, then calls
`schemaui::web::session::bind_session` to embed the static assets and APIs from
the crate. The terminal prints the bound address (port `0` selects a random free
port). Hit **Save** to persist edits without leaving, or **Save & Exit** to shut
down the temporary server and emit the resulting JSON through the configured
outputs.
Flags specific to the subcommand:
| `--host <IP>` | Bind address for the temporary HTTP server. |
| `--port <PORT>` | Bind port (`0` requests an ephemeral port). |
All other arguments (`--schema`, `--config`, `--output`, etc.) behave exactly
like the TUI mode—either inlined or file-backed specs, multiple destinations,
and the same diagnostics.
With these patterns you can script `schemaui` confidently in CI/CD pipelines or
developer tooling.