Commit Graph
83 Commits
Author SHA1 Message Date
jpmschweitzerandClaude 02814b35f3 add POLICY.md and set line length to 160
POLICY.md codifies runtime behavior rules (no network on default
launch path), dependency vetting, vendored binary rebuild process,
telemetry prohibition, and licensing requirements. Binding on all
contributors including agents.

Line length 160 in .editorconfig (all files) and
analysis_options.yaml (dart formatter).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 22:20:42 +02:00
jpmschweitzerandClaude 50bd3012bd add wasmtime Apache-2.0 license file per POLICY.md
Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 22:13:58 +02:00
jpmschweitzerandClaude ce8529e424 add tree-sitter syntax highlighting via dart:ffi
Vendor libtree-sitter.so (v0.26.8, wasmtime 44.0 statically linked)
and call its C API through dart:ffi. Grammar WASM files are loaded by
tree-sitter's embedded wasmtime engine via ts_wasm_store_load_language.

48 grammars compiled with tree-sitter build --wasm, 48 highlight
queries (42 from upstream repos, 6 written in-house for comment,
erlang, gdscript, gitignore, hcl, hlsl, swift). SQLite grammar
replaces full SQL (974K-line parser exhausted RAM at compile time).

Removes wasm_run and wasm_run_flutter — they downloaded a 22 MB
binary from GitHub at first launch, violating the no-network-on-
default-launch-path policy.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 22:08:00 +02:00
jpmschweitzerandClaude 4f5d97ebc5 define core frame vs shipped extension boundary (D-046)
Core frame builtins are infrastructure the shell can't function
without. Content extensions (editor, claude, canvas, etc.) are
bundled but architecturally removable — users swap the surface,
not the data.

Removes builtin.jira stub: Jira belongs as a third-party
extension, not a frame builtin. Git is a split component —
daemon-side process stays in frame, UI surfaces are extensions.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 22:07:04 +02:00
jpmschweitzerandClaude 5aa153334d update welcome screen per hi-fi design
test / unit + widget + golden + a11y (push) Failing after 41s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
Larger wordmark (48px), START section header, icon-prefixed
action rows for Open project and New Claude session. Semantics
hint preserved for a11y.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 17:31:10 +02:00
jpmschweitzerandClaude ad3e35709e require confirmation before discarding unstaged changes
The discard button in the git panel now opens a dialog warning
that changes will be permanently lost. Prevents accidental data
loss from a misclick.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 17:30:55 +02:00
jpmschweitzerandClaude 45054f7aec add git branch picker + status bar indicator
git.branches and git.checkout IPC verbs. Status bar shows current
branch with ahead/behind count; clicking opens a branch picker
dialog for checkout.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 17:30:37 +02:00
jpmschweitzerandClaude 6592a88695 add command palette widget + layout keybindings
ClidePalette renders as a floating overlay with fuzzy-filtered
command list. Ctrl+Shift+P toggles it. Ctrl+B toggles sidebar,
Ctrl+J toggles context panel. All wired through CommandRegistry
via the default layout extension.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 17:30:21 +02:00
jpmschweitzerandClaude eda3b30382 add sidebar icon rail replacing top tab bar
Four new icon painters (git branch, search, terminal, warning).
ClideIconRail widget with parent-owned hover state so only one
icon highlights at a time. Sidebar slot renders content above +
icon rail below; workspace and context slots keep the tab bar.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 17:29:00 +02:00
jpmschweitzerandClaude 1f23ba40f2 fix make run — use PID file, add make stop
test / unit + widget + golden + a11y (push) Failing after 40s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
PID file at /tmp/clide-daemon-<uid>.pid replaces pkill pattern
matching. make run depends on stop so stale daemons are killed
before build. Flutter exit via ctrl-C no longer aborts Make.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 16:54:18 +02:00
jpmschweitzerandClaude 8b5615426a wire design palette through resolver with fallback chains
Surface map now tries palette keys (bgSunken, surfaceHi, textHi,
etc.) first, falling back to semantic refs for legacy themes.
Sidebar/panel bg differentiates from workspace bg. Buttons use
accent colour with onAccent text. Four-level text gradient flows
to widgets.

WCAG-AA contrast fixes: clide textDim lightened, midnight
onAccent darkened, paper textDim darkened. Contrast test updated
to cover all four themes. Resolver tests updated for the new
palette shape. Goldens regenerated.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 16:54:11 +02:00
jpmschweitzerandClaude 861fa6652a fix make run daemon lifecycle
test / unit + widget + golden + a11y (push) Failing after 40s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
Kill stale daemon before build to prevent "Text file busy". Trap
EXIT + INT + TERM for reliable cleanup on ctrl-C. Add make stop
for standalone daemon kill.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 16:32:11 +02:00
jpmschweitzerandClaude 5869697297 add four design themes + syntax tokens to theme pipeline
test / unit + widget + golden + a11y (push) Failing after 39s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
SurfaceTokens gains seven syntax-role fields (keyword, type,
string, number, comment, method, punct). Theme loader parses
the syntax: YAML block and injects values into the surface
override layer. Resolver defaults map syntax roles to semantic
colours so themes without explicit syntax blocks still compile.

Four new theme YAMLs (clide, midnight, paper, terminal) replace
summer-night. Palette keys mapped to the existing semantic layer;
syntax values pass through directly. Goldens regenerated for the
14→font-size change.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 16:29:41 +02:00
jpmschweitzerandClaude de9a7b9745 update design handoff with framework-free token exports
New tokens/ directory with YAML palette + syntax files for all
four themes, plus a pure dart:ui Dart file (no Material). README
updated to reflect the no-Material constraint and open typography
question.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 16:29:17 +02:00
jpmschweitzerandClaude 272b59e752 record design handoff decisions (D-043–D-045, Q-025, R-012)
test / unit + widget + golden + a11y (push) Failing after 41s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
D-043: adopt token palettes from design, reject Material wrapper.
D-044: four bundled themes replace summer-night.
D-045: syntax highlighting tokens in the theme pipeline.
Q-025: body text face — mono everywhere vs Josefin Sans + mono.
R-012: MaterialApp wrapper rejected (conflicts with D-007).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 16:11:40 +02:00
jpmschweitzerandClaude ae1c3d8a34 add claude.ai/design handoff under docs/claude-design/
Four self-contained HTML mockups (wireframe, flows, hi-fi, design
system), four Dart theme files (clide, midnight, paper, terminal),
and flat PNG renders. Reference material for the UI build — not
runtime assets.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 16:11:22 +02:00
jpmschweitzerandClaude 1a5e682dc8 brand all build targets with the clide logo
test / unit + widget + golden + a11y (push) Failing after 41s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
Replace Flutter default icons across Linux (GTK window icon via
bundled asset), macOS (AppIcon.appiconset all sizes), and web
(favicon, PWA icons, manifest, meta description). Logo PNGs at
16–1024px generated from the SVG source. Window title set to
"clide" everywhere. Web manifest colours match summer-night.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 16:02:08 +02:00
jpmschweitzerandClaude d4f5f7c09f add clide logo SVG
test / unit + widget + golden + a11y (push) Failing after 41s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
Angle-bracket chevrons with teal accent underline, matching the
summer-night palette.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 15:18:54 +02:00
jpmschweitzerandClaude 303e449ef4 add make run target
Builds the daemon binary if stale, starts it in the background,
launches flutter run -d linux, and cleans up the daemon on exit.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 15:18:40 +02:00
jpmschweitzerandClaude 4f8840ccd2 add type scale constants; remove scattered font size overrides
Sidebar and panel text was too small — dozens of bare fontSize:
10/11/12 values fighting the ambient DefaultTextStyle. Root font
bumped from 13 to 14. Three semantic constants replace the magic
numbers: clideFontBody (14), clideFontCaption (12), clideFontMono
(13). Widgets that render body text now inherit instead of
overriding.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 15:18:30 +02:00
jpmschweitzerandClaude e290ae6dbd wire builtin.pql + builtin.problems panels
test / unit + widget + golden + a11y (push) Failing after 40s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
PqlExtension contributes a sidebar tab (files, query, decisions,
tickets views) and a context-panel tab (backlinks + outlinks for
the active file, auto-refreshing on editor.active-changed).

ProblemsExtension contributes a sidebar tab aggregating pql.doctor
and decisions.sync diagnostics with actionable hints.

Both upgraded from stubs to 0.1.0.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 14:03:32 +02:00
jpmschweitzerandClaude 93ab6ea3bd add pql subsystem — daemon-side client + IPC handlers
PqlClient wraps pql CLI per D-003 (shell-out, never duplicate).
IPC verbs: pql.files, pql.meta, pql.backlinks, pql.outlinks,
pql.tags, pql.schema, pql.query, pql.doctor, pql.decisions.*,
pql.tickets.*, pql.plan.status. 15 new core tests.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 14:02:47 +02:00
jpmschweitzerandClaude e43438d369 remove Python stopgap; rewire to pql 1.0
test / unit + widget + golden + a11y (push) Failing after 38s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
pql 1.0 ships full feature parity for decisions and tickets.
Sunset condition from D-040 met; deletion per R-011.

Removed: tools/scripts/plan entrypoint, tools/scripts/planning/
Python modules, tools/scripts/README.md, .gitignore pycache
entries.

Rewired: make decisions-validate now calls pql decisions validate.
CLAUDE.md decision discipline guardrail points at pql. Extension
stub comments updated. decisions/README.md examples use pql.
D-040 amended as superseded.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 13:39:28 +02:00
jpmschweitzerandClaude 7164ec11d6 install pql skill and add pql permissions
pql init --with-skill=yes installs .claude/skills/pql/SKILL.md
covering vault queries and the planning surface (decisions +
tickets). Lock file tracks version + SHA-256 for drift detection.

Bash(pql) and Bash(pql *) added to .claude/settings.json so
pql commands run without permission prompts.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 13:39:11 +02:00
jpmschweitzerandClaude 6bce2621b7 wire builtin.git sidebar panel + builtin.diff workspace tab
test / unit + widget + golden + a11y (push) Failing after 37s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
GitController hydrates from git.status IPC and auto-refreshes on
git.changed events. Panel shows staged/unstaged/untracked/conflict
groups with per-file actions and an inline commit field.

DiffController renders unified diffs with line numbers, addition/
removal colouring, and a staged/unstaged toggle. Both extensions
upgraded from stubs to 0.1.0.

ClideText gains an optional fontFamily parameter so diff lines can
render in JetBrainsMono without breaking golden tests (font still
inherits from ambient DefaultTextStyle by default).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 11:09:48 +02:00
jpmschweitzerandClaude 17936bf215 add clide git CLI shortcuts
Maps clide git status|diff|stage|unstage|discard|commit|log|stash|
pull|push to the git.* IPC verbs. Updates --help to list the new
tier-3 subcommands.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 11:09:25 +02:00
jpmschweitzerandClaude f619760e7b add git subsystem — daemon-side status, diff, operations + IPC
Shell-outs to git for status (porcelain v1/v2), unified-diff
parsing, and operations (stage, unstage, hunk-apply, discard,
commit, stash, log, pull, push). IPC verbs git.* registered on
the daemon dispatcher with git.changed event emission on
mutations. 42 new core tests.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 11:09:16 +02:00
jpmschweitzerandClaude 681ce3b447 wire builtin.editor to the active buffer + open files from the tree
test / unit + widget + golden + a11y (push) Failing after 38s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
EditorController mirrors the daemon's active buffer into the Flutter
UI. Hydrates on mount (editor.active → editor.read), subscribes to
editor.opened / active-changed / edited / saved / closed, and pushes
local edits back via editor.set-content. A one-shot echo-suppression
flag keeps the daemon's authoritative edit echo from clobbering the
caret the user just moved.

Text surface is EditableText directly — no TextField / Material
import, so D-007's "bare WidgetsApp" guardrail carries into the
editor tab. JetBrainsMono via the shared mono-family constants;
cursor + selection colours come from the theme tokens.

File-tree click now calls ipc.request('editor.open', {path}) instead
of the kernel command registry (which wouldn't have reached the
daemon). The opened file becomes active, the editor tab's controller
sees editor.active-changed, and the text content reconciles.

Linux release bundle still builds; 174 app tests + 74 core tests
stay green.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 10:31:01 +02:00
jpmschweitzerandClaude 50d0143afc add tier-2 CLI shortcuts and clide tail --events
`bin/clide` gains the single-word shortcuts CLAUDE.md's tier 2 spells
out: open, active, insert, replace-selection, save. Each maps the
flat positional argv into the canonical editor.* IPC shape. Insert
and replace-selection accept a lone `-` to read text from stdin so
piping works (`pbpaste | clide replace-selection -`).

`clide tail --events` is the subscribe mode. Same socket as the
request side; the client just reads + filters events. --filter
SUBSYSTEM or SUBSYSTEM:ID narrows the stream. Exits cleanly on
SIGINT.

defaultSocketPath() now respects CLIDE_SOCKET_PATH before XDG — the
existing override callers always had this up their sleeve (via
XDG_RUNTIME_DIR manipulation) but making it explicit unblocks
parallel test runs where each test needs its own daemon socket. The
new end-to-end CLI suite does exactly that: 5 tests spin up real
daemon subprocesses and exercise the shortcut surface through the
live IPC stack.

74 core tests pass; round-trip verified by hand (open README.md →
insert → tail --events captures editor.opened / edited /
selection-changed / saved).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 10:21:03 +02:00
jpmschweitzerandClaude d32e8fdc17 add editor subsystem — daemon state + editor.* IPC
EditorBuffer + Selection + EditorRegistry hold the daemon-side
active-file model (D-006 subsystem 'editor'). Active buffer
tracking means `clide insert "…"` and `clide replace-selection
"…"` target the UI's focused file without the caller supplying an
id. Mutations mark buffers dirty; editor.save writes back to disk
through the workspace root; events fire on every state change so
subscribers can mirror.

IPC surface matches CLAUDE.md's tier-2 list + the natural extras
(list, read, activate, set-selection, set-content, close). Tests
cover open-idempotence, insert at caret, replace-selection range
swap, dirty→save→clean round-trip, close picks a new active
buffer, out-of-range selection clamping.

69 core tests pass.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 10:10:42 +02:00
jpmschweitzerandClaude 37108230f2 decouple Pane from PtySession so the web build compiles
test / unit + widget + golden + a11y (push) Failing after 37s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
Pane is now a pure data class — id, kind, pid, argv, cwd, title,
isClosed. The daemon-side PaneRegistry holds a parallel map of
PtySession keyed on id; registry methods look up both sides when
writing / resizing / closing.

The `clide.dart` barrel no longer re-exports `src/pty/*`,
`src/panes/registry.dart`, or the `*_commands.dart` modules — all
three transitively import `dart:ffi` which isn't available when
compiling to WebAssembly. The daemon entrypoint (bin/clide.dart) +
core tests import them via deep paths now. Pane / PaneKind /
DaemonEventSink / RecordingEventSink stay in the barrel since
they're pure data the Flutter app references over IPC.

Verified: `dart analyze` clean, 53 core tests green, 174 app tests
green, `make ui-smoke` compiles + serves + Playwright smoke passes,
daemon boots + ping round-trips + SIGTERMs cleanly.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 10:01:06 +02:00
jpmschweitzerandClaude b9fbcd43a2 implement builtin.claude per D-041
test / unit + widget + golden + a11y (push) Failing after 45s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
Tier-0 stub flipped to the real Claude pane. Primary-per-repo
semantics: session name is `clide-claude-<hash>` where <hash> is
FNV-1a over the workspace root path, so reopening clide attaches
to the same `claude` process through `tmux new-session -A`.

Primary has no close button — closing the tab disposes the widget
but deliberately does NOT call pane.close, so the tmux session
survives until the user actually exits claude or clide is shut
down. Secondary sessions (spawned via the claude.new-secondary
command registered here, UI wiring lands next) close normally and
the pane.close cascades into tmux kill-session.

Graceful fallback when tmux isn't on PATH: retries the spawn with
argv=['claude'], surfaces "no-tmux · fresh every launch" in the
header subtitle so the user knows persistence is off.

Session-naming unit tests cover determinism + uniqueness per repo.
Full app suite: 174 tests passing.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:40:30 +02:00
jpmschweitzerandClaude 0b451c133d record D-041: Claude panes — one primary per repo, tmux-backed
Captures the session-persistence + primary-vs-secondary policy
referenced from ptyc/README.md and deferred through the Tier 1
substrate work. Primary per repo (keyed on git root) survives app
restart via `tmux new-session -A`; secondaries are ephemeral and
collapse back to the primary on close; primary has no close
affordance. Daemon owns the session lifecycle, the UI just asks
pane.spawn / pane.close and observes events.

Required by the next commit (builtin.claude) which consumes this
policy.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:37:04 +02:00
jpmschweitzerandClaude 4ff5556896 implement builtin.files — workspace file tree with live watcher
Flutter sidebar tab that lazy-loads the workspace tree via IPC
files.ls and refreshes subtrees on files.changed events. Click-to-
open routes through a future editor.open command; until Tier 2
registers it, the execute call no-ops gracefully.

Daemon side adds a new files subsystem:
  - files.root returns the resolved workspace root (git root if
    present, otherwise cwd)
  - files.ls lists a directory with ignore filtering applied
  - files.watch starts a recursive Directory.watch and fans
    FileSystemEvents out as files.changed IPC events
  - FilesService owns the watcher + ignore set lifecycle

IgnoreSet + IgnorePattern implement the common gitignore subset:
anchored (/foo), directory-only (foo/), negation (!foo), **
crossing dirs, ** at trailing position. Built-in layer hides clide-
owned dirs (.git, .pql, .clide, .dart_tool, build, node_modules);
.gitignore + .clideignore at the root layer on top per D-004. Full
multi-file ignore_files: layering from .pql/config.yaml is future
work.

11 new ignore-matcher tests + 5 files.* dispatcher tests.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:36:02 +02:00
jpmschweitzerandClaude e1ea52c5e4 implement builtin.terminal — general-purpose shell pane
Flips the Tier-0 stub into a real extension. Contributes a Terminal
tab in the workspace slot that spawns $SHELL -l via IPC pane.spawn,
feeds pane.output events into xterm.dart's Terminal, and routes user
input back through pane.write. Viewport resize propagates via
pane.resize. Surface for disconnected-daemon / exited-shell states so
there's no silent dead tab.

Knows nothing about Claude deliberately — the Claude-specific pane
(primary-per-repo, tmux-backed, D-041) lives under builtin.claude in
the next steps.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:23:44 +02:00
jpmschweitzerandClaude 50d9e00ea5 add shared pane widgets + Q-023 ssh-remote question
ClidePtyView is a theme-bound wrapper around xterm.dart's TerminalView
— token-derived TerminalTheme, JetBrainsMono as the face, Semantics
live-region label so screen readers + Playwright both hear it. The
consumer (terminal / Claude extensions) owns the `Terminal` model and
wires IPC pane.write / pane.output → terminal.write() themselves; the
widget deliberately has no IPC dependency so it stays trivially
testable.

ClidePaneChrome is the shared pane header — title + subtitle + leading
icon + trailing widgets + optional close button. The close button is
null-conditional so primary Claude panes (D-041, landing in step 7)
can render without one.

xterm 4.0.0 added as a justified runtime dep + logged in
licenses.yaml per D-042. 3 new widget tests cover header rendering,
close-button presence, and the close-tap round-trip.

Q-023 records the SSH-remote-development question so the daemon + IPC
seams don't accrete local-only assumptions during Tier 1-5.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:19:24 +02:00
jpmschweitzerandClaude 3715a2e191 add pane subsystem to the daemon + IPC event broadcast
Implements the Tier-1 pane subsystem from D-006: spawn / list / focus /
close / write / resize / tail commands, plus pane.spawned / output /
exit / resized / focused / closed events. PaneRegistry owns per-pane
PtySession lifecycles and id generation (p_N); a DaemonEventSink seam
keeps pane code decoupled from the IPC server package.

DaemonServer.broadcast() fans events out to every connected client.
Per-client subsystem/id filtering (`tail --filter pane:p_7`) is
deferred — Tier 1 broadcasts everything and the subscriber discards.

Panes carry a `kind:` field (terminal | claude). Step 7 (builtin.claude)
adds the claude-specific pane flow on top of this generic substrate —
the subsystem itself stays neutral.

14 new core tests: registry unit coverage (spawn → pane.spawned event,
output → base64 events, write/resize/close round-trips, idempotent
close, claude kind on the wire) plus dispatcher coverage (argv
validation, unknown-id → not-found, text vs bytes_b64, etc). All 37
core tests pass in ~3s under test-core.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:05:51 +02:00
jpmschweitzerandClaude edd8a20e0d add Dart PTY wrapper and test-core harness
PtySession wraps the ptyc helper: socketpair + Process.start + recvmsg
with SCM_RIGHTS for master-fd transfer, a background isolate that
loops on blocking read() and posts byte chunks, plus write/resize/
kill/close. close() SIGTERMs the child so the PTY's EOF wakes the
reader naturally; SIGKILL + fd close + isolate kill cover the edge
where the shell ignores SIGTERM — avoids the known Linux quirk where
closing an fd doesn't unblock an in-flight read() on it.

Env defaults stamp TERM=xterm-256color, COLORTERM=truecolor,
CLICOLOR_FORCE=1 so shells + tmux + Claude emit 24-bit sequences
that xterm.dart can render. User env (HOME / USER / SHELL) still
inherits via mergePtyEnv().

ffi: 2.1.3 added as a runtime dep — the FFI bindings for socketpair,
recvmsg, read/write, and ioctl(TIOCSWINSZ) need an allocator we're
not writing by hand. Justified in pubspec + listed in licenses.yaml
per D-042.

make test-core (ci/test_core.sh) runs the Flutter-free core tests
under a 120s hard timeout with setsid + process-group kill, wired
ahead of the fast app tests in push-check so a hung PTY test can't
wedge a pre-push. Current core suite: 24 tests in ~1s.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 09:01:01 +02:00
jpmschweitzerandClaude c94ad2c05b restructure licenses.yaml: self + runtime deps + dev deps
test / unit + widget + golden + a11y (push) Successful in 1m30s
test / integration_test (xvfb) (push) Failing after 1m14s
test / bundle smoke (xvfb 5s) (push) Failing after 1m3s
test / daemon subprocess + web WASM smoke (push) Successful in 1m42s
Three sections instead of one flat list. `self:` carries clide's own
MIT license (rendered first in the About screen so the user knows
what they're running before the dependency list). `dependencies:`
covers artefacts that actually ship in the binary — JetBrainsMono,
JosefinSans, yaml. `dev_dependencies:` tracks build-time tooling
(mocktail, alchemist, flutter_lints, lints, test) for audit
completeness without polluting the user-facing About panel.

Also backfilled the two root-package dev deps that were missed the
first pass: `lints: 5.0.0` and `test: 1.25.8` (root pubspec, not
app/). Root LICENSE mirrored into app/assets/LICENSE + declared as
a bundled asset so the About screen can read it at runtime (Flutter
can't reference paths above the package root).

D-042 updated to describe the three-section split and the dev-vs-
runtime distinction.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 08:26:36 +02:00
jpmschweitzerandClaude 1b00d88a0d document bundled deps in licenses.yaml; record D-042
Every third-party artefact shipping in the clide binary — fonts,
Dart packages, native tools, bundled assets — now has an entry in
app/assets/licenses.yaml with name, kind, version, homepage, license
identifier, relative path to the bundled license text, and a
one-line purpose. The About screen (Tier 6) will render this file
verbatim. Seeded with the current set: JetBrainsMono, JosefinSans,
yaml, mocktail, alchemist, flutter_lints.

D-042 captures the two-step-commit rule (artefact + licenses.yaml
entry in the same changeset) alongside D-031's prefer-zero-deps
budget: preferring zero deps is the budget; licenses.yaml is the
visible consequence when the budget grows.

CLAUDE.md "Dependencies & supply chain" gains a matching guardrail
line. The per-dep license text files (OFL.txt for both fonts) are
declared as pubspec assets too so the About screen has something to
display, not just a manifest.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 08:18:39 +02:00
jpmschweitzerandClaude c1ad33f1b0 bundle Josefin Sans as the default UI face at weight 300
Vendor the JosefinSans variable font (upright + italic, weight range
100-700), OFL licensed. _AppRoot installs it as the ambient
DefaultTextStyle at weight w300 (Light); ClideText inherits rather
than re-specifying the family, so Alchemist's Ahem injection keeps
goldens deterministic per D-024 while production renders the
intended face.

typography.dart gains clideUiFamily + clideUiFamilyFallback
alongside the existing mono constants; .gitignore learns about
Alchemist's failures/ diff output dir so local re-runs don't leak
into `git status`.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 08:18:15 +02:00
jpmschweitzerandClaude 7bdeb9ab24 bundle JetBrains Mono for terminal panes
Vendor the 4 core weights (Regular, Italic, Bold, BoldItalic) of
JetBrains Mono v2.304 under app/assets/fonts/jetbrains_mono/, ~1 MB
total. OFL license checked in alongside. Declared as the
JetBrainsMono family in pubspec so Flutter bundles it automatically.

app/lib/widgets/src/typography.dart exposes clideMonoFamily plus a
platform-ordered fallback chain (SF Mono / Menlo / Monaco →
JetBrains Mono system install / Fira Code / Hack / DejaVu / Liberation →
Cascadia / Consolas → monospace) for web builds and test harnesses
that don't load asset fonts. Terminal widgets pick both up via a
single import.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-22 08:02:10 +02:00
jpmschweitzerandClaude 0412a2284a scaffold ptyc — C PTY-spawn helper (libc only)
One-shot helper that opens a PTY, forks a child, execvp's the given
argv with the slave as stdin/stdout/stderr, and hands the master fd
back to the caller over a unix socket via SCM_RIGHTS. Wire contract
is stdin JSON → stdout JSON + fd transfer per D-005; socket fd
defaults to 3 with PTYC_SOCK_FD override for language runtimes whose
subprocess machinery shuffles the low fd numbers.

Minimal JSON parser (no deps) scoped to the exact accepted shape.
Exec-failure pipe (CLOEXEC) reports child-side errors back without
zombies. Window size applied via TIOCSWINSZ before fork; child
becomes session leader + makes the slave its controlling TTY.

Root Makefile PTYX_PRESENT typo fixed → PTYC_PRESENT, and a
ptyc-test target added alongside ptyc-build / ptyc-clean. Eight
smoke tests pass (happy path, env replacement, cwd, window size,
bad argv, type errors, exec failure, unknown keys).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 22:27:20 +02:00
jpmschweitzerandClaude e2b3f7cff1 update CLAUDE.md and reserve decision/ticket/claude-control slots
test / unit + widget + golden + a11y (push) Successful in 4m34s
test / integration_test (xvfb) (push) Failing after 1m4s
test / bundle smoke (xvfb 5s) (push) Failing after 58s
test / daemon subprocess + web WASM smoke (push) Successful in 2m27s
CLAUDE.md gains a "Decision discipline" guardrail pointing at
decisions/<domain>.md, rewrites every inline ADR link to the new
anchor-link style (ADR 0001 → D-001, etc.), collapses the bottom
"Open questions" section to a one-line pointer, and updates the
parent-project note to reference decisions/architecture.md instead
of the deleted docs/ADRs/.

Three extension slots are reserved with id-only stubs, registered
alongside the existing 21 built-ins in main.dart:
  - builtin.decisions — future sidebar for D/Q/R records
  - builtin.tickets — future sidebar + kanban workspace
  - builtin.claude-control — future .claude/ first-class surface
    (Settings / Skills / Agents / Hooks / MCP). Distinct from the
    existing builtin.claude PTY-pane stub.

`flutter analyze` clean; builtin + a11y test suites still pass.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 17:32:06 +02:00
jpmschweitzerandClaude 4dd9a74be7 add decisions-validate pre-push gate
One new Makefile target (tools/scripts/plan decisions validate)
wired as a prerequisite of push-check so malformed records fail
locally before they reach a reviewer. Parser dry-run is cheap
(~100ms) and stays within the <90s pre-push budget.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 17:28:44 +02:00
jpmschweitzerandClaude a96a54ec7f add Python stopgap planning tooling under tools/scripts/plan
Ports settled-reach's decisions_sync.py + ticket + decision scripts,
Scrum-stripped. Writes to .pql/pql.db (gitignored). Verb shape
mirrors the eventual `pql` subcommands so migration is a call-site
find-replace once pql ships feature parity (D-040, R-011).

Ticket IDs are T-NNN (TEXT PKs) — reshape from settled-reach's
integer auto-increment so the stopgap's writes are compatible with
pql's future reads without a data migration. No `sprints` table; the
pyramid is kanban / waterfall (D-035).

Verified end-to-end: sync parses 71 records (39 confirmed, 23 open
questions, 9 rejected) with 62 cross-refs and zero broken links;
`ticket new`, `ticket status`, `ticket board`, and `decisions show
--with-refs` all round-trip correctly.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 17:28:10 +02:00
jpmschweitzerandClaude cede971646 migrate ADRs into D/R records; delete docs/ADRs/
Lift docs/ADRs/0001-0006 into decisions/:
  0001 → D-001 (CLI-first, not MCP)
  0002 → R-002 (Go sidecar; superseded by D-005)
  0003 → D-003 (pql as supporter tool; wrap, don't duplicate)
  0004 → D-004 (ignore file strategy)
  0005 → D-005 (Dart core; sidecar dissolved; ptyc as pql-peer)
  0006 → D-006 (CLI and event surface contract)

ADR 0006's trailing open-questions footer migrates to
questions-architecture.md as Q-001 / Q-002 / Q-003 (already landed
in the scaffold commit). Titles preserved verbatim; cross-references
updated to the new anchor-link style.

docs/ADRs/ deleted — originals remain in git history.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 17:13:37 +02:00
jpmschweitzerandClaude 4d515ce51e scaffold decisions/ with backlog from planning sessions
Adopt settled-reach's Q&D record convention. Confirmed decisions
live under decisions/<domain>.md as D-NNN; open questions under
questions-<domain>.md as Q-NNN; rejected alternatives in rejected.md
as R-NNN. Markdown is source of truth; .pql/pql.db (added later) is a
query index.

Backlog captured from the Tier-0 Flutter planning sessions: bare
WidgetsApp, theme pipeline, kernel admission rule, feature-first
layout, a11y + i18n as Tier-0 contracts, test pyramid, kanban over
Scrum, pql-owns-planning, Python stopgap sunset clause.

ADR migration (D-001, D-003-D-006 confirmed, R-002 rejected) is
staged for the next commit so the diff stays readable.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 17:10:42 +02:00
jpmschweitzerandClaude 77e395b3f2 document test layers and Claude's UI workflow
Three docs under docs/testing/:

  * README.md — layer-by-layer reference (what each covers, the
    runner, how to invoke, local vs CI flow). Points at the load-
    bearing startup gate and the client-side-only constraint so a
    macOS clone runs the same suite as Linux.
  * a11y-manual.md — 15-minute manual checklist run at every tier
    cut. Orca on Linux, VoiceOver on macOS. Catches prose drift
    automation can't judge.
  * claude-ui-workflow.md — how Claude Code drives the WASM build
    through Playwright, including the `flt-semantics-placeholder`
    quirk (semantics are opt-in in Flutter web; the driver
    auto-clicks the placeholder to enable them).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:50:05 +02:00
jpmschweitzerandClaude 7507e6c7fc add Makefile test-layer targets + rename coverage.sh
Makefile grows targets for each test layer (test, test-a11y,
test-integration, test-e2e, test-all), the coverage + smoke-bundle
helpers, and the UI harness (ui-dev, ui-stop, ui-smoke). push-check
now runs `test + test-a11y` — fast pre-push gate under 90s.

ci/coverage.sh is renamed to ci/test_coverage.sh so it matches the
`test_*.sh` naming of the other layer scripts and sidesteps the
repo's `coverage.*` gitignore pattern (intended for coverage output
files like coverage.lcov, not scripts).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:49:45 +02:00
jpmschweitzerandClaude 02cabcad35 add per-layer CI scripts and Gitea workflow (not activated)
ci/*.sh — shell-only, client-side-only so `git clone && make test`
works on any Linux or macOS dev box without network or shared state.
One script per testing layer so both Makefile targets and the CI
workflow can call them without duplicating logic. Rewrite of the
existing ci/test.sh to shell out to dart + flutter layers in one
pass (analyze, format, dart test, flutter test) plus five new
scripts for the other layers.

smoke_bundle.sh is the "tests passed but app doesn't start" gate
the user flagged: builds the Linux release bundle, runs it under
xvfb for 5s, fails on any non-SIGTERM exit — catches dynamic-linker
errors, missing-asset regressions, plugin-init crashes that widget
tests can't see.

.gitea/workflows/test.yml is a four-job pipeline (unit, integration,
startup-bundle, e2e) that shells out to the ci/*.sh scripts. NOT
activated — Gitea Actions has to be enabled in the instance settings
first. GitHub-Actions-compatible, so copying to .github/workflows/
is the whole migration if the repo moves.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:48:41 +02:00
jpmschweitzerandClaude c8d019e630 add web WASM Playwright harness for UI driving
tools/ui/ — scripts + Playwright config that let Claude Code (and
humans) drive the Flutter WASM build in a real browser. The point is
to avoid screenshot round-trips: every interactive widget in clide
ships a Semantics wrapper anyway (a11y requirement), so the automation
layer just queries the `flt-semantics[aria-label]` DOM.

  * build.sh — `flutter build web --wasm` from app/
  * serve.sh — `python3 -m http.server 4280` in the background.
    Before binding, kills any stale listener on the port (orphans
    from earlier failed runs no longer accumulate).
  * stop.sh — port-based kill; escalates to SIGKILL after 300ms.
    The pidfile is now advisory — port ownership is the source of
    truth.
  * driver.ts — `ClideDriver` class with `byLabel`, `click`, `type`,
    `readText`, `screenshot`, `dumpSemanticsTree`, and
    `waitUntilReady` that auto-clicks the `flt-semantics-placeholder`
    so the semantic tree is populated before queries.
  * tests/smoke.spec.ts — first driver test; asserts welcome +
    disconnected labels surface in the Semantics DOM.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:48:07 +02:00
jpmschweitzerandClaude 370e800864 add integration tests for app boot, theme picker, extension lifecycle
Three tests under app/integration_test/, run against the real built
app via the integration_test package. The load-bearing one is
app_starts_test.dart — boots ClideApp, waits for the root shell to
settle, asserts the three-column layout + welcome tab + statusbar
indicator all render. This is the "tests pass and then app fails to
start" gate that widget tests can't see because they never pump the
real bindings.

theme_picker_test.dart invokes theme.pick, asserts the modal opens,
selects a theme, asserts the modal dismisses.

extension_lifecycle_test.dart disables ipc-status via settings,
asserts its statusbar item unmounts, re-enables, asserts it
reappears.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:47:36 +02:00
jpmschweitzerandClaude 96b26e29f0 add app test suite — unit, widget, golden, a11y (168 tests)
Four layers under app/test/:

  * kernel/, extension/ — unit tests for every kernel service and
    the extension contract. i18n fallback chain gets the full
    matrix (exact/lang/default/placeholder, namespace isolation,
    unknown namespace, interpolation). Theme resolver and
    extension-manager topo sort covered.
  * widgets/, builtin/ — widget tests for every primitive and each
    Tier 0 built-in. Assertions reach into the Semantics node so
    a missing label fails structurally, not visually.
  * goldens/ — Alchemist + Ahem font for cross-platform pixel
    stability; primitives only (button, tab bar, icon set). No
    goldens for compositions — they'd churn through every tier.
  * a11y/ — contract-level gate: semantic coverage walks the
    built-in catalogue, contrast walks every token pair in every
    bundled theme against WCAG-AA thresholds (catches real
    regressions: the first run caught `tab.inactive_text` at 2.81
    in summer-night), i18n coverage asserts every referenced key
    exists in its catalog (exists-in-map, not "key == value" — too
    ambiguous for keys that happen to equal their translation).

Helpers under helpers/: `KernelFixture.create()` boots a
KernelServices with in-memory stores + a FakeDaemonClient (no
socket, drivable connected-state), `widget_harness` wraps a
widget in the minimum tree that resolves theme + i18n.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:47:14 +02:00
jpmschweitzerandClaude b13483e2d5 scaffold Flutter app — kernel, extensions, widgets, Tier 0 built-ins
First real content under app/. Lays the whole Tier 0 foundation in one
commit because the pieces depend on each other circularly (kernel →
extension → widgets → built-ins all reference types from the layer
below); splitting would leave intermediate commits that don't compile.

Key shapes:

  * bare WidgetsApp root — no Material, no Cupertino, no Scaffold.
    ClideTheme InheritedWidget is the only source of tokens.
  * ClideKernel InheritedWidget aggregates 18 services (settings,
    project, extensions, theme, panels, events, ipc, commands +
    palette + keybindings, clipboard, files, notify, dialog, tray,
    secrets, os, net, focus, log, i18n). ExtensionContext exposes
    them through a stable interface.
  * ClideExtension + sealed ContributionPoint hierarchy (Tab,
    StatusItem, Toolbar, Command, TrayItem, LayoutPreset). One
    manifest ships N contributions into kernel slots.
  * Three-tier theme pipeline: palette (named colors) → semantic
    roles → ~60 surface tokens. Defaults at each layer so legacy
    palette-only themes produce a complete SurfaceTokens.
  * A11y baked in from day one — every interactive primitive wraps
    in Semantics(label:, hint:, button:); ensureSemantics() at boot;
    theme/contrast.dart helper exposes token pairs for the WCAG
    gate in the a11y test suite.
  * i18n ported from fframe's L10n pattern (text-driven, namespaced
    JSON catalogs, caller-supplied placeholders) with a proper
    locale fallback chain (exact → language → default → placeholder)
    fframe lacks.
  * Four Tier-0 built-ins live (default-layout, welcome, ipc-status,
    theme-picker) plus 17 id-reserving stubs so later tiers fill in
    without rename churn.

.gitignore extended to cover app/ sub-package artefacts and the
Playwright harness scratch dirs.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:39:41 +02:00
jpmschweitzerandClaude 235cbcc046 add Dart core package — IPC envelopes, daemon, ping round-trip
First real content for the `clide` Dart package at the repo root.
One AOT-compiled binary (ADR 0005) with two modes:

  * `clide --daemon`  long-running unix-socket server; listens on
    `$XDG_RUNTIME_DIR/clide-$USER.sock` with stale-socket
    reclaim, accepts JSON-lines request/response traffic, clean
    SIGTERM shutdown unlinks the socket file.
  * `clide <subcommand>`  one-shot; opens the socket, sends a
    request, writes the response JSON to stdout, exits with the
    dispatcher's error code per ADR 0006 (0/1/2/3/4). Unknown
    subcommands forward to the daemon so extensions can register
    their own without CLI changes.

Tier 0 handlers: `ping` (returns pong + version + UTC ts) and
`version`. Both are covered by `test/ipc/` + `test/daemon/`; the
subprocess test builds `bin/clide`, starts it, pings it, SIGTERMs
it, and asserts the socket file disappears.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:36:40 +02:00
jpmschweitzerandClaude bded1a2b65 add Bazzite Flutter dev setup script
One-shot installer that drops the Flutter SDK under ~/opt/flutter,
wires PATH in ~/.bashrc and ~/.zshrc, and layers the desktop build
deps (GTK, ninja, clang, etc.) via rpm-ostree install. Reboot
required before `flutter doctor` will report green.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:36:11 +02:00
jpmschweitzerandClaude 329923538e swap .claude permissions from Go tooling to Dart + Flutter
Go sidecar is retired (ADR 0005). The matching Claude-Code allow list
still permitted `go`, `golangci-lint`, `goreleaser`, `govulncheck`,
`npm` — none of which are used anymore. Narrow the allow list to the
commands that actually run in this project.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 15:35:47 +02:00
jpmschweitzerandClaude 9522625304 retire Go sidecar; adopt Dart core (ADR 0005)
ADR 0005 supersedes ADR 0002. The "sidecar vs app" split was
load-bearing on Go-vs-Dart being a meaningful boundary. Going
all-Dart collapses that — the daemon becomes clide --daemon mode
of the same AOT binary the CLI lives in, both sharing lib/ with
the Flutter app. The one native gap (Dart's multi-threaded VM
can't safely fork+exec) is filled by a small C supporter tool —
ptyc, Project Terminal Controller, peer of pql — rather than
introducing a second core language.

ADR 0006 defines the CLI/event surface on top of that Dart core:
subsystem list (pane/tab/editor/panel/tree/git/pql/canvas/graph/
theme/settings/project), command shape, versioned JSON event
schema, pql-parity exit codes, and command-event duality as the
operational form of user/Claude parity.

Deleted: sidecar/cmd, sidecar/go.mod, every sidecar/internal
package. Rewritten: Makefile (dart compile exe, flutter
analyze/format/test, build-linux/build-macos, ptyc-build),
ci/*.sh, .githooks/pre-push (no more GOBIN PATH dance),
.gitignore (Flutter/Dart at repo root, ptyc section),
project.yaml (drop module: and go_version:), CLAUDE.md
(guardrails, dependencies, commands refreshed).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-21 00:28:27 +02:00
jpmschweitzerandClaude Opus 4.7 0de5f06f43 add pre-push quality gate
.githooks/pre-push runs make push-check, which aggregates the gates
that must pass before a push lands: Go lint, test, test-race, build,
test-integration, vuln, plus Flutter app-analyze and app-test. App-
side targets gracefully noop until Flutter is scaffolded, so the
gate is usable today without waiting on the app bootstrap.

Hooks are versioned under .githooks/ rather than the usual local
.git/hooks so the gate travels with the repo. `make hooks` wires
them up by pointing git core.hooksPath at the tracked directory —
one-time setup, documented in CLAUDE.md alongside `make tools`.

The hook prepends $GOBIN/$HOME/go/bin to PATH before invoking make,
so govulncheck / goimports / golangci-lint installed via `make tools`
resolve even when the user hasn't added that directory to their
login PATH.

The git-commit skill already forbids --no-verify, which is what keeps
this gate meaningful: "the hook is slow" is a reason to fix the slow
test, not to bypass the gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 22:14:12 +02:00
jpmschweitzerandClaude Opus 4.7 c39c2df6f5 add Go sidecar and CLI skeleton
cmd/clide/main.go is the single entry; the same binary will later
switch into sidecar-daemon mode via --daemon. internal/cli holds the
dispatch (stdlib flag for now, Cobra arrives with the first real
subcommand in Tier 2). internal/diag mirrors pql's exit-code contract
so the two tools share one mental model for callers. internal/version
exposes the build-info struct that the Makefile's -ldflags -X targets
stamp; Info() is wired to --version so the binary reports both the
declared project.yaml version and the commit it was built from.

The daemon, pty, proc, git, ipc, and pql sub-packages ship as doc.go
stubs naming the subsystem they will own. They keep the layout legible
before the code lands so tier work has a home on arrival.

Module path targets Gitea (git.schweitz.net/jpmschweitzer/clide/sidecar),
matching where the repo lives. Go module resolution works if the host
serves the meta tags; a vanity import path can be added later if
needed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 22:11:54 +02:00
jpmschweitzerandClaude Opus 4.7 4ae53ba16a add Makefile, ci scripts, and pinned tooling
Root Makefile drives both the Go sidecar under sidecar/ and the Flutter
app under app/ through one interface. Mirrors the pql/claudian pattern:
VERSION read from project.yaml via awk and stamped into the sidecar
binary via -ldflags -X, so the version the codebase claims to be and
the version the binary reports cannot drift.

Flutter targets (app-analyze, app-test, app-build-*) check for
app/pubspec.yaml and flutter on PATH and gracefully noop when either
is missing. That makes the Makefile usable today — before the app is
scaffolded — without ceremony.

ci/ scripts shell out to the Makefile so local dev and CI run the same
commands. lint.sh includes the supply-chain gate (make security) so
there is no version of "green lint, known-vulnerable dep" that CI
accepts.

make tools installs govulncheck, goimports, and golangci-lint at
exact pinned versions — bump deliberately, never floating.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:47:53 +02:00
jpmschweitzerandClaude Opus 4.7 16e43d3096 add CLAUDE.md orientation for the Flutter rebuild
Lean orientation doc for future Claude Code instances. States the
three surfaces (Flutter app, Go sidecar/CLI, pql as supporter),
summarizes the guardrails as one-liners with pointers into ADRs
0001-0004, lists the tier ordering so new work doesn't skip ahead,
and names the parent projects (legacy/ for Python clide, the
discarded claudian experiment that contributed the architectural
patterns, pql as the active supporter). Commands section is a
placeholder until the Makefile lands in the next commit.

Orientation, not a decision log — rationale lives in the ADRs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:44:44 +02:00
jpmschweitzerandClaude Opus 4.7 a48ccedfd4 add Flutter-rebuild project identity at the repo root
project.yaml is fresh and declares version 2.0.0-dev — a clean break
from Python clide's v1.2.0 (which remains under legacy/). It carries
module path, toolchain pins (go >=1.25, Flutter stable, Dart >=3.5),
and the Gitea repository URL. Same schema as the Makefile will read
via awk for sidecar version stamping.

README.md and LICENSE land alongside. The README pitches the rebuild
tersely and points at docs/initial-plan.md for the full story; the
Python README is preserved under legacy/README.md.

.gitignore is rewritten for the new toolchain. The previous file was
wall-to-wall Python rules; now the root ignores Flutter/Dart/Go build
output plus the usual OS/editor/secrets/.claude-local entries, and
Python-specific rules scope to legacy/** so they don't fire on any
stray caches at the repo root.

.editorconfig sets tabs for Go, two-space for Dart and everything
else, and the usual EOL + trailing-whitespace rules.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:43:41 +02:00
jpmschweitzerandClaude Opus 4.7 005d19ae93 add initial plan for the Flutter rebuild
docs/initial-plan.md is the new north star. It states the rebuild's
premise explicitly: Python Clide's IDE skeleton gets rebuilt native
in Flutter, a sharpened subset of Obsidian's ideas (just canvas and
graph — no vault, no bases, no plugin inheritance) folds in, and
the architectural patterns from the short-lived claudian plugin
port over via ADRs 0001–0004.

Tier 0 is "Flutter app + sidecar daemon connected, empty IDE."
Tier 1 is "Claude runs inside clide, session survives app restart."
Later tiers layer panes, git, pql integration, canvas and graph,
and an extension API — each ordered so the guardrails (CLI-first,
user/Claude parity, pql-as-subsystem) stay enforceable at every
step.

Future Claude Code instances should read this before proposing
changes that touch architecture.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:41:43 +02:00
jpmschweitzerandClaude Opus 4.7 a782511470 carry forward ADRs, Claude Code config, and changelog discipline
Ports the patterns that crystallized during the short-lived claudian
plugin project (discarded in favour of this Flutter rebuild):

- ADRs 0001-0004 capture decisions that survive the host change —
  CLI-first over MCP, Go for the sidecar, pql as a supporter tool
  that becomes a clide-managed subsystem when present, and the
  ignore-file strategy that wires all file-enumerating surfaces
  through one knob in .pql/config.yaml.
- .claude/settings.json and the git-commit and skill-create skills
  come over with naming updated for clide. The git-commit skill's
  "no Conventional Commits" convention supersedes the Python-era
  clide style under legacy/; the Keep-a-Changelog discipline and
  the project.yaml-version-and-changelog-bumped-together rule
  apply going forward.
- CHANGELOG.md starts fresh at the repo root to track the Flutter
  rebuild. The Python changelog is preserved under legacy/.

.gitignore narrows from `.claude/` to just `.claude/settings.local.json`
so project-level config and skills travel with the repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 20:38:49 +02:00
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
jpmschweitzerandClaude Opus 4.6 30b8cf7db9 docs: update documentation for clide-web and v1.2.0
- CHANGELOG: add v1.2.0 with clide-web, database layer, workspace tabs,
  and ttyd/zellij removal
- CLAUDE.md: add clide-web to tech stack, dev commands, and project
  structure
- web-deployment.md: document /projects/<name> routing, setup wizard,
  auto-respawn, database schema, and make targets
- install-clide-web.sh: update URLs to path-based routing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:06:12 +01:00
jpmschweitzerandClaude Opus 4.6 a14f15d675 chore: replace echo with printf in Makefile
Use printf instead of echo for consistent ANSI color rendering
across shells and make implementations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:04:31 +01:00
jpmschweitzerandClaude Opus 4.6 0c1c935230 fix: match context panel backgrounds to sidebar
Change JiraView, TodosView, and ProblemsView backgrounds from
\$background to \$surface so the right panel visually matches the
left sidebar panel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:04:04 +01:00
jpmschweitzerandClaude Opus 4.6 b2a18b6b20 refactor: remove ttyd + zellij, update deploy for clide-web
Remove all external binary dependencies that clide-web replaces:
- ttyd-nerd-font git submodule (C binary)
- zellij config (config.kdl, bare.kdl)
- clide-launcher shell script
- update-ttyd.sh build script

Update systemd service and install script for the new FastAPI stack.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:03:53 +01:00
jpmschweitzerandClaude Opus 4.6 56a8ea4ba4 feat: add clide-web package replacing ttyd + zellij
Python web server that wraps Clide for browser access. Replaces the
previous ttyd (C binary) + zellij (Rust binary) stack with a single
FastAPI application using tmux for session persistence.

Key features:
- WebSocket ↔ PTY bridge via tmux attach
- Project switching via /projects/<name> URL routing
- Vendored xterm.js for offline LAN operation
- Auto-respawn on Clide exit (tmux pane-died hook)
- Setup wizard for first-run configuration
- No scrollbar (TUI manages its own scrolling)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:03:43 +01:00
jpmschweitzerandClaude Opus 4.6 29a858d7a8 feat: add SQLite database layer with SQLModel
Add shared database infrastructure to clide core for use by both
the CLI and clide-web. SQLModel provides Pydantic-native models
that double as SQLAlchemy table definitions.

Models: Project, Session, UserPreference, ConnectionLog.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:01:55 +01:00
jpmschweitzerandClaude Opus 4.6 a14ee82883 feat: dynamic tabbed workspace with multi-file and multi-terminal support
Replaces the fixed 3-tab workspace (Editor/Diff/Terminal) with a VS Code-style
dynamic tab system. Users can now open multiple files, terminals, and diffs in
closeable tabs with type icons, modified indicators, and file deduplication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:33:47 +01:00
jpmschweitzerandClaude Opus 4.6 cd949e4d9c Update TODO: mark completed items
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:14:18 +01:00
jpmschweitzerandClaude Opus 4.6 86ceb2de56 Add terminal tabs TODO item
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 02:44:58 +01:00
jpmschweitzerandClaude Opus 4.6 27b19d4698 feat: Nerd Font support, clipboard paste, and PTY environment fixes
- Add ttyd-nerd-font submodule with embedded JetBrains Mono Nerd Font
  for proper icon rendering in browser via ttyd
- Add Ctrl+Shift+V / Shift+Insert paste support in ttyd frontend
- Strip Zellij env vars from PTY child processes to prevent workspace
  terminal from inheriting Zellij session context
- Launch PTY commands through login shell for proper PATH resolution
- Use /etc/passwd shell lookup instead of $SHELL (Zellij overrides it)
- Soften ANSI 256-color palette to match modern dark themes
- Handle Nerd Font PUA glyphs as width 1 in pyte terminal emulator
- Fix brightmagenta typo in pyte graphics
- Update install script to build ttyd from submodule source
- Add web deployment TODO items for image paste and context menu

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 02:44:08 +01:00
jpmschweitzerandClaude Opus 4.6 b1d0b2a5af feat: replace simple terminal with full PTY terminal emulator
Extract TerminalDisplay from ClaudePanel into a shared widget module
and rewrite TerminalPane to use it. The workspace terminal now runs
an interactive shell via PTY instead of a simple command runner,
supporting colors, escape sequences, tab completion, and interactive
programs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:36:05 +01:00
jpmschweitzerandClaude Opus 4.6 91703e2d11 Harden service restart and disable Zellij UI artifacts
Service: add TimeoutStopSec=5 and SendSIGKILL=yes so restarts don't
hang on stubborn claude processes. Reduce RestartSec to 3s.

Zellij: disable session serialization, release notes, and splash screen
so sessions always start fresh with the bare layout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:19:40 +01:00
jpmschweitzerandClaude Opus 4.6 7fcdae3f2e Remove goto line keybinding from CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:01:20 +01:00
jpmschweitzerandClaude Opus 4.6 dba0e4805f Add web deployment layer and docs for browser-based setup
Pull ttyd/zellij/clide-launcher scripts into deploy/ so the web access
layer lives with the project. Zellij is configured in locked mode with a
bare layout so it only provides session persistence without intercepting
keys or showing UI. Remove Ctrl+G goto-line binding from Clide to avoid
conflict with Zellij's unlock key.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:00:20 +01:00
jpmschweitzerandClaude Opus 4.5 c5f8b2e615 Add Clide project structure and initial implementation
Set up the TUI IDE wrapper for Claude Code CLI with:
- Core app structure using Textual framework
- Panel architecture (sidebar, workspace, claude, context)
- Theme system with 22 built-in themes (Summer Night default)
- Pydantic models for configuration and data
- Makefile for development commands
- Project documentation and specs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 21:04:44 +01:00
jpmschweitzer 12825e15e2 Initial commit 2026-01-31 10:30:14 +01:00