Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Benji

Benji

A design-engineering agent with taste, a memory that leaves your material behind, and a constitution you can check.

by AgentsORG · built on eve


Benji reviews and builds interfaces against a craft bar — motion, colour, typography, layout, accessibility — and holds an opinion when you push back. He learns how you design and applies it. And when he moves on to someone else, he leaves your material behind.

He is not a linter. transform-origin: center is correct on a modal, and reporting it is a worse error than missing it. Knowing the exemptions is the whole job.

Install

One line, from any directory. No clone, no prerequisites beyond Node.

npx degit AgentsORG/Benji/.agents .agents && node .agents/install.mjs --agent

That is the whole thing. It:

  1. fetches only the .agents/ directory — the agent, the 41 skills, the rules — with no git history and none of this repository's wiki or tooling;
  2. writes a pointer into 17 harness rule files so design work routes to Benji in whichever editor anyone on the team happens to use;
  3. installs the agent runtime, so it is ready to start when the command returns.

Then start him:

npm --prefix .agents/benji run dev

You do not need an API key

Benji is model-agnostic — no model id or provider appears anywhere in his source. If you already have a coding CLI installed, he drives it, and there is no gateway key and no second bill:

BENJI_MODEL=cli npm --prefix .agents/benji run dev

BENJI_MODEL accepts a local CLI, a gateway model id, or nothing at all. Left unset, a per-turn router picks a tier from a signed registry snapshot; with no snapshot, routing switches off and everything goes to the most capable model available. Every failure path degrades up, so the router can only ever be an opt-in downgrade.

Other ways in

Hand the .agent file to an assistant

Drop benji.agent into a repository. Any assistant that reads it will install it without being told how — the file opens with that instruction, because handing an agent a .agent file is the request, not a prompt for one.

Skills only — no runtime
npx skills add AgentsORG/Benji --all

Gives the 41 skills and nothing else. --all is --skill '*' --agent '*' -y, so it installs non-interactively and detects your harness itself. It writes .agents/skills/ (read by ~19 harnesses directly), symlinks .claude/skills/ and agent/, and emits a skills-lock.json with content hashes.

This is the lightweight path. It gives you Benji's taste but not the part that learns, and it writes no rule files — so nothing makes design work route to him. A skill only fires when the model decides it is relevant, and "make this button nicer" does not always read as a design task mid-refactor.

Import into Buzz

benji.agent.json is a buzz-agent-snapshot v1 file. In the Buzz desktop app: My Agents → Import, or drag it onto the drop zone. Import mints a new keypair, so the agent is yours.

No model or provider is pinned, so your configured defaults apply. respondTo is omitted, which defaults to owner-only.

Copy the folder by hand
cp -r .agents /path/to/your-repo/
cd /path/to/your-repo && node .agents/install.mjs --agent

Drop --agent for rules and skills only. --check reports what is missing; --remove reverses everything and leaves no trace — files it created are deleted, directories it created are pruned, and anything holding your own content is left byte-for-byte.

Using him in your harness

Installing writes a pointer into every rule file below, each referencing one source of truth at .agents/rules/using-benji.md. Edit that file and every harness updates at once; there is no set of stale copies to reconcile.

Harness What gets written How you use him
Claude Code CLAUDE.md (as an @-import) + .claude/skills/benji/ Ask for design work normally. /benji loads the router skill.
Codex AGENTS.md Normally — AGENTS.md is the cross-harness standard.
Cursor .cursor/rules/benji.mdc with alwaysApply: true Always resident. A glob-scoped rule would miss the request that creates the first stylesheet.
GitHub Copilot .github/copilot-instructions.md + .github/agents/benji.md The second makes Benji selectable in Copilot's agents panel, assignable to an issue, and callable from the Copilot CLI.
Windsurf .windsurf/rules/benji.md Normally.
Gemini CLI GEMINI.md Normally.
Cline .clinerules/benji.md Normally.
Roo Code .roo/rules/benji.md Normally.
Kilo Code .kilocode/rules/benji.md Normally.
Trae .trae/rules/project_rules.md Normally.
Kiro .kiro/steering/benji.md Normally.
JetBrains Junie .junie/guidelines.md Normally.
Continue .continue/rules/benji.md Normally.
Goose .goosehints Normally.
Zed, OpenCode, Amp, Droid, Antigravity, Jules AGENTS.md and .rules Normally. One file covers all of them.

AGENTS.md alone reaches most of them — the other rows exist only where a harness reads a path of its own that AGENTS.md would miss.

Connecting the running agent over MCP

The rule files give you his taste. Connecting the running agent gives you memory, learned preferences, and verdict tracking, as a callable benji_review tool.

configs/ holds a ready-to-paste config for all seventeen harnesses. Copy the one you need:

cp configs/mcp.json .mcp.json                    # Claude Code
cp configs/cursor_mcp.json .cursor/mcp.json      # Cursor
cp configs/codex_config.toml .codex/config.toml  # Codex
cp configs/vscode_mcp.json .vscode/mcp.json      # Copilot / VS Code

Three of them need more than a copy, and the differences are easy to get wrong:

  • Codex takes a single-bracket TOML table [mcp_servers.benji], and has no type field — its transport enum is deserialised untagged, so adding type = "stdio" breaks it.
  • VS Code / Copilot uses servers as the top-level key where everyone else uses mcpServers. A Claude-style config pasted here silently does nothing.
  • Amp requires amp mcp approve benji before a workspace server will run.

A name instead of a port

eve dev binds 2000; eve start binds 3000. Any port you write into a config is therefore wrong half the time. portless gives him a stable hostname instead:

npx portless proxy start --tld agent      # once — registers the TLD, syncs hosts
npm --prefix .agents/benji run serve      # https://benji.agent

The MCP bridge dials https://benji.agent by default, and when it cannot reach it, it prints the commands that fix it rather than a bare fetch failed — the model calling the tool is the one that has to recover.

Portless is optional. Without it, set the port explicitly:

"env": { "BENJI_URL": "http://localhost:2000" }

Windows: the hosts-file write needs Administrator, and without it portless fails silently — the route registers but the name never resolves. Run portless hosts sync once from an elevated prompt, or use BENJI_URL. Binding port 443 and trusting the CA do not need Administrator.

How it fits together

flowchart TB
    subgraph you["Your repository"]
        H["Claude Code · Cursor · Codex<br/>Copilot · Windsurf · Zed · +70 more"]
        S[".agents/skills/<br/><b>41 design skills</b>"]
        R[".agents/rules/using-benji.md<br/><i>when design work routes here</i>"]
    end

    subgraph agent["The agent (optional)"]
        C["CONSTITUTION.md<br/><i>what he is for</i>"]
        SO["SOUL.md<br/><i>voice and stance</i>"]
        I["instructions.md<br/><i>floor · reflexes · routing</i>"]
        M[("Memory<br/>two tiers")]
    end

    subgraph out["Reach"]
        MCP["MCP bridge"]
        A2A["A2A"]
        HTTP["HTTP + dashboard"]
    end

    H -->|reads| S
    H -->|reads| R
    H -.->|"benji_review"| MCP
    MCP --> agent
    A2A --> agent
    HTTP --> agent
    C --> SO --> I --> M

    style C fill:#1e293b,color:#fff
    style S fill:#0f766e,color:#fff
    style M fill:#7c2d12,color:#fff
Loading

What makes him different

He has a floor he will not cross

Contrast, focus indication, target size, keyboard reach, reduced motion. No learned preference, seniority, or deadline overrides these — he refuses and proposes a compliant alternative.

The reason is in the constitution and it is not "rules are rules":

The person who cannot read your contrast choice, cannot reach your tap target, or cannot see your focus ring is affected by every decision you make and is present for none of them. That asymmetry is why the floor is not negotiable.

He does not fold

Changing a position because someone repeated themselves makes every previous judgment worthless. There is an eval for exactly this, and a routing rule: any pushback forces the most capable model, because folding under pressure is what weaker models reliably do.

He learns two different things, and keeps them apart

flowchart LR
    W["A session"] --> P{"Is this about<br/>THEM or about<br/>MY METHOD?"}
    P -->|about them| PR["<b>Workspace-private</b><br/>tokens · timings · paths<br/>product names · verdicts"]
    P -->|about my method| L["<b>Portable lesson</b><br/>a check to run<br/>a finding that keeps failing"]

    PR --> PRF[".benji/workspaces/id.json<br/><i>never leaves this file</i>"]
    L --> K{"Seen in 3+<br/>separate<br/>workspaces?"}
    K -->|no| WAIT["stays a candidate<br/>never applied"]
    K -->|yes| PUB[".benji/lessons.json<br/><i>travels with him</i>"]

    style PRF fill:#7c2d12,color:#fff
    style PUB fill:#0f766e,color:#fff
    style WAIT fill:#374151,color:#fff
Loading

A preference is a fact about you. Generalising it is not anonymising it — "this team likes faster drawers" still describes you, and enough such statements reconstruct your design system. So preferences never travel, at any confidence.

What travels is only what he learned about his own method, and only after the same pattern appears in three unrelated codebases.

Ask him:  review_lessons → list · export · keep · decline · audit

The audit action proves the boundary rather than asserting it.

He picks the right model for the task

No model ids are written in the source. Tiers resolve from a signed, reviewable snapshot; with none installed, routing switches off and the declared model runs. Every failure path degrades up — a missing registry makes him expensive, never careless.

Tier The work Why not one tier down
triage classify, extract, scan for a literal pattern
mechanical apply a rule already in hand triage can match transition: all but can't know a modal is exempt
taste rank options none of which is wrong mechanical produces a plausible ordering with no way to detect it's wrong
arbitration hold a position under pressure this is exactly what weaker models fail at

Two things run counter to intuition and are deliberate. Loading a skill lowers the tier — the skill body is the knowledge the expensive model was being paid to supply. And diff size is a hump, not a ramp: past ~800 lines there is no escalation at all, just an instruction to split, because no model reviews 1,200 lines honestly and routing up buys a longer wrong answer.

Screenshots, verdicts, and pushback are hard floors — no cost setting can route them down.

Reaching him

From How
Claude Code, Cursor, Codex, and 14 more bridge/benji-mcp.mjs — stdio MCP, carries images. Configs in configs/.
Zed, JetBrains, Neovim, Emacs eve acp
Another agent A2A at /a2a/rpc, card at /.well-known/agent-card.json
A browser the dashboard at / — see and edit what he has learned
Anything POST /eve/v1/session

MCP carries images, which is the thing a design reviewer needs most and the reason the bridge exists at all: ACP mode cannot send a screenshot.

Why not ACP everywhere?

ACP has a role asymmetry. Clients are editors; agents are coding tools. Claude Code, Cursor and Codex sit in the agent column — the same column as eve — and two agents cannot peer. So ACP reaches Zed and the JetBrains family, and MCP reaches everyone else. This is why the bridge is a separate artifact rather than a flag.

Configuration

Everything is optional and nothing is pinned to a vendor. These are all fifteen variables Benji reads; wiki/configuration.md documents each one's default, an example, and what happens when it is unset.

Models and routing

Variable Effect
BENJI_MODEL anthropic/…, openai/…, or cli / cli:codex for a local CLI. Set it and routing turns off — you named a model, so he uses it.
BENJI_ROUTING off disables the router entirely.
BENJI_ROUTING_MODE frugal · balanced (default) · uncompromising. Applied before the hard floors, so it can never cross one.
BENJI_TIER_TRIAGE / _MECHANICAL / _TASTE / _ARBITRATION Pin one tier by hand: vendor/model@1000000. Highest precedence — a person typed it.
BENJI_TIER_CONTEXT Context window for a pin that omits @<tokens>.
BENJI_REGISTRY Path to the signed model-registry snapshot.
BENJI_JUDGE_MODEL Model that grades eval assertions.

Storage, identity and reach

Variable Effect
BENJI_STORE_DIR Where memory lives. Defaults to .benji/.
BENJI_PUBLIC_REGISTRIES Path to the public-registry allow-list snapshot.
BENJI_SANDBOX Sandbox backend.
BENJI_URL / BENJI_TOKEN What the MCP bridge dials, and its bearer token.
BENJI_PUBLIC_URL Base URL advertised in the A2A agent card.
BENJI_DEV_USER_ID / _TEAM_ID / _ORG_ID Local dev identity for memory scoping.

PaymentBENJI_PAYEE_*, BENJI_RATE_*, BENJI_X402_*. Never shipped in the repository; see below.

Running with nothing configured

With no variables set at all, and a coding CLI on your PATH:

BENJI_MODEL=cli npm --prefix .agents/benji run dev

AI_GATEWAY_API_KEY is only consulted when a gateway model id is in play. It is not required, and there is no code path that fails without it when BENJI_MODEL=cli.

Getting paid

Benji holds no key and cannot move funds. He records work, issues invoices, and names a payee. A human settles.

That is a constitutional limit, not caution: he reads untrusted repositories, design docs and agent messages by design, and an agent that reads what an attacker wrote while holding a spending key is one bad input away from theft.

The payee is deployment configuration, never repository content — if it shipped in the bundle, every self-hosted instance would route its operator's earnings to whoever published it. Whoever runs an instance is its payee.

Invoices default to accepted findings, not raised ones. An agent paid per finding learns to raise findings, which is precisely what the review design exists to prevent.

Verify it yourself

npm test          # 200+ deterministic checks, no model, no network
npm run eval:local # taste and memory, graded through a local CLI — no API key
npm run audit     # 389 files, 9 checks, exit 1 on any finding

npm run eval is the same suite against a gateway model and does need AI_GATEWAY_API_KEY. eval:local is the key-free equivalent and the one to reach for.

The tests drive the real stores with real attacks — client names, file paths, hex values, hand-edited files, replayed snapshots, inflated invoices — and fail loudly if any of it gets through.

Docs

CONSTITUTION.md What he is for, five hard limits, how conflicts resolve
SOUL.md Voice and stance
AGENTS.md Repository schema — read before changing anything
wiki/ How it works and why, maintained as an LLM wiki
wiki/sharing.md What is shared and what never leaves your machine
wiki/memory.md Every threshold, and why that number

Who Benji commits as

Upskilling commits are signed with Benji's own ed25519 key and authored as Benji <benji@agents.org.in>. The key signs lesson and profile commits and nothing else — the publisher stages nothing else, and the guard rejects a commit that touches anything else.

There is deliberately no GitHub account for Benji. The consequence is small and worth stating rather than hiding: commits show a default avatar, because GitHub renders an avatar from the account matching the commit email and there is no such account. The signature is what establishes authorship, and it verifies from .allowed_signers without any platform's involvement:

git verify-commit HEAD

That is the property worth having. An avatar is a platform rendering a picture; a signature is evidence.

Licence

MIT. Use him, fork him, self-host him. If you improve his method, the lessons are welcome upstream — the guard will check them.

About

A design-engineering agent with taste, a memory that leaves your material behind, and a constitution you can check. Built on eve. Drop .agents/ into any repo.

Resources

Code of conduct

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages