27 KiB
27 KiB
BTerminal — Claude Behavioral Guide
Workflow
- v1 is a single-file Python app (
bterminal.py). Changes are localized. - v2 docs are in
docs/. Architecture decisions are indocs/task_plan.md. - v2 Phases 1-7 + multi-machine (A-D) + profiles/skills complete. Extras: SSH, ctx, themes, detached mode, auto-updater, shiki, copy/paste, session resume, drag-resize, session groups, Deno sidecar, Claude profiles, skill discovery.
- v3 Mission Control (All Phases 1-10 Complete + S-1 Phase 1/1.5/2/3 + S-2 Session Anchors + Provider Adapter Pattern + Provider Runners + Memora Adapter + SOLID Phase 3 + Multi-Agent Orchestration): project groups, workspace store, 15 Workspace components, session continuity, workspace teardown, file overlap conflict detection, inotify-based external write detection, multi-provider adapter pattern (3 phases + Codex/Ollama runners), worktree isolation, session anchors, Memora adapter (read-only SQLite), SOLID refactoring (agent-dispatcher split → 4 utils, session.rs split → 7 sub-modules, branded types), multi-agent orchestration (btmsg inter-agent messaging, bttask kanban task board, agent prompt generator, BTMSG_AGENT_ID env passthrough, periodic re-injection, role-specific tabs: Manager=Tasks, Architect=Arch, Tester=Selenium+Tests, Reviewer=Tasks), dead v2 component cleanup, dashboard metrics panel (MetricsPanel.svelte — live health + task counts + SVG sparkline history), auto-wake Manager scheduler (3 strategies: persistent/on-demand/smart, 6 signal types, configurable threshold), reviewer agent role (workflow prompt, #review-queue/#review-log auto-channels, reviewQueueDepth attention scoring 10pts/task cap 50, Tasks tab). 388 vitest + 76 cargo tests.
- v3 docs:
docs/v3-task_plan.md,docs/v3-findings.md,docs/v3-progress.md. - Consult Memora (tag:
bterminal) before making architectural changes.
Documentation References
- Architecture & decisions: docs/task_plan.md
- Implementation phases: docs/phases.md
- Research findings: docs/findings.md
- Progress log: docs/progress.md
- v3 architecture: docs/v3-task_plan.md
- v3 findings: docs/v3-findings.md
- v3 progress: docs/v3-progress.md
Rules
- Do not modify v1 code (
bterminal.py) unless explicitly asked — it is production-stable. - v2/v3 work goes on the
v2-mission-controlbranch, not master. - v2 architecture decisions must reference
docs/task_plan.mdDecisions Log. - v3 architecture decisions must reference
docs/v3-task_plan.mdDecisions Log. - When adding new decisions, append to the Decisions Log table with date.
- Update
docs/progress.mdafter each significant work session.
Key Technical Constraints
- WebKit2GTK has no WebGL — xterm.js must use Canvas addon explicitly.
- Agent sessions use
@anthropic-ai/claude-agent-sdkquery() function (migrated from raw CLI spawning due to piped stdio hang bug). SDK handles subprocess management internally. All output goes through the adapter layer (src/lib/adapters/claude-messages.tsviamessage-adapters.tsregistry) — SDK message format matches CLI stream-json. Multi-provider support: message-adapters.ts routes by ProviderId to provider-specific parsers (claude-messages.ts, codex-messages.ts, ollama-messages.ts — all 3 registered). - Sidecar uses per-provider runner bundles (
sidecar/dist/{provider}-runner.mjs). Currently onlyclaude-runner.mjsexists. SidecarManager.resolve_sidecar_for_provider(provider) finds the right runner file. Deno preferred (faster startup), Node.js fallback. Communicates with Rust via stdio NDJSON. Claude CLI auto-detected at startup viafindClaudeCli()— checks ~/.local/bin/claude, ~/.claude/local/claude, /usr/local/bin/claude, /usr/bin/claude, thenwhich claude. Path passed to SDK viapathToClaudeCodeExecutableoption. Agents error immediately if CLI not found. Provider env var stripping: strip_provider_env_var() strips CLAUDE*/CODEX*/OLLAMA* vars (whitelists CLAUDE_CODE_EXPERIMENTAL_*). Dual-layer: (1) Rust env_clear() + clean_env, (2) JS runner SDKenvoption. Session stop uses AbortController.abort().agent-runner-deno.tsexists as standalone alternative runner but is NOT used by SidecarManager. - AgentPane does NOT stop agents in onDestroy — onDestroy fires on layout remounts, not just explicit close. Stop-on-close is handled externally (was TilingGrid in v2, now workspace teardown in v3).
- Agent dispatcher (
src/lib/agent-dispatcher.ts) is a thin coordinator (260 lines) routing sidecar events to the agent store. Delegates to extracted modules:utils/session-persistence.ts(session-project maps, persistSessionForProject),utils/subagent-router.ts(spawn + route subagent panes),utils/auto-anchoring.ts(triggerAutoAnchor on compaction),utils/worktree-detection.ts(detectWorktreeFromCwd pure function). Provider-aware via message-adapters.ts. - AgentQueryOptions supports
providerfield (defaults to 'claude', flows Rust -> sidecar),provider_configblob (Rust passes through as serde_json::Value),permission_mode(defaults to 'bypassPermissions'),setting_sources(defaults to ['user', 'project']),system_prompt,model,claude_config_dir(for multi-account),additional_directories,worktree_name(when set, passed asextraArgs: { worktree: name }to SDK →--worktree <name>CLI flag),extra_env(HashMap<String,String>, injected into sidecar process env; used for BTMSG_AGENT_ID). - Multi-agent orchestration: Tier 1 (management agents: Manager, Architect, Tester, Reviewer) defined in groups.json
agents[], converted to ProjectConfig viaagentToProject(), rendered as full ProjectBoxes. Tier 2 (project agents) are regular ProjectConfig entries. Both tiers get system prompts. Tier 1 prompt built bygenerateAgentPrompt()(utils/agent-prompts.ts): 7 sections (Identity, Environment, Team, btmsg docs, bttask docs, Custom context, Workflow). Tier 2 gets optionalproject.systemPromptas custom context. BTMSG_AGENT_ID env var injected for Tier 1 agents only (enables btmsg/bttask CLI usage). Periodic re-injection: AgentSession runs 1-hour timer, sends context refresh prompt when agent is idle (autoPrompt → AgentPane → startQuery with resume=true). - bttask kanban: Rust bttask.rs module reads/writes tasks table in shared btmsg.db (~/.local/share/bterminal/btmsg.db). 7 operations: list_tasks, create_task, update_task_status, delete_task, add_comment, task_comments, review_queue_count. Frontend: TaskBoardTab.svelte (kanban 5 columns, 5s poll). CLI
bttasktool gives agents direct access; Manager has full CRUD, Reviewer has read + status + comments, other roles have read-only + comments. On task→review transition, auto-posts to #review-queue btmsg channel (ensure_review_channels creates #review-queue + #review-log idempotently). Reviewer agent gets Tasks tab in ProjectBox (reuses TaskBoardTab). reviewQueueDepth in AttentionInput: 10pts per review task, capped at 50 (priority between file_conflict 70 and context_high 40). ProjectBox polls review_queue_count every 10s for reviewer agents → setReviewQueueDepth() in health store. - btmsg/bttask SQLite conventions: Both btmsg.rs and bttask.rs open shared btmsg.db with WAL mode + 5s busy_timeout (concurrent access from Python CLIs + Rust backend). All queries use named column access (
row.get("column_name")) — never positional indices. Rust structs use#[serde(rename_all = "camelCase")]; TypeScript interfaces MUST match camelCase wire format. TestingTab usesconvertFileSrc()for Tauri 2.x asset URLs (notasset://localhost/). - ArchitectureTab: PlantUML diagram viewer/editor. Stores .puml files in
.architecture/project dir. Renders via plantuml.com server using ~h hex encoding (no Java dependency). 4 templates: Class, Sequence, State, Component. Editor + SVG preview toggle. - TestingTab: Dual-mode component (mode='selenium'|'tests'). Selenium: watches
.selenium/screenshots/for PNG/JPG, displays in gallery with session log, 3s poll. Tests: discovers files in standard dirs (tests/, test/, spec/, tests/, e2e/), shows content. - Worktree isolation (S-1 Phase 3): Per-project
useWorktreestoggle in SettingsTab. When enabled, AgentPane passesworktree_name=sessionIdin queryAgent(). Agent runs in<repo>/.claude/worktrees/<sessionId>/. CWD-based detection:utils/worktree-detection.tsdetectWorktreeFromCwd()matches.claude/worktrees/,.codex/worktrees/,.cursor/worktrees/patterns on init events → callssetSessionWorktree()for conflict suppression. Dual detection: CWD-based (primary, from init event) + tool_call-basedextractWorktreePath()(subagent fallback). - Claude profiles: claude_list_profiles() reads ~/.config/switcher/profiles/ with profile.toml metadata. Profile set per-project in Settings (project.profile field), passed through AgentSession -> AgentPane
profileprop -> resolved to config_dir for SDK. Profile name shown as info-only in ProjectHeader. - ProjectBox has project-level tab bar: Model | Docs | Context | Files | SSH | Memory + role-specific tabs. Three mount strategies: PERSISTED-EAGER (Model, Docs, Context — always mounted, display:flex/none), PERSISTED-LAZY (Files, SSH, Memory, Metrics, Tasks, Architecture, Selenium, Tests — mount on first activation via {#if everActivated} + display:flex/none). Tab type:
'model' | 'docs' | 'context' | 'files' | 'ssh' | 'memories' | 'metrics' | 'tasks' | 'architecture' | 'selenium' | 'tests'. Role-specific tabs: Manager gets Tasks (kanban), Architect gets Arch (PlantUML), Tester gets Selenium+Tests. Metrics tab (all projects): MetricsPanel.svelte — Live view (fleet aggregates, project health grid, task board summary, attention queue) + History view (SVG sparklines for cost/tokens/turns/tools/duration, stats row, session table from session_metrics_load). Conditional onisAgent && agentRole. Model tab = AgentSession+TeamAgentsPanel. Docs tab = ProjectFiles (markdown viewer). Context tab = ContextTab.svelte (LLM context window visualization: stats bar, segmented token meter, file references, turn breakdown; reads from agent store via sessionId prop; replaced old ContextPane ctx database viewer). Files tab = FilesTab.svelte (VSCode-style directory tree + CodeMirror 6 editor with 15 language modes, dirty tracking, Ctrl+S save, save-on-blur setting, image display via convertFileSrc, 10MB gate; CodeEditor.svelte wrapper; PdfViewer.svelte for PDF files via pdfjs-dist with canvas multi-page rendering + zoom 0.5x–3x; CsvTable.svelte for CSV with RFC 4180 parser, delimiter auto-detect, sortable columns). SSH tab = SshTab.svelte (CRUD for SSH connections, launch spawns terminal tab in Model tab). Memory tab = MemoriesTab.svelte (pluggable via MemoryAdapter interface in memory-adapter.ts; MemoraAdapter registered at startup, reads ~/.local/share/memora/memories.db via Rust memora.rs). Tasks tab = TaskBoardTab.svelte (kanban board, 5 columns, 5s poll, Manager only). Arch tab = ArchitectureTab.svelte (PlantUML viewer/editor, .architecture/ dir, plantuml.com ~h hex encoding, Architect only). Selenium tab = TestingTab.svelte mode=selenium (screenshot gallery, session log, 3s poll, Tester only). Tests tab = TestingTab.svelte mode=tests (test file discovery, content viewer, Tester only). Rust backend: list_directory_children + read_file_content + write_file_content (FileContent tagged union: Text/Binary/TooLarge). Frontend bridge: files-bridge.ts. - ProjectHeader shows CWD (ellipsized from START via
direction: rtl) + profile name as info-only text on right side. AgentPane no longer has DIR/ACC toolbar — CWD and profile are props from parent. - Skill discovery: claude_list_skills() reads ~/.claude/skills/ (dirs with SKILL.md or .md files). claude_read_skill() reads content. AgentPane
/prefix triggers autocomplete menu. Skill content injected as prompt via expandSkillPrompt(). - claude-bridge.ts adapter wraps profile/skill Tauri commands (ClaudeProfile, ClaudeSkill interfaces). provider-bridge.ts wraps claude-bridge as generic provider bridge (delegates by ProviderId).
- Provider adapter pattern: ProviderId = 'claude' | 'codex' | 'ollama'. ProviderCapabilities flags gate UI (hasProfiles, hasSkills, hasModelSelection, hasSandbox, supportsSubagents, supportsCost, supportsResume). ProviderMeta registered via registerProvider() in App.svelte onMount. AgentPane receives provider + capabilities props. SettingsTab has Providers section with collapsible per-provider config panels. ProjectConfig.provider field for per-project selection. Settings persisted as
provider_settingsJSON blob. - Sidecar build:
npm run build:sidecarbuilds all 3 runners via esbuild (claude-runner.mjs, codex-runner.mjs, ollama-runner.mjs). Each is a standalone ESM bundle. Codex runner dynamically imports @openai/codex-sdk (graceful failure if not installed). Ollama runner uses native fetch (zero deps). - Agent preview terminal:
AgentPreviewPane.svelteis a read-only xterm.js terminal (disableStdin:true) that subscribes to an agent session's messages via$derived(getAgentSession(sessionId))and renders tool calls/results in real-time. Bash commands shown as cyan❯ cmd, file ops as yellow[Read] path, results as plain text (80-line truncation), errors in red. Spawned via 👁 button in TerminalTabs (appears when agentSessionId prop is set). TerminalTab type:'agent-preview'withagentSessionIdfield. Deduplicates — won't create two previews for the same session. ProjectBox passes mainSessionId to TerminalTabs. - Maximum 4 active xterm.js instances to avoid WebKit2GTK memory issues. Agent preview uses disableStdin and no PTY so is lighter, but still counts.
- Store files using Svelte 5 runes (
$state,$derived) MUST have.svelte.tsextension (not.ts). Import with.sveltesuffix. Plain.tscompiles but fails at runtime with "rune_outside_svelte". - Session persistence uses rusqlite (bundled) with WAL mode. Data dir:
dirs::data_dir()/bterminal/sessions.db. - Layout store persists to SQLite on every addPane/removePane/setPreset/setPaneGroup change (fire-and-forget). Restores on app startup via
restoreFromDb(). - Session groups: Pane.group? field in layout store, group_name column in sessions table, collapsible group headers in sidebar. Right-click pane to set group.
- File watcher uses notify crate v6, watches parent directory (NonRecursive), emits
file-changedTauri events. - Settings use key-value
settingstable in SQLite (session/settings.rs). Frontend:settings-bridge.tsadapter. v3 uses SettingsTab.svelte rendered in sidebar drawer panel (v2 SettingsDialog.svelte deleted in P10). SettingsTab has two sections: Global (single-column layout, split into Appearance [theme dropdown, UI font dropdown with sans-serif options + size stepper, Terminal font dropdown with monospace options + size stepper] and Defaults [shell, CWD] — all custom themed dropdowns, no native<select>, all persisted via settings-bridge with keys: theme, ui_font_family, ui_font_size, term_font_family, term_font_size, default_shell, default_cwd) and Group/Project CRUD. - Notifications use ephemeral toast system:
notifications.svelte.tsstore (max 5, 4s auto-dismiss),ToastContainer.sveltedisplay. Agent dispatcher emits toasts on agent complete/error/crash. - StatusBar → Mission Control bar: running/idle/stalled agent counts (color-coded), total $/hr burn rate, "needs attention" dropdown priority queue (up to 5 cards sorted by urgency score, click-to-focus), total tokens + cost. Uses health.svelte.ts store (not workspace store for health signals).
- health.svelte.ts store: per-project health tracking via ProjectTracker map. ActivityState = inactive|running|idle|stalled (configurable per-project via stallThresholdMin in ProjectConfig, default 15 min, range 5–60 min step 5, synced via setStallThreshold() API). Burn rate from 5-min EMA costSnapshots. Context pressure = tokens/model limit. File conflict count from conflicts.svelte.ts. Attention scoring: stalled=100, error=90, ctx>90%=80, file_conflict=70, ctx>75%=40. 5-second tick timer (auto-stop/start). API: trackProject(), recordActivity(), recordToolDone(), recordTokenSnapshot(), getProjectHealth(), getAttentionQueue(), getHealthAggregates().
- conflicts.svelte.ts store: per-project file overlap + external write detection. Records Write/Edit/Bash-write tool_call file paths per session. Detects when 2+ sessions in same worktree write same file. S-1 Phase 2: inotify-based external write detection via fs_watcher.rs — uses 2s timing heuristic (AGENT_WRITE_GRACE_MS) to distinguish agent writes from external. EXTERNAL_SESSION_ID='external' sentinel. Worktree-aware. Dismissible. recordExternalWrite() for inotify events. FileConflict.isExternal flag, ProjectConflicts.externalConflictCount. Session-scoped, no persistence.
- tool-files.ts utility: shared extractFilePaths(tc) → ToolFileRef[], extractWritePaths(tc) → string[], extractWorktreePath(tc) → string|null. Bash write detection via regex (>, >>, sed -i, tee, cp, mv). Used by ContextTab (all ops) and agent-dispatcher (writes + worktree tracking for conflict detection).
- ProjectHeader shows status dot (green pulse=running, gray=idle, orange pulse=stalled, dim=inactive) + external write badge (orange ⚡ clickable, shown when externalConflictCount > 0) + agent conflict badge (red ⚠ clickable with ✕) + context pressure badge (>90% red, >75% orange, >50% yellow) + burn rate badge ($/hr). Health prop from ProjectBox via getProjectHealth(). ProjectBox starts/stops fs watcher per project CWD via $effect.
- wake-scheduler.svelte.ts store: Manager auto-wake with 3 user-selectable strategies (persistent=resume prompt, on-demand=fresh session, smart=threshold-gated on-demand). Configurable via SettingsTab (strategy segmented button + threshold slider for smart). 6 wake signals from tribunal S-3 hybrid: AttentionSpike(1.0), ContextPressureCluster(0.9), BurnRateAnomaly(0.8), TaskQueuePressure(0.7), ReviewBacklog(0.6), PeriodicFloor(0.1). Pure scorer in wake-scorer.ts (24 tests). Types in types/wake.ts. GroupAgentConfig: wakeStrategy, wakeThreshold fields. ProjectBox registers managers via $effect. AgentSession polls wake events every 5s. Cleared on group switch via clearWakeScheduler().
- session_metrics SQLite table: per-project historical session data (project_id, session_id, timestamps, peak_tokens, turn_count, tool_call_count, cost_usd, model, status, error_message). 100-row retention per project. Tauri commands: session_metric_save, session_metrics_load. Persisted on agent completion via agent-dispatcher.
- Session anchors (S-2): Preserves important turns through compaction chains. Types: auto (on first compaction, 3 turns, observation-masked — reasoning preserved in full, only tool outputs compacted), pinned (user-created via pin button in AgentPane), promoted (user-promoted from pinned, re-injectable). Configurable budget via AnchorBudgetScale ('small'=2K|'medium'=6K|'large'=12K|'full'=20K) — per-project slider in SettingsTab, stored as ProjectConfig.anchorBudgetScale in groups.json. Re-injection: anchors.svelte.ts → AgentPane.startQuery() → system_prompt field → sidecar → SDK. ContextTab shows anchor section with budget meter (derived from scale) + promote/demote. SQLite: session_anchors table. Files: types/anchors.ts, adapters/anchors-bridge.ts, stores/anchors.svelte.ts, utils/anchor-serializer.ts.
- Agent tree (AgentTree.svelte) uses SVG with recursive layout. Tree data built by
agent-tree.tsutility from agent messages. - ctx integration opens
~/.claude-context/context.dbas SQLITE_OPEN_READ_ONLY — never writes. CtxDb uses Option for graceful absence if DB doesn't exist. - SSH sessions spawn TerminalPane with shell=/usr/bin/ssh and args array. No SSH library needed — PTY handles it natively.
- Theme system: 17 themes in 3 groups — 4 Catppuccin + 7 Editor (VSCode Dark+, Atom One Dark, Monokai, Dracula, Nord, Solarized Dark, GitHub Dark) + 6 Deep Dark (Tokyo Night, Gruvbox Dark, Ayu Dark, Poimandres, Vesper, Midnight). All map to same 26 --ctp-* CSS custom properties — zero component changes needed. ThemeId replaces CatppuccinFlavor. getCurrentTheme()/setTheme() are primary API (deprecated wrappers exist). THEME_LIST has ThemeMeta with group metadata for custom dropdown UI. Open terminals hot-swap via onThemeChange() callback registry in theme.svelte.ts. Typography uses --ui-font-family/--ui-font-size (UI elements, sans-serif fallback) and --term-font-family/--term-font-size (terminal, monospace fallback) CSS custom properties (defined in catppuccin.css). initTheme() restores all 4 font settings (ui_font_family, ui_font_size, term_font_family, term_font_size) from SQLite on startup.
- Detached pane mode: App.svelte checks URL param
?detached=1and renders a single pane without sidebar/grid chrome. Used for pop-out windows. - Shiki syntax highlighting uses lazy singleton pattern (avoid repeated WASM init). 13 languages preloaded. Used in MarkdownPane and AgentPane text messages.
- Cargo workspace at v2/ level: members = [src-tauri, bterminal-core, bterminal-relay]. Cargo.lock is at workspace root (v2/), not in src-tauri/.
- EventSink trait (bterminal-core/src/event.rs) abstracts event emission. PtyManager and SidecarManager are in bterminal-core, not src-tauri. src-tauri has thin re-exports.
- RemoteManager (src-tauri/src/remote.rs) manages WebSocket client connections to bterminal-relay instances. 12 Tauri commands prefixed with
remote_. - remote-bridge.ts adapter wraps remote machine management IPC. machines.svelte.ts store tracks remote machine state.
- Pane.remoteMachineId?: string routes operations through RemoteManager instead of local managers. Bridge adapters (pty-bridge, agent-bridge) check this field.
- bterminal-relay binary (v2/bterminal-relay/) is a standalone WebSocket server with token auth, rate limiting, and per-connection isolated managers. Commands return structured responses (pty_created, pong, error) with commandId for correlation via send_error() helper.
- RemoteManager reconnection: exponential backoff (1s-30s cap) on disconnect, attempt_tcp_probe() (TCP-only, no WS upgrade), emits remote-machine-reconnecting and remote-machine-reconnect-ready events. Frontend listeners in remote-bridge.ts; machines store auto-reconnects on ready.
- v3 workspace store (
workspace.svelte.ts) replaces layout store for v3. Groups loaded from~/.config/bterminal/groups.jsonviagroups-bridge.ts. State: groups, activeGroupId, activeTab, focusedProjectId. Derived: activeGroup, activeProjects. - v3 groups backend (
groups.rs): load_groups(), save_groups(), default_groups(). Tauri commands: groups_load, groups_save. - Telemetry (
telemetry.rs): tracing + optional OTLP export to Tempo.BTERMINAL_OTLP_ENDPOINTenv var controls (absent = console-only). TelemetryGuard in AppState with Drop-based shutdown. Frontend events route throughfrontend_logTauri command → Rust tracing (no browser OTEL SDK — WebKit2GTK incompatible).telemetry-bridge.tsprovidestel.info/warn/error()convenience API. Docker stack atdocker/tempo/(Grafana port 9715). - v3 SQLite additions: agent_messages table (per-project message persistence), project_agent_state table (sdkSessionId, cost, status per project), sessions.project_id column.
- v3 App.svelte: VSCode-style sidebar layout. Horizontal: left icon rail (GlobalTabBar, 2.75rem, single Settings gear icon) + expandable drawer panel (Settings only, content-driven width, max 50%) + main workspace (ProjectGrid always visible) + StatusBar. Sidebar has Settings only — Sessions/Docs/Context are project-specific (in ProjectBox tabs). Keyboard: Ctrl+B (toggle sidebar), Ctrl+, (settings), Escape (close).
- v3 component tree: App -> GlobalTabBar (settings icon) + sidebar-panel? (SettingsTab) + workspace (ProjectGrid) + StatusBar. See
docs/v3-task_plan.mdfor full tree. - MarkdownPane reactively watches filePath changes via $effect (not onMount-only). Uses sans-serif font (Inter, system-ui), all --ctp-* theme vars. Styled blockquotes with translucent backgrounds, table row hover, link hover underlines. Inner
.markdown-pane-scrollwrapper withcontainer-type: inline-sizefor responsive padding via--bterminal-pane-padding-inline. - AgentPane UI (redesigned 2026-03-09): sans-serif root font (
system-ui, -apple-system, sans-serif), monospace only on code/tool names. Tool calls paired with results in collapsible<details>groups via$derived.bytoolResultMap (cache-guarded by tool_result count). Hook messages collapsed into compact<details>with gear icon. Context window meter inline in status strip. Cost bar minimal (no background, subtle border-top). Session summary with translucent surface background. Two-phase scroll anchoring ($effect.pre+$effect). Tool-aware output truncation (Bash 500 lines, Read/Write 50, Glob/Grep 20, default 30). Colors softened viacolor-mix(). Inner.agent-pane-scrollwrapper withcontainer-type: inline-sizefor responsive padding via shared--bterminal-pane-padding-inlinevariable. - ProjectBox uses CSS
style:display(flex/none) instead of{#if}for tab content panes — keeps AgentSession mounted across tab switches (prevents session ID reset and message loss). Terminal section also usesstyle:display. Grid rows: auto auto 1fr auto. - Svelte 5 event syntax: use
onclicknoton:click. Svelte 5 requires lowercase event handler attributes (no colon syntax).
Memora Tags
Project tag: bterminal
Common tag combinations: bterminal,architecture, bterminal,research, bterminal,tech-stack
Operational Rules
All operational rules live in .claude/rules/. Every .md file in that directory is automatically loaded at session start by Claude Code with the same priority as this file.
Rule Index
| # | File | Scope |
|---|---|---|
| 01 | security.md |
PARAMOUNT — secrets, input validation, least privilege |
| 02 | error-handling.md |
PARAMOUNT — handle every error visibly |
| 03 | environment-safety.md |
PARAMOUNT — verify target, data safety, K8s isolation, cleanup |
| 04 | communication.md |
Stop on ambiguity, scope discipline |
| 05 | git-practices.md |
Conventional commits, authorship |
| 06 | testing.md |
TDD, unit tests, E2E tests |
| 07 | documentation.md |
README, CLAUDE.md sync, docs/ |
| 08 | branch-hygiene.md |
Branches, naming, clean state before refactors |
| 09 | dependency-discipline.md |
No deps without consent |
| 10 | code-consistency.md |
Match existing patterns |
| 11 | api-contracts.md |
Contract-first, flag breaking changes (path-conditional) |
| 12 | performance-awareness.md |
No N+1, no unbounded fetches (path-conditional) |
| 13 | logging-observability.md |
Structured logging, OTEL (path-conditional) |
| 14 | resilience-and-config.md |
Timeouts, circuit breakers, externalized config (path-conditional) |
| 15 | memora.md |
Persistent memory across sessions |
| 16 | sub-agents.md |
When to use sub-agents and team agents |
| 17 | document-imports.md |
Resolve @ imports in CLAUDE.md before acting |
| 18 | relative-units.md |
Use rem/em for layout, px only for icons/borders |
| 51 | theme-integration.md |
All colors via --ctp-* CSS vars, never hardcode |
| 52 | no-implicit-push.md |
Never push unless explicitly asked |