move python clide to legacy/

Clide is being rebuilt as a Flutter desktop app. The Python Textual
implementation moves wholesale into legacy/ rather than being deleted:
its pane model, panel set, git skills, and panel communication design
are real thought that should remain readable next to the new code
while the rebuild finds its shape. Git's rename tracking preserves
history, so `git log -- legacy/` still works.

The Flutter rebuild lives at the repo root alongside a Go sidecar
(the architecture claudian was heading toward, which folds into
clide as a core component rather than a separate plugin project).
Bootstrap of the new shape lands in subsequent commits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-20 20:30:51 +02:00
co-authored by Claude Opus 4.7
parent 30b8cf7db9
commit a355751437
163 changed files with 0 additions and 0 deletions
-432
View File
@@ -1,432 +0,0 @@
# Clide Architecture
Technical documentation covering Clide's architecture, the frameworks it builds on, and implementation patterns.
## Table of Contents
- [Application Architecture](#application-architecture)
- [Textual TUI Framework](#textual-tui-framework)
- [Pydantic Data Validation](#pydantic-data-validation)
- [Extension System](#extension-system)
- [Testing Strategy](#testing-strategy)
- [Build and Distribution](#build-and-distribution)
---
## Application Architecture
Clide follows a layered architecture with clear separation between UI, business logic, and data.
### Layer Overview
```
┌─────────────────────────────────────────────────────────┐
│ ClideApp (app.py) │
│ Main application, layout, keybindings │
├─────────────────────────────────────────────────────────┤
│ Widgets Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Panels │ │ Components │ │ Themes │ │
│ │ (layout) │ │ (reusable) │ │ (styling) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Controllers Layer │
│ Business logic, state management │
├─────────────────────────────────────────────────────────┤
│ Services Layer │
│ Git, files, scanning, settings, skills │
├─────────────────────────────────────────────────────────┤
│ Models Layer │
│ Pydantic data structures │
└─────────────────────────────────────────────────────────┘
```
### Data Flow
```
User Action (click, keypress)
Widget Event
Message Bubbles Up
App Event Handler
Controller Method
Service Call
Return Data/Status
Update UI State
Reactive UI Update
```
### Key Patterns
**Message-based communication** — Widgets emit messages that bubble up. Parent widgets or the app handle messages and coordinate responses.
**Reactive properties** — UI state uses Textual's `reactive` type. Changes automatically trigger `watch_*` methods.
**Background workers** — Long operations use `@work(thread=True)` to avoid blocking the UI.
**State preservation** — Hiding panels uses `display: none`, never destroying widgets. All state persists.
For detailed code organization, see [Code Organization](code-organization.md).
---
## Textual TUI Framework
Textual provides the foundation for Clide's terminal UI.
### Core Concepts
**Widgets** — Building blocks of the UI. Everything visible is a widget.
**Containers** — Widgets that hold other widgets (Vertical, Horizontal, Container).
**Reactive Programming** — State changes trigger automatic UI updates.
**CSS Styling** — Layout and appearance defined in CSS, similar to web development.
### Layout System
Clide uses CSS Grid for the main layout:
```css
Screen {
layout: grid;
grid-size: 3 1;
grid-columns: 20% 1fr 25%;
}
```
Panels use percentage widths with minimum sizes:
```css
#panel-sidebar {
width: 20%;
min-width: 25;
}
```
### Widget Lifecycle
```python
class MyWidget(Widget):
def __init__(self):
super().__init__()
# Initialize instance variables
def compose(self) -> ComposeResult:
# Yield child widgets
yield Label("Hello")
def on_mount(self) -> None:
# Called after widget is added to DOM
# Safe to query other widgets here
def on_unmount(self) -> None:
# Cleanup when removed
```
### Event Handling
Events bubble up through the widget tree:
```python
# Define a message
class FileSelected(Message):
def __init__(self, path: Path):
self.path = path
super().__init__()
# Emit the message
self.post_message(self.FileSelected(path))
# Handle in parent (naming convention: on_<widget>_<message>)
def on_files_view_file_selected(self, event: FilesView.FileSelected):
self.open_file(event.path)
```
### Background Tasks
Use `@work` for operations that shouldn't block the UI:
```python
from textual import work
@work(thread=True)
def fetch_data(self) -> dict:
"""Runs in thread pool."""
result = expensive_operation()
return result
def on_worker_state_changed(self, event: Worker.StateChanged) -> None:
if event.state == WorkerState.SUCCESS:
self.update_ui(event.worker.result)
```
### References
- [Textual Documentation](https://textual.textualize.io/)
- [Textual Widgets](https://textual.textualize.io/widgets/)
- [Textual CSS](https://textual.textualize.io/guide/CSS/)
---
## Pydantic Data Validation
All data models use Pydantic v2 with strict mode.
### Model Configuration
```python
from pydantic import BaseModel, ConfigDict
class GitChange(BaseModel):
model_config = ConfigDict(strict=True, frozen=True)
path: str
status: Literal["added", "modified", "deleted"]
staged: bool
```
**strict=True** — No type coercion. `"123"` won't become `123`.
**frozen=True** — Immutable instances. Enables hashing for use as dict keys.
### Settings Management
Application settings use `pydantic-settings`:
```python
from pydantic_settings import BaseSettings, SettingsConfigDict
class ClideSettings(BaseSettings):
model_config = SettingsConfigDict(
env_prefix="CLIDE_",
env_file=".env",
)
theme: str = "summer-night"
jira_enabled: bool = False
```
Settings load from (in priority order):
1. Environment variables (`CLIDE_THEME=dracula`)
2. `.env` file
3. Default values
### References
- [Pydantic Documentation](https://docs.pydantic.dev/latest/)
- [Pydantic Settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)
---
## Extension System
Clide uses Pluggy for hook-based extensibility.
### Hook Specifications
Hooks define extension points:
```python
# clide/extensions/hookspecs.py
import pluggy
hookspec = pluggy.HookspecMarker("clide")
hookimpl = pluggy.HookimplMarker("clide")
class ClideHookSpec:
@hookspec
def clide_startup(self, app: App) -> None:
"""Called when the app starts."""
@hookspec
def clide_on_file_changed(self, event: FileEvent) -> None:
"""Called when a file changes."""
```
### Implementing Hooks
Extensions implement hooks with the `@hookimpl` decorator:
```python
from clide.extensions import hookimpl
class MyExtension:
@hookimpl
def clide_startup(self, app: App) -> None:
app.notify("Extension loaded!")
@hookimpl
def clide_on_file_changed(self, event: FileEvent) -> None:
if event.path.suffix == ".py":
# React to Python file changes
pass
```
### Distribution
Extensions can be packaged and distributed via entry points:
```toml
# pyproject.toml of extension package
[project.entry-points."clide.extensions"]
my_extension = "my_package:MyExtension"
```
### Available Hooks
| Hook | When Called |
|------|-------------|
| `clide_startup` | App initialization |
| `clide_shutdown` | App cleanup |
| `clide_on_file_changed` | File created/modified/deleted |
| `clide_on_file_saved` | File saved in editor |
### References
- [Pluggy Documentation](https://pluggy.readthedocs.io/)
---
## Testing Strategy
### Test Organization
```
tests/
├── unit/ # Isolated component tests
├── integration/ # Component interaction tests
└── snapshots/ # Visual regression tests
```
### Async Testing
Configure pytest-asyncio in auto mode:
```toml
[tool.pytest.ini_options]
asyncio_mode = "auto"
```
Tests can be async without decorators:
```python
async def test_async_operation():
result = await some_async_function()
assert result == expected
```
### Snapshot Testing
Visual regression testing with pytest-textual-snapshot:
```python
def test_layout(snap_compare):
assert snap_compare(ClideApp(), terminal_size=(120, 40))
def test_with_interaction(snap_compare):
async def setup(pilot):
await pilot.press("tab", "enter")
assert snap_compare(ClideApp(), run_before=setup)
```
Update snapshots after intentional changes:
```bash
pytest tests/snapshots/ --snapshot-update
```
### Mocking
Use `AsyncMock` for async dependencies:
```python
from unittest.mock import AsyncMock
async def test_with_mock():
mock_service = AsyncMock(return_value={"status": "ok"})
result = await mock_service()
assert result["status"] == "ok"
```
### References
- [pytest-asyncio](https://pytest-asyncio.readthedocs.io/)
- [pytest-textual-snapshot](https://github.com/Textualize/pytest-textual-snapshot)
- [Textual Testing Guide](https://textual.textualize.io/guide/testing/)
---
## Build and Distribution
### Development
```bash
make setup # Create venv, install deps
make run # Run application
make test # Run all tests
make typecheck # Run mypy
make lint # Run ruff
make format # Format code
```
### PyInstaller
Build standalone executables:
```bash
pip install -e ".[build]"
pyinstaller clide.spec --clean
```
**Important**: PyInstaller cannot cross-compile. Build on each target platform.
### CI/CD
Multi-platform builds via Gitea Actions:
```yaml
jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: pip install -e ".[build]"
- run: pyinstaller clide.spec --clean
build-macos:
runs-on: macos-latest
# ... same steps
```
### Optimization
- Use `--onefile` for single executable
- Apply `--strip` to reduce size
- Use UPX compression for further reduction
- Exclude unused modules with `--exclude-module`
### References
- [PyInstaller Documentation](https://pyinstaller.org/)
- [Gitea Actions](https://docs.gitea.com/usage/actions/overview)
-342
View File
@@ -1,342 +0,0 @@
# Code Organization
Clide follows a layered architecture separating UI components from business logic, enabling testability and maintainability.
## Directory Structure
```
clide/
├── app.py # Main application, layout, keybindings
├── cli.py # Typer entry point
├── models/ # Pydantic data models
├── services/ # Background services and utilities
├── controllers/ # Business logic (no UI)
├── widgets/
│ ├── panels/ # Main layout containers
│ └── components/ # Reusable UI pieces
├── themes/ # Theme definitions and registry
├── extensions/ # Plugin system (hookspecs, manager)
├── templates/ # Bundled templates (skills, etc.)
└── vendor/ # Vendored dependencies (pyte)
```
## Layers
### Models (`clide/models/`)
Pure data structures using Pydantic with strict mode. Models are immutable and contain no business logic.
```python
from pydantic import BaseModel, ConfigDict
class GitChange(BaseModel):
model_config = ConfigDict(strict=True, frozen=True)
path: str
status: Literal["added", "modified", "deleted", "untracked", "renamed"]
staged: bool
```
**Key models:**
- `git.py` — Git-related types (GitBranch, GitCommit, GitChange, GitStatus)
- `config.py` — Application settings (ClideSettings, PanelConfig)
- `problems.py` — Linter output (Problem, Severity)
- `todos.py` — TODO items (TodoItem, ProjectTodoItem, TodoType)
### Services (`clide/services/`)
Stateless utilities that perform work without UI interaction. Services may be async or use background threads.
```python
class GitService:
"""Git operations via subprocess."""
def __init__(self, workdir: Path):
self._workdir = workdir
async def get_status(self) -> GitStatus:
"""Get current repository status."""
...
async def get_branches(self) -> list[GitBranch]:
"""List all branches."""
...
```
**Key services:**
- `git_service.py` — Git CLI operations
- `file_service.py` — File read/write operations
- `todo_scanner.py` — Scans codebase for TODO/FIXME comments
- `settings_service.py` — User settings persistence
- `skill_installer.py` — Claude Code skill management
- `file_watcher.py` — File system change monitoring
- `syntax_service.py` — Tree-sitter syntax highlighting
### Controllers (`clide/controllers/`)
Bridge between services and UI. Controllers contain business logic, manage state, and emit Textual messages. Controllers have no direct UI rendering.
```python
from clide.controllers.base import controller
@controller
class GitController:
"""Manages git state and operations."""
def __init__(self, workdir: Path):
self._service = GitService(workdir)
self._status: GitStatus | None = None
async def refresh_status(self) -> GitStatus:
"""Refresh and cache git status."""
self._status = await self._service.get_status()
return self._status
def stage_file(self, path: str) -> None:
"""Stage a file for commit."""
...
```
**Key controllers:**
- `git.py` — Git operations, skill integration
- `editor.py` — File editing state
- `diff.py` — Diff viewing and management
- `problems.py` — Linter integration
- `todos.py` — TODO tracking
- `jira.py` — Jira CLI integration
### Widgets (`clide/widgets/`)
UI components split into panels (layout containers) and components (reusable pieces).
#### Panels (`clide/widgets/panels/`)
Top-level layout containers that compose the application UI.
```python
class SidebarPanel(Vertical):
"""Left sidebar with Files, Git, and Tree tabs."""
class FileSelected(Message):
"""Emitted when a file is selected."""
def __init__(self, path: Path):
self.path = path
super().__init__()
def compose(self) -> ComposeResult:
with TabbedContent():
with TabPane("Files"):
yield FilesView(path=self._workdir)
with TabPane("Git"):
yield GitChangesView()
with TabPane("Tree"):
yield GitGraphView()
yield BranchStatus()
```
**Panels:**
- `sidebar.py` — Left sidebar (files, git, graph)
- `context.py` — Right sidebar (problems, todos, jira)
- `workspace.py` — Center workspace (editor, diff, terminal)
- `claude.py` — Claude Code terminal integration
#### Components (`clide/widgets/components/`)
Reusable UI pieces composed into panels.
**File browsing:**
- `files_view.py` — Project file tree
- `file_entry.py` — Single file/directory entry
**Git:**
- `git_changes.py` — Staged/unstaged file lists
- `git_graph.py` — Visual branch graph
- `branch_status.py` — Branch indicator with popout selector
**Context:**
- `problems_view.py` — Linter problems list
- `todos_view.py` — TODO/FIXME list with sub-tabs
- `jira_view.py` — Jira issue display
**Editor:**
- `editor_pane.py` — Code editor with syntax highlighting
- `diff_pane.py` — Side-by-side diff viewer
- `terminal_pane.py` — Command execution terminal
## Communication Patterns
### Message Flow
Components communicate via Textual's message system. Messages bubble up through the widget tree.
```
Component emits message
Parent panel receives and may re-emit
App handles and coordinates response
App calls controller methods
Controller updates state, may emit messages
UI updates reactively
```
**Example: File selection**
```python
# In FilesView (component)
class FileSelected(Message):
def __init__(self, path: Path):
self.path = path
super().__init__()
def on_tree_node_selected(self, event):
if event.node.data.is_file:
self.post_message(self.FileSelected(event.node.data.path))
# In SidebarPanel (panel)
def on_files_view_file_selected(self, event: FilesView.FileSelected):
# Re-emit for app to handle
self.post_message(self.FileSelected(event.path))
# In ClideApp (app)
def on_sidebar_panel_file_selected(self, event: SidebarPanel.FileSelected):
self.editor_controller.open_file(event.path)
self.show_workspace("editor")
```
### Reactive Properties
State that affects UI uses Textual's reactive system:
```python
class ClideApp(App):
# Reactive state
workspace_visible: reactive[bool] = reactive(False)
problem_count: reactive[int] = reactive(0)
current_branch: reactive[str] = reactive("main")
def watch_workspace_visible(self, visible: bool) -> None:
"""React to workspace visibility changes."""
workspace = self.query_one("#panel-workspace")
workspace.display = visible
claude = self.query_one("#panel-claude")
claude.styles.height = "40%" if visible else "100%"
```
### Background Tasks
Long-running operations use the `@work` decorator to avoid blocking the UI:
```python
from textual import work
class ClideApp(App):
@work(thread=True)
def refresh_git_status(self) -> None:
"""Refresh git status in background."""
status = self.git_controller.get_status_sync()
self.call_from_thread(self._update_git_ui, status)
def _update_git_ui(self, status: GitStatus) -> None:
"""Update UI with git status (runs on main thread)."""
sidebar = self.query_one(SidebarPanel)
sidebar.update_git_status(status.staged, status.unstaged)
```
## Extension System
Clide uses Pluggy for extensibility. Extensions implement hooks defined in `hookspecs.py`.
```python
# clide/extensions/hookspecs.py
class ClideHookSpec:
@hookspec
def clide_startup(self, app: App) -> None:
"""Called when app starts."""
@hookspec
def clide_on_file_changed(self, event: FileEvent) -> None:
"""Called when a file changes."""
# User extension
class MyExtension:
@hookimpl
def clide_on_file_changed(self, event: FileEvent) -> None:
if event.path.suffix == ".py":
# Custom logic for Python files
...
```
**Available hooks:**
- `clide_startup` — App initialization
- `clide_shutdown` — App cleanup
- `clide_on_file_changed` — File system changes
- `clide_on_file_saved` — File saved in editor
## Skills System
Clide integrates with Claude Code skills for git operations. Skills are installed to the project's `.claude/skills/` directory.
```python
# clide/services/skill_installer.py
class SkillInstaller:
def install(self, skill_name: str, scope: Literal["user", "project"] = "project"):
"""Install a skill from bundled templates."""
template_dir = TEMPLATES_DIR / skill_name
target_dir = self.project_skills_dir / skill_name
shutil.copytree(template_dir, target_dir)
```
**Bundled skills** (`clide/templates/skills/`):
- `commit` — Git commit workflow
- `stash` — Git stash operations
- `pull` — Git pull with rebase
- `push` — Git push to remote
- `branch` — Branch management
When a git action button is clicked, Clide ensures the skill is installed before sending the command to Claude.
## Testing
Tests mirror the source structure:
```
tests/
├── unit/
│ ├── test_models.py
│ ├── test_services.py
│ ├── test_controllers.py
│ ├── test_widgets.py
│ └── test_app.py
├── integration/
│ └── test_files_view.py
└── snapshots/
└── test_app_snapshots.py
```
**Unit tests** verify individual components in isolation.
**Integration tests** verify component interactions.
**Snapshot tests** catch visual regressions using pytest-textual-snapshot.
## Configuration
### Application Settings
`ClideSettings` in `clide/models/config.py` defines app configuration loaded from environment or `.config/settings.toml`.
### User Settings
`UserSettings` persisted to `~/.clide/settings.json` stores user preferences:
- Theme selection
- Panel visibility defaults
- Compact mode preference
- Jira integration settings
-366
View File
@@ -1,366 +0,0 @@
# TUI IDE Specification
Design specification for Clide's terminal user interface. This document describes the layout, interactions, and design decisions.
## Design Principles
- **Claude-centric** — Claude Code is the primary workspace, always visible
- **Contextual panels** — Editor/Diff/Terminal appear only when needed
- **Alt-key shortcuts** — Keybindings use Alt to avoid conflicts with Claude Code input
- **Responsive** — Works on 13" laptops to widescreen monitors
- **State preservation** — Hiding panels preserves all state (never destroy widgets)
---
## Panel Structure
### Layout Overview
```
┌─────────────────┬─────────────────────────┬──────────────────┐
│ panel-sidebar │ panel-workspace (60%) │ panel-context │
│ 20% │ [Editor][Diff][Terminal]│ 25% │
│ │ (hidden when inactive) │ │
│ [Files][Git] ├─────────────────────────┤ [Jira][TODOs] │
│ [Tree] │ │ [Problems] │
│ │ panel-claude │ │
│ (content area) │ (40% when workspace │ (content area) │
│ │ visible, else 100%) │ │
├─────────────────┤ ├──────────────────┤
│ branch-status │ │ │
│ ⎇ main ▾ │ │ │
│ staged: 2 │ │ │
└─────────────────┴─────────────────────────┴──────────────────┘
```
### Panel IDs
```python
PANELS = {
# Left sidebar
"sidebar": "panel-sidebar",
# Center
"claude": "panel-claude",
"workspace": "panel-workspace",
# Right context
"context": "panel-context",
}
```
---
## Left Sidebar
### Tabs
| Tab | Content | Purpose |
|-----|---------|---------|
| Files | Project file tree | Navigate and open files |
| Git | Staged/Unstaged changes | Review and manage changes |
| Tree | Branch graph | Visualize git history |
### Git Tab
Two collapsible sections showing staged and unstaged changes.
**File status indicators:**
- `+` Added
- `~` Modified
- `-` Deleted
- `?` Untracked
- `→` Renamed
**Action buttons:**
- **Commit** — Delegate to Claude with `/commit` skill
- **Stash** — Delegate to Claude with `/stash` skill
- **Pull** — Delegate to Claude with `/pull` skill
- **Push** — Delegate to Claude with `/push` skill
### Tree Tab
Visual git graph using box-drawing characters:
```
● main: Latest commit message
├─● feature: Feature work
●─┴ Merge branch 'feature'
◆ Tagged release v1.0
```
**Symbols:**
- `●` Regular commit
- `◆` Merge commit
- `│` Branch line
- `├` Branch point
- `┴` Merge point
### Branch Status Bar
Fixed at bottom of sidebar. Shows current branch and git stats.
```
┌─────────────────────────────────┐
│ ⎇ main ▾ staged: 2 unstaged: 5│
└─────────────────────────────────┘
```
Click to expand branch selector:
```
┌─────────────────┐
│ Recent branches │
│ ● main │
│ ○ feature/xyz │
│ ○ develop │
├─────────────────┤
│[Checkout] [New] │
└─────────────────┘
```
---
## Center Column
### Claude Panel
The primary workspace. Always visible.
**Default state:** 100% height of center column
**With workspace:** 40% height (bottom)
**Content:**
- Full PTY terminal running Claude Code CLI
- Scrollback history (1000 lines)
- Input at bottom
### Workspace Panel
Tabbed container for Editor, Diff, and Terminal. Hidden by default.
**Visibility principle:** Hiding is not closing. All panels retain state:
- Editor: Open file, cursor position, scroll, unsaved changes
- Diff: Current diff content, scroll position
- Terminal: Command history, output buffer
**Visibility triggers:**
| Trigger | Result |
|---------|--------|
| Click file in sidebar | Show workspace, focus Editor |
| Click problem/TODO | Show workspace, focus Editor at line |
| Press `` Alt+` `` | Show workspace, focus Terminal |
| Close all content | Hide workspace, Claude reclaims space |
#### Editor Tab
Code editor with:
- Syntax highlighting (tree-sitter based)
- Line numbers
- Current line highlighting
#### Diff Tab
Side-by-side diff viewer for:
- Git changes (staged and unstaged)
- Claude-proposed edits
#### Terminal Tab
Command execution terminal:
- Working directory tied to project root
- Output preserved when panel hidden
---
## Right Context Panel
### Tabs
| Tab | Badge | Content |
|-----|-------|---------|
| Jira | — | Jira issue display |
| TODOs | Count | TODO/FIXME from code and TODO.md |
| Problems | Count | Linter errors and warnings |
Tab badges update reactively as counts change.
### Jira Tab
Displays Jira issues via CLI integration. Manual refresh button.
### TODOs Tab
Two sub-tabs:
**Project tab:** Items from `TODO.md` (checkbox format)
**Comments tab:** TODO/FIXME/HACK/XXX comments in code
Click any item to jump to source location.
### Problems Tab
Linter output showing:
- File path
- Line number
- Severity (error/warning)
- Message
Click to navigate to source.
---
## Responsiveness
### CSS Strategy
```css
/* Default layout */
#panel-sidebar { width: 20%; min-width: 25; }
#panel-context { width: 25%; min-width: 30; }
#panel-claude { width: 1fr; }
```
### Compact Mode
Toggle with `Alt+C`. Hides both sidebars:
```css
.compact #panel-sidebar { display: none; }
.compact #panel-context { display: none; }
```
All panel state preserved when hidden.
---
## Keybindings
All shortcuts use `Alt` modifier to avoid conflicts with Claude Code input.
### Panel Navigation
| Action | Binding |
|--------|---------|
| Toggle left sidebar | `Alt+B` |
| Toggle right sidebar | `Alt+Shift+B` |
| Toggle terminal | `` Alt+` `` |
| Focus Claude | `Alt+1` |
| Focus Editor | `Alt+2` |
| Focus Terminal | `Alt+3` |
| Toggle compact mode | `Alt+C` |
### Application
| Action | Binding |
|--------|---------|
| Command palette | `Alt+P` |
| Quick open file | `Alt+O` |
| Select theme | `Alt+T` |
| Quit | `Alt+Q` |
### Git
| Action | Binding |
|--------|---------|
| Open Git panel | `Alt+G` |
### Editor
| Action | Binding |
|--------|---------|
| Save | `Alt+S` |
| Go to line | `Alt+L` |
| Go to problems | `Alt+M` |
---
## Panel Communication
### File Navigation Flow
```
Sidebar file click
Workspace appears (if hidden)
Editor tab focused
File loaded in Editor
```
### Problem/TODO Navigation Flow
```
Click problem/todo item
Workspace appears (if hidden)
Editor tab focused
File opened at specific line
Line scrolled into view
```
### Git Action Flow
```
Click git action button (Commit, Stash, etc.)
Ensure skill installed (async, with notification)
Send /command to Claude
Claude executes git workflow
```
---
## State Management
### Reactive Properties
```python
class ClideApp(App):
workspace_visible: reactive[bool] = reactive(False)
problem_count: reactive[int] = reactive(0)
todo_count: reactive[int] = reactive(0)
current_branch: reactive[str] = reactive("main")
compact_mode: reactive[bool] = reactive(False)
```
### State Preservation
| Panel | Preserved State |
|-------|-----------------|
| Editor | Open file, cursor, scroll, unsaved changes |
| Diff | Current diff, scroll position |
| Terminal | Session, history, output buffer |
| Sidebar tabs | Scroll, expanded sections, selection |
| Context tabs | Scroll, selected item |
---
## Themes
22 built-in themes with custom theme support.
**Default:** summer-night (dark theme)
Theme selection persists in user settings (`~/.clide/settings.json`).
Custom themes can be added to `~/.clide/themes/` as TOML files.
-398
View File
@@ -1,398 +0,0 @@
# Clide User Manual
Clide is a terminal-based IDE that puts Claude Code at the center of your development workflow. This manual covers installation, daily usage, and customization.
## Installation
### Requirements
- Python 3.12 or later
- Git
- Claude Code CLI installed and authenticated
### Setup
```bash
# Clone the repository
git clone <repo-url>
cd clide
# Install dependencies and create virtual environment
make setup
# Run Clide
make run
```
Or install directly:
```bash
pip install -e .
clide
```
### First Run
On first launch, Clide creates a configuration directory at `~/.clide/` for user settings. Project-specific settings are stored in `.clide/` within your project.
## Interface Overview
```
┌─────────────────┬─────────────────────────┬──────────────────┐
│ Sidebar │ Workspace │ Context │
│ │ [Editor][Diff][Terminal]│ │
│ [Files][Git] │ (appears when needed) │ [Jira][TODOs] │
│ [Tree] ├─────────────────────────┤ [Problems] │
│ │ │ │
│ │ Claude │ │
│ │ (always visible) │ │
│ │ │ │
├─────────────────┤ ├──────────────────┤
│ ⎇ main ▾ │ │ │
│ staged: 2 │ │ │
└─────────────────┴─────────────────────────┴──────────────────┘
```
### Panels
**Left Sidebar** — File browser, git changes, and branch graph
**Center** — Claude Code (always visible) and workspace panels (editor, diff, terminal) that appear when needed
**Right Context** — Jira integration, TODO list, and problems from linters
## Keyboard Shortcuts
All shortcuts use `Alt` as the modifier to avoid conflicts with Claude Code input.
### Panel Navigation
| Action | Shortcut |
|--------|----------|
| Toggle left sidebar | `Alt+B` |
| Toggle right sidebar | `Alt+Shift+B` |
| Toggle terminal | `` Alt+` `` |
| Focus Claude | `Alt+1` |
| Focus Editor | `Alt+2` |
| Focus Terminal | `Alt+3` |
| Toggle compact mode | `Alt+C` |
### File Operations
| Action | Shortcut |
|--------|----------|
| Quick open file | `Alt+O` |
| Save file | `Alt+S` |
| Go to line | `Alt+L` |
### Git Operations
| Action | Shortcut |
|--------|----------|
| Open Git panel | `Alt+G` |
| Open Problems panel | `Alt+M` |
### Application
| Action | Shortcut |
|--------|----------|
| Command palette | `Alt+P` |
| Select theme | `Alt+T` |
| Quit | `Alt+Q` |
## Working with Claude
Claude Code runs in the center panel and is always visible. Type your prompts directly and Claude will respond with code suggestions, explanations, and file operations.
### Git Integration
The sidebar includes buttons for common git operations that delegate to Claude:
- **Commit** — Claude reviews staged changes and creates a well-formatted commit
- **Stash** — Claude stashes your working changes
- **Pull** — Claude pulls with rebase and helps resolve conflicts
- **Push** — Claude pushes to remote, setting upstream if needed
On first use, Clide installs the corresponding skill to your project's `.claude/skills/` directory. These skills guide Claude through each operation following best practices.
### Branch Status
The branch status bar at the bottom of the sidebar shows:
- Current branch name
- Staged and unstaged file counts
Click the branch name to open the branch selector:
```
┌─────────────────┐
│ Recent branches │
│ ● main │
│ ○ feature/xyz │
│ ○ develop │
├─────────────────┤
│[Checkout] [New] │
└─────────────────┘
```
## Left Sidebar
### Files Tab
Browse your project structure. Click a file to open it in the editor.
- Directories expand/collapse on click
- Hidden files (starting with `.`) are shown but dimmed
- Noisy directories (`.git`, `__pycache__`, `node_modules`) are filtered
### Git Tab
View staged and unstaged changes:
```
Staged (2)
+ src/new_file.py
~ src/modified.py
Unstaged (3)
~ README.md
? untracked.txt
- deleted.py
```
**Status indicators:**
- `+` Added
- `~` Modified
- `-` Deleted
- `?` Untracked
- `` Renamed
Click a file to view its diff. Use the action buttons to commit, stash, pull, or push via Claude.
### Tree Tab
Visual git graph showing branch history:
```
● main: Latest commit message
├─● feature: Feature work
●─┴ Merge branch 'feature'
```
**Commit types:**
- `` Regular commit
- `` Merge commit
## Right Context Panel
### Jira Tab
Displays Jira issues when configured. Click the refresh button to update.
Configure Jira integration in settings:
```json
{
"jira_enabled": true,
"jira_cli_path": "jira"
}
```
### TODOs Tab
Scans your codebase for TODO comments and project tasks.
**Sub-tabs:**
- **Project** — Items from `TODO.md` (checkbox format)
- **Comments** — TODO/FIXME/HACK/XXX comments in code
Click an item to jump to that location in the editor.
**Supported comment markers:**
- `TODO` — Tasks to complete
- `FIXME` — Bugs to fix
- `HACK` — Temporary solutions
- `XXX` — Dangerous or problematic code
- `NOTE` — Important notes
- `BUG` — Known bugs
### Problems Tab
Displays linter errors and warnings. Click a problem to jump to the source location.
## Workspace Panels
The workspace appears when you need to view or edit files. It contains three tabs:
### Editor
Full-featured code editor with:
- Syntax highlighting (Python, JavaScript, TypeScript, HTML, CSS, JSON, YAML, Markdown, and more)
- Line numbers
- Current line highlighting
### Diff
Side-by-side diff viewer for reviewing changes. Used when:
- Viewing git changes
- Reviewing Claude's proposed edits
### Terminal
Command-line terminal for running commands. Output is preserved when the panel is hidden.
## Themes
Clide includes 22 built-in themes. Press `Alt+T` to open the theme selector.
**Theme categories:**
| Category | Themes |
|----------|--------|
| Core | summer-night (default), summer-day |
| Popular | one-dark, one-dark-pro, one-light, dracula, nord, gruvbox-dark, gruvbox-light |
| Seasonal | winter-is-coming, monokai-winter, fall, dark-autumn |
| Halloween | all-hallows-eve, halloween |
| Christmas | christmas, santa-baby |
| Hacker | pro-hacker, hacker-style |
| Other | gamma, one-dark-teal, houston |
Your theme choice is saved and persists across sessions.
### Custom Themes
Create custom themes in `~/.clide/themes/`:
```toml
# ~/.clide/themes/my-theme.toml
name = "my-theme"
display_name = "My Custom Theme"
dark = true
[colors]
primary = "#007acc"
secondary = "#3c3c3c"
accent = "#0e639c"
background = "#1e1e1e"
surface = "#252526"
panel = "#2d2d30"
foreground = "#d4d4d4"
success = "#4ec9b0"
warning = "#dcdcaa"
error = "#f44747"
```
## Configuration
### User Settings
Settings are stored in `~/.clide/settings.json`:
```json
{
"theme": "summer-night",
"compact_mode": false,
"jira_enabled": false,
"jira_cli_path": "jira"
}
```
### Project Settings
Project-specific settings in `.clide/`:
```
.clide/
├── settings.json # Project overrides
└── skills/ # Installed Claude skills
├── commit/
├── stash/
└── ...
```
### Environment Variables
Override settings with environment variables prefixed with `CLIDE_`:
```bash
CLIDE_THEME=dracula clide
```
## Compact Mode
Press `Alt+C` to toggle compact mode, which hides both sidebars for focused work. All panel state is preserved—nothing is lost when hiding panels.
## Project TODOs
Clide integrates with a `TODO.md` file in your project root. Format:
```markdown
# TODO
## Features
- [ ] Implement user authentication
- [ ] Add search functionality
- [x] Set up database connection
## Bugs
- [ ] Fix login redirect
```
Items appear in the TODOs panel, grouped by section. Click to jump to that line. Check off items directly in the file.
If no `TODO.md` exists, click "Create TODO.md" in the TODOs panel to generate a template.
## Tips
### Efficient Navigation
1. Use `Alt+1/2/3` to quickly switch between Claude, Editor, and Terminal
2. Click items in Problems or TODOs to jump directly to source
3. Use compact mode (`Alt+C`) when you need more space for Claude
### Git Workflow
1. Make changes to your code
2. Review changes in the Git tab
3. Click "Commit" to have Claude create a well-formatted commit
4. Use "Push" when ready to share
### Working with Claude
- Claude sees your project context automatically
- Use the git action buttons for consistent commit messages
- Click files in the sidebar to show Claude what you're working on
## Troubleshooting
### Claude Code not starting
Ensure Claude Code CLI is installed and authenticated:
```bash
claude --version
claude auth status
```
### Theme not applying
Check that the theme name in settings matches exactly. Theme names are case-sensitive.
### Skills not working
Skills are installed to `.claude/skills/` in your project. If a skill fails:
1. Check that the skill folder exists
2. Verify `SKILL.md` is present
3. Try removing and re-triggering the action
### Panels not updating
Try refreshing with the relevant shortcut or clicking the refresh button. File changes should update automatically via file watching.
-173
View File
@@ -1,173 +0,0 @@
# Web Deployment
Clide runs in a browser via a two-layer stack:
```
Browser (code.schweitz.net)
└─ clide-web (FastAPI + uvicorn, port 8888)
└─ tmux (session persistence)
└─ clide (Textual TUI)
└─ claude code (embedded PTY)
```
## Components
| Layer | Purpose | Config |
|-------|---------|--------|
| **clide-web** | FastAPI server: HTML page, WebSocket ↔ PTY bridge, REST API | systemd service on port 8888 |
| **tmux** | Session persistence (detach/reattach on browser disconnect) | Managed by clide-web |
| **clide** | TUI IDE wrapper around Claude Code | Spawned by tmux |
## Installation
From the clide project root:
```bash
sudo bash deploy/install-clide-web.sh
```
This:
1. Installs `clide-web` Python package into the clide venv
2. Installs `clide-web.service` systemd unit
3. Enables and starts the service
### First-Run Setup
After installing, run the setup wizard to configure projects directory and clide binary path:
```bash
clide-web-setup
```
Settings are stored in `~/.clide/clide.db` as UserPreference records.
### Prerequisites
- Python 3.12+ with clide venv set up (`make setup`)
- `tmux` installed (`sudo dnf install tmux` / `sudo apt install tmux`)
### Reverse Proxy
For external access, configure your reverse proxy (e.g., Nginx Proxy Manager) to:
- Proxy `code.schweitz.net``localhost:8888`
- Enable WebSocket support
## Architecture
### clide-web
FastAPI application serving:
- `GET /` — HTML page with xterm.js terminal + toolbar
- `GET /projects/{name}` — Project terminal page
- `WS /projects/{name}/ws` — WebSocket terminal bridge
- `GET /api/projects` — List available git repos
- `GET /api/sessions` — List active tmux sessions
- `GET /health` — Health check for reverse proxy
**WebSocket Protocol:**
| Prefix | Direction | Purpose |
|--------|-----------|---------|
| `0` | both | Terminal data |
| `1` | both | Control message (JSON) |
| `2` | client→server | Resize: `cols,rows` |
### tmux
Managed programmatically by clide-web. One session per project (`clide-<project>`).
- Browser disconnect → tmux session persists, reconnect shows current state
- Clide exit (Alt+Q) → `pane-died` hook auto-respawns a fresh Clide instance
- Status bar hidden for clide-web sessions only (user's other tmux sessions unaffected)
- Full environment inherited (HOME, PATH, etc.)
### Keybindings
All keys pass through directly to Clide — no intermediate layer captures keys.
No keybinding conflicts (unlike the previous Zellij-based setup).
### Database
SQLite database at `~/.clide/clide.db` shared between clide and clide-web.
Uses SQLModel (Pydantic-native ORM by FastAPI's creator).
Tables:
- **Project** — name, path, theme, last_accessed
- **Session** — tmux session name, status, last_activity
- **UserPreference** — key/value settings (projects_dir, clide_bin, port, etc.)
- **ConnectionLog** — client IP, connect/disconnect timestamps
## Configuration
Settings priority: environment variables > database preferences > defaults.
Environment variables (prefix `CLIDE_WEB_`):
| Variable | Default | Description |
|----------|---------|-------------|
| `CLIDE_WEB_HOST` | `0.0.0.0` | Server bind address |
| `CLIDE_WEB_PORT` | `8888` | Server port |
| `CLIDE_WEB_PROJECTS_DIR` | `/mnt/media/Projects` | Directory containing git repos |
| `CLIDE_WEB_CLIDE_BIN` | `clide` | Path to clide binary |
| `CLIDE_WEB_DB_PATH` | `~/.clide/clide.db` | SQLite database path |
## URL Patterns
- `code.schweitz.net` — auto-selects first project
- `code.schweitz.net/projects/clide` — opens/attaches to the clide project
The toolbar dropdown allows switching projects. URL updates via `history.pushState`.
## Operations
### Service Management
```bash
# Using make targets (from clide-web/ directory)
make start-server # Start the systemd service
make stop-server # Stop the systemd service
make restart-server # Restart the systemd service
make status-server # Show service status
make logs-server # Tail service logs
# Or directly with systemctl
systemctl status clide-web
sudo systemctl restart clide-web
journalctl -u clide-web -f
```
### Session Management
```bash
# List sessions
tmux list-sessions
# Kill a specific session
tmux kill-session -t clide-myproject
# Kill all clide sessions
tmux list-sessions | grep ^clide- | cut -d: -f1 | xargs -I{} tmux kill-session -t {}
```
## Files
```
clide-web/ # Python package
├── clide_web/
│ ├── server.py # FastAPI app, routes, WebSocket handler
│ ├── sessions.py # tmux session manager
│ ├── pty_bridge.py # PTY ↔ WebSocket bridge
│ ├── config.py # Pydantic settings with DB overlay
│ ├── setup_wizard.py # Interactive first-run configuration
│ └── static/
│ ├── index.html # HTML page (toolbar + xterm.js)
│ └── vendor/ # Vendored xterm.js (no CDN dependencies)
├── pyproject.toml
└── Makefile
deploy/
├── install-clide-web.sh # Installation script (run with sudo)
└── clide-web.service # systemd unit file
clide/
├── models/db.py # SQLModel table definitions (shared)
└── services/database.py # SQLite engine and session factory
```
Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB