<p align="center">
<picture>
<source srcset="assets/forj-logo-2x.webp" type="image/webp">
<img src="assets/forj-logo-2x.png" alt="forj — Forge your code in the REPL fire" width="600">
</picture>
</p>
<p align="center">
Give your AI coding agent a Clojure REPL.<br>
MCP server with eval, reload, test, and scaffolding tools.
</p>
## Supported Platforms
| Platform | MCP Tools | Hooks/Plugin | Skills | Install |
|----------|-----------|-------------|--------|---------|
| [Claude Code](https://claude.com/claude-code) | ✅ | ✅ Hooks | ✅ | `bb install` |
| [OpenCode](https://opencode.ai) | ✅ | ✅ Plugin | ✅ | `bb install` |
## Components
| Package | What it does |
|---------|-------------|
| forj-mcp | MCP server — 29 tools for REPL eval, testing, scaffolding, process management |
| forj-hooks | Claude Code hooks (session context, REPL guidance, paren repair, Lisa Loop sync) |
| forj-opencode | OpenCode plugin (same hooks, adapted for OpenCode's plugin API) |
| forj-skill | Skills: `/clj-repl`, `/clj-init`, `/lisa-loop` |
## Prerequisites
- [Babashka](https://babashka.org/) (bb)
- [clojure-mcp-light](https://github.com/bhauman/clojure-mcp-light) - provides `clj-nrepl-eval` for REPL communication
```bash
# Install Babashka
curl -sLO https://raw.githubusercontent.com/babashka/babashka/master/install
chmod +x install && ./install
# Install clojure-mcp-light (provides clj-nrepl-eval)
bbin install io.github.bhauman/clojure-mcp-light
```
## Quick Start
```bash
git clone https://github.com/ATeal/forj.git
cd forj
bb install # Interactive wizard - choose Claude Code, OpenCode, or both
```
The installer presents a platform menu:
```
forj installer
==============
Choose platform:
[1] Claude Code (default)
[2] OpenCode
[3] Both
```
Then restart your editor. The tools will be available automatically in any Clojure project.
To uninstall:
```bash
bb uninstall # Remove all integrations (Claude Code + OpenCode)
bb uninstall --claude # Remove Claude Code only
bb uninstall --opencode # Remove OpenCode only
```
## MCP Tools
### Core REPL Tools
| Tool | Description | Like |
|------|-------------|------|
| `repl_eval` | Evaluate Clojure code in nREPL | Direct eval |
| `reload_namespace` | Reload a namespace from file | `,ef` |
| `eval_at` | Evaluate form at specific line (root/inner) | `,er` / `,ee` |
| `eval_comment_block` | Evaluate all forms in a comment block | `,eb` |
| `doc_symbol` | Look up documentation for a symbol | `K` |
| `discover_repls` | Find running nREPL servers | - |
| `repl_snapshot` | Snapshot of loaded namespaces and vars | - |
### Project Tools
| Tool | Description |
|------|-------------|
| `analyze_project` | Get project configuration (tasks, aliases, builds) |
| `run_tests` | Run tests (auto-detects bb/clj/shadow/lein) |
| `validate_project` | Validate project setup (deps, npm, Java version) |
| `scaffold_project` | Create new project from composable modules |
| `view_repl_logs` | View backend/shadow/expo logs |
### Process Management
| Tool | Description |
|------|-------------|
| `track_process` | Track a background process for cleanup |
| `stop_project` | Stop all tracked processes |
| `list_tracked_processes` | List tracked processes |
### Lisa Loop (Autonomous Development)
| Tool | Description |
|------|-------------|
| `lisa_create_plan` | Create LISA_PLAN.edn with checkpoints |
| `lisa_get_plan` | Read current plan and progress |
| `lisa_mark_checkpoint_done` | Mark a checkpoint complete |
| `lisa_run_orchestrator` | Run the autonomous loop |
| `lisa_plan_to_tasks` | Convert plan to Agent Teams task descriptions |
| `lisa_watch` | Monitor loop progress |
| `validate_changed_files` | Validate changed files via REPL |
| `lisa_run_validation` | Run validation checks (REPL/Chrome/Judge) |
| `lisa_check_gates` | Check checkpoint gates |
| `lisa_append_sign` | Record a learning/failure |
| `lisa_get_signs` | Read learnings from previous iterations |
| `lisa_clear_signs` | Clear signs file |
## Features
### Path-Based REPL Routing
Automatically routes code to the right REPL based on file type:
- `.cljs` → ClojureScript REPL
- `.bb` → Babashka REPL
- `.clj` → Clojure/Babashka REPL (based on project)
### Hooks
- **SessionStart**: Detects Clojure projects, injects context about tasks/aliases/REPLs
- **UserPromptSubmit**: Reminds Claude to use REPL-first workflow
- **PreToolUse**: Auto-fixes Clojure delimiter errors before file writes (via `clj-paren-repair-claude-hook`)
- **TaskCompleted**: Validates REPL gates and syncs Agent Teams task completions to LISA_PLAN.edn
- **TeammateIdle**: Redirects idle Agent Teams teammates to next ready checkpoint
### Skills
| Skill | Description |
|-------|-------------|
| `/clj-repl` | Start or connect to nREPL servers with auto-detection |
| `/clj-init` | Create new Clojure projects with interactive wizard |
| `/lisa-loop` | REPL-driven autonomous development loops |
#### /clj-init Project Types
- **Script/CLI** - Babashka with tasks
- **Library** - deps.edn with tests
- **Web API** - Ring/Reitit backend
- **Full-stack** - Clojure + ClojureScript + shadow-cljs
- **Mobile** - Expo + ClojureScript (Reagent/Re-frame)
- **Flutter** - ClojureDart + Flutter (experimental)
#### /lisa-loop
Breaks a task into checkpoints, then runs them in a loop — each iteration gets a fresh Claude instance with REPL access. Failed attempts are recorded in `LISA_SIGNS.md` so the next iteration doesn't repeat the same mistakes.
```bash
/lisa-loop "Build a REST API for users" --max-iterations 20
```
You describe the task, approve the proposed checkpoints, and the orchestrator takes over. Independent checkpoints run in parallel. Each completed checkpoint auto-commits as a rollback point. Plans are EDN with a dependency graph, so checkpoints can express ordering constraints and acceptance criteria.
UI-heavy checkpoints can use Chrome/Playwright for validation instead of (or alongside) the REPL.
**Agent Teams mode** (experimental):
```bash
export FORJ_AGENT_TEAMS=1
/lisa-loop "Build a REST API for users" --agent-teams
```
Uses [Claude Code Agent Teams](https://code.claude.com/docs/en/agent-teams) natively — you're the team lead, teammates inherit forj's REPL tools. The `TaskCompleted` hook validates REPL gates on completion, and `TeammateIdle` redirects idle teammates to the next ready checkpoint.
Requires `FORJ_AGENT_TEAMS=1` and `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` (add to `~/.claude/settings.json` under `env`). Falls back to parallel mode if Agent Teams isn't available.
## Project Structure
```
forj/
├── bb.edn # Root tasks (install, test, etc.)
├── packages/
│ ├── forj-mcp/ # MCP server
│ │ ├── src/forj/mcp/
│ │ └── test/forj/mcp/
│ ├── forj-hooks/ # Claude Code hooks
│ │ ├── src/forj/hooks/
│ │ └── test/forj/hooks/
│ ├── forj-opencode/ # OpenCode plugin
│ │ └── plugin.mjs
│ └── forj-skill/ # Skills
│ ├── SKILL.md # /clj-repl skill
│ ├── clj-init/ # /clj-init skill
│ │ ├── SKILL.md
│ │ └── templates/ # Project templates
│ ├── lisa-loop/ # /lisa-loop skill
│ │ └── SKILL.md
│ └── test/forj/
├── examples/ # Config templates
└── .claude/
└── settings.json # Hook registration
```
## Contributing / Developing forj
These tasks are for working on forj itself, not for using it in your projects.
```bash
bb tasks # List available tasks
bb nrepl # Start nREPL server on port 1669
bb test # Run all tests (34 tests, 273 assertions)
bb test:mcp # Test MCP tools
bb test:hooks # Test hooks
bb test:skill # Validate skill definition
bb mcp:dev # Run MCP server for testing
bb logs # View forj logs
bb cleanup:sessions # Remove old session files (>7 days)
```
## Manual Configuration
### MCP Server
Add to `~/.claude.json` (user scope):
```json
{
"mcpServers": {
"forj": {
"command": "bb",
"args": ["-cp", "/path/to/forj/packages/forj-mcp/src", "-m", "forj.mcp.server"]
}
}
}
```
### Hooks
Add to `~/.claude/settings.json`:
```json
{
"hooks": {
"SessionStart": [{
"hooks": [{
"type": "command",
"command": "bb -cp /path/to/forj/packages/forj-mcp/src:/path/to/forj/packages/forj-hooks/src -m forj.hooks.session-start"
}]
}]
}
}
```
### OpenCode
`bb install` handles everything, but for manual setup see [examples/README.md](examples/README.md).
**What gets installed:**
| Component | Location | Description |
|-----------|----------|-------------|
| MCP server | `~/.config/opencode/opencode.json` | Same REPL tools as Claude Code |
| Plugin | `~/.config/opencode/plugins/forj/plugin.mjs` | Session context, REPL-first guidance, paren repair |
| Skills | `~/.config/opencode/skills/` | `/clj-repl`, `/clj-init`, `/lisa-loop` |
The OpenCode plugin provides equivalent functionality to Claude Code hooks:
| Claude Code Hook | OpenCode Plugin Hook | Purpose | Notes |
|-----------------|---------------------|---------|-------|
| SessionStart | `session.created` | Detect Clojure project, inject context | |
| UserPromptSubmit | `tool.execute.before` | REPL-first workflow reminder | Debounced (30s) since it fires per tool call |
| PreToolUse (Write/Edit) | `tool.execute.after` | Auto-fix Clojure delimiters | Runs after write (vs before in Claude Code) |
**Uninstall:** `bb uninstall` or `bb uninstall --opencode`
## Architecture
Built entirely in Babashka for fast startup (~10ms). Uses:
- `clj-nrepl-eval` for nREPL communication
- `edamame` for Clojure parsing (line/column tracking for `eval_at`)
- Path-based routing for multi-REPL projects
## License
EPL-2.0