Files
clide/legacy/CLAUDE.md
T
jpmschweitzerandClaude Opus 4.7 a355751437 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>
2026-04-20 20:30:51 +02:00

346 lines
11 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Clide is a TUI IDE wrapper for Claude Code CLI, designed to be Claude-centric with VSCode-familiar keybindings. See `docs/tui-ide-spec.md` for full specification.
### Design Principles
- **Claude-centric**: Claude Code is the primary workspace, always visible
- **Contextual panels**: Editor/Diff/Terminal appear only when needed
- **Alt-key shortcuts**: Alt-based keybindings don't interfere with input fields
- **Responsive**: Works on 13" laptop to widescreen monitors
- **State preservation**: Hiding panels preserves all state (never destroy widgets)
## Tech Stack
| Component | Library | Version |
|-----------|---------|---------|
| Runtime | Python | 3.12+ |
| TUI Framework | Textual | latest |
| CLI | Typer | latest |
| Data Validation | Pydantic | v2 (strict mode) |
| Settings | pydantic-settings | latest |
| Database | SQLModel + SQLite | latest |
| Web Server | FastAPI + uvicorn | latest |
| Testing | pytest + pytest-asyncio + pytest-textual-snapshot | latest |
| Extensions | pluggy | latest |
## Development Commands
### Clide (TUI)
```bash
make setup # Create venv, install deps
make run # Run application
make test # Run all tests
make test-single # Run single test (TEST=path::test_name)
make typecheck # Run mypy
make lint # Run ruff check
make format # Run ruff format
make build # Build for current platform
```
### clide-web (Web Server)
```bash
cd clide-web/
make setup # Create venv, install deps, run setup wizard
make run # Run the web server (foreground)
make dev # Run with auto-reload
make start-server # Start systemd service
make stop-server # Stop systemd service
make restart-server # Restart systemd service
make status-server # Show service status
make logs-server # Tail service logs
```
## Panel Architecture
```
┌─────────────────┬─────────────────────────┬──────────────────┐
│ panel-sidebar │ panel-workspace (60%) │ panel-context │
│ │ [Editor][Diff][Terminal]│ │
│ [Files][Git] │ (hidden when inactive) │ [Problems][TODOs]│
│ [Tree] ├─────────────────────────┤ [Jira] │
│ │ │ │
│ (content area) │ panel-claude │ (content area) │
│ │ (40% when workspace │ │
│ │ visible, else 100%) │ │
├─────────────────┤ ├──────────────────┤
│ ⎇ main ▾ │ │ [⚠ 3][✓12][Jira]│
└─────────────────┴─────────────────────────┴──────────────────┘
```
## Project Structure
```
clide/
├── clide/ # Package source
│ ├── __init__.py
│ ├── __main__.py
│ ├── app.py # Main App, layout, keybindings
│ ├── cli.py # Typer entry point
│ ├── controllers/ # Domain logic (no UI)
│ ├── widgets/ # UI components
│ │ ├── panels/ # Main layout containers
│ │ └── components/ # Reusable UI pieces
│ ├── models/ # Pydantic data models
│ ├── services/ # Background task logic
│ ├── themes/ # Theme system
│ ├── extensions/ # Plugin system
│ └── helpers/ # Utility functions
├── tests/
│ ├── conftest.py
│ ├── harnesses/
│ │ ├── app_harness.py
│ │ └── controller_harness.py
│ ├── unit/
│ ├── integration/
│ └── snapshots/
├── .config/ # User config (gitignored)
│ ├── settings.toml # User settings
│ └── themes/ # Custom user themes
│ └── my-theme.toml
├── docs/
│ ├── tui-ide-spec.md # Full UI/UX specification
│ ├── web-deployment.md # Web deployment architecture
│ └── ARCHITECTURE.md # Framework best practices
├── pyproject.toml
└── Makefile
clide-web/ # Web server package (wraps clide)
├── 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 config
│ └── static/
│ ├── index.html # HTML page (toolbar + xterm.js)
│ └── vendor/ # Vendored xterm.js (offline)
├── pyproject.toml
└── Makefile
```
## Key Patterns
### Panel Visibility (Hide, Don't Destroy)
```python
def toggle_workspace(self, visible: bool) -> None:
workspace = self.query_one("#panel-workspace")
workspace.display = visible # Preserves all child state
claude = self.query_one("#panel-claude")
claude.styles.height = "40%" if visible else "100%"
```
### Background Tasks
Use `@work` decorator for non-blocking operations:
```python
@work(thread=True)
def refresh_git_status(self) -> None:
result = subprocess.run(["git", "status", "--porcelain"], ...)
self.call_from_thread(self.update_git_view, result.stdout)
```
### Reactive State
```python
class ClideApp(App):
current_file: reactive[str | None] = reactive(None)
workspace_visible: reactive[bool] = reactive(False)
problem_count: reactive[int] = reactive(0)
todo_count: reactive[int] = reactive(0)
compact_mode: reactive[bool] = reactive(False)
```
### Pydantic Models (Strict + Frozen)
```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
```
### Controller → Widget Communication
Controllers emit Textual messages; widgets subscribe:
```python
# In controller
class GitStatusUpdated(Message):
def __init__(self, status: GitStatus) -> None:
self.status = status
super().__init__()
self.post_message(GitStatusUpdated(status))
# In widget
def on_git_status_updated(self, event: GitStatusUpdated) -> None:
self.refresh_view(event.status)
```
## Theme System
### Default Theme: Summer Night
Based on [jackw01/summer-night-vscode-theme](https://github.com/jackw01/summer-night-vscode-theme):
```python
SUMMER_NIGHT = ThemeColors(
primary="#00a3d2", # cyan
secondary="#00a9b9", # teal
accent="#fa5f8b", # pink
background="#21262f", # mono_8
surface="#393e48", # mono_7
panel="#292e38",
foreground="#e2e8f5", # mono_1
success="#00ab9a", # green
warning="#d08447", # orange
error="#f06c6f", # red
)
```
### Built-in Themes (22 total)
| Category | Themes |
|----------|--------|
| Core | summer-night (default), summer-day |
| Popular | one-dark, one-dark-pro, one-light, dracula, nord, gruvbox-dark, gruvbox-light |
| GitKraken | one-dark-teal, gamma |
| Seasonal - Winter | winter-is-coming, monokai-winter |
| Seasonal - Fall | fall, dark-autumn |
| Seasonal - Halloween | all-hallows-eve, halloween |
| Seasonal - Christmas | christmas, santa-baby |
| Hacker | pro-hacker, hacker-style |
| Bonus | houston |
### Theme Definition
```python
class ThemeColors(BaseModel):
model_config = ConfigDict(strict=True, frozen=True)
primary: str # Main accent
secondary: str # Secondary accent
accent: str # Highlight accent
background: str # Main background
surface: str # Elevated surfaces
panel: str # Panel backgrounds
foreground: str # Primary text
success: str # Success/green
warning: str # Warning/yellow
error: str # Error/red
class ThemeDefinition(BaseModel):
name: str # Identifier (e.g., "summer-night")
display_name: str # Human-readable name
dark: bool # Dark or light theme
colors: ThemeColors
```
### Custom Themes
Users can add themes in `.config/themes/`:
```toml
# .config/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"
```
### Theme Switching
- Keybinding: `Ctrl+K Ctrl+T`
- Settings: `theme = "summer-night"` in ClideSettings
- Runtime: `app.theme = "dracula"`
## Keybindings (Alt-based)
| Action | Binding |
|--------|---------|
| Quit | `Alt+Q` |
| Command palette | `Alt+P` |
| Quick open | `Alt+O` |
| 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` |
| Git panel | `Alt+G` |
| Problems panel | `Alt+M` |
| Select theme | `Alt+T` |
| Save file | `Alt+S` |
## Configuration
Settings are loaded from multiple sources (in priority order):
1. Environment variables (`CLIDE_*`)
2. `.config/settings.toml`
3. Defaults in ClideSettings
```python
class ClideSettings(BaseSettings):
model_config = SettingsConfigDict(
env_prefix="CLIDE_",
env_file=".env",
extra="ignore",
)
theme: str = "summer-night"
jira_enabled: bool = False
jira_cli_path: str = "jira"
panels: PanelConfig = PanelConfig()
keybindings: KeybindingsConfig = KeybindingsConfig()
```
## Documentation Links
### Core Stack
- [Textual Documentation](https://textual.textualize.io/)
- [Textual Testing Guide](https://textual.textualize.io/guide/testing/)
- [Textual Themes Guide](https://textual.textualize.io/guide/design/)
- [Typer Documentation](https://typer.tiangolo.com/)
- [Pydantic v2 Documentation](https://docs.pydantic.dev/latest/)
- [Pydantic Settings](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)
### Testing
- [pytest-asyncio](https://pytest-asyncio.readthedocs.io/en/latest/)
- [pytest-textual-snapshot](https://github.com/Textualize/pytest-textual-snapshot)
### Extensions
- [Pluggy Documentation](https://pluggy.readthedocs.io/)
### Build
- [PyInstaller Documentation](https://pyinstaller.org/)
- [Gitea Actions](https://docs.gitea.com/usage/actions/overview)
### Theme References
- [Summer Night VSCode Theme](https://github.com/jackw01/summer-night-vscode-theme)