Paste source code, get a streamed review from a local LLM, and read the findings in the UI.
Nx monorepo layout:
apps/web React + Vite frontend (port 3000)
apps/api Express API (port 4200)
packages/shared-types Shared TypeScript types, Zod, SSE wire format
You need:
On Windows, use Git Bash or another shell that can run bash. The Ollama helper is a bash script.
git clone https://github.com/kevinsmithwebdev/aicr.git
cd aicr
cp .env.example .env
npm install
npm run ollama
npm run ollama:pull
npm run devnpm run ollama finds the Ollama binary (including the default Windows install path, which Git Bash often misses), starts the local server on port 11434 if it is not already running, and lists installed models. npm run ollama:pull also downloads OLLAMA_MODEL from .env (default: qwen2.5-coder).
When Vite and Express are ready you should see:
Local: http://localhost:3000/
[ ready ] http://localhost:4200
[ llm ] provider=ollama model=qwen2.5-coder
Open http://localhost:3000. Paste code on the left, pick a language and review focus, then click Review Code. The right panel streams Markdown as the model writes it. You can stop generation, ask a follow-up about the same snippet, Continue after a stop, Try Again, or Start Over.
Leave those processes running until you stop them with Ctrl+C.
To start the apps in separate terminals:
npm run serve:api
npm run serve:web- Web: http://localhost:3000
- API health: http://localhost:4200/api/health
- Models: http://localhost:4200/api/models
The Vite dev server proxies /api to the Express app, so the browser can call /api/health and /api/reviews without CORS issues.
Set LLM_PROVIDER=mock in .env to stream a canned review. You can skip npm run ollama and npm run ollama:pull.
If npm fails with UNABLE_TO_VERIFY_LEAF_SIGNATURE (corporate proxy or TLS inspection), retry with:
export NODE_OPTIONS="--use-system-ca"| Script | What it does |
|---|---|
npm run dev |
Serve web + API together |
npm run serve:web |
Vite on port 3000 |
npm run serve:api |
Express on port 4200 |
npm run ollama |
Start local Ollama if needed |
npm run ollama:pull |
Download OLLAMA_MODEL |
The browser talks only to the local API. The API talks only to Ollama, or to the mock provider if you set that. Submitted code stays in memory for the current review session and is gone when the API process exits.
A review goes through this path:
sequenceDiagram
participant React
participant Express
participant Ollama
alt New review
React->>Express: POST /api/reviews
else Follow-up
React->>Express: POST /api/reviews/:id/follow-up
end
Express->>Express: Zod + prompt
Express->>Ollama: stream chat
Ollama-->>Express: tokens
Express-->>React: SSE start / token / error / done
- The React app posts the snippet, language, focus, optional file name, and optional extra instructions.
- Express validates the body with Zod (shared schemas in
packages/shared-types) and rejects oversized or invalid requests. - It builds a structured system prompt (summary, findings by severity, recommended changes) plus a user prompt that wraps the code.
- It creates an in-memory session and asks the LLM provider to stream tokens. The default provider is Ollama (
POST /api/chat).LLM_PROVIDER=mockreturns a fixed review instead. - The API forwards those tokens to the browser as SSE events:
start,token,error,done. - The UI appends tokens and renders Markdown as they arrive.
EventSource cannot POST, so the client uses fetch plus ReadableStream and parses the SSE wire format itself. Stop aborts the HTTP request and the Ollama call, and keeps any partial Markdown.
After a review starts, follow-ups reuse the same session (original code plus prior messages). Continue asks the model to pick up from the cutoff. Try Again replays the last request. Start Over clears the panel. Sessions are not persisted. Restarting the API forgets them.
Shared types, limits, and the SSE wire format live in packages/shared-types. LLM adapters live in apps/api/src/llm. The web app does not talk to Ollama directly.
Copy .env.example to .env next to the repo root. The API loads it at startup.
| Variable | Default | Purpose |
|---|---|---|
HOST |
localhost |
API bind host |
PORT |
4200 |
API port |
WEB_ORIGIN |
http://localhost:3000 |
CORS origin for the web app |
LLM_PROVIDER |
ollama |
ollama or mock |
OLLAMA_BASE_URL |
http://localhost:11434 |
Ollama HTTP API |
OLLAMA_MODEL |
qwen2.5-coder |
Default chat model |
