Who said what
Stated, decided and inferred are labeled apart. An agent’s guess never passes for your decision.
Exported files include a UTF-8 BOM
“Yes, or non-English text comes out garbled.”Zhou · 10:12 · answers Q-1
Keep your project aligned, from discussion to delivery.
Notes and tradeoffs scatter, and one requirement can be read two ways.
Keep one sourced reading, then bring commit evidence back into the discussion.
Below is a discussion about exporting bills. Turn on a message and Nema files it as entries, noting whether someone stated it, someone decided it, or the agent inferred it.
Stated, decided and inferred are labeled apart. An agent’s guess never passes for your decision.
Exported files include a UTF-8 BOM
“Yes, or non-English text comes out garbled.”Zhou · 10:12 · answers Q-1
The knowledge base is a Git repository. What changed, why, and what it said before are all on record.
Bind a local repository and the agent reads a snapshot of main and searches it, so the discussion knows what already exists.
A diagram drawn from code remembers which commit it came from. When the code moves on, the diagram says so.
Unclear points, and a statement that conflicts with an active decision, become questions. Nema asks and waits for you. Only what needs your answer is marked red.
Switch between Chinese, English and Japanese at any time. The language entries are written in is a separate setting.
First, talk it through. Entries file themselves.
Then answer the open questions, one by one.
Next, approve the work package for a coding agent.
Commit reports come back into the discussion.
The desktop app packs the whole stack into one program: the database, the local core, and Node. It uses Git 2.31 or later already installed on your machine. On a Mac, an app opened from the Finder also finds Homebrew and MacPorts Git. No Docker, and no database server. Discussion text goes only to the model provider you choose, and Nema never touches your GitHub token.
Status
Yes. The latest release has a Windows x64 installer, a Windows portable ZIP, and an Apple Silicon disk image. The ZIP is the unpacked app: unzip it and run Nema.exe. It has no shortcuts or uninstaller. The installer and the ZIP both use ~/.nema/desktop. Pick one. Installers are unsigned, so Windows shows “Windows protected your PC” the first time, and macOS asks you to open it from Privacy & Security. The app also needs Git 2.31 or later on the machine. Intel Macs have no desktop build. On Linux, use the linux/amd64 hub and web images, or build from source.
Nema Room itself is open source under the MIT license. Filing entries calls a model, so cost or quota depends on your provider: a ChatGPT or Claude subscription, or your own API key.
The database and knowledge base stay on your computer. Only when entries are generated is the relevant text sent to the model provider you chose. Services listen on your machine only; don’t expose them to the internet.
Run nema report install to add report hooks to Codex or Claude Code. Each commit notifies Nema; if Nema isn’t running, reports wait locally and go out next time.
The first release is for one person on one machine. Multi-device sync, backups and read-only team access come after the local core is done.
The name comes from nemawashi (根回し): understanding before a decision. Disagreements stay visible, and the decision keeps its evidence.

Windows x64 and Apple Silicon builds are on the latest release. On Windows, pick the installer or the portable ZIP. The ZIP unzips to Nema.exe, with no shortcuts or uninstaller. Both use ~/.nema/desktop. The app needs Git 2.31 or later already on the machine.
The host command is nema, from npm i -g @nema-project/nema@<locked version>. That number is the version both image: pins in the docker-compose.yml you fetched carry. Hub and web images are linux/amd64. docker-compose.yml is a fixed-name asset of the latest release, rendered with both images pinned to that release's version. Fetch it, check that both pins print the same version, write NEMA_IMAGE_TAG=<that version> into .env (keep an existing value and fetch releases/download/v<locked>/docker-compose.yml instead), then start them. The v0.1.6 file still opens with the template's "not an installable version" comment; the two pinned image: lines are what count. A lock older than v0.1.6 has no release asset; take raw.githubusercontent.com/Nema-Project/nema-room/v<locked>/docker-compose.yml instead. On Linux and macOS, export NEMA_UID and NEMA_GID first. To develop this repository, clone it and run the setup wizard.
# Hub and web, linux/amd64. The compose file is a fixed-name asset of the latest release; an existing NEMA_IMAGE_TAG in .env keeps its own version.
NEMA_FETCHED= NEMA_LOCKED= NEMA_UP= NEMA_INSTALLED=
NEMA_PIN=$(sed -n 's/^NEMA_IMAGE_TAG=//p' .env 2>/dev/null | tail -1)
NEMA_URL=https://github.com/Nema-Project/nema-room/releases/latest/download/docker-compose.yml
test -n "$NEMA_PIN" \
&& NEMA_URL=https://github.com/Nema-Project/nema-room/releases/download/v$NEMA_PIN/docker-compose.yml
{ curl -fsSL -o docker-compose.yml.download "$NEMA_URL" \
|| { test -n "$NEMA_PIN" && curl -fsSL -o docker-compose.yml.download \
"https://raw.githubusercontent.com/Nema-Project/nema-room/v$NEMA_PIN/docker-compose.yml"; }; } \
&& mv docker-compose.yml.download docker-compose.yml && NEMA_FETCHED=1
# Prints the version only when hub and web agree, then locked when .env holds it. Stop if either is missing.
NEMA_VERSION=$(grep -o 'nema-room-hub:[0-9.]*' docker-compose.yml | head -1 | cut -d: -f2)
WEB_VERSION=$(grep -o 'nema-room-web:[0-9.]*' docker-compose.yml | head -1 | cut -d: -f2)
test -n "$NEMA_FETCHED" && test -n "$NEMA_VERSION" && test "$NEMA_VERSION" = "$WEB_VERSION" \
&& echo "$NEMA_VERSION"
test -n "$NEMA_FETCHED" && test -n "$NEMA_VERSION" && test "$NEMA_VERSION" = "$WEB_VERSION" \
&& { test -n "$NEMA_PIN" || printf '\nNEMA_IMAGE_TAG=%s\n' "$NEMA_VERSION" >> .env; } \
&& test "$(sed -n 's/^NEMA_IMAGE_TAG=//p' .env | tail -1)" = "$NEMA_VERSION" \
&& NEMA_LOCKED=$NEMA_VERSION && echo "locked $NEMA_LOCKED"
# Each step runs only if the one before it succeeded. Export NEMA_HUB_PORT and NEMA_DATA_HOST_DIR first if .env sets them.
export NEMA_UID="$(id -u)" NEMA_GID="$(id -g)" # Linux and macOS only
NEMA_DIR=${NEMA_DATA_HOST_DIR:-$HOME/.nema/data}
test -n "$NEMA_LOCKED" && mkdir -p -m 700 "$NEMA_DIR" && test -w "$NEMA_DIR" \
&& NEMA_IMAGE_TAG=$NEMA_LOCKED docker compose up -d --wait && NEMA_UP=1
test -n "$NEMA_UP" && npm i -g "@nema-project/nema@$NEMA_LOCKED" && NEMA_INSTALLED=1
# Compose does not run the daemon; keep it running.
test -n "$NEMA_INSTALLED" \
&& NEMA_DATA_DIR=$NEMA_DIR nema daemon --hub "http://127.0.0.1:${NEMA_HUB_PORT:-4400}"
# Or build this repository from source
git clone https://github.com/Nema-Project/nema-room.git
cd nema-room
node scripts/setup.mjs --lang en
Download latest