DevHub-GPUI Decision Log [Architecture Decision Records]

Living project brief, implementation plan, decision log, and handoff context. Keep this document current throughout the project. If implementation and this document disagree, stop and update the document or explicitly record why the implementation must differ.

Config Paths

config.toml: %AppData%\Roaming\devhub-gpui\config\config.toml projects.toml: %AppData%\Local\devhub-gpui\cache\projects.toml

Remaining differences

  • Remote .gitignore behavior does not match local discovery.
  • SSH requires a POSIX/GNU remote; SFTP and PowerShell-only servers are unsupported.
  • In-flight SSH operations cannot be manually cancelled.

Good to haves (defer until later)

  • Per-source scan status and errors
  • Manual refresh per root or host
  • Pin/favorite projects
  • Hide/archive projects
  • SSH config parsing (~/.ssh/config) via ssh_config crate
  • Build/test command shortcuts
  • tokei/code statistics (defer until manually requested)
  • Global full-text search index (grep)
  • tokei (library) + grep hybrid JSON over SSH
  • keyring-core for credential storage
  • ignore for .gitignore-style pattern matching

Status

  • Current stage: Standalone cross-platform release automation
  • Next gate: first tagged GitHub Actions release
  • Implementation started: semantic dark theme and compact application shell
  • Workspace observed on 2026-06-30: minimal generated-and-reviewed Cargo workspace
  • Renamed-workspace audit on 2026-07-01: stale [REDACTED]\gpui paths in this plan corrected to [REDACTED]\devhub-gpui; static validation gate green (fmt-check, check, 8 tests, clippy with warnings denied, release build from cache)
  • Milestone 1 on 2026-07-01: added devhub-core config and cache modules with serde/toml/directories dependencies, distinct devhub-gpui identity, versioned cache, configured scan roots/max depth, and explicit rescan. 14 tests pass.
  • Milestone 2 on 2026-07-01: added editor launching, incremental keyboard filtering, and Enter-to-open workflow. 23 tests pass.
  • Milestone 2 revision on 2026-07-01: replaced hardcoded editor config with Windows native "Open with" dialog (SHOpenWithDialog). 14 tests pass.
  • Milestone 3 on 2026-07-01: added local workbench (file tree, bounded file reading, content search) with tabbed details panel. 23 tests pass.
  • Deep audit on 2026-07-01 found Milestone 3 incomplete in practice: the flat global tree sort breaks hierarchy, hidden mode conflates dotfiles with ignored and generated files, workbench tasks accept stale results, preview text is not selectable or highlighted, the plan overstates implemented UI state, clippy fails, and the moved release target contains stale artifacts.
  • Remediation Phase 1 static implementation on 2026-07-01: restored hierarchical tree ordering, separated dotfile visibility from ignore/generated-directory policy, added explicit workbench load states and stale-result rejection, moved folder picking off the foreground executor, surfaced persistence errors, added crash-safe config/cache replacement, split reusable UI primitives into ui.rs, replaced the placeholder README, and removed stale artifacts. All 32 tests, fmt, check, clippy with warnings denied, and release build pass; native visual and interaction review remains.
  • Remediation Phase 1 native review passed on 2026-07-01.
  • Remediation Phase 2A on 2026-07-01 implemented a custom eager document and Markdown renderer. Native review rejected it because scrolling and selection were laggy and inaccurate, Markdown fidelity was poor, and README content could truncate. That implementation is superseded rather than accepted.
  • Remediation Phase 2B on 2026-07-01 replaced the failed custom renderer with gpui-component 0.5.1: a rope-backed read-only code editor with Tree-sitter highlighting and a selectable virtualized Markdown view. README now owns the main Overview area below a compact metadata-card header. Remote Markdown and HTML images are sanitized to omission markers before rendering. Static validation passes with 35 tests.
  • Remediation Phase 2B native review passed on 2026-07-01: README layout and scrolling, Markdown preview, code scrolling and selection, clipboard feedback, wrapping, highlighting, search positioning, read-only behavior, and existing window interactions were accepted by the user. Remediation Phase 2 is complete.
  • Remediation Phase 3 SSH implementation on 2026-07-02: added persisted SSH host and root configuration, a unified custom local/SSH folder picker, remote project discovery, tree browsing, README/file reading, content search, and VS Code Remote SSH launch. OpenSSH operations use BatchMode, validated targets, connection/operation deadlines, bounded output, and stale-result rejection. The full static gate passes with 42 tests; native review remains. Its initial VS Code launch choice was later superseded by the Zed-first parity closure.
  • Remediation Phase 3B on 2026-07-02: increased the inherited application font weight to medium with semibold section labels; replaced file-tree text glyphs with gpui-component chevrons, folder states, and recognizable file-type icons; enabled README raster/SVG web images; and resolved relative image paths through recognized GitHub/GitLab remotes. Static validation passes with 43 tests; native review rejected image and icon rendering because the application still used GPUI's null asset source and NullHttpClient.
  • Remediation Phase 3C on 2026-07-02: installed the published component asset bundle, added a bounded reqwest-backed GPUI HTTP client, embedded appicon.svg in the title strip and Windows executable resources, and replaced GPUI's maximize-only Windows call with an IsZoomed-aware maximize/restore toggle. The full static gate passes with 43 tests.
  • Remediation Phase 3 native review passed on 2026-07-02: the user confirmed the application/taskbar icon, typography, tree icons, GIF/SVG/raster README images, maximize/restore, Snap Layout hover, local/SSH picker and persistence, mixed scanning and partial failure, remote README/tree/file/search, hidden mode, stale-result rejection, errors/timeouts, and the then-current VS Code Remote SSH launch. Zed-first launch now replaces that historical path.
  • Post-Phase 3 README image experiment was reverted on 2026-07-02. README images now become explicit alt-text placeholders and no application HTTP client is installed. Local and SSH project browsing therefore does not contact image hosts. Linked-image destinations remain available as ordinary links. The full static gate passes with 44 tests; the release build used the documented machine-local GPUI_FXC_PATH workaround.
  • Parity-closure implementation on 2026-07-02 replaced the temporary VS Code remote launcher with Zed-first local/SSH launching, using Zed's documented ssh://user@host[:port]/path CLI target. The details bar now shows host, Git remote, markers, and modified time; SSH hosts retain independent scan depths; the five legacy palettes and System/Dark/Light modes persist in config. Fmt, all-target check, 46 tests, warning-denied clippy, and release build pass; native review remains.
  • The unsuccessful decorative titlebar icon was removed on 2026-07-02. Settings now occupies the leftmost titlebar slot as a Lucide hamburger button outside the window drag region; its state and behavior are unchanged. The canonical app icon remains embedded in the executable for Windows Task View/taskbar use.
  • Production fixtures were removed on 2026-07-02. A first launch is now defined as both config and cache being absent; only that condition opens Settings automatically. Existing installations with an empty cache retain the normal empty-project state. The truth table is covered by a unit test.
  • The learning-phase current-directory scan fallback was removed on 2026-07-02. Scan with no configured local/SSH sources performs no filesystem access and reports Add at least one local folder or SSH source before scanning.
  • Configuration schema versioning was added on 2026-07-02. New files serialize as version 1; existing unversioned files are treated as version 0, normalized, and atomically rewritten as version 1. A configuration declaring a newer version is rejected without modification, and ordinary saves refuse to overwrite it. Fmt, all-target check, 48 tests, warning-denied clippy, and the release build pass.
  • Replacement-readiness remediation on 2026-07-02 added an isolated DEVHUB_GPUI_STATE_DIR validation path, an IME-capable project filter, Ctrl+F focus, virtualized project rows, 10,000-project cache and 50,000-project filtering tests, partial local-root failure handling, and preservation of the last known-good cache on total scan failure. Native review then caught two virtualization regressions: project rows now explicitly fill the sidebar so hover/selection remain edge-to-edge, and scan startup clears workbench state while suppressing selection of retained cached projects so stale details never flash during scanning.
  • The user confirmed the isolated clean-install, IME input, keyboard navigation, large-list scrolling, partial failure, and total-failure recovery gate on 2026-07-02. The temporary validation checklist was then removed; this living plan retains the durable result. Filter changes and keyboard selection now use the same selection path as mouse clicks, immediately resetting and loading the newly selected project's details.
  • Standalone release automation was added on 2026-07-02 after reviewing the read-only DevHub tag-release workflow and GPUI's platform requirements. Release Windows binaries use the GUI subsystem; GitHub Actions tests, builds, and archives Windows x64, Linux x64, and macOS Apple Silicon, then publishes tagged builds with generated release notes and SHA-256 checksums. macOS fallback opening uses open rather than Linux's xdg-open. The complete local gate passes with 55 tests, warning-denied clippy, thin-LTO release build, and a direct PE-header check confirming subsystem 2 (Windows GUI). The first tag remains the required hosted-run validation of the GitHub Actions matrix.
  • RELEASE.md now provides the v1.0.0 download map, portable installation, first-run, SSH, checksum, upgrade, and rollback instructions. It ships inside every archive and is used verbatim as the tagged GitHub release body.
  • Source application: [REDACTED]\devhub (read-only)
  • Target platform for the first working build: native Windows

The plan was approved on 2026-06-30. Phase 1 created only the minimal scaffold; no DevHub source was copied and no Git operation or DevHub modification occurred.

Intent

Build a small native GPUI playground that teaches GPUI by implementing a narrow slice of DevHub. This is not initially a production rewrite. It should be safe to build, break, discard, and improve while preserving the existing DevHub as a working behavioral and visual reference.

The first useful outcome is DevHub Lite: a GPUI window that can display a small project list, select a project, and show basic details. Real project discovery is added only after the basic GPUI concepts work with fixture data.

The project may mature over time, but each increase in scope must earn its complexity.

After the real local-data path works, the project will deliberately develop a Zed-inspired visual language. GPUI supplies rendering and interaction primitives; it does not supply Zed's appearance by default.

Goals

  1. Create the smallest currently viable standalone GPUI application on Windows.
  2. Learn GPUI in an explicit sequence: application, window, entity, render, elements, interaction, actions, focus, and background work.
  3. Keep the existing DevHub operational and untouched.
  4. Reuse DevHub's framework-independent Rust logic only after the GPUI shell is understood.
  5. Preserve clean dependency direction so domain logic never depends on GPUI.
  6. Maintain a runnable application at every completed milestone.
  7. Build a distinct, Zed-inspired DevHub interface after real data and state transitions are available to design against.

Non-goals for the learning phase

  • A complete DevHub rewrite or feature-parity promise
  • An editor, IDE, terminal emulator, or generic workbench
  • Remote SSH project discovery
  • File-tree browsing, full-text search, or file preview
  • Git mutation or repository management
  • Telemetry cards, remote SVG loading, or HTTP integration
  • Custom window chrome before the dedicated polish phase
  • Pixel-for-pixel Zed cloning or direct reuse of Zed's internal UI crates
  • Theme parity with the egui application before the visual phase
  • A broad reusable component library without multiple concrete consumers
  • Packaging, installers, automatic updates, or release automation
  • Linux cross-platform validation before the native Windows path works

These are deferred, not forbidden. They require an explicit later decision.

Permissions and safety boundaries

Writable target

All implementation writes are confined to:

[REDACTED]\devhub-gpui

Read-only reference

The following source may be inspected and selectively copied. Its Rust/egui code is never edited, renamed, formatted, built in a way that writes into it, or used as a mutable workspace:

[REDACTED]\devhub

Exception granted on 2026-07-02: the [REDACTED]\devhub\web folder (the Astro marketing site) may be edited in place for website updates. This is the only writable path inside the read-only reference; the egui Rust source in [REDACTED]\devhub\src remains strictly read-only.

Additional rules:

  • Do not add a Cargo path dependency pointing at [REDACTED]\devhub; it would make the new project machine-specific and couple it to an application crate.
  • Do not create symlinks or hard links into DevHub.
  • Do not purge egui from DevHub.
  • Do not run Git commands unless the user explicitly requests Git work.
  • Do not launch editors, SSH sessions, URLs, or other external programs during early milestones.
  • Do not reuse DevHub's live config/cache directories initially. The playground must use a distinct application/config identity so it cannot corrupt or migrate the existing application's data accidentally.

Technical facts and assumptions

  • GPUI is pre-1.0; breaking API changes are expected.
  • Use the latest installed stable Rust toolchain that is compatible with the selected GPUI release.
  • The selected published release is gpui 0.2.2, whose crates.io package still contains application and Windows platform startup through Application::new(). Zed's current main branch is moving platform startup into gpui_platform, but that package was not available on crates.io during Phase 1.
  • The machine needs working MSVC build tools, a Windows SDK, and a current GPU driver with DirectX 11 support.
  • The published create-gpui-app tool exists, but its generated template must be reviewed because scaffolding tools may lag GPUI's current API.
  • DevHub currently uses egui/eframe immediate-mode UI. Its UI code is a rewrite, not a mechanical translation to GPUI.
  • DevHub's config, cache, discovery, workspace, and editor-launch modules contain reusable logic, but small UI couplings must be removed when copied.

Current reference links:

Official GPUI source/API documentation takes precedence over tutorials and community examples. Record the exact dependency versions selected during bootstrap in the decision log below.

Architecture direction

The workspace began with one application crate and added a core crate only when real DevHub logic was introduced. Current structure after Phase 6:

[REDACTED]\devhub-gpui\
├── ADR.md
├── Cargo.toml                 # workspace manifest
├── Cargo.lock                 # committed application lockfile once generated
├── README.md                  # concise build/run instructions
├── appicon.svg               # canonical application icon source
└── crates\
    ├── devhub-core\           # UI-independent local/SSH domain and workspace logic
    │   ├── Cargo.toml
    │   └── src\
    │       ├── lib.rs
    │       ├── config.rs      # TOML config with distinct devhub-gpui identity
    │       ├── cache.rs       # versioned project cache
    │       ├── discovery.rs
    │       ├── remote.rs      # bounded OpenSSH transport and remote operations
    │       └── workspace.rs   # project-aware tree, read, and search API
    └── devhub-gpui\           # GPUI state and presentation
        ├── Cargo.toml
        ├── build.rs           # rasterizes/embeds the Windows icon resource
        └── src\
            ├── app.rs         # application state and workbench rendering
            ├── assets.rs      # component icons plus embedded application icon
            ├── lib.rs         # scan model plus tested offline Markdown helpers
            ├── platform.rs    # isolated Windows frame and drag integration
            ├── scan.rs        # testable scan coordination/state machine
            ├── theme.rs       # local semantic visual tokens and font roles
            ├── ui.rs          # reusable presentation primitives
            └── main.rs        # minimal executable bootstrap

Dependency direction:

devhub-gpui  --->  devhub-core  --->  std / narrowly justified libraries
     |
     +------------> gpui 0.2.2 (platform included in this published release)
     |
     +------------> gpui-component 0.5.1 (text views and editor only)
     |
     +------------> gpui-component-assets 0.5.1 (bundled Lucide SVGs)

devhub-core must not import GPUI, egui, colors, widgets, window types, or UI contexts. Presentation mappings such as project type to color belong in the GPUI crate.

Dependency policy

  • Use the reviewed gpui 0.2.2 crates.io baseline. Do not use * or Zed's moving Git main branch in the checked-in manifest. Revisit the separate gpui_platform package only when a compatible release is published and an upgrade has a concrete benefit.
  • Preserve Cargo.lock because this is an application and GPUI is pre-1.0.
  • Do not depend on Zed's full repository or internal Zed UI crates initially.
  • gpui-component was excluded during bootstrap. Phase 2's native smoke test demonstrated concrete selection, scrolling, and Markdown-layout failures, so Phase 2B adopts its text components without migrating the whole UI kit. The tree-sitter-languages feature deliberately increases compile time and the dependency graph in exchange for maintained language parsing.
  • Add no application async runtime merely out of habit; first use GPUI's executor.
  • Add no logging, HTTP, SVG, theme, or serialization dependency until a milestone needs it.
  • Keep default features minimal only when doing so is documented and does not make the Windows setup fragile.
  • Every added dependency must be recorded under Decisions with its purpose.

Visual direction

GPUI does not provide Zed's appearance automatically. The visual language was deliberately created locally and accepted by the user.

Accepted direction:

  • Stark, near-black shell
  • #0e0e0e primary application surface
  • Edge-to-edge panes
  • 1px separators
  • Almost-square geometry
  • Compact rows and headers
  • Restrained accent usage
  • Flat metadata instead of cards and pill badges
  • Client-drawn titlebar integrated with the application
  • Zed-inspired principles without copying Zed UI source

Current approximate geometry:

  • 34px title strip
  • 30px project rows
  • 28px section headers
  • 22px status strip
  • 260px project sidebar
  • 680x440 minimum window size

Typography was increased by 1px during the final Phase 8 pass because the earlier compact type was too difficult to read.

Do not regress toward rounded dashboard cards, large padding, bright layered surfaces, or generic SaaS styling.

GPUI concepts already exercised

The project has validated the following GPUI primitives. Avoid replacing these with unnecessary abstractions before understanding the existing implementation.

  • Application
  • WindowOptions
  • Transparent titlebars
  • Root entities
  • Context<T>
  • Render
  • Element composition
  • Entity-backed state
  • cx.notify()
  • Background and foreground executors
  • Actions and KeyBinding
  • FocusHandle
  • Scroll tracking
  • Stable element IDs
  • Client-drawn window controls
  • Native platform fallbacks

Implementation phases

Each phase is a reviewable checkpoint. Complete its acceptance criteria, update this document, explain what changed and why, and stop for user review before a large scope increase.

Phase 0 — Approve the living plan

Deliverable:

  • This reviewed plan accurately captures scope, permissions, sequencing, and validation.

Acceptance criteria:

  • User approves the plan or requested revisions are incorporated.
  • No implementation has started prematurely.

Phase 1 — Preflight and scaffold

Purpose: prove the Windows toolchain and create only the minimal project shape.

Steps:

  1. Read-only preflight checks:
    • rustc --version
    • cargo --version
    • rustup show active-toolchain
    • verify the MSVC host target
  2. Check whether create-gpui-app is installed and inspect its --version and --help output.
  3. If absent, request approval to install the published tool with Cargo.
  4. Use create-gpui-app --workspace because the user explicitly prefers the generator when available.
  5. Since the target root already contains ADR.md, generate into a temporary writable staging directory rather than overwriting or nesting blindly.
  6. Inspect the generated files before copying the minimal scaffold into this workspace.
  7. Compare generated GPUI dependencies and startup code with current official GPUI guidance.
  8. If the generator is stale, make the smallest compatible corrections and record them. If it cannot generate a repairable current Windows project, manually create the official minimal scaffold and document the exact reason for the fallback.
  9. Keep ADR.md; do not initialize or mutate Git.

Acceptance criteria:

  • Workspace contains only the minimal manifests, README, and one Rust source file in addition to this plan.
  • Dependency versions and generator version are recorded below.
  • No DevHub source has been copied.
  • cargo metadata resolves the intended workspace.

Likely failure cases and responses:

  • Cargo network/DNS failure: retry only with the required network approval.
  • Missing MSVC linker or SDK: stop and report the exact Visual Studio Installer components needed.
  • Generator emits obsolete APIs: repair minimally or use the documented manual fallback; do not pull in the full Zed workspace.
  • Dependency version conflict: select one compatible GPUI/platform pair and pin it; do not mix versions from unrelated examples.

Phase 2 — Static native window

Purpose: establish the smallest understandable GPUI lifecycle.

Implement in one main.rs:

  • platform application creation
  • application run callback
  • one native window with system decorations
  • one root entity/view
  • one Render implementation
  • a small element tree using div and text
  • a reasonable initial and minimum window size

Comments should explain only non-obvious GPUI concepts: who owns the entity, when render runs, and how the application/window contexts are used.

Do not add themes, assets, custom title bars, macros beyond what GPUI requires, or extra modules.

Acceptance criteria:

  • cargo fmt succeeds.
  • cargo check --workspace --all-targets succeeds without warnings caused by our code.
  • cargo run -p devhub-gpui opens a visible native Windows window.
  • Resizing and closing the window work normally.
  • Any visual verification limitation is stated explicitly.

Phase 3 — Entity state and interaction

Purpose: learn state updates before introducing DevHub complexity.

Add one deliberately small interaction, such as a counter or selected fixture project:

  • state stored in the root entity
  • click handler mutating state through the GPUI context
  • explicit notification/refresh behavior
  • hover/focus styling only if it clarifies lifecycle behavior

Keep everything in one source file unless it becomes materially harder to read.

Acceptance criteria:

  • Interaction updates the visible UI repeatedly without recreating state.
  • The code explains why state survives across renders.
  • Formatting, checking, and visible run validation pass.

Implementation status on 2026-06-30:

  • Counter entity and click listener implemented.
  • cx.notify() explicitly requests the follow-up render.
  • cargo fmt, cargo fmt --check, cargo check --workspace --all-targets --locked, and clippy with warnings denied pass.
  • Visible repeated-click behavior and state retention through resize were confirmed by the user. Closing the app intentionally resets in-memory state.

Phase 4 — DevHub Lite with fixture data

Purpose: validate that GPUI suits the target interaction model before copying backend code.

Use a tiny in-memory Project fixture and implement only:

  • a project list
  • selected-row state
  • a details region
  • simple responsive layout within sensible minimum dimensions
  • one keyboard action for selection or refresh, if the basic action API remains small enough

Use system fonts and simple colors. A polished visual match is not a goal.

Acceptance criteria:

  • List selection works by mouse.
  • Details update from selected state.
  • Empty-list and no-selection states render without panic.
  • Narrow-window behavior remains usable or has an explicit minimum width.
  • No DevHub production config/cache is read or written.

Implementation status on 2026-06-30:

  • Three in-memory project fixtures render in a left pane (historical learning phase; removed from production startup during parity closure).
  • Stable row IDs and entity-backed selected index drive a right detail pane.
  • Explicit no-selection and empty-list branches are present.
  • The native window uses an 820x520 initial size and 640x400 minimum.
  • Formatting, locked workspace checking, and clippy with warnings denied pass.
  • Visible mouse selection, row highlighting, detail updates, and resize behavior were confirmed by the user.

Phase 5 — Introduce devhub-core

Purpose: reuse proven backend behavior without importing egui architecture.

Create crates/devhub-core only now. Copy the smallest coherent subset from the read-only DevHub reference. Start with project model and local discovery; defer everything else.

Candidate source modules, in adoption order:

  1. project model and local discovery from src/discovery
  2. cache logic, only after a distinct playground cache identity is defined
  3. configuration, only after theme/appearance types are separated from UI
  4. workspace/file operations, only when the UI needs them
  5. editor launching, only after external-process behavior is explicitly approved

Required adaptations:

  • Move project-color mappings out of the model and into devhub-gpui.
  • Move theme and appearance configuration out of framework-independent config.
  • Preserve paths as PathBuf; convert to display strings only at the UI edge.
  • Avoid reading or migrating existing DevHub data automatically.
  • Audit all subprocess calls. Early local discovery must not mutate Git or launch interactive commands.
  • Record copied file/function provenance in this plan so future DevHub changes can be compared deliberately.

Testing focus:

  • marker-file detection
  • duplicate-project handling
  • missing/unreadable directories
  • non-UTF-8 or unusual Windows paths where practical
  • empty results
  • deterministic sorting

Acceptance criteria:

  • devhub-core compiles without GPUI or egui dependencies.
  • Core tests pass and do not touch real user config/cache data.
  • Fixture UI can switch to core Project values without changing its visual architecture.

Implementation status on 2026-06-30:

  • Added crates/devhub-core with only ignore 0.4.26 as a direct dependency.
  • Ported the project model, marker detection, local walking, deterministic sort, direct .git/config origin reading, timestamps, search keys, and deduplication.
  • Removed egui colors, serialization, tracing, remote SSH, UI scan status, config, cache, and editor-launch concerns from the copied boundary.
  • Adapted Rust 2024 let-chains to Rust 2021 nested conditions.
  • Avoided the source scanner's synthetic parent entry when real child projects have already been discovered.
  • Added four isolated temporary-directory tests; all pass.
  • Switched GPUI fixture values to the shared core Project model without running discovery from the UI.
  • Formatting, locked workspace checks/tests, and clippy with warnings denied pass.
  • The user confirmed the Phase 5 visual smoke test remained unchanged.

Phase 6 — Background local scanning

Purpose: learn GPUI's executor and safe entity updates using a real workload.

Implement:

  • an explicit user-triggered local scan
  • filesystem work off the UI thread
  • loading, success, empty, and error states
  • safe delivery of results back to the owning entity
  • protection against stale results when multiple scans overlap
  • cancellation or generation-token behavior if GPUI's task model makes it straightforward

Do not add SSH, continuous watching, or incremental indexing.

Acceptance criteria:

  • The window remains responsive while scanning.
  • Repeated refreshes do not apply stale results or panic after window close.
  • Errors are visible and actionable rather than silently logged.
  • Large result sets are bounded or rendered with an appropriate GPUI list primitive before they can freeze the UI.

Implementation status on 2026-07-01:

  • Added an explicit Scan/Scan again action for the process's current working directory; no source is scanned automatically.
  • Blocking discovery runs on GPUI's background executor and returns through a foreground task holding only a weak entity reference.
  • A generation counter rejects stale overlapping results; entity release after window close is handled without updating released state.
  • Loading, loaded, empty, and error states are modeled explicitly and rendered.
  • The project list has a stable element ID and vertical scrolling.
  • Moved pure scan coordination into the small testable devhub-gpui library; disabled the native binary test harness after rustc stack overflowed on its deeply composed GPUI element type. The binary remains covered by cargo check --all-targets and clippy.
  • Six tests pass: four discovery tests and two scan-state/staleness tests.
  • Formatting, locked tests/checking, and clippy with warnings denied pass.
  • Visible responsiveness, real-result replacement, repeated scans, selection, and safe closing were confirmed by the user.

Phase 7 — Zed-inspired visual foundation

Purpose: modernize DevHub's presentation deliberately after real project data, loading, empty, and error states exist. GPUI does not provide a Zed skin; this phase creates a small local visual language using GPUI primitives.

Implement:

  • a dark-first set of named design tokens for surfaces, text, borders, accents, selection, focus, success, warning, and error states
  • intentional UI and monospace font roles with a compact type scale
  • a stark, compact geometry: 28-32px rows, 1px separators, 0-1px radii, restrained padding, and edge-to-edge panes instead of card-like surfaces
  • a Zed-inspired application shell for the project list, detail region, toolbar, and status feedback
  • client-drawn Windows chrome integrated into the shell, including native drag, minimize, maximize/Snap Layout, close, resize, and restore behavior
  • complete hover, active, selected, focused, and disabled states
  • a small number of local repeated components only when duplication proves the boundary, such as project row, section header, badge, and status message
  • contrast and fractional-DPI checks on Windows

Constraints:

  • Recreate design principles; do not copy Zed's internal UI crate code.
  • Hide the Windows system title bar only through GPUI's supported transparent titlebar and native window-control hit-test APIs; do not use Win32 bindings.
  • Do not add animation, remote assets, or a broad component framework yet.
  • Preserve all loading, empty, error, and populated states while restyling.
  • Keep design tokens in devhub-gpui; no visual type may leak into devhub-core.

Acceptance criteria:

  • Raw one-off colors and spacing in feature code are replaced by named local tokens where repetition or semantics justify them.
  • Project list, details, loading, empty, and error states share one coherent visual hierarchy.
  • Selection remains distinguishable without relying only on color; the focus token is defined for Phase 8 keyboard/focus wiring.
  • Layout remains usable at the minimum size and at common Windows DPI scales.
  • Integrated chrome preserves drag, resize, minimize, maximize, restore, Snap Layout hover, close, and inactive-window presentation.
  • Visual changes do not alter core behavior or introduce Zed source coupling.

Implementation status on 2026-07-01:

  • The first visual pass was rejected during user review: it was a conventional dark dashboard, not the intended compact and stark Zed-inspired shell.
  • Phase 7 is reopened. Rounded cards/badges, generous spacing, 44px rows, the lighter layered palette, and the native Windows title bar must be replaced.
  • The accepted direction starts from #0e0e0e, uses almost-square geometry, thin separators, denser typography, and client-drawn integrated chrome.
  • Replaced the layered blue-gray palette with a near-black semantic palette; the application, title strip, sidebar, and detail pane now begin at #0e0e0e, with #202020 separators and restrained state colors.
  • Replaced 44px two-line rows, rounded badges/cards, and generous pane padding with 30px single-line rows, flat metadata, 28px section headers, and a 22px status strip. The only circles left are semantic status indicators.
  • Enabled GPUI's transparent Windows titlebar and added a 34px client-drawn title strip with platform hit-test regions for drag, minimize, maximize/restore with Snap Layout, and close.
  • Window controls render active/inactive states, a destructive close hover, and a maximized-state restore glyph. The outer edge is suppressed while maximized.
  • Phase 6 scanning and selection behavior remains unchanged. Formatting, six tests, locked all-target checking, and clippy with warnings denied pass.
  • Native visual, DPI, and window behavior passed user review for the corrected shell, apart from the frame border/corner issue carried into Phase 8.
  • User accepted the corrected visual direction and advanced the project to Phase 8, with the outer gray border and overly round DWM corners identified as a carry-forward frame correction.

Phase 8 — Interaction and visual polish

Purpose: refine the proven visual foundation without turning the playground into an unbounded design-system project.

Candidate work, adopted only when each item has a clear benefit:

  • keyboard navigation, focus traversal, and visible focus treatment
  • compact filtering or command actions using GPUI's action/keybinding model
  • a restrained local icon set and polished project-type/status badges
  • refined loading, empty, error, retry, and stale-result communication
  • subtle transitions or animation where they explain state changes
  • light appearance after the dark theme is coherent
  • large-list profiling and virtualization if real project counts require it
  • evaluation of a third-party GPUI component crate only for a demonstrated gap

Acceptance criteria:

  • Primary flows are implemented for mouse and keyboard.
  • Focus, loading, error, selected, active, and hover states are complete; there are no persistently disabled controls in this scope.
  • Animation was deliberately omitted because it does not clarify state yet.
  • Custom chrome has GPUI hit regions plus explicit Windows fallbacks.
  • Formatting, checking, eight tests, clippy, and release build pass.
  • Final native smoke test of the latest control fallbacks remains user-owned.

Implementation status on 2026-07-01:

  • Removed the original gray application border, then added a deliberate 1px #202020 edge after the native DWM edge proved inconsistent.
  • Added a Windows-only DWM surface adapter using Windows' supported small-corner treatment. DWM does not expose an exact 2px radius; DWMWCP_ROUNDSMALL is the closest platform-owned option.
  • DWM border suppression was first suspected when the user reported that the window could not move, but restoring a native border color did not fix drag behavior and the requested 1px edge remained invisible.
  • Added an explicit GPUI 1px #202020 outer edge. The title region retains GPUI's WindowControlArea::Drag and now has a Windows-native move-loop fallback for configurations where it receives a client mouse-down instead. Double-click still toggles maximize/restore.
  • Added a root focus handle and GPUI actions/keybindings for Up/Down project selection, Home/End bounds, and Ctrl+R scanning.
  • Mouse selection and the titlebar scan action return focus to the root so keyboard navigation remains available.
  • Added a restrained shortcut hint to the status strip.
  • Added explicit click fallbacks for minimize, maximize/restore, and close while retaining GPUI control hit regions for native behavior such as Snap Layout.
  • Increased every rendered text role by 1px for legibility without loosening the compact layout.
  • Keyboard selection now scrolls the active project into view; its empty, boundary, and stale-index behavior is covered by isolated tests.
  • Moved Windows DWM and native move-loop code into platform.rs so unsafe, platform-specific work is not mixed into view rendering.
  • Optional filtering UI, animation, light theme, virtualization, and third-party components were not added because no demonstrated need justifies them yet.

Phase 9 — Maturity and repository-direction review

At this point, stop and decide whether the experiment should remain small or become the new DevHub implementation.

Review questions:

  • Is GPUI productive enough for this application?
  • Are Windows rendering, text, focus, accessibility, and DPI behavior acceptable?
  • Is core/UI separation clean?
  • Does the Zed-inspired visual language feel coherent without copying Zed?
  • Which DevHub feature gives the most value next?
  • Is a third-party component crate now justified?
  • Should development remain here or eventually move into the DevHub repository?

Outcome on 2026-07-01:

  • The user deems the GPUI experiment successful.
  • GPUI is productive enough for a DevHub successor: native rendering, async scanning, entity state, actions, focus, scrolling, and a distinct visual language have all been exercised without importing Zed UI crates.
  • devhub-core is a sound boundary and should remain UI-independent.
  • Windows client chrome is viable but is the clearest maintenance risk; keep platform fallbacks isolated and test them on each GPUI upgrade.
  • Accessibility, IME/text input, persisted configuration, and larger project sets are not yet validated and must be treated as maturity work, not assumed.
  • No third-party GPUI component crate is justified at this point.
  • Keep [REDACTED]\devhub intact as the reference application. Continue this workspace as the successor (preferably renamed devhub-gpui or devhub-next) rather than purging egui in place. Promote it to the canonical DevHub repository only after the first two successor milestones below pass.

Recommended successor roadmap, in order:

  1. Persist distinct devhub-gpui configuration and cache data, add configurable local scan roots/max depth, and preserve explicit background rescans.
  2. Add compact project filtering and configured editor launching so the app completes DevHub's core discover-select-open workflow.
  3. Port the local file tree/read/search workbench, then evaluate remote SSH discovery separately; do not couple remote complexity to local maturity.

Successor Milestone 1 — Configuration and persistence

Purpose: give the successor a distinct, migration-safe persistence layer so it can remember configured scan roots, max depth, and scanned project results without touching egui DevHub data.

Implemented:

  • crates/devhub-core/src/config.rs
    • Versioned Config schema containing appearance, local sources/depth, and SSH hosts/depth
    • Missing version means legacy version 0 and migrates atomically to version 1
    • Newer versions are rejected and protected from accidental overwrite
    • load_or_create, save, ensure_dirs_exist, config_path, config_dir, cache_dir
    • Distinct application identity "devhub-gpui" via directories::ProjectDirs
    • TOML format; missing fields fall back to defaults via #[serde(default)]
  • crates/devhub-core/src/cache.rs
    • Versioned ProjectCache starting at version 1 (distinct from egui DevHub v4)
    • load_projects, save_projects, cache_path
    • Version mismatch returns no projects rather than attempting migration
  • crates/devhub-core/src/discovery.rs
    • Added Serialize/Deserialize derives to Project, ProjectSource, ProjectType so the cache can round-trip the domain model
  • crates/devhub-gpui/src/main.rs
    • Loads config on startup and ensures config/cache directories exist
    • Loads cached projects on first launch; falls back to fixture data only when no cache exists yet
    • Scans all configured scan_dirs (not just the current working directory) using the configured max_depth
    • Saves scanned results to the cache after a successful scan
    • Explicit rescan only; no automatic filesystem access
    • Status strip shows the first configured root (or the fallback current dir)

New dependencies (recorded in the decision log):

  • serde 1 with derive feature
  • toml 0.8
  • directories 6

Acceptance criteria:

  • Distinct devhub-gpui configuration/cache identity
  • Configurable local scan roots
  • Configurable maximum depth
  • Persistence to the platform configuration directory
  • Versioned cache format
  • Versioned configuration format with tested v0-to-v1 migration
  • Future configuration versions are rejected without being rewritten
  • Explicit rescan behavior
  • Migration safety that cannot overwrite existing egui DevHub data
  • Remote hosts excluded from this milestone
  • Formatting, checking, 14 tests, clippy, and release build pass
  • User native smoke test of Milestone 1 remains user-owned

Implementation status on 2026-07-01:

  • Added config and cache modules to devhub-core with serde/toml/directories.
  • The Project model now derives Serialize/Deserialize so the cache can round-trip it without a separate DTO.
  • The distinct "devhub-gpui" identity means config and cache files live in a separate directory from the egui DevHub; there is no shared path and no migration logic that could touch the old data.
  • Cached projects load on startup. The original fixture fallback was removed during parity closure; after a scan, results persist to projects.toml.
  • The scan task now validates all configured roots before walking; the first invalid root produces a visible error state.
  • Tests cover config defaults, TOML round-trip, missing-field defaults, identity distinctness, cache round-trip, and wrong-version rejection. No test touches real user config/cache data.
  • Formatting, 14 tests (10 core + 4 gpui), clippy with warnings denied, and the release build all pass.

Exp 3 addition on 2026-07-01 after Milestone 2 passed:

  • crates/devhub-gpui/src/platform.rs
    • pick_folder(hwnd_raw) — wraps the Windows native IFileOpenDialog with FOS_PICKFOLDERS. Blocks the calling thread; must run on a background executor. Uses CoInitializeEx/CoUninitialize for COM apartment init.
    • window_hwnd_raw(window) — extracts the raw HWND as isize so it can cross thread boundaries.
  • crates/devhub-gpui/src/main.rs — settings overlay
    • Settings gear button in the titlebar (next to Scan) toggles the overlay
    • Overlay replaces the main content area when active
    • Lists pending scan directories with "x" remove buttons
    • "+ Add directory" spawns a background task calling pick_folder, then pushes the result to the pending list (deduplicated)
    • "-" / "+" buttons adjust max depth (1–20 range)
    • "Cancel" discards pending changes and closes the overlay
    • "Save && Rescan" persists to config, closes the overlay, and triggers a fresh scan
    • Escape also closes the overlay if active
  • Drive-by: Enter keybinding fixed. handle_filter_keydown now silently consumes Enter when the filter query is non-empty. Additionally, open_selected_project guards against opening while the filter is active. (GPUI 0.2.2 on_key_down callbacks cannot stop action dispatch, so both the key handler and the action handler participate.)
  • Drive-by: platform.rs import cleanup — use crate::PathBuf -> use std::path::PathBuf, removed duplicate function-scoped import.
  • 23 tests pass (19 core + 4 gpui), check, clippy, and release build pass.
  • No new dependencies added.

Superseded on 2026-07-02: the COM folder picker, pick_folder, and window_hwnd_raw were removed when Phase 3 introduced the unified custom local/SSH picker. This block remains as historical implementation context.

Successor Milestone 2 — Complete the core DevHub loop

Purpose: complete the discover → select → open workflow so the successor can replace the egui DevHub for its primary use case: finding a project and opening it in an editor.

Implemented:

  • crates/devhub-gpui/src/platform.rs
    • open_with_picker(path, window) — shows the Windows native "Open with" dialog using SHOpenWithDialog with OAIF_EXEC | OAIF_ALLOW_REGISTRATION
    • Enumerates all registered applications on the user's system; no hardcoded editor paths or config needed
    • The selected program is launched by Windows with the project path
    • Runs on a background thread so the GPUI window stays responsive; the HWND is passed as isize to cross the thread boundary (raw pointers are not Send)
    • Added Win32_UI_Shell feature to the windows dependency
  • crates/devhub-gpui/src/main.rs
    • Incremental keyboard filtering via on_key_down:
      • Typing printable characters filters the project list by search_key
      • Backspace removes the last character
      • Escape clears the filter
      • Modifier-combined keys (Ctrl+R, etc.) pass through to actions
    • OpenSelectedProject action bound to Enter
    • An "OPEN" button in the details panel header for mouse users
    • Filtered project list: filtered_indices() maps the filtered view to underlying project indices; keyboard navigation, mouse selection, and auto-scroll all operate within the filtered set
    • Auto-selects the first match when filtering narrows the list
    • "NO MATCHES" empty state when the filter has no results
    • Sidebar header shows visible/total count when filtering
    • Status strip shows the active filter query
    • Keyboard hints updated: type filter · ↑↓ select · Enter open · Ctrl+R scan
    • Filter state cleared on new scans

Revised from the initial Milestone 2 approach:

  • The first implementation used hardcoded editor config (EditorConfig with template strings) and VS Code install-path fallback. This was rejected because hardcoded paths are fragile and machine-specific.
  • Replaced with SHOpenWithDialog, which delegates entirely to the Windows shell. The user picks from all registered applications on their system; no editor configuration is needed or stored in config.toml.
  • Removed crates/devhub-core/src/editor.rs and editors/default_editor from Config. Old config files with those fields still load (serde ignores unknown fields by default).
  • The launch_error field is the current shared application-error surface. The Windows picker handles its own dialog errors, while config/cache load and save failures are reported through this field rather than silently discarded.

New GPUI concepts exercised:

  • on_key_down with cx.listener — capturing raw keystrokes for incremental text input without a full text-input widget (IME/text input remains unvalidated; this is an action-path filter, not a text field)
  • KeyDownEvent / Keystroke — reading key, key_char, and modifiers to distinguish printable characters from action shortcuts

New Windows API exercised:

  • SHOpenWithDialog with OPENASINFO and OAIF_EXEC — the native "Open with" dialog, isolated in platform.rs

Acceptance criteria:

  • Compact project filtering
  • Local editor launching (via native Windows picker)
  • Keyboard operation for filter/select/open
  • The complete discover → select → open workflow
  • Formatting, checking, 14 tests, clippy, and release build pass
  • User native smoke test of Milestone 2 remains user-owned

Implementation status on 2026-07-01:

  • The filter uses the existing search_key field on Project (already lowercase) so no new indexing is needed. The query is lowercased on input.
  • GPUI 0.2.2 has no high-level text input widget; on_key_down + Keystroke.key_char provides an incremental filter without IME complexity.
  • The "OPEN" button and Enter key both call open_selected_project, which calls open_with_picker in platform.rs.
  • SHOpenWithDialog is called on a background thread because it blocks until the user picks or cancels. The HWND is extracted as isize to cross the thread boundary safely (raw pointers are not Send).
  • Removed editor.rs from devhub-core; editor launching is now entirely a platform concern in platform.rs, not domain logic.
  • Config no longer stores editor definitions; config.toml contains only scan_dirs and max_depth.
  • 14 tests (10 core + 4 gpui). Formatting, clippy with warnings denied, and release build all pass.

Successor Milestone 3 — Local workbench

Purpose: port the local file tree, bounded file reading, and content search workbench from the egui DevHub reference, providing a usable local-only workbench before evaluating remote SSH complexity.

Implemented:

  • crates/devhub-core/src/workspace.rs
    • list_tree(root, max_depth, show_hidden) -> Result<TreeListing, String> — gitignore-aware tree walk with stable parent/child preorder, per-directory directories-first sorting, a 500-row output bound, a 5,000-entry scan bound, truncation metadata, and non-fatal walker warnings
    • Dotfile visibility is independent from ignore rules; .git, generated, dependency, and vendor directories remain pruned in both modes
    • read_file(path) -> Result<String, String> — bounded at 512 KiB, returns clear error strings for directories, missing files, and oversized files; uses String::from_utf8_lossy for non-UTF-8 tolerance
    • search_content(root, query) -> Vec<SearchHit> — case-insensitive substring search, walks files with ignore, skips binary/large files by extension and size, capped at 200 hits, preview trimmed to 240 chars
    • Tests cover hierarchy, sibling ordering, hidden/ignored policy, invalid roots, bounded reading, and search behavior
  • crates/devhub-gpui/src/main.rs
    • Tabbed details panel: OVERVIEW | FILES | SEARCH
    • DetailsTab enum with Overview, Files, and Search states
    • Files tab: async file tree loading on tab open, click-to-view files, "← back" button to return to tree, error state for unreadable files
    • Search tab: type query (captured via on_key_down when in search mode), press Enter to search, click result to view the file, Escape clears query
    • Selecting a new project resets all workbench state
    • Tree, README, file, and search each use explicit idle/loading/loaded/empty/ error state and generation/path/query guards reject stale async results
    • File tree shows depth indentation, dir/file icons, and entry count
    • Search results show file:line and preview, with match count header
  • crates/devhub-gpui/src/ui.rs
    • reusable message, metadata, status, icon, and window-control primitives separated from application/workbench state

New GPUI concepts exercised:

  • A project-list ScrollHandle for selection visibility
  • Conditional keyboard routing based on UI mode (filter vs search)
  • Async work with explicit state and stale-result rejection
  • File viewer with scrollable content display

Acceptance criteria:

  • File tree
  • Bounded file reading (512 KiB limit, clear errors)
  • Content search (case-insensitive, result limits, binary skipping)
  • Result limits (500 tree entries, 200 search hits, 240-char previews)
  • Error states (directory, missing, oversized, unreadable)
  • Background execution (all I/O on GPUI's background executor)
  • Formatting, checking, 32 tests, clippy pass
  • Release build
  • User native smoke test of Milestone 3 remains user-owned

Implementation status on 2026-07-01:

  • Added workspace.rs to devhub-core with list_tree, read_file, search_content, TreeListing, FileEntry, and SearchHit; no anyhow or tracing dependency was introduced.
  • The workbench UI uses three tabs: OVERVIEW (metadata), FILES (tree + viewer), SEARCH (type-to-search + results). All filesystem work runs on GPUI's background executor with explicit loading states.
  • Keyboard routing: handle_filter_keydown checks details_tab and routes keystrokes to the search query when in Search mode, or the project filter otherwise. Escape clears the active context's query.
  • Clicking a file in the tree or a search hit loads the file content via read_file on the background executor and displays it with a "← back" button.
  • Binary files are skipped during search by extension check (exe, dll, png, zip, etc.) and by the 512 KiB size bound in read_file.
  • Remote SSH was deliberately excluded per the roadmap; evaluate it as a separate decision after the local workbench proves mature.

Remediation Phase 1 — Stabilize the local workbench

Purpose: make Milestone 3 truthful and dependable before expanding scope.

Implement:

  • replace global filename sorting with parent-preserving, directories-first hierarchical ordering
  • make "show hidden" affect hidden paths only; continue respecting gitignore and pruning .git, build, dependency, and vendor directories
  • represent tree, README, file, and search work with explicit idle/loading/ loaded/empty/error states
  • reject stale async results after project, file, query, or hidden-mode changes
  • move the native folder picker off GPUI's foreground executor
  • surface config/cache persistence failures instead of discarding them
  • split the monolithic application file along concrete workbench/UI boundaries
  • correct README, plan drift, clippy, release-target, and stray-file hygiene

Acceptance criteria:

  • Tree rows remain adjacent to their parents and directories sort before files within each parent.
  • Hidden mode does not disable gitignore or expose generated directories.
  • Empty, loading, error, loaded, and truncated states are distinct.
  • Stale async work cannot replace state for a newer user selection.
  • Folder picking does not block the GPUI foreground executor.
  • Persistence failures are visible and writes are atomic where practical.
  • Main application responsibilities are split into maintainable modules.
  • Formatting, checking, tests, clippy, release build, and native review pass.

Remediation Phase 2 — Document and Markdown subsystem

Purpose: replace passive string rendering with a real read-only document model.

Implement:

  • selectable text, Ctrl+A/C, mouse drag selection, and keyboard navigation
  • line numbers, wrap toggle, horizontal/vertical scrolling, and search-hit line positioning
  • binary detection and bounded line-oriented layout
  • background syntax highlighting selected by file extension
  • Markdown parsing and styled README preview with a raw/preview toggle
  • shared rendering foundations for code blocks and ordinary text

Implementation status on 2026-07-01:

  • Phase 2A's custom eager renderer failed native review and was removed.
  • gpui-component 0.5.1 is initialized at application startup and its Root wraps the existing application entity; the rest of the DevHub shell remains locally implemented.
  • Files use the component's disabled rope-backed InputState code editor. It provides virtualized rendering, selection/copy, line numbers, wrap control, and extension-selected Tree-sitter highlighting while rejecting edits.
  • Search-result clicks position the component editor at the matched line.
  • README uses selectable, scrollable TextView::markdown for the full remaining Overview pane, with a compact fixed metadata-card header and raw/preview mode.
  • Markdown and HTML images are sanitized into explicit alt-text placeholders before component rendering. A Phase 3 experiment with network-backed images was reverted because image decoration does not justify making local and SSH project inspection contact arbitrary internet hosts.
  • Binary and invalid UTF-8 rejection remains in devhub-core; file and README reads remain bounded background operations.
  • Selection copy and copy-all actions produce temporary visible status feedback.

Acceptance criteria:

  • Text selection and clipboard copy work with mouse and keyboard.
  • Code can wrap or remain horizontally scrollable by explicit user choice.
  • Syntax highlighting and scrolling remain responsive on representative files.
  • Markdown headings, paragraphs, lists, quotes, links, and code render locally.
  • README image policy is explicit and covered by offline-sanitization tests.
  • Formatting, checking, tests, clippy, release build, and native review pass.

Remediation Phase 3 — Selective DevHub parity

Purpose: port product value deliberately after the local foundation is sound.

Implement in priority order:

  • reliable source enable/disable, onboarding, editor preferences, open-folder, diagnostics, and system-appearance behavior
  • a local/remote backend boundary that keeps UI state independent of transport
  • remote SSH discovery/tree/read/search with timeout, cancellation, BatchMode, bounded output, and explicit errors
  • evaluate telemetry and remote SVG cards separately; do not assume parity means every legacy feature must return

SSH implementation status on 2026-07-02:

  • devhub-core exposes one project-aware tree/read/README/search API and routes each operation by ProjectSource; GPUI does not contain transport scripts.
  • remote.rs owns validated OpenSSH invocation, POSIX shell scripts, parsing, hierarchy reconstruction, fixed limits, and a 30-second operation deadline.
  • SSH uses BatchMode=yes, ConnectTimeout=8, one connection attempt, existing user OpenSSH config/keys, and the user's normal host-key policy. It neither stores credentials nor weakens host-key checking.
  • Remote discovery detects direct project markers and Git repositories under configured roots, prunes known generated directories, and caps candidate and project output. Failed hosts are reported without discarding successful local or remote results.
  • The custom source picker navigates local drives/directories and remote directories in the same settings flow. It persists normalized, deduplicated hosts and roots only under the separate devhub-gpui identity.
  • Remote projects support tree browsing, hidden-file control, bounded UTF-8 file and README reads, fixed-string content search, and stale-result rejection.
  • Opening a project is Zed-first. Local paths are passed to zed; SSH projects use ssh://user@host[:port]/path. OPEN IN… invokes the Windows application chooser for either a local path or the SSH URI as a best-effort fallback.
  • Static validation passed with 36 core and 6 GPUI tests before the later asset pass. A real SSH host passed the native acceptance gate on 2026-07-02.

Acceptance criteria:

  • Local behavior remains unchanged when remote support is unavailable.
  • Remote operations run off the UI executor, reject stale results, and time out.
  • Config/cache formats remain versioned and migration-safe.
  • Features selected for omission are documented as product decisions.
  • Formatting, checking, tests, clippy, release build, and native review pass.

Run validation after every meaningful code change, proportionate to the change:

  1. cargo fmt
  2. cargo fmt --check
  3. cargo check --workspace --all-targets
  4. cargo test --workspace once tests exist
  5. cargo run -p devhub-gpui when application behavior changes

cargo clippy --workspace --all-targets -- -D warnings is introduced after the first stable window milestone. Do not let framework-generated warnings block the bootstrap without first distinguishing them from warnings in our code.

GUI run procedure:

  • Launch the native application with a bounded observation period.
  • Confirm a window was created and remains responsive.
  • Verify expected text/interaction visually when possible.
  • Close gracefully; do not leave background processes running.
  • If the environment cannot inspect a native window, ask the user for visual confirmation and report what was verified from process status/logs.

If validation fails:

  • capture the exact command and concise error
  • determine whether the cause is code, dependency/API drift, missing toolchain, GPU/driver support, or sandbox/network restriction
  • fix in-scope code failures
  • request required permission rather than bypassing restrictions
  • report exact installation steps for external prerequisites
  • update Known issues when a failure may recur

Windows-specific edge cases

  • MSVC linker/build tools absent or not visible to the active shell
  • Windows SDK version missing
  • stale GPU driver or Microsoft Basic Display Adapter in use
  • unsupported/virtualized GPU despite DirectX availability
  • long path handling when Cargo's registry/git caches become deeply nested
  • antivirus or indexing software locking Cargo build artifacts
  • native window launch succeeding while automated visual inspection is unavailable
  • display scaling and fractional DPI affecting layout assumptions
  • system light/dark appearance changing while the app runs
  • paths containing spaces, Unicode, drive roots, or UNC prefixes
  • shell differences between PowerShell and Developer Command Prompt

The first milestone uses native Windows directly, not WSL/WSLg.

Windows chrome fallback inventory

This is the most platform-specific area of the application. The app hides the native Windows titlebar using GPUI's transparent titlebar support and draws its own title strip. GPUI window-control hit regions alone were unreliable on the user's system.

Observed behavior during development:

  • Minimize/maximize/close worked at one point
  • Window movement later failed
  • DWM border suppression was suspected but was not the actual complete cause
  • Native DWM border color did not produce a consistently visible edge
  • User requested a visible 1px border
  • Window controls later became nonfunctional again

The current implementation therefore includes fallbacks that must not be removed merely because the code looks redundant. They exist because actual Windows behavior differed from the expected GPUI path.

  • WindowControlArea::Drag remains attached to the title region.
  • platform.rs provides a Windows-native move-loop fallback using ReleaseCapture, PostMessageW, WM_NCLBUTTONDOWN, and HTCAPTION.
  • Double-clicking the drag region should maximize or restore the window.
  • Minimize, maximize/restore, and close retain GPUI window-control hit regions.
  • They also have explicit click fallbacks: window.minimize_window(), window.zoom_window() (superseded by the IsZoomed-aware toggle), and window.remove_window().
  • The GPUI root draws an explicit 1px #202020 edge.
  • Windows DWM is asked to use its small-corner treatment. DWM does not expose an exact 2px corner radius; DWMWCP_ROUNDSMALL is the closest supported platform option.

All Windows-specific API calls stay isolated in platform.rs. Treat custom Windows chrome as a maintenance risk that must be retested on GPUI upgrades. If window controls fail, diagnose the precise event path before rewriting the titlebar again.

Coding rules

  • Prefer clear Rust and concrete types over generic abstractions.
  • Keep the file structure minimal; split a module only when it has a distinct responsibility and the current file is becoming difficult to navigate.
  • Explain GPUI-specific ownership/context behavior near the relevant code.
  • Do not comment obvious Rust syntax.
  • Avoid unsafe unless GPUI itself requires interaction that cannot be expressed safely; any use requires explicit review.
  • Avoid global mutable state.
  • Keep blocking filesystem/subprocess work off the UI thread.
  • Model empty, loading, success, and failure states explicitly.
  • Use stable IDs for interactive/list elements where GPUI state retention depends on identity.
  • Do not hide errors merely to keep the demo running.
  • Prefer system window behavior and accessibility over custom chrome initially.

Scope-control rules

Before adding a feature, answer:

  1. Which GPUI concept does this teach or validate?
  2. Can it be implemented without adding a dependency?
  3. Does it belong in the UI crate or core crate?
  4. Does it threaten the runnable checkpoint?
  5. Is it already listed as a non-goal?

If the feature does not improve learning or validate the DevHub direction, defer it.

Progress-reporting protocol

After each meaningful change, report:

  • outcome first
  • files changed
  • GPUI concept introduced
  • why the change was scoped that way
  • validation commands and results
  • known limitation or next review gate

Update this document in the same change with:

  • current stage and completed checkboxes
  • exact dependency/tool versions when they become known
  • decisions and deviations
  • current project tree if it materially changes
  • known issues
  • next approved checkpoint

The final handoff for any milestone must:

  • summarize the project structure
  • explain the GPUI concepts currently used
  • suggest exactly three next experiments, no more

Treat the user as the visual observer. Do not claim native behavior is verified from compilation alone.

Validation gate

After every meaningful change, run validation proportional to the change. The full static gate is:

cargo fmt --all
cargo fmt --all -- --check
cargo check --workspace --all-targets --locked
cargo test --workspace --locked
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo build --release --workspace --locked

The last completed test validation had 43 devhub-core tests, 12 devhub-gpui tests, 55 total passing tests, all-target checking passing, clippy passing with warnings denied, and a release build passing.

The native GPUI binary has test = false because embedding unit tests in the deeply composed binary previously caused rustc stack overflow. Pure testable behavior belongs in the library modules.

If the release executable is currently running, Windows may lock target\release\devhub-gpui.exe. Do not terminate the user's process without permission; ask them to close the app before rebuilding.

Definition of the first learning milestone

The initial journey is successful when all of the following are true:

  • A native Windows GPUI application starts with cargo run -p devhub-gpui.
  • The user can explain where application, window, entity, render, and element responsibilities live in the code.
  • Entity-backed state updates through one mouse interaction.
  • A DevHub-like list/details layout works with fixture data.
  • One local background scan feeds results into the UI without blocking it.
  • Core discovery logic is independent of GPUI.
  • Formatting, checking, tests, and release build validation pass.
  • DevHub remains untouched and functional as the reference implementation.

Definition of the visual-modernization milestone

The later visual journey is successful when all of the following are true:

  • Real project data and every operational state use one coherent token set.
  • The interface is recognizably Zed-inspired without copying Zed UI code.
  • Compact layout, typography, borders, selection, and focus states are consistent across the application.
  • Mouse and keyboard flows work at the minimum window size and common Windows DPI scales.
  • Polish remains local and maintainable rather than becoming a speculative general component framework.

Decision log

Date Decision Reason
2026-06-30 Use native Windows for the first build It is the available visual desktop and GPUI supports Windows natively.
2026-06-30 Keep [REDACTED]\devhub read-only Preserve the working application as a behavioral and visual baseline.
2026-06-30 Build separately in [REDACTED]\devhub-gpui Avoid a big-bang egui purge and allow the experiment to fail safely.
2026-06-30 Start with one GPUI app crate; add devhub-core later Keeps bootstrap beginner-friendly while preserving a clean future boundary.
2026-06-30 Use create-gpui-app when installable, then review its output Honors the requested bootstrap path without trusting a potentially stale template blindly.
2026-06-30 Use fixture data before copying DevHub logic Separates GPUI learning problems from filesystem/domain integration problems.
2026-06-30 Use a distinct config/cache identity Prevent accidental corruption or migration of existing DevHub user data.
2026-06-30 Pin published gpui 0.2.2 instead of Zed Git main Gives the playground a reproducible baseline and avoids unreleased platform API drift.
2026-06-30 Retain the generator's Rust 2021 edition for bootstrap Avoids an unrelated edition change while validating the generated scaffold.
2026-06-30 Use system decorations with explicit 820x520 and 640x400 minimum bounds Validates ordinary Windows behavior before attempting custom chrome or responsive layouts.
2026-06-30 Schedule Zed-inspired design after real data integration GPUI supplies primitives rather than Zed's skin; designing against real states avoids polishing disposable fixture UI.
2026-06-30 Recreate Zed design principles without copying internal UI code Keeps the playground independent, small, and clear of Zed application-code coupling.
2026-06-30 Add ignore 0.4.26 as the sole devhub-core dependency Reuses DevHub's gitignore-aware walking without importing UI, async, logging, or serialization layers.
2026-06-30 Do not emit a synthetic scan-root project after finding children Keeps configured source folders from appearing as misleading aggregate projects.
2026-07-01 Scan only the current working directory on explicit request Validates real background work without config, persistence, or automatic filesystem access.
2026-07-01 Isolate scan coordination in a testable library module Tests stale results and state transitions without using the deeply composed native GPUI binary test harness.
2026-07-01 Use a local semantic dark theme instead of Zed UI crates Creates a Zed-inspired hierarchy without copying application code or coupling core models to presentation.
2026-07-01 Keep native decorations through the visual-foundation phase Preserves correct Windows movement, resize, minimize, maximize, close, DPI, and accessibility behavior during restyling.
2026-07-01 Supersede the native-decoration Phase 7 decision with GPUI client chrome User review established integrated chrome as part of the visual target; GPUI hit-test regions retain native commands.
2026-07-01 Treat the experiment as successful and continue as a successor The playground validates GPUI state, async work, actions, scrolling, visual styling, and Windows integration.
2026-07-01 Keep the egui DevHub intact until successor milestones 1 and 2 pass Preserves a working reference while configuration, persistence, and the discover-select-open workflow are rebuilt.
2026-07-01 Add serde 1, toml 0.8, directories 6 to devhub-core Required for TOML config and versioned project cache persistence. No presentation or async runtime introduced.
2026-07-01 Use "devhub-gpui" as the distinct config/cache identity Structural migration safety: separate directory from egui DevHub's "devhub" identity; cannot collide or overwrite.
2026-07-01 Start devhub-gpui project cache at version 1 Distinct from egui DevHub's cache v4; version mismatch returns empty rather than migrating, preserving isolation.
2026-07-01 Derive Serialize/Deserialize on the core Project model Lets the cache round-trip the domain model without a separate DTO or UI coupling.
2026-07-01 Add editor.rs to devhub-core for editor launching Keeps subprocess launching in the domain layer; returns Result<(), String> instead of anyhow for direct UI display.
2026-07-01 Use on_key_down for filtering instead of a text input widget GPUI 0.2.2 has no high-level text input; on_key_down + key_char provides incremental filtering without IME complexity.
2026-07-01 Replace hardcoded editor config with SHOpenWithDialog Hardcoded editor paths are fragile and machine-specific; the native Windows "Open with" dialog enumerates all registered apps on the user's system without configuration.
2026-07-01 Move editor launching from devhub-core to platform.rs SHOpenWithDialog is a Windows Shell API call, not domain logic; keeping it in platform.rs preserves the core/UI separation and isolates all unsafe platform code.
2026-07-01 Add Win32_UI_Shell feature to the windows dependency Required for SHOpenWithDialog and OPENASINFO; no other Shell APIs are used.
2026-07-01 Guard OpenSelectedProject action when filter is active GPUI on_key_down callbacks cannot prevent action dispatch; the action handler checks filter_query as a practical fix for Enter opening projects during search.
2026-07-01 Experiment 1 — Remote SSH discovery evaluation (initially deferred) Superseded on 2026-07-02 after Phase 2 matured and the user promoted SSH to required scope.
2026-07-01 Experiment 2 — List virtualization evaluation (not needed) Tree cap is 500 entries. GPUI renders thousands of elements eagerly without issue. No demonstrated benefit.
2026-07-01 Experiment 3 — Config UI settings overlay (initial implementation) Initially used IFileOpenDialog; Phase 3 retained depth/save behavior but replaced the picker with the custom local/SSH browser.
2026-07-01 Add Win32_System_Com to Windows dependency features Historical COM picker requirement; removed from the manifest on 2026-07-02.
2026-07-01 Add pick_folder and window_hwnd_raw to platform.rs Historical native-picker bridge; both functions were removed on 2026-07-02.
2026-07-01 Add settings overlay with folder picker, depth controls, save/rescan The overlay remains; its blocking native picker was replaced by asynchronous custom local/SSH directory listing.
2026-07-01 Note: on_click and overflow_y_scroll are on StatefulInteractiveElement These methods require Stateful<Div> (obtained via .id()). Bare Div does not provide them. Documented for future GPUI work.
2026-07-01 Adopt gpui-component 0.5.1 for Phase 2 text surfaces Its GPUI 0.2.2-compatible virtualized Markdown view and rope-backed editor directly address measured scrolling, selection, wrapping, and rendering failures. The broader component library is not adopted as the application design system.
2026-07-01 Enable gpui-component/tree-sitter-languages Maintained syntax parsing is worth the larger compile graph for the document viewer; this replaces the failed custom lexical highlighter.
2026-07-02 Promote SSH parity into Remediation Phase 3 SSH discovery and workbench access are staple DevHub capabilities; the user explicitly accepted the implementation complexity.
2026-07-02 Use the installed OpenSSH client with POSIX scripts Reuses SSH config, agents, keys, proxies, and host-key policy without embedding credentials or adding a second SSH stack.
2026-07-02 Replace the native local picker with one custom local/SSH picker One source workflow can navigate Windows drives and remote directories while making the configured provider explicit.
2026-07-02 Keep SSH transport in devhub-core/src/remote.rs UI state remains transport-agnostic; process limits, validation, scripts, parsing, and deadlines have one testable owner.
2026-07-02 Open remote projects through VS Code Remote SSH initially (superseded) Historical Phase 3 choice replaced by the Zed-first product decision later on 2026-07-02.
2026-07-02 Raise inherited text weight to medium Improves legibility without increasing the compact geometry; structural labels use semibold for hierarchy.
2026-07-02 Use gpui-component icons in the file tree SVG chevrons, open/closed folders, and recognizable file categories are clearer than font-dependent geometric glyphs.
2026-07-02 Enable README raster and SVG web images GPUI 0.2.2 and TextView already decode both; repository-relative paths are rewritten through recognized GitHub/GitLab raw URLs.
2026-07-02 Add gpui-component-assets 0.5.1 Native review exposed that IconName provides paths, not files; the published matching asset bundle supplies the required Lucide SVGs.
2026-07-02 Install a bounded reqwest-backed GPUI HTTP client Application::new() defaults to NullHttpClient; a one-worker client with 10s connect, 30s total, and 12 MiB response limits makes README images operational.
2026-07-02 Embed appicon.svg in assets and Windows resource ID 1 Displays the supplied icon in client chrome and lets GPUI load the native taskbar/window icon from the executable.
2026-07-02 Bypass GPUI's Windows zoom_window() for restore GPUI 0.2.2 always calls SW_MAXIMIZE; the isolated platform fallback checks IsZoomed and selects SW_RESTORE or SW_MAXIMIZE.
2026-07-02 Revert network-backed README images README images are decorative and inconsistent in GPUI Component; deterministic alt-text placeholders preserve offline local/SSH inspection and avoid third-party requests. The app HTTP client, Tokio runtime, URL rewriting, and badge extraction were removed.
2026-07-02 Make DevHub a Zed-first project hub Both local paths and documented Zed SSH URLs open through zed; the native application chooser remains a secondary best-effort path rather than maintaining editor profiles.
2026-07-02 Persist legacy theme and appearance choices Five DevHub palettes and System/Dark/Light modes are small serializable preferences; Monochrome Dark remains the migration-safe default for existing visual direction.
2026-07-02 Keep independent SSH scan depth RemoteHostConfig.max_depth is now edited per host and is no longer overwritten by the local/global depth on save.
2026-07-02 Defer source toggles, FTUE, and Explorer opening A single-host workflow does not justify temporary-disable state or another onboarding layer; Explorer cannot represent SSH paths without an external filesystem mapping.
2026-07-02 Ship v1.0.0 as the first standalone tagged release Cross-platform Windows/Linux/macOS archives and SHA-256 checksums attached to the GitHub release; release workflow verified via github-actions[bot]; user confirmed native Windows validation of the shipped binary.
2026-07-02 Coexistence over cutover The egui devhub and GPUI devhub-gpui coexist as separate products. No identity rename, no config migration, no archival of devhub. Internal names stay as-is. The website will present GPUI as the primary "DevHub" and egui as a "Legacy" download.
2026-07-02 Grant a writable exception for [REDACTED]\devhub\web The Astro marketing site lives in the read-only egui repo. Website updates require editing it in place. The exception is scoped to web/ only; egui Rust source remains read-only.
2026-07-02 Retire prompt.md; consolidate into ADR.md prompt.md duplicated plan content and had gone stale (missing gpui-component, listed main.rs as the large file). Unique content (visual direction, chrome fallback inventory, validation gate, GPUI concepts exercised) merged into ADR.md.

Versions to record during Phase 1:

Item Selected version Notes
Rust toolchain 1.93.1 stable-x86_64-pc-windows-msvc
Cargo 1.93.1 Generated a 688-package cross-platform lockfile
create-gpui-app 0.1.5 Workspace shape retained; moving Git dependency replaced
gpui 0.2.2 Published crates.io release recorded in Cargo.lock
gpui_platform Not selected Not published separately on crates.io at this checkpoint

Source-reuse ledger

New destination DevHub source Adaptations Tests added
crates/devhub-core/src/discovery.rs [REDACTED]\devhub\src\discovery\scanner.rs local subset Removed egui/serde/tracing/anyhow/SSH/status coupling; Rust 2021 conditions; suppressed synthetic parent after child discovery; added Serialize/Deserialize derives for cache round-trip Four isolated filesystem tests
crates/devhub-core/src/config.rs [REDACTED]\devhub\src\config.rs Distinct "devhub-gpui" identity; retained only local/SSH source fields; normalized and merged remote hosts without migrating legacy data Six config tests
crates/devhub-core/src/cache.rs [REDACTED]\devhub\src\cache.rs Start at version 1 (distinct from egui v4); Option-returning API; no anyhow dependency Two cache tests (round-trip, wrong-version rejection)
crates/devhub-gpui/src/main.rs fixture construction Previous local UI-only fixture struct Uses shared Project, ProjectSource, and ProjectType; loads config/cache on startup; scans configured roots Covered by workspace compile/clippy; visual structure unchanged
crates/devhub-gpui/src/platform.rs (open_with_picker) Windows SHOpenWithDialog API Isolated in platform.rs; runs on background thread; HWND passed as isize for Send safety Covered by workspace compile/clippy
crates/devhub-core/src/remote.rs [REDACTED]\devhub\src\workspace.rs and discovery/scanner.rs Rebuilt around validated targets, hard deadlines, bounded output, hierarchy preservation, partial scan errors, strict UTF-8/binary handling, and no anyhow Five parser, validation, quoting, and hierarchy tests
crates/devhub-gpui/src/app.rs source picker [REDACTED]\devhub\src\app.rs picker behavior Reimplemented in GPUI as one custom local-drive and SSH-directory browser; removed the Windows COM folder picker Covered by core picker-operation tests and workspace compile

Functional parity matrix

Capability Status Notes
Local and SSH discovery Complete Explicit background scan, partial failures, stale-result rejection
Configurable local/SSH roots Complete Unified custom picker and crash-safe persistence
Local and per-host scan depth Complete Independent values from 1 through 20
Versioned configuration Complete Unversioned/v0 migrates atomically to v1; future versions are read/write protected
Versioned project cache Complete Separate devhub-gpui identity
Project filtering and keyboard navigation Complete Includes automatic list scrolling
Local/SSH tree, read, README, and search Complete Bounded operations; README images remain offline placeholders
Zed local and SSH opening Complete User-confirmed native behavior for zed <path> and zed ssh://… targets
Native OPEN IN… fallback Complete User-confirmed; remote apps must understand ssh://
Project metadata Complete Source, host, Git remote, markers, modified time
Legacy themes and appearance Complete Five palettes; System/Dark/Light
First-time user experience Complete No config and no cache opens Settings; no production fixtures

Known issues and open questions

  • cl.exe and link.exe are not exposed on the ordinary PowerShell PATH, but Cargo successfully discovered the installed MSVC toolchain during compilation.
  • gpui 0.2.2 failed to discover fxc.exe because its build script's hard-coded fallback expects Windows SDK 10.0.26100.0. This machine has the required x64 compiler at [Windows_SDK]\bin\10.0.19041.0\x64\fxc.exe. Set GPUI_FXC_PATH to that file in the build shell. Keep this machine-specific path out of committed Cargo configuration.
  • A normal cargo run can succeed in a fresh shell after GPUI's shaders have already been built and cached. A clean build may still require GPUI_FXC_PATH; cached success does not prove global SDK discovery is fixed.
  • Sandboxed Cargo registry access failed with a Windows Schannel credential error; approved external network access resolved dependency metadata and the lockfile. This is an execution-environment restriction, not yet a project bug.
  • create-gpui-app 0.1.5 generates a moving Zed Git dependency. The scaffold was deliberately changed to the published gpui 0.2.2 API and lockfile.
  • Rustc overflowed its stack when the native GPUI binary contained unit tests. Pure scan-state tests now live in the package library and the binary declares test = false; all-target checking and clippy still compile the binary.
  • Native interaction and visual behavior remain user-observed phase gates; a successful static build does not certify text hit testing or scroll behavior.
  • SSH hosts currently require a POSIX sh environment and GNU-compatible find, grep, stat, wc, and head. Native Windows PowerShell-only SSH servers and SFTP transport are not implemented.
  • Authentication must already work non-interactively through OpenSSH config, keys, or an agent. DevHub does not collect passwords or key passphrases. New host keys should be reviewed and accepted in a terminal before using the app.
  • Remote ignore files are not interpreted. Remote discovery/search prune known generated directories but do not yet match local ignore crate semantics.
  • Running SSH subprocesses are bounded by deadlines and stale results are discarded, but there is no user-facing button that kills an in-flight command.
  • Zed must be installed and its zed command available, or installed in a known Windows location, for the primary launch action. The current machine resolves zed to [REDACTED]\Zed.exe.
  • Windows OPEN IN… can pass an SSH URI to a selected application, but the selected application must understand ssh://; this is not generic remote filesystem mounting.
  • README preview deliberately does not load images. Markdown and HTML images show explicit alt-text placeholders, image syntax inside code is preserved, and linked-image destinations remain clickable. Offline local/SSH asset loading is not implemented.

Next action

The v1.0.0 standalone release is shipped and verified. The immediate task is the website update in [REDACTED]\devhub\web:

  1. Repoint primary release/badge/chart fetches from ujjwalvivek/devhub to ujjwalvivek/devhub-gpui (Downloads.svelte, Hero.svelte, Footer.svelte).
  2. Add a "Legacy (egui)" download section fetching from ujjwalvivek/devhub.
  3. Rewrite the egui subtitle/copy in Hero.svelte for the GPUI framing; remove the telemetry claim (the GPUI app has none).
  4. Replace hardcoded SIZES in Downloads.svelte with a.size from the API so future releases display correct byte counts without site edits.
  5. Swap egui screenshots for GPUI screenshots once the user captures them.

Parity work (in-flight SSH/scan cancellation, remote .gitignore semantics) is deferred until after the website is up to date, targeted at v1.1.0.