- name
- clj-repl
- description
- Start or connect to a Clojure/ClojureScript/Babashka nREPL. Detects project type and starts appropriate REPL in background. Use when user wants to evaluate code, start REPL, or needs nREPL connection.
# Clojure REPL Skill
Start or connect to an nREPL server for REPL-driven development.
## Quick Reference
| Command | Action |
|---------|--------|
| `/clj-repl` | Auto-detect project, start REPL (asks if existing found) |
| `/clj-repl fresh` | Restart all - stop existing, start new (no prompts) |
| `/clj-repl keep` | Use existing REPLs if running (no prompts) |
| `/clj-repl bb` | Start Babashka nREPL |
| `/clj-repl clj` | Start JVM Clojure nREPL |
| `/clj-repl shadow` | Start shadow-cljs nREPL |
| `/clj-repl status` | Check tracked + discovered REPLs |
| `/clj-repl stop` | Stop all tracked REPLs |
| `/clj-repl --verbose` | Show detailed MCP tool output |
## Output Style
**Default: Concise** - Show brief status updates, final summary table only.
**With `--verbose`** - Show MCP tool call details and intermediate output.
Example concise output:
```
Starting backend + shadow-cljs...
✓ Backend REPL on port 1669
✓ shadow-cljs on port 9630
✓ App server started
| Service | Port | URL |
|---------|------|-----|
| Backend | 1669 | - |
| shadow-cljs | 9630 | http://localhost:9630 |
| Web App | 8080 | http://localhost:8080 |
```
**DO NOT** show raw MCP JSON responses or tool call internals unless `--verbose` is specified.
## CRITICAL: Use MCP Tools for REPL Operations
**After REPLs are running, ALWAYS use forj MCP tools instead of bash commands:**
| Task | MCP Tool | NOT bash |
|------|----------|----------|
| Evaluate code | `repl_eval` | ~~`clj-nrepl-eval -p ...`~~ |
| Find REPLs | `discover_repls` | ~~`clj-nrepl-eval --discover-ports`~~ |
| Reload namespace | `reload_namespace` | ~~manual require~~ |
| Look up docs | `doc_symbol` | ~~`(doc ...)`~~ |
| Eval at line | `eval_at` | ~~copy/paste~~ |
| Run tests | `run_tests` | ~~`clj -M:test`~~ |
**Bash is ONLY for starting/stopping REPL servers.** All evaluation should use MCP tools.
## You Are NOT Done Until...
**Before reporting success, ALL of these must be true:**
- [ ] All required processes started for the project type
- [ ] Application server is running (not just REPL process)
- [ ] **Checked shadow-cljs.edn for `:dev-http` ports** (web apps served here!)
- [ ] You've reported ALL ports AND URLs to user
**⚠️ COMMON MISS: The `:dev-http` port in shadow-cljs.edn!**
```bash
grep ":dev-http" shadow-cljs.edn
# Example output: :dev-http {8080 "resources/public"}
# This means web app is at http://localhost:8080 - REPORT IT!
```
## Instructions
### Step 1: Check for Existing Processes
**Handle flags first:**
| Flag | Behavior |
|------|----------|
| `fresh` | Skip prompts. Stop all tracked processes, start new ones. |
| `keep` | Skip prompts. Use existing REPLs if found, start only what's missing. |
| (none) | Ask user if existing processes found. |
**Check for tracked processes:**
```
list_tracked_processes
discover_repls
```
**With `fresh` flag:**
```
stop_project # Stop all tracked processes
# Then proceed to start new ones (Step 2+)
```
**With `keep` flag:**
- If REPLs are already running for this project → report them and done
- If some are missing → start only what's missing
- No prompts, just proceed
**With no flag (default):**
If there are tracked processes that are still alive:
- Tell the user what's already running (brief: "Found backend on 1669, shadow on 9630")
- Ask: "Keep existing, restart fresh, or stop only?"
If processes are tracked but all dead, clean them up silently:
```
stop_project
```
### Step 2: Detect Project Type & What to Start
Check which config files exist:
| Files Present | What to Start |
|---------------|---------------|
| `deps.edn` + `shadow-cljs.edn` + `app.json` | Backend + shadow-cljs (check for multiple builds!) + Expo |
| `deps.edn` + `shadow-cljs.edn` | Backend + shadow-cljs (check for multiple builds!) |
| `shadow-cljs.edn` + `app.json` | shadow-cljs + Expo |
| `deps.edn` only | Backend REPL |
| `shadow-cljs.edn` only | shadow-cljs |
| `bb.edn` only | Babashka REPL |
---
**⚠️ CHECK FOR MULTIPLE SHADOW BUILDS:**
Many projects have BOTH `:web` and `:mobile` builds. **Check shadow-cljs.edn:**
```bash
grep -E "^\s+:(web|mobile|app|main)" shadow-cljs.edn
```
If you see multiple builds (e.g., `:web` AND `:mobile`):
- Start **both** shadow builds: `bb shadow:web` AND `bb shadow:mobile`
- Don't assume one is enough!
**Example project with both:**
```
bb dev # Backend REPL
bb shadow:web # Web frontend (port 8080)
bb shadow:mobile # Mobile frontend
bb expo:web # Expo dev server
```
**Do NOT stop after starting REPLs. The app server must also be running.**
---
### Step 3: Use bb Tasks (Required When Available)
If `bb.edn` has relevant tasks, **you MUST use them** instead of raw commands.
| Task | Use For |
|------|---------|
| `bb dev` or `bb repl` | Backend REPL |
| `bb shadow:mobile` | ClojureScript for Expo (outputs to `app/`) |
| `bb shadow:web` | ClojureScript for browser |
| `bb expo` / `bb expo:android` / `bb expo:ios` / `bb expo:web` | Expo dev server |
**Only fall back to raw commands if NO bb task exists.**
### Step 4: Start ALL Required Processes
Use `run_in_background: true` for each. **Start them all before moving on.**
**First, create log directory:**
```bash
mkdir -p .forj/logs
```
**Use `setsid -f` with `tee` to daemonize processes (survive terminal close):**
```bash
# Pattern: setsid -f bash -c 'command 2>&1 | tee .forj/logs/<name>.log' &
setsid -f bash -c 'bb dev 2>&1 | tee .forj/logs/backend.log' &
setsid -f bash -c 'bb shadow:web 2>&1 | tee .forj/logs/shadow.log' & # or shadow:mobile for Expo
```
**IMPORTANT: Track each process after starting!**
After each background process starts, call `track_process` with the PID (from Bash tool output):
```
track_process with pid=<PID> name="backend-repl" port=<PORT> command="bb dev"
track_process with pid=<PID> name="shadow-cljs" port=9630 command="bb shadow:mobile" # or shadow:web
track_process with pid=<PID> name="expo" port=8081 command="bb expo"
```
This enables `/clj-repl stop` to cleanly shut down all processes later.
**To view logs later, use the `view_repl_logs` MCP tool:**
- `view_repl_logs` with `log: "all"` - see all logs at once
- `view_repl_logs` with `log: "backend"` / `"shadow"` / `"expo"` - specific log
- `lines: 50` (default) - number of lines to return
**Full-stack with web + mobile (check shadow-cljs.edn for builds!):**
```bash
mkdir -p .forj/logs
setsid -f bash -c 'bb dev 2>&1 | tee .forj/logs/backend.log' &
# Check shadow-cljs.edn for builds - start ALL that exist:
setsid -f bash -c 'bb shadow:web 2>&1 | tee .forj/logs/shadow-web.log' & # If :web build exists
setsid -f bash -c 'bb shadow:mobile 2>&1 | tee .forj/logs/shadow-mobile.log' & # If :mobile build exists
# Then prompt for device (see Step 4a)
```
### Step 4a: Mobile Device Selection (For Mobile Projects)
**First, check if Expo Web is available:**
```bash
# Check package.json for react-native-web
grep -q "react-native-web" package.json && echo "WEB_ENABLED"
```
**Ask the user (include Web option only if detected):**
> "How do you want to run the app?"
> 1. Android emulator (launches automatically)
> 2. iOS simulator (launches automatically)
> 3. Physical device (enter URL in Expo Go)
> 4. Web browser (if react-native-web installed) - great for Playwright/automation testing
**Use bb tasks (NOT npx):**
**Android:**
```bash
setsid -f bash -c 'bb expo:android 2>&1 | tee .forj/logs/expo.log' &
```
**iOS:**
```bash
setsid -f bash -c 'bb expo:ios 2>&1 | tee .forj/logs/expo.log' &
```
**Physical Device (Manual URL):**
```bash
# Get local IP
LOCAL_IP=$(ip route get 1 | awk '{print $7; exit}')
# Start Expo in background with logging (daemonized)
setsid -f bash -c 'bb expo 2>&1 | tee .forj/logs/expo.log' &
# Wait for startup
sleep 3
# Display connection info
echo "Open Expo Go on your device and enter URL:"
echo " exp://${LOCAL_IP}:8081"
```
**Web Browser (if react-native-web installed):**
```bash
setsid -f bash -c 'bb expo:web 2>&1 | tee .forj/logs/expo.log' &
# Wait for startup
sleep 3
echo "Open http://localhost:8081 in your browser"
```
**Full-stack web:**
```bash
mkdir -p .forj/logs
setsid -f bash -c 'bb dev 2>&1 | tee .forj/logs/backend.log' &
setsid -f bash -c 'bb shadow:web 2>&1 | tee .forj/logs/shadow.log' &
```
**Backend only:**
```bash
mkdir -p .forj/logs
setsid -f bash -c 'bb dev 2>&1 | tee .forj/logs/backend.log' &
```
### Step 5: Start Application Server (REQUIRED - Don't Skip!)
**REPL running ≠ Done.** The application server must be started from within the REPL.
**Detection priority:**
1. **Common functions** - Search `src/**/core.clj` for:
- `(defn start-server` → eval `(<namespace>/start-server)`
- `(defn start` → eval `(<namespace>/start)`
- `(defn go` → eval `(<namespace>/go)`
2. **State management** - Check requires:
- `mount.core` → eval `(mount.core/start)`
- `integrant.core` → look for `(ig/init ...)`
- `component` → look for `(component/start ...)`
3. **Comment blocks** - Read them for startup examples
4. **Fallback** - Read core.clj and figure out how to start it
**Example:**
```
repl_eval with code="(require '[myapp.core :as core] :reload)"
repl_eval with code="(core/start-server {:port 3000})"
```
### Step 6: Verify Everything Works
Wait 2-5 seconds after starting, then:
```
discover_repls
```
Test each REPL:
```
repl_eval with code="(+ 1 2)" port=<backend-port>
repl_eval with code="(+ 1 2)" port=<shadow-port>
```
### Step 7: Report Success (Only After Everything Running)
**Final checklist before reporting:**
- [ ] All REPLs started for project type?
- [ ] Application server running and accepting requests?
- [ ] Expo running (if mobile project)?
**Check shadow-cljs.edn for dev-http ports:**
```bash
grep -o ':dev-http {[0-9]*' shadow-cljs.edn
```
If `:dev-http` is present (e.g., `{8080 "resources/public"}`), the web app is served on that port.
**Report all services in a table:**
GitHubで見る