AI coding assistant: Rust engine (LSP/HTTP server) + React chat UI + IDE plugins (VSCode, JetBrains) + cloud backend.
| Subproject | Path | Language | AGENTS.md |
|---|---|---|---|
| Agent Engine | refact-agent/engine/ |
Rust 2021, async/tokio | ✅ refact-agent/engine/AGENTS.md |
| Agent GUI | refact-agent/gui/ |
TypeScript/React 18 | ✅ refact-agent/gui/AGENTS.md |
| VSCode Extension | plugins/vscode/ |
TypeScript | — |
| JetBrains Plugin | plugins/intellij/ |
Kotlin, Gradle | — |
| Documentation | docs/ |
Astro (static site) | — |
| IDE metadata | .idea/ |
IntelliJ project config | keep local/editor files out of commits; .idea/workspace.xml is ignored |
| Agent notes | .agents/ |
onboarding notes | checked for repo-specific guidance when present |
| Codex workspace | .codex/ |
Codex config/data | checked for repo-specific guidance when present |
Root .gitignore |
.gitignore |
repository ignore rules | includes local editor and build output exclusions; check before adding new generated files |
Sub-project AGENTS.md files contain detailed architecture, patterns, and checklists. Read them before working in those directories.
Always verify your changes compile and pass tests before finishing. Both engine and GUI builds are heavy — plan accordingly.
cd refact-agent/engine
# Fast check — type/borrow errors only (~1-3 min, no codegen)
cargo check
# Unit + doc tests (~3-8 min first build, ~1-3 min incremental)
cargo test --lib && cargo test --doc
# Full release build (~10-20 min cold, ~2-5 min incremental)
# LTO + opt-level=z + strip — very slow from scratch
cargo build --releasecargo test --release on 7 platform targets.
Python integration tests (tests/*.py) require a running refact-lsp instance — don't run them as a quick check.
cd refact-agent/gui
# All CI checks (~1-3 min total)
npm run test # vitest (unit, excludes integration)
npm run format:check # prettier — no code changes
npm run types # tsc --noEmit
npm run lint # eslint, 0 warnings allowed
# Full build (~30-60s)
npm run build--max-warnings 0. Any new warning fails CI. Run npm run lint before committing TypeScript changes.
If you changed only engine Rust code: cd refact-agent/engine && cargo check && cargo test --lib
If you changed only GUI TypeScript: cd refact-agent/gui && npm run types && npm run lint && npm run test
If you changed both: run both sets.
| Workflow | Trigger paths | Checks |
|---|---|---|
agent_engine_build |
refact-agent/engine/** |
cargo test --release on 7 targets (Win/Linux/macOS × x86_64/aarch64) |
agent_gui_build |
refact-agent/gui/** |
npm test → format:check → types → lint → build (Node LTS + latest) |
server_build |
refact-server/** |
Docker multi-arch build |
docs_build |
docs/** |
Docker build + push |
plugin_vscode_build |
plugins/vscode/**, engine, GUI |
VS Code extension packaging against same-commit engine/GUI artifacts |
plugin_intellij_build |
plugins/intellij/**, engine, GUI |
JetBrains plugin build against same-commit engine/GUI artifacts |
┌─────────────────┐ postMessage ┌──────────────────┐
│ IDE Plugins │◄────────────────────►│ Agent GUI │
│ (VSCode/JB) │ │ (React webview)│
└────────┬────────┘ └────────┬─────────┘
│ LSP (stdin/stdout) │ HTTP + SSE
│ or HTTP │
└──────────────┬─────────────────────────┘
▼
┌─────────────────────┐
│ Agent Engine │
│ (refact-lsp) │
│ HTTP :8001 + LSP │
└──────────┬──────────┘
│
┌─────────────────┼──────────────────┬──────────────────┐
▼ ▼ ▼ ▼
┌─────────────┐ hidden roles wire map ┌──────────────┐ ┌──────────────┐
│ Chat Layer │────────────────────────►│ LLM APIs │ │ Scheduler │
│ event/plan │ │ 15+ providers│ │ cron + sleep │
└──────┬──────┘ └──────────────┘ └──────┬───────┘
│ │
├──────────────► Local indexes (AST, VecDB) ◄─────────────┘
└──────────────► Integrations (GitHub, MCP, shell, browser, DBs)
- Engine ↔ GUI: HTTP REST + SSE streaming (
/v1/chats/subscribe). GUI sends commands viaPOST /v1/chats/{id}/commands, receives state via SSE events with monotonicseqnumbers. - Engine ↔ IDE: LSP protocol (tower-lsp) for completions/code-lens, plus HTTP for chat and tools.
- IDE ↔ GUI:
postMessagebridge (VSCodeacquireVsCodeApi, JetBrainspostIntellijMessage). Events: file context, theme, tool calls.
Hidden Plan Roles
set_planinstalls one hidden baseplanonly, using exactly one of inlinecontentor an absolute.mdpath; never call it twice in one chat.update_planrecords append-only hiddenevent(plan_delta)notes.get_planreads the synthesized current plan from the base plan plus deltas.- Hidden
planandplan_deltaareNevercompression-exempt. Provider wire adapters lower the base as<plan>and deltas as<plan-update>user-context blocks so the base plan remains cache-safe. - Plan bodies are capped at 96KB chars, and transitions into Task Planner auto-create a pinned
initial-plantask document when an initial plan is provided.
- Formatting:
rustfmt.toml— 100 char lines, 4-space indent, Unix newlines,reorder_imports = false. - Async discipline: All shared state through
GlobalContext(Arc<ARwLock<>>). Drop read guards before.await. Never holdgcx.read()across await points. - Shutdown: Check
shutdown_flag.load(Ordering::Relaxed)in loops. Useselect!with shutdown arm for channel receivers. Neverloop { sleep }without a shutdown check. StoreJoinHandlefor spawned tasks — no fire-and-forgettokio::spawn. - Lock ordering: Always acquire
gcxARwLock before inner mutexes. Reversing order risks deadlocks in background threads. - Error handling:
Result<>with contextual errors..ok_or_else()over.unwrap()for runtime data.
- Linting: ESLint strict-type-checked, 0 warnings. Prettier enforced in CI.
- State: Redux Toolkit + RTK Query. Always use selectors from
features/Chat/Thread/selectors.ts. Never accessstate.chat.threads[id]directly. - Styling: Radix UI primitives + CSS Modules + design tokens. No inline styles, no hardcoded colors, no magic numbers.
- File naming:
PascalCase.tsx(components),useCamelCase.ts(hooks),camelCase.ts(utils),PascalCase.module.css. - No
anytypes.
- Java 17 target. Gradle build with IntelliJ Platform Plugin. Communicates with engine via HTTP + JCEF webview for chat.
- Python 3.10+. FastAPI + Uvicorn. Type hints expected.
| Scope | Path | Contents |
|---|---|---|
| User config | ~/.config/refact/ |
default_privacy.yaml, providers.d/*.yaml |
| Cache | ~/.cache/refact/ |
Shadow repos, logs, telemetry, integrations |
| Project | .refact/ |
trajectories/, knowledge/, tasks/, integrations.d/ |
| System prompts | refact-agent/engine/yaml_configs/defaults/ |
Modes, subagents, toolbox commands |
AGENTS.md files can appear at any directory level. Scope = entire directory tree rooted at that folder. More-deeply-nested files take precedence on conflicts. Direct user instructions override all AGENTS.md content.
- Shutdown hangs:
loop {}withoutshutdown_flag, bare.recv().await/.changed().awaitwithoutselect!+ timeout,tokio::spawnwithout stored handle. - Lock inversion:
gcx.read().await→ inner mutex is safe order. Reversing (inner mutex → gcx) causes deadlocks under load. - SSE sequence gaps: Every event has monotonic
seq. Gap → client reconnects for fresh snapshot. Never skip or reorder events. - Thinking block signatures: Anthropic thinking blocks with cryptographic signatures must be preserved byte-for-byte. No JSON rebuilding, no field reordering.
- GUI state: Chat/history state is ephemeral (not persisted). Only
touranduserSurveysurvive Redux persist.