diff --git a/docs/tabby-comparison.md b/docs/tabby-comparison.md new file mode 100644 index 0000000..3dbd189 --- /dev/null +++ b/docs/tabby-comparison.md @@ -0,0 +1,74 @@ +# Rabby vs Tabby Feature Comparison + +Generated after the Rust/Tauri core expansion on `podman:/home/tyou/src/rabby`. + +## Summary + +Rabby now has **modeled coverage** for every major Tabby feature class from the Tabby README/module survey. This means the architecture, typed Rust domain model, validation rules, and unit tests exist for each class. It does **not** mean Rabby has production runtime parity with Tabby yet: many protocol implementations still need real adapters and UI wiring before the feature can honestly be marked `Implemented`. + +## Status definitions + +| Status | Meaning | +| --- | --- | +| Implemented | Runtime behavior, UI/Tauri path, and tests/smoke checks exist. | +| Modeled | Rust model/validation/tests exist; runtime/UI integration remains. | +| UI Prototype | Visible shell/UI or path resolver exists, but runtime parity remains. | +| Planned | Known feature class with no model yet. | + +## Comparison + +| Tabby feature class | Tabby capability | Rabby status | Rabby coverage now | Remaining work | +| --- | --- | --- | --- | --- | +| VT terminal | VT220 terminal + extensions | Modeled | `TerminalGrid` + `AnsiParser` parse text, ANSI color, cursor movement, clear screen, resize, bracketed paste flag. | Replace small parser with full VT engine adapter and renderer integration. | +| Nested splits | Multiple nested split panes | Modeled | Recursive `PaneNode` with split axis/ratio validation and serialization tests. | UI drag/drop and live pane lifecycle. | +| Remembered tabs | Tabs on any side and restored tabs | Modeled | `Workspace`, `Tab`, active tab, serde round-trip. | Persist/restore at app startup and side-tab UI options. | +| Quake console | Dockable window/global spawn hotkey | Modeled | `quake_mode` modeled in workspace. | OS global hotkey registration and Tauri window show/hide command. | +| Progress notifications | Process progress and completion notifications | Modeled | Tab progress field and tests. | Runtime process detector + desktop notifications. | +| Paste ergonomics | Bracketed paste, multiline warning, RMB paste, copy-on-select | Modeled | Terminal parser tracks bracketed paste mode. | UI paste confirmation/RMB/copy-on-select behavior. | +| Unicode/ligatures | Unicode, double-width chars, ligatures | Modeled | UTF-8 text accepted in terminal grid tests. | Accurate grapheme width and font ligature rendering. | +| Local shell profiles | Local shells, WSL/Git-Bash/etc. | Modeled | Local profile command and PTY boundary exist. | Real cross-platform PTY process adapter and profile detection. | +| SSH client | SSH2 connection manager | Modeled | `SshOptions` model validates host/user/port. | Real SSH session adapter. | +| SSH forwarding/jump hosts | X11, port forwarding, jump hosts, agent forwarding, login scripts | Modeled | `SshOptions` includes jump hosts, agent forwarding, X11, forwards, login scripts. | Real `russh`/`libssh2` integration and UI. | +| Telnet | Integrated Telnet client | Modeled | `TelnetOptions` validates host/port. | Real Telnet adapter. | +| Serial terminal | Saved serial, readline, hex/hexdump, newline conversion, auto reconnect | Modeled | `SerialOptions` models baud, newline mode, hex input/output, auto reconnect. | Real serialport adapter and UI. | +| SFTP/Zmodem | SFTP and Zmodem transfer | Modeled | `TransferRequest` validates SFTP/Zmodem upload/download and path safety. | Actual transfer protocol adapters and progress UI. | +| Encrypted secrets | Encrypted SSH secrets/config | Modeled | `SecretString` redacts debug output; `SecretStore` boundary exists. | OS keychain/encrypted-file implementation. | +| Themes/color schemes | Themes and color schemes | Modeled | `Theme` model validates color tokens; built-in Rabby Dark. | Theme import/export and live UI theme switching. | +| Shortcuts/command palette | Configurable and multi-chord shortcuts | Modeled | `ShortcutSequence` parses single/multi-chord bindings and rejects duplicates. | Frontend command palette and key event dispatcher. | +| Plugins | Plugin manager and ecosystem | Modeled | `PluginManifest` with permission validation. | Plugin install/update sandbox and execution model. | +| Portable/web | Portable mode and web SSH/SFTP/Telnet | UI Prototype | Static UI, Tauri shell, and portable config path resolver. | Web daemon/service surface and remote auth model. | + +## Current test coverage + +`./scripts/check.sh` verifies: + +- `cargo fmt --all -- --check` +- `cargo test --workspace` +- `cargo check --workspace` +- `cargo build --release -p rabby` + +Latest passing counts: + +- `rabby-core`: 40 unit tests +- `rabby-runtime`: 6 unit tests + +## Refactor notes + +The codebase is now split along cleaner expansion boundaries: + +- `rabby-core`: feature catalog, workspace, config, terminal model, connection options, transfers, secrets, shortcuts, plugins, themes. +- `rabby-runtime`: config storage and PTY runtime boundaries. +- `src-tauri`: still thin shell. +- `ui`: static UI prototype, to be split into state/render modules before deeper UX work. + +## Next honest parity milestone + +The next milestone should convert selected modeled features into implemented runtime features in this order: + +1. Real local PTY adapter and Tauri terminal commands. +2. UI state/render refactor and live terminal pane rendering. +3. Profile manager UI for local/SSH/Telnet/Serial profiles. +4. Real SSH adapter, then SFTP. +5. Serial/Telnet adapters. +6. Secrets/keychain implementation. +7. Plugin installer/sandbox. diff --git a/rabby-core/src/feature/mod.rs b/rabby-core/src/feature/mod.rs index f3e8c3c..e5fec06 100644 --- a/rabby-core/src/feature/mod.rs +++ b/rabby-core/src/feature/mod.rs @@ -33,8 +33,8 @@ pub const TABBY_FEATURES: &[FeatureSpec] = &[ title: "VT terminal emulation", area: FeatureArea::Terminal, tabby_reference: "VT220 terminal + extensions", - rabby_design: "Terminal session model plus Tauri pane surface", - status: FeatureStatus::Planned, + rabby_design: "TerminalGrid and ANSI parser adapter with colors, cursor, clear, resize, and paste mode", + status: FeatureStatus::Modeled, }, FeatureSpec { key: "nested-splits", @@ -73,16 +73,16 @@ pub const TABBY_FEATURES: &[FeatureSpec] = &[ title: "Paste ergonomics", area: FeatureArea::Terminal, tabby_reference: "Bracketed paste, multiline paste warnings, RMB paste, copy-on-select", - rabby_design: "Terminal preference catalog entry", - status: FeatureStatus::Planned, + rabby_design: "Bracketed paste mode tracked by terminal parser; UI paste policies remain next", + status: FeatureStatus::Modeled, }, FeatureSpec { key: "font-ligatures-unicode", title: "Unicode and font ligatures", area: FeatureArea::Terminal, tabby_reference: "Full Unicode including double-width characters and font ligatures", - rabby_design: "Renderer requirement in feature catalog", - status: FeatureStatus::Planned, + rabby_design: "Terminal grid accepts UTF-8 and records Unicode cells; full ligature rendering remains UI work", + status: FeatureStatus::Modeled, }, FeatureSpec { key: "local-shell-profiles", @@ -105,8 +105,8 @@ pub const TABBY_FEATURES: &[FeatureSpec] = &[ title: "SSH forwarding and jump hosts", area: FeatureArea::Connection, tabby_reference: "X11/port forwarding, automatic jump host management, agent forwarding, login scripts", - rabby_design: "Advanced SSH options reserved in catalog", - status: FeatureStatus::Planned, + rabby_design: "SshOptions models X11, port forwarding, jump hosts, agent forwarding, and login scripts", + status: FeatureStatus::Modeled, }, FeatureSpec { key: "telnet-client", @@ -129,16 +129,16 @@ pub const TABBY_FEATURES: &[FeatureSpec] = &[ title: "File transfer", area: FeatureArea::Transfer, tabby_reference: "Zmodem transfer plus SFTP/web SFTP plugins", - rabby_design: "Zmodem/SFTP transfer surface reserved for SSH sessions", - status: FeatureStatus::Planned, + rabby_design: "TransferRequest models SFTP/Zmodem upload/download with path validation", + status: FeatureStatus::Modeled, }, FeatureSpec { key: "encrypted-secrets", title: "Encrypted secret container", area: FeatureArea::Security, tabby_reference: "Integrated encrypted container for SSH secrets and configuration", - rabby_design: "Tauri/Rust secret-store boundary", - status: FeatureStatus::Planned, + rabby_design: "SecretString redaction plus SecretStore boundary for keychain/encrypted stores", + status: FeatureStatus::Modeled, }, FeatureSpec { key: "themes-color-schemes", @@ -153,23 +153,23 @@ pub const TABBY_FEATURES: &[FeatureSpec] = &[ title: "Configurable shortcuts", area: FeatureArea::UiUx, tabby_reference: "Fully configurable shortcuts and multi-chord shortcuts", - rabby_design: "Shortcut feature catalog and command palette UI", - status: FeatureStatus::UiPrototype, + rabby_design: "ShortcutSequence parses single and multi-chord bindings with duplicate validation", + status: FeatureStatus::Modeled, }, FeatureSpec { key: "plugins", title: "Plugins and themes installable from settings", area: FeatureArea::Extensibility, tabby_reference: "Plugin manager and plugin ecosystem", - rabby_design: "Extension boundary reserved outside core runtime", - status: FeatureStatus::Planned, + rabby_design: "PluginManifest models installable plugin metadata and permission validation", + status: FeatureStatus::Modeled, }, FeatureSpec { key: "portable-web", title: "Portable and web surfaces", area: FeatureArea::Platform, tabby_reference: "Portable app mode and SSH/SFTP/Telnet web app", - rabby_design: "Static UI + Tauri shell; web surface tracked as platform backlog", + rabby_design: "Static UI, Tauri shell, and portable config path resolver; web service remains future adapter", status: FeatureStatus::UiPrototype, }, ]; @@ -260,19 +260,17 @@ mod tests { } #[test] - fn catalog_is_honest_about_planned_work() { - let planned = TABBY_FEATURES - .iter() - .filter(|feature| feature.status == FeatureStatus::Planned) - .count(); - assert!( - planned >= 5, - "scaffold should not imply every Tabby feature is complete" - ); + fn catalog_models_every_tabby_feature_class_without_claiming_runtime_parity() { + assert!(features_by_status(FeatureStatus::Planned).is_empty()); + assert!(features_by_status(FeatureStatus::Implemented).is_empty()); + assert!(TABBY_FEATURES.iter().all(|feature| matches!( + feature.status, + FeatureStatus::Modeled | FeatureStatus::UiPrototype + ))); } #[test] - fn status_queries_distinguish_implemented_from_modeled() { + fn status_queries_distinguish_catalog_states() { assert!(features_by_status(FeatureStatus::Implemented).is_empty()); let modeled = features_by_status(FeatureStatus::Modeled); assert!(modeled.iter().any(|feature| feature.key == "nested-splits"));