de9a3b8b74
Slash-command surface for the community-skill installer: - `/skill install <github:owner/repo|https://...|<registry-name>>` parses the spec via `InstallSource::parse`, calls `install_with_registry`, and surfaces `NeedsApproval`/`NetworkDenied` with actionable messages pointing at `[network]` config (we deliberately don't dispatch a modal from the sync slash-command path; the underlying installer returns the outcome so a future approval wiring can reuse it). - `/skill update <name>` re-fetches and prints "no upstream change" when the checksum matches. - `/skill uninstall <name>` and `/skill trust <name>` both refuse to touch system skills (no `.installed-from` marker). - `/skills --remote` (or `/skills remote`) fetches the curated registry through the same network gate and prints `name — description (source)`. Internals: - Sub-command dispatch happens in `run_skill` before activation lookup, so a user can't accidentally activate a skill literally named `install`. Async install/update/uninstall plumbed through `tokio::task::block_in_place` + `Handle::current().block_on`, matching the existing pattern in `commands/cycle.rs`. - `installer_settings` loads `Config` on demand — `App` doesn't carry a `Config` reference, and the cost of a single TOML parse is negligible next to the network round-trip the install will make. Config: - New `[skills]` section in both `crates/tui/src/config.rs::Config` and the workspace `crates/config/src/lib.rs::ConfigToml` with `registry_url` (default: bundled raw GitHub index) and `max_install_size_bytes` (default: 5 MiB). - `merge_config` propagates the new field, default impls cover the unset case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>