Files
1jehuang--jcode/docs/DESKTOP_SUPERAPP_WORKSPACE.md
T
wehub-resource-sync a789495a98
FreeBSD Smoke / FreeBSD Smoke (x86_64) (push) Has been cancelled
CI / Quality Guardrails (push) Has been cancelled
CI / Build & Test (macos-latest) (push) Has been cancelled
CI / Build & Test (ubuntu-latest) (push) Has been cancelled
CI / Build & Test (windows-latest) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / PowerShell Syntax (push) Has been cancelled
CI / Windows Cross-Target Check (Linux) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:34 +08:00

14 KiB

Desktop Superapp Workspace Direction

Status: Proposed Updated: 2026-04-25

This document refines the Jcode Desktop product direction from a single chat-like app into a Niri-like agent workspace superapp.

The app should eventually host multiple kinds of surfaces:

  • agent sessions
  • task/activity views
  • code/file surfaces
  • diffs
  • terminals or command output surfaces
  • settings/auth/tools/debug surfaces

The goal is not to clone a general-purpose window manager. The goal is to give Jcode users a fast, keyboard-driven, spatial environment for supervising multiple agent sessions and related development tools inside one custom desktop app.

See also:

Product thesis

Jcode Desktop should be a local AI development superapp:

one native app
  many sessions
  many surfaces
  fast spatial navigation
  strong keyboard workflow
  agent-first activity visibility
  custom rendering and layout

The key UX is closer to:

  • Niri / scrollable tiling workspace
  • Vim-like keyboard navigation
  • command palette
  • agent mission control

And less like:

  • a single chat window
  • a conventional IDE clone
  • a web-app shell
  • a generic desktop window manager

Why Niri-like

Niri's useful idea for Jcode is not the compositor implementation. It is the mental model:

  • surfaces are arranged spatially
  • focus moves predictably
  • users navigate with keyboard-first commands
  • new work appears in a structured place
  • layout is persistent enough to build muscle memory
  • many parallel tasks can be monitored without losing context

Jcode Desktop can bring that workflow to macOS users who do not have a Niri-like environment, while still working well on Linux.

Workspace model

The desktop app should be built around these concepts:

Workspace
  -> Rows / Workspaces / Lanes
    -> Columns
      -> Surfaces

Terminology can be adjusted, but the core model should support:

  • multiple agent sessions visible or quickly reachable
  • spatial navigation with h/j/k/l-style movement
  • opening related surfaces next to a session
  • moving surfaces between columns/lanes
  • zooming/focusing one surface temporarily
  • preserving layout per project/workspace

Suggested initial terms:

Term Meaning
Workspace A project/repo-level desktop environment
Lane A vertical grouping or Niri-like workspace row
Column A horizontal focus/navigation unit
Surface A visible app panel: session, file/code view, diff, activity, settings, debug, etc.
Session surface A surface attached to a server-owned Jcode session
Tool surface File/code/diff/activity/settings/debug/etc.

Surface types

The app should be architected around a generic surface registry from the start.

enum SurfaceKind {
    AgentSession,
    Activity,
    WorkspaceFiles,
    CodeView,
    Diff,
    TerminalOutput,
    Settings,
    Debug,
    Extension,
}

A surface should have:

struct SurfaceState {
    id: SurfaceId,
    kind: SurfaceKind,
    title: String,
    workspace_id: WorkspaceId,
    lane_id: LaneId,
    column_id: ColumnId,
    focus_state: FocusState,
    local_state: SurfaceLocalState,
}

The surface model should be independent from the renderer so it can support:

  • one window with many surfaces
  • multiple windows later
  • pop-out surfaces later
  • session surfaces and non-session utility surfaces using the same navigation model

Agent sessions as first-class surfaces

An agent session should be one surface type, not the whole app.

AgentSessionSurface
  - transcript timeline
  - composer
  - inline tool cards
  - session status
  - session-local queue/interrupts

This allows layouts like:

[Session A] [Session B] [Diff     ]
[Activity ] [Files    ] [CodeView ]

Or:

Lane 1: main task
  Column 1: coordinator session
  Column 2: implementation agent session
  Column 3: diff/editor

Lane 2: review
  Column 1: changed files
  Column 2: notes/session

Navigation model

The app should have a modal/command-oriented keyboard model inspired by Vim, but adapted for macOS and desktop expectations.

Important macOS constraint

Do not rely on plain Cmd+H for left navigation.

On macOS:

  • Cmd+H hides the app
  • Cmd+M minimizes
  • Cmd+Q quits
  • Cmd+W closes the current window/surface depending on app convention
  • Cmd+, opens settings

Overriding these will make the app feel hostile to Mac users.

Use one or both of these:

  1. Leader/command mode

    • Press a leader key, then h/j/k/l.
    • Example: Space h, Space j, Space k, Space l when focus is not in text input.
    • Or Cmd+K h/j/k/l as a command chord.
  2. Direct advanced shortcuts

    • Cmd+Option+H/J/K/L for focus movement on macOS.
    • Ctrl+Alt+H/J/K/L or Super+Alt+H/J/K/L on Linux.

The leader model is safer because it avoids macOS reserved shortcuts and works well with Vim muscle memory.

Suggested initial keymap

Focus movement:
  leader h      focus left
  leader j      focus down / next lane
  leader k      focus up / previous lane
  leader l      focus right

Surface movement:
  leader H      move surface left
  leader J      move surface down
  leader K      move surface up
  leader L      move surface right

Workspace/session:
  leader n      new agent session
  leader s      session switcher
  leader a      activity center
  leader e      editor/files surface
  leader d      diff surface
  leader /      command palette
  leader z      zoom focused surface
  leader x      close focused surface

Agent control:
  leader Enter  focus composer / submit depending mode
  leader Esc    cancel/stop focused agent run, with confirmation if risky

The exact leader key should be configurable. Reasonable defaults:

  • Space when focus is not in a text input
  • Cmd+K as a universal command chord
  • Ctrl+Space as an alternate for users who prefer explicit mode entry

Input modes

The app should distinguish between navigation mode and text-entry mode.

Navigation mode
  - hjkl controls focus/layout
  - keys trigger commands
  - typing can open command palette or focused composer depending setting

Text-entry mode
  - keys edit composer/editor/input
  - Escape returns to navigation mode
  - platform shortcuts still work: copy/paste/select all

This is critical once the app has text-entry surfaces. Without explicit input modes, global Vim-like keys will conflict with text entry.

Layout behavior

The first implementation does not need full Niri behavior. It should start with a simpler model that can evolve.

MVP layout

single app window
  left sidebar: workspaces/sessions
  central surface grid: columns with focused surface
  right activity/inspector panel optional

MVP navigation:

  • focus next/previous surface
  • move focus left/right between columns
  • open new session to the right
  • close surface
  • zoom focused surface
  • activity panel toggle

Later layout

Niri-like scrollable layout:

  • horizontal columns per lane
  • vertical lane/workspace movement
  • smooth animated focus movement
  • persistent surface positions
  • per-workspace layout restoration
  • drag surfaces with mouse, but keyboard remains primary
  • pop-out surface into native window
  • dock pop-out surface back into workspace

Surface lifecycle

Surface commands should be consistent across surface kinds.

new-surface(kind)
close-surface(id)
focus-surface(direction)
move-surface(direction)
zoom-surface(id)
split-surface(kind, direction)
pop-out-surface(id)
dock-surface(id)

Agent session-specific commands become specialized actions on an AgentSession surface:

send-message
cancel-run
soft-interrupt
background-tool
resume-session
fork-session

Non-session surfaces can add specialized commands later without changing generic surface lifecycle commands.

Optional future surfaces

Do not preplan any large embedded app right now. The workspace model should stay generic enough to host future surface kinds, but the implementation plan should focus on agent sessions, activity, files, diffs, and command routing.

If a major embedded surface is considered later, it should go through its own design decision rather than being assumed by the initial desktop architecture.

Built-in code editor direction

A built-in editor is a large system and should remain optional until the workspace/session workflow is strong.

Suggested levels:

Level 1: file viewer and external editor

MVP-friendly:

  • file tree / changed files
  • read-only file preview
  • open in external editor
  • open diff externally
  • copy paths/snippets

Level 2: lightweight code viewer/diff editor

Useful and realistic:

  • syntax-highlighted file view
  • search within file
  • inline diff viewer
  • accept/reject generated changes later
  • simple text selection/copy

Level 3: real code editor

Large but possible later:

  • rope text buffer
  • multi-cursor maybe
  • undo/redo
  • syntax highlighting
  • LSP integration
  • diagnostics
  • completion
  • file save/reload conflict handling
  • large-file performance

Recommendation

Start with Level 1, then Level 2. Do not build a full editor before the agent workspace, transcript, activity, and diff workflow are excellent.

The architecture should support file/code surfaces generically, but should not commit to a full editor implementation early.

Activity as a persistent surface

For a superapp, activity should not be just a small panel.

Activity should be a surface type that can be:

  • pinned to the side
  • opened as a full surface
  • filtered by workspace/session/tool type
  • navigated with the same surface commands
  • used to jump to the relevant session/tool output

This is important because Jcode users may run many agents/tasks concurrently.

Command palette as the universal router

The command palette should be the universal way to access everything:

  • sessions
  • surfaces
  • files
  • commands
  • settings
  • tools
  • files and code views
  • background tasks
  • debug views

It should be backed by a shared command registry in jcode-client-core, not hardcoded separately per UI.

Data model additions

jcode-client-core should include a workspace layout state model:

struct WorkspaceLayoutState {
    workspaces: Vec<WorkspaceNode>,
    active_workspace: WorkspaceId,
    active_surface: Option<SurfaceId>,
}

struct WorkspaceNode {
    id: WorkspaceId,
    name: String,
    lanes: Vec<LaneNode>,
}

struct LaneNode {
    id: LaneId,
    columns: Vec<ColumnNode>,
}

struct ColumnNode {
    id: ColumnId,
    surfaces: Vec<SurfaceId>,
    active_surface_index: usize,
}

Surface-local data should be separated by kind:

enum SurfaceLocalState {
    AgentSession(AgentSessionSurfaceState),
    Activity(ActivitySurfaceState),
    WorkspaceFiles(WorkspaceFilesSurfaceState),
    CodeView(CodeViewSurfaceState),
    Diff(DiffSurfaceState),
    TerminalOutput(TerminalOutputSurfaceState),
    Settings(SettingsSurfaceState),
    Debug(DebugSurfaceState),
    Extension(ExtensionSurfaceState),
}

This preserves the core rule:

A session is server-owned runtime state. A surface is client-owned UI state.

Renderer implications

A Niri-like superapp increases the importance of the custom UI engine.

The UI engine must support:

  • nested split/column/lane layout
  • animated or smooth focus movement later
  • virtualized surfaces
  • focus rings and active-surface indicators
  • surface chrome/title bars that do not waste space
  • zoom/focus mode
  • drag-to-rearrange later
  • stable IDs for accessibility/debugging
  • cheap offscreen/inactive surface representation

Do not keep every surface fully rendered at all times. Inactive surfaces should keep state but avoid expensive layout/text/render work unless visible or prewarmed.

Suggested first superapp milestone

Update the earlier fake-data desktop prototype to prove the superapp model, not only one transcript.

Milestone: fake-data spatial workspace

Success criteria:

  • one native window on Linux
  • custom wgpu rendering
  • workspace layout with multiple fake agent session surfaces
  • focus movement with leader + h/j/k/l
  • open/close/move/zoom fake surfaces
  • activity surface with fake running tasks
  • command palette can create session/activity/file/diff/debug placeholder surfaces
  • transcript surfaces are virtualized independently
  • debug HUD shows per-surface layout/render stats
  • idle CPU remains near zero

Optional non-session surfaces can be placeholders at this stage. The important part is proving that the workspace model can host multiple surface kinds without committing to specific future apps.

Product guardrails

Because “superapp” can explode in scope, keep these guardrails:

  1. Agent sessions and activity are the core product.
  2. Non-session surfaces are supporting tools, not the first milestone.
  3. External integrations should come before embedded implementations.
  4. Keyboard navigation must work before mouse drag layout polish.
  5. Surface architecture must be generic from day one.
  6. Do not build large embedded apps before diff/review workflows are excellent.
  7. Keep the server as the source of truth for sessions and agents.

Summary decision

Jcode Desktop should become a keyboard-driven, Niri-like agent workspace superapp.

The initial desktop app should prove:

  • many session surfaces
  • spatial navigation
  • generic surface lifecycle
  • command palette routing
  • activity visibility
  • performance under multiple visible surfaces

Then additional file/diff/tool surfaces can be added without changing the fundamental app model.