Contribute
Ephesus is early, opinionated about how work is done, and both of those are on purpose. This page tells you exactly what you are walking into so you can decide whether it is for you.
There is no installer, and that is the honest answer
Signed builds are a planned milestone and have not shipped. If you are here to use Ephesus — not yet. Star the repository and come back.
If you are here to build it, everything below applies and you are very welcome. What exists today is real and runs: the Electron shell, the terminal vertical, the 2D floor, real agent CLIs under management, the Agora, the Odeon, the Stoa and the Gymnasium loop. What it cannot yet do is survive being packaged and handed to a stranger.
What a fresh clone gives you
You need Node 20, a toolchain that can compile native modules
(node-pty and better-sqlite3 build on install), and at least one
agent CLI on your PATH if you want to drive real agents. The app runs without
one — it says it has no engine rather than pretending to work.
git clone https://github.com/mertefesensoy/Ephesus.git
cd Ephesus
npm install
npm run dev Then confirm your checkout is healthy. All three must be green on a fresh clone; if they are not, that is a bug and we want the issue.
npm run typecheck && npm run lint && npm test What will be missing, on purpose
The floor’s sprite sheets are commercially licensed and are not in this repository — only our own index files are. Without them the floor reports a visible missing-tileset state rather than crashing, which is the same rule the whole app follows: every degradation is visible, never silent. You can develop everything else against that.
The rules that surprise people
- The docs are the source of truth, not the code. When they disagree, the code is wrong. Precedence is design document, then decision records, then specification, then README.
- Accepted decision records are append-only. Never edit one — supersede it. CI enforces this on every pull request.
- The invariants are non-negotiable. Violating one is a defect even when everything appears to work.
- No new dependencies without a decision memo. Open an issue before you write the import.
- A wiring seam with no test is a defect, not a gap. Your evidence names the production call path — file and line — or records that there is none.
- No AI attribution anywhere in the tree. No agent, session or model name in commits, code, comments or docs. CI has a tripwire for it.
Definition of done
- Typecheck, lint and the test suite pass locally and in CI
- New behaviour has tests at the right level; every fixed bug has a regression test
- Evidence is attached to the pull request — the output, not the claim
- Docs updated in the same PR: design document if the design changed, a new decision record if policy demanded one
- Degradation paths implemented and visible, never silent
- No new lint-boundary violations, no schema without a version, no stray hex colours
- The seam is tested, or its absence is recorded with the reason
Seven issues you could pick up today
Every one is grounded in something checkable — the untested-module list in the coverage
record, or a field genuinely absent from package.json. None of them dissolve
when you open the file.
Build and run on macOS, report the first thing that breaksgood first issue
No codebase knowledge needed. Currently the highest-value contribution available.
Build and run on Linux, report the first thing that breaksgood first issue
CI runs the suite on Ubuntu, but nothing has ever launched the app there.
Add an engines field to package.jsongood first issue
Small and self-contained. .nvmrc says Node 20; nothing enforces it.
Add tests for shims/eph-usage.mjsgood first issue
The friendliest module to test — dependency-free Node, no Electron, no React.
Add tests for src/renderer/src/fonts.tsgood first issue
A degradation path: it reports a missing pixel face visibly. Nothing proves the report fires.
Add tests for src/renderer/src/floor/vfx-art.tsgood first issue
The effects are specified normatively, so the right answer is written down.
Raise coverage of the panels subsystemhelp wanted
The weakest subsystem at roughly 30% lines. The work is deciding how to fake the preload bridge.