The Problem

Maintaining a single long‑running conversation with an AI while keeping context, summarization, and tooling intact is hard. Existing chat systems typically truncate history or require a new session, leading to loss of state and repeated prompts.

What This Does

uniichat keeps one persistent chat. Every message is condensed to a single line. Adjacent lines are merged pairwise into a binary tree, so the whole dialogue is represented in a compact, searchable structure. The server exposes the same chat to every browser tab or terminal client (unii), allowing any client to send messages, pause the agent, or change the model. The core logic lives in Memory.ts (the tree and view), AskAI.ts (model API calls and prompt cache), and Server.ts (the Express‑style HTTP interface and worker orchestration). Tooling support—running shell commands, editing files, driving the Mac screen—is provided by the agent classes (Computer.ts, Paint.ts, Screen.ts, etc.). The web/ folder supplies a minimal UI that talks to the server; web/src/main.ts bundles it with bun build.

How It Is Wired

Execution starts with bun Server.ts. Inside Server.ts a Bun server listens on the configured port and registers routes:

  • POST /message → Server.handleMessage → AskAI.call → model API → Memory.add
  • GET /state → Memory.view → JSON to client
  • GET /tool/:name → dispatch to the corresponding tool class

AskAI.call builds a prompt by reading the current view from Memory.view, appending any custom rules from ~/.unii/config.json, and sending the text to the chosen vendor (Claude or OpenAI). The response is streamed back to the client and appended to the memory tree. The memory tree is persisted under ~/.unii/users/<id>/ as JSON lines: main/ for raw messages and tree/ for summary nodes. Every write is a single append, so the server never rewrites large files. Tool classes expose a run(args) method; Server invokes them via Tools.dispatch(name, args), which writes logs to ~/.unii/work/<device>/. The UI simply fetches GET /state and posts to POST /message.

How To Use It

Setup

git clone https://github.com/moses-y/uniichat
cd uniichat
bun i          # installs deps (no lockfile)
export ANTHROPIC_API_KEY=sk-…

Configuration Edit ~/.unii/config.json or set UNII_<KEY> variables. Key entries:

  • site – server origin (default http://127.0.0.1:8788)
  • pick – default model and effort (claude-api:sonnet-5.5:medium:slow)
  • compactor – summarizer (claude-api:haiku-5.5:high:slow)

Running

bun Server.ts           # starts HTTP server on 127.0.0.1:8788

Open http://127.0.0.1:8788 in a browser. The first request prompts you for an email; a link is printed to the console. Follow it to authenticate, then start chatting. Alternatively, from a terminal:

bun Term.ts http://127.0.0.1:8788

The CLI asks for the same email and shows a sign‑in link.

Building the client

bun run web            # rebuilds web/app.js from web/src

The bundled client lives in web/app.js and can be served statically.

Real-World Use

A research lab can spin up a private instance to run a long‑term dialogue with a policy model. The lab writes a custom tool Analyze.ts that parses CSV files, registers it in Tools.ts, and invokes it via the chat interface. The memory tree lets the model refer back to earlier findings without re‑requesting them from the LLM.

Code Health & Issues

Low (Dependency) – package.json declares dependencies without a lockfile, which may cause non‑reproducible builds. Low (Tests) – 11 test files exist but cover only isolated modules; integration coverage is limited. Low (Docs) – README.md explains usage but lacks a detailed API reference. Low (CI) – GitHub Actions workflow only tests iOS (.github/workflows/ios.yml); web and server tests run locally.

The Bottom Line

uniichat offers a lightweight, persistent chat server that merges conversation history into a compact tree. Its architecture is clear: a Bun server, a memory module, and a pluggable AI call layer. The main drawbacks are the absence of a lockfile and limited test coverage. Teams needing long‑term conversational memory and extensible tooling will find it useful, provided they manage the environment and credentials carefully.