semula¶
semula is a fake OpenAI-compatible server for development and tests. The first time your app sends a prompt it has never seen, semula holds the call and waits for your coding agent to write the answer. Every run after that replays the answer instantly, offline and for free.
Start it in record mode:
docker run -d --name semula -p 127.0.0.1:8080:8080 \
-e SEMULA_MODE=record -v semula-data:/data ghcr.io/leejianrong/semula
Send it a prompt, the way your app would. The call hangs, because nobody has answered yet:
curl http://127.0.0.1:8080/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model": "gpt-4o", "messages": [{"role": "user", "content": "Name a fruit."}]}'
In a second terminal, see what is waiting and answer it:
The first curl returns Mango. Run it again and the answer comes back in a few milliseconds, with no one in the loop. That is the whole idea.
sequenceDiagram
participant App as Your app
participant S as semula
participant A as Coding agent
App->>S: chat completion
alt recorded
S-->>App: stored answer (milliseconds)
else new prompt, record mode
S->>S: park the call
A->>S: wait_for_pending
S-->>A: the parked request
A->>S: answer_pending
S->>S: validate and save
S-->>App: the answer
end
Why bother¶
Test runs call the same prompts again and again, and a paid API bills for every one. Hand-written mocks break the moment a framework adds a timestamp or reorders a tool list. semula normalises that noise, matches tolerantly, and never serves a weak guess in silence: near misses wait in a review queue for you.
Where to go next¶
- Tutorial: nine short pages, each one idea, each one runnable.
- Let an agent answer: connect Claude Code or Codex so nobody types answers by hand.
- Guide: install options, running it as a service, upgrades and backups.
- Reference: every command, MCP tool, endpoint and setting.
Pre-1.0
semula is 0.x. A minor release can change behaviour, and the changelog lists each change. Recordings made with one release open in the next.