The tallest structures we have ever built. The Great Pyramid stands among them: for nearly 4,000 years it was the tallest of all, and forty-five centuries on it is still standing.
Hemiunu was the architect of the Great Pyramid of Giza (around 2560 BCE). What he built was the tallest structure humankind would raise for nearly four thousand years, and it still stands today, forty-five centuries later.
Hemiunu (the agent) is a product agent for product teams, and its purpose is the same as its namesake's: to help you build things that last the way the Great Pyramid has lasted. Using it, a product team becomes the great builder that Hemiunu was.
It is one agent with two front-ends: a terminal CLI and a local web app.
It answers product questions grounded in your connected sources (local files plus
any MCP servers you add), builds wireframe then hi-fi prototypes for a feature,
remembers what it learns per-feature in a PROTOTYPE.md committed to that
feature's repo, and keeps full conversations on disk.
It is model agnostic. Hemiunu runs on its own engine (packages/engine, built
on the Vercel AI SDK), not on any single vendor. You bring whatever provider you
already have: Anthropic, OpenAI, Gemini, Groq, xAI, DeepSeek, Mistral, a gateway
(LiteLLM / OpenRouter / vLLM), or a local Ollama with no key at all. No Anthropic
key is required. Any model in the registry can be the brain.
Open the Memory panel in the web app and the agent's memory unfolds as an
interactive 3D graph: every memory file and every agent is a node, and the
edges show who can read or write what. The main agent sits at the gold hub,
its cyan specialist subagents around it, your violet context files nearby, and the
rest of memory in slate. Click any node to read it. The ones that are yours you
edit in place: user.md, the feature's PROTOTYPE.md, skills, and source maps.
It is not just a view. It is how you shape what the agent knows:
- Add context files and attach them to any agent (main or a subagent). Each is
injected into that agent's prompt every turn. A file attached to
mainis your parallel tosoul.md(which stays read-only). - Customise the knowledge packs. Edit a pack and your version overrides the shipped one and persists across updates. Delete the override to restore the original.
- Define your own subagents. Give one a name, a when-to-summon description, a model, and a system prompt, and the main agent summons it on its own whenever a request matches, right alongside the built-in researcher, prototyper, designer, strategist, and analyst.
Shipping is the game. Every time you publish a prototype to a team's main
branch, you discover a famous monument of the world, drawn at random by rarity
and pinned to your personal world map, the Atlas. The more you build and
publish, the more of the planet you collect. Become the ultimate builder: the
one whose Atlas is covered edge to edge.
Each find rolls one of five tiers:
| Tier | Odds | |
|---|---|---|
| Common | 50% | everyday landmarks |
| Rare | 28% | |
| Epic | 14% | |
| Legendary | 7% | a banner day for the Atlas |
| Wonder of the World | 1% | a once-in-a-blue-moon find |
77 real landmarks span the globe, and at the very top sit the 8 Wonders: the
New7Wonders (Taj Mahal, Machu Picchu, Christ the Redeemer, Colosseum, Chichen
Itza, Petra, the Great Wall of China) plus the Great Pyramid of Giza, the one
Hemiunu himself designed. At a 1% draw they are the trophies of the collection.
Chase the Wonders. Every push to main is another roll of the dice. Keep
building, keep publishing, and watch the world fill in.
This walks a first-timer all the way from nothing to a first conversation. Copy each command as you go and check what you should see after it.
You need three things:
-
Node 22 or newer. Check what you have:
node -v
If it prints
v22.or higher you are set. If the version is lower, or the command is not found, install the current LTS from nodejs.org. (Node ships Corepack, which manages the exact pnpm version Hemiunu pins, so you do not install pnpm separately.) -
git. Check with
git --version. If it is missing, install it from git-scm.com. -
A way to reach a model. Any ONE of these is enough:
- a provider API key (Anthropic, OpenAI, Gemini, Groq, xAI, DeepSeek, or Mistral),
- a gateway URL and key (for example a LiteLLM, OpenRouter, or vLLM endpoint that fronts many models at once), or
- a local Ollama running on your machine, which needs no key.
You do not need to decide now. First-run setup will walk you through it.
The one-line install (recommended for most people):
curl -fsSL https://raw.githubusercontent.com/AntoineF23/hemiunu/main/install.sh | bashWhat it does: clones Hemiunu to ~/.hemiunu/app, installs its dependencies (no
build step, it runs the TypeScript directly), and adds two commands to your PATH:
hemiunu (terminal) and hemiunu-web (browser app). Your config under
~/.hemiunu/ is never touched, so re-running the line later just updates the code.
If afterwards your shell says hemiunu: command not found, the install directory
is not on your PATH yet. The installer prints the exact line to add (something
like export PATH="$HOME/.local/bin:$PATH"). Paste it into your shell profile
(~/.zshrc or ~/.bashrc), open a new terminal, and try again.
From source (for developers who want to hack on it):
git clone https://github.com/AntoineF23/hemiunu.git && cd hemiunu
corepack pnpm installThere is no build step: tsx runs the TypeScript directly, so your edits are
live on the next launch. Run the CLI with corepack pnpm dev and the web app with
corepack pnpm web.
Launch either front-end:
hemiunu # terminal
# or
hemiunu-web # browser app on http://127.0.0.1:5173The very first launch runs setup and asks which provider you want. Everything
it collects is written to ~/.hemiunu/.env for you, so hand-editing files is
optional. There are three concrete paths:
- (a) A direct provider key. Choose your provider (say OpenAI or Anthropic), paste the key, done. That provider's models are now usable.
- (b) A gateway (LiteLLM / OpenRouter / vLLM). Give the base URL and the key, then Test & discover lists the models the gateway exposes and you tick which ones to add. This is the recommended path if you have one LiteLLM key that opens access to many models at once: you register them all in one step.
- (c) A local Ollama. Pick Ollama, no key needed. Hemiunu talks to it on your machine.
The app is ready as soon as one model is usable. You are not locked in: in the web Settings tab you can add or change keys and pick your Brain model and your Research model at any time. Models whose key is missing are hidden behind an Add API keys link, so the list only shows what you can actually run.
Hemiunu reads the folder you launch it in. Launch it from inside a project so the agent can see that project's files:
cd ~/code/my-product
hemiunuTo bring in more sources (Slack, Linear, Notion, a docs site, and so on), connect MCP servers:
- In the CLI, run
/mcpto add and manage servers. - In the web app, use the MCP panel.
Once a source is connected, run /scan to map it: a cheap-tier scanner
subagent explores the server and writes a Markdown source map (structure, the ids
of key pages or databases, how to query it) so the agent goes straight to the
right place instead of groping around. /scan <name> maps one server; /scan
maps them all in parallel.
Ask something grounded in what you connected, for example:
What are the open questions on the checkout redesign, and where did each come from?
What to expect:
- A permission prompt on every tool call. Before the agent reads a file or queries a source it asks, with a yes / always / no menu. "always" remembers that choice so it stops asking for that kind of action.
- Plan-first mode. Toggle it with
/plan(CLI) or the composer toggle (web) and the agent works read-only: it researches and proposes a plan, then waits for you to approve before it changes anything./autoruns tools without asking, scoped per team. - Building a prototype. Ask for a screen and the
prototypersubagent builds a low-fi grayscale wireframe first. Approve it (or hand over a clear brief) and thedesignersubagent upgrades it into a hi-fi, on-brand React + Tailwind prototype. Previews open inline in the web app, or in your browser from the CLI.
A team = a feature = a repo (one to one). Work on a feature and Hemiunu keeps
that feature's brief and memory in a PROTOTYPE.md at the repo root: goal,
primary user, research findings with sources, decisions, open questions. It
maintains that file itself as it learns, straight through the GitHub API, so you
(or a teammate) can enrich a feature without cloning the repo.
To connect GitHub, run /github. The agent signs you in with GitHub's OAuth
device flow: it shows a short code, opens github.com/login/device, and once
you authorize it saves the token to ~/.hemiunu/.env and never asks again. No gh
install and no hand-made token required. (Fallback: /github <token> with a
fine-grained PAT that has Contents: read & write on the repo.)
hemiunu # pick a team interactively
hemiunu owner/repo # start on that team (added if new)
hemiunu local # no team, local iterationOne team per terminal. To work on several at once, open another terminal and pick a different team there; each is its own isolated session, pinned to its own repo.
Update: re-run the one-line installer. It pulls the latest code into
~/.hemiunu/app. Your config in ~/.hemiunu/ (keys, MCP servers, conversations,
skills, source maps) is preserved. That guarantee is locked in by
packages/memory/src/preserve-on-update.test.ts.
Uninstall: remove the two command symlinks and the app code:
rm ~/.local/bin/hemiunu ~/.local/bin/hemiunu-web
rm -rf ~/.hemiunu/appYour config under ~/.hemiunu/ stays put unless you also delete it:
rm -rf ~/.hemiunu # only if you want to wipe keys, conversations, and memory toohemiunu: command not found. The bin directory is not on your PATH. Add the line the installer printed (for exampleexport PATH="$HOME/.local/bin:$PATH") to your shell profile and open a new terminal.- "needs
SOME_KEY" when you pick a model. That model's provider key is not set. Open Settings (web) or re-run first-run setup, add the key, and the model becomes usable. You can also add it directly to~/.hemiunu/.env. - A model fails with a context error. Context windows are per-model now, so
a long conversation can overflow a small window. Either switch to a
larger-window model (
/models) or run/compactto summarise the history. - Web port already in use. Something else is on
:5173or:4317. Close the other process, or set a different web port withHEMIUNU_WEB_PORT. - Ollama not running. If you chose the local Ollama path, make sure the Ollama
app or
ollama serveis running before you launch, otherwise the model is unreachable.
- Grounded answers. Connects to MCP servers (the launch folder via the built-in filesystem server, plus anything you add) and searches them before answering. Every tool call is gated by a yes / always / no permission prompt.
- Web search. Built-in
web_searchandweb_fetchtools (server-side, no extra key) for public and current information, weighed against your own sources. - Source maps (
/scan)./scan <mcp>(or/scanfor all, in parallel) sends a cheap-tier scanner subagent into a server to map what is inside it: structure, the ids of key pages and databases with one-line summaries, and how to query it. Each map is a per-user Markdown file in~/.hemiunu/sources/you can also edit by hand. Only the one-line description is surfaced each turn; the agent pulls the full map on demand, so it goes straight to the right place. Re-running reconciles the map, and the agent also updates maps on its own when they drift. What is visible depends on your access, hence per-user. - Researcher subagent and model tiers. Anything that needs looking things up is
delegated to a
researchersubagent on a cheaper tier (HEMIUNU_MODEL_RESEARCH), then synthesized on the main model. - Prototyping. A
prototypersubagent builds low-fi grayscale wireframes; adesignersubagent upgrades an approved wireframe (or a clear brief) into a hi-fi, on-brand React + Tailwind prototype, using your connected design system if one is present, else a solid Vite + React + TS + Tailwind fallback. Previews surface inline (web) or open in your browser (CLI). - Plan-first mode (
/plan, or the web toggle). The agent works read-only, researches, and proposes a plan, then waits for your approval (auto-accept edits, approve each step, or keep planning to refine) before it builds anything./autoruns tools without asking, scoped per team. - Other models as tools. An
ask_modeltool lets the brain consult any other model in the registry (OpenAI, Google, Groq, xAI, DeepSeek, Mistral, another Claude, a gateway model, or a local Ollama) for a second opinion, then integrate the result. Whichever model you set as the brain stays the primary agent; any of the others can be summoned for a focused subtask. - Parallel execution. When a task splits into independent pieces, a
paralleltool fans them out across subagents concurrently (real code-level fan-out), each in its own isolated context, and merges the results. - Persistent conversations in SQLite (
~/.hemiunu/hemiunu.db): list, resume, replay, with per-model context windows and automatic compaction. - File-based context (Hermes-inspired). Each turn the system prompt is built from
context/soul.md(persona, ships with the app) and a globaluser.mdof learned user facts in~/.hemiunu/(carried into every project). The agent maintainsuser.mdautonomously via aremembertool; feature knowledge lives in each team'sPROTOTYPE.md(see Teams below), not in the launch folder.
Keys and settings live in ~/.hemiunu/, separate from the code, so updates
never touch them: ~/.hemiunu/.env (keys), ~/.hemiunu/mcp.json (your MCP servers,
merged over the default), ~/.hemiunu/hemiunu.db, ~/.hemiunu/skills/,
~/.hemiunu/sources/. Updating only ever replaces the app code at ~/.hemiunu/app;
your conversations and memory are left in place, a guarantee locked in by
packages/memory/src/preserve-on-update.test.ts. See
.env.example for the full, commented template.
Variable (~/.hemiunu/.env) |
Purpose |
|---|---|
ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, GROQ_API_KEY, XAI_API_KEY, DEEPSEEK_API_KEY, MISTRAL_API_KEY |
Per provider. Any ONE is enough: it unlocks that provider's models. A local keyless endpoint (Ollama) needs none. |
LITELLM_API_KEY |
Gateway. Key for the shipped LiteLLM-routed models (gpt-4o, deepseek-v3, qwen3-235b-instruct, mistral-medium); their base URL is set per entry in the registry. |
ANTHROPIC_BASE_URL |
Optional. Anthropic-compatible gateway or proxy for the Claude entries. Unset means Anthropic direct. |
HEMIUNU_MODEL |
Main / synthesis model id, e.g. claude-opus-4.8. Unset (or unusable) falls back to the first available registry model. |
HEMIUNU_MODEL_RESEARCH |
Retrieval tier for the researcher subagent. Unset falls back to the first available "research"-tagged entry. |
HEMIUNU_COMPACT_THRESHOLD |
Auto-compaction threshold (default 0.5). |
HEMIUNU_TOOL_RESULT_BUDGET |
Per-tool-result token budget (default 60000); larger results are truncated with a notice. |
HEMIUNU_THINKING_BUDGET |
Extended-thinking tokens. 0 or unset means disabled (cheaper, works everywhere). |
| (MCP server secrets) | Optional. Any ${ENV_VAR} a server you add to mcp.json references. |
Context windows are per-model in the registry now (a HEMIUNU_CONTEXT_WINDOW
override exists but is rarely needed). See
docs/providers.md for the tested provider matrix (live
smoke plus capability results per model) and what to expect from weaker
tool-callers.
Models are bring-your-own: no provider is required. First-run setup (CLI and web) asks which provider you want and only requires THAT credential: one provider key, a gateway (LiteLLM / OpenRouter / vLLM, base URL plus key, models discovered and registered), or a local Ollama with no key at all. If a selected model's key is missing, the agent tells you which one to add.
Add servers in-app (CLI /mcp, or the web MCP panel) or by editing
~/.hemiunu/mcp.json, standard mcpServers shape (stdio / http / sse). Use
${ENV_VAR} for secrets (kept in .env) and ${CWD} for the launch directory. A
server is auto-skipped if it is disabled or any of its env vars are unset. The
only built-in default is the filesystem server (it reads the folder you launch
in).
Hemiunu can emit OpenTelemetry traces of everything it does — off by default, and a no-op until you turn it on. It speaks the standard OTLP env contract, so it exports to whatever collector your team already runs (Jaeger, Grafana Tempo, Honeycomb, Datadog, an OTel Collector, …) — nothing Hemiunu-specific to host. Anyone who runs the agent from GitHub gets the same traces in their own stack.
Turn it on by pointing it at your collector (or forcing it on):
# in ~/.hemiunu/.env (or your shell env)
HEMIUNU_OTEL=1
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 # your collector
# OTEL_EXPORTER_OTLP_HEADERS=authorization=Bearer%20... # e.g. a SaaS backendNo collector handy? Run one locally in seconds and open http://localhost:16686:
docker run --rm -p 16686:16686 -p 4318:4318 jaegertracing/all-in-one
HEMIUNU_OTEL=1 OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 hemiunuWhat you get — one span tree per turn:
hemiunu.turn (model, tokens, cost, stop reason)
├── hemiunu.step[0] (one per model round-trip)
│ ├── ai.streamText (the GenAI model call: prompt, tokens, output)
│ └── hemiunu.tool.web_search (input, result, permission decision, ms)
└── hemiunu.step[1]
└── hemiunu.tool.delegate
└── hemiunu.subagent.designer
(knowledge_pack=hifi-design, knowledge_hash=…, override=true)
└── hemiunu.step… → ai.streamText + hemiunu.tool.save_prototype …
Use it to improve the agent. Each subagent span is tagged with the
context/knowledge/*.md pack that drove it plus a content hash. Edit a pack
(shipped, or your ~/.hemiunu override), run the same task again, and compare the
two traces by knowledge_hash — that is prompt-engineering your agent with evidence
instead of guessing. Model, token, and cost attributes on every span also make it
easy to spot which model/step is slow or expensive.
Privacy. Two defaults keep shared traces safe: the actor is pseudonymous (a random, persisted instance id — no host name or user identity), and a redacting exporter scrubs API keys/tokens out of recorded content. Prompt/output content is recorded by default (richest for evaluation); dial it back if you need to.
Variable (~/.hemiunu/.env) |
Purpose |
|---|---|
HEMIUNU_OTEL |
1 to enable, 0 to force off. If unset, auto-enables when an OTEL_EXPORTER_OTLP_* endpoint is present. |
OTEL_EXPORTER_OTLP_ENDPOINT |
Your collector's OTLP/HTTP endpoint (e.g. http://localhost:4318). Standard OTel var. |
OTEL_EXPORTER_OTLP_HEADERS, OTEL_SERVICE_NAME |
Standard OTel: auth headers for a hosted backend; service name (default hemiunu). |
HEMIUNU_OTEL_RECORD_CONTENT |
Record prompt/output text on spans. Default 1; set 0 for metadata-only. |
HEMIUNU_OTEL_REDACT |
Content redaction level: secrets (default) · pii (also emails/phones) · off · all (drop content). |
HEMIUNU_OTEL_ACTOR |
Override the random instance id with a team-chosen pseudonym. |
HEMIUNU_OTEL_REDACT_PATTERNS |
Extra redaction regexes (one per line) applied to recorded content. |
- Slash commands. Type
/helpfor the full grouped list. Highlights:/plan(plan-first),/auto(auto-accept, per team),/models,/team,/mcp,/scan,/github,/new,/resume <id>,/compact. # <note>. Type#followed by a line to save it straight to the current team'sPROTOTYPE.md(the prompt turns blue to show it is a command).- Permissions. Every tool call is gated yes / always / no;
Escinterrupts a turn. - Folder trust. On startup the CLI asks whether to trust the current folder for
file access (remembered per folder;
/trustre-opens it).
Skills are reusable, saved procedures, each a Markdown file in the canonical
SKILL.md structure (YAML frontmatter plus instruction body), stored per-user in
~/.hemiunu/skills/ so they persist across every session and project.
---
name: weekly-report
description: Draft the weekly product status report from the team's updates.
argument-hint: "[week]"
---
Gather this week's updates from the connected sources (delegate to the researcher), then write a
concise status report covering shipped / in-progress / blocked, scoped to:
$ARGUMENTS- Run one with its slash command:
/weekly-report Q3(the body becomes the turn's prompt;$ARGUMENTSand$1,$2are filled from what you type). - Discover.
/skillslists what you have; each skill'sdescriptionis surfaced to the agent so it can recognise when a request matches one. The full body loads only when it runs. - Create or edit two ways. Ask the agent ("save a skill that...") and it writes
the file via its
save_skilltool, or edit the.mddirectly, changes take effect on the next run, no restart.
A team = a feature = a repo (1:1). One team per terminal: on launch Hemiunu asks which team to work on (skipped on a fresh install, you start local and it offers to create one). To work on several teams at once, open another terminal and pick a different team there. Each is its own isolated session, pinned to its own repo, so they never step on each other.
The current team is shown under the chat. Within a terminal, Shift+Tab switches
teams sequentially, /team opens a switcher, and /team-new <name> creates a
fresh private repo named after it and switches in. Each team carries its own
conversation and context.
Every feature has a living PROTOTYPE.md at its repo root, the feature's brief
and memory (goal, primary user, research findings plus sources, decisions, open
questions). The agent maintains it proactively as it learns durable things about
the feature, and reorganizes it when useful, all straight through the GitHub API, so
it (or a teammate) can enrich a feature without cloning the repo. (In the CLI you
can also append a line yourself with # <note>.)
Device sign-in needs a one-time GitHub OAuth App (its client id is public):
- GitHub, then Settings, Developer settings, OAuth Apps, New OAuth App.
- Any name and homepage; the callback URL is unused by device flow.
- After creating, tick Enable Device Flow, and copy the Client ID.
- Set
HEMIUNU_GITHUB_CLIENT_IDin~/.hemiunu/.env(or paste it intoDEFAULT_GITHUB_CLIENT_IDinpackages/agent-core/src/github.tsto ship it for everyone).
The device flow grants the classic repo scope (covers Contents read/write on the
user's private repos).
Active directions on the roadmap:
- Automatic deployment. Today
deploy_prototypepublishes a prototype to a shareable Cloudflare Pages URL on demand (/cloudflareto connect once with your own free account's API token; your whole team can share one dashboard). Next: auto-deploy on every change, a live preview link that updates itself as the agent builds, plus a choice of targets beyond Cloudflare (Vercel, Netlify, or your own host) picked per team. - Synthesized feature memory. Automatically assemble each feature's
PROTOTYPE.mdby pulling and de-duplicating substance across all connected sources (Slack, Linear, docs), with provenance and timestamps, so a feature's shared context accrues instead of being re-discovered each turn. - One-click MCP auth. OAuth for remote MCP servers, so SaaS sources connect without a hand-made token.
- Hosted web app with per-user accounts, so a team can share one Hemiunu instead of each person running it locally.
Want a different next step? The roadmap follows what teams ask for. Open an issue.
corepack pnpm typecheck # tsc across the workspace
corepack pnpm lint # eslint
corepack pnpm test # node:test unit tests
corepack pnpm smoke --offline # structural checks, no API calls, no cost
corepack pnpm smoke # offline checks plus one live turn through the model
corepack pnpm smoke --model gpt-4o # target a specific registry model for the live turn
corepack pnpm cap # live capability eval (scenarios S1, S11)smoke --offline is free and deterministic (config, context, MCP registry,
remember, prototype/workspace/teams, the engine runtime and TurnEvent stream). The
live smoke runs one real turn to verify the persona is wired through; add
--model <registry-id> to point it at a specific model. There is no build step for
development (tsx runs the TypeScript directly); build:release bundles a release
with esbuild.
apps/
cli/ # Ink chat REPL, banner, slash commands, permission menu, status line
web/ # local web app, Hono worker (:4317) + Vite/React client (:5173)
eval/ # smoke / capability harness
packages/
engine/ # the model-agnostic engine (Vercel AI SDK): model registry, the
# tool-calling loop, TurnEvent protocol, transcript store, compactor,
# MCP host, web_search / web_fetch, permission pipeline. The only
# package that imports `ai` / `@ai-sdk/*`.
agent-core/ # createEngineRuntime() (the drop-in runtime facade both apps use) plus
# the in-process tool servers, subagents, github / deploy / scan
memory/ # context loader (soul/user) + remember() + SQLite conversation store
mcp/ # mcp.json registry, stdio/http/sse, ${ENV} interpolation, auto-skip
format/ # shared presentation helpers (CLI + web)
context/ # soul.md (persona), knowledge/, user.md.example template
mcp.json # the default MCP server (filesystem)