
Jade
io.github.julianbei由 GitHub 账号 julianbei 发布v0.0.11更新于 Oct 24, 2026
The IDE for agents: read by symbol, edit against a revision, validate with your own build, revert.
概览
让助手按符号读取、编辑、验证并回退某个代码仓库中的代码,并使用项目自身的构建与测试命令。
- 可以做什么
- Jade(ARNO)是一个本地 stdio MCP 服务器,为助手提供四组共 31 个工具:检查类(outline、find、read_range、grep、references、context)、修改类(replace_symbol、replace_text、insert、rename、apply、create_file、delete_file)、验证类(check、run_tests、run_command、declare_command、job_status、job_output)和状态类(changes、diff、history、checkpoint、revert、events、telemetry、workspace)。编辑以 path::Name@line 这类符号 ID 定位,可带 expectedRevision 前置条件,返回的是修订变化、移动的符号和诊断信息,而不是简单的成功提示。验证会从仓库清单中发现项目自己的构建、类型检查或测试命令;仓库特有的命令可一次性声明在 .arno/commands.json 中,之后按名称调用。
- 适用场景
- 当助手需要在单个代码仓库内工作,进行符号级读写、带修订感知的修改,并通过项目真实的构建和测试命令做验证时使用。它的定位是替代助手自带的 shell 和文件工具,而不是与之并存,因为工具列表每轮都会重新发送。
- 运行要求
- 在 macOS 或 Linux 上作为本地进程运行;不支持 Windows。可通过安装脚本、Go 安装、发布二进制、容器镜像或 Claude Desktop 的 .mcpb 包安装。需设置 ARNO_WORKSPACE_ROOT 或用 --root 指定仓库。可选的语言服务器(gopls、jdtls、metals 等)可提供精确引用、跨文件重命名和类型诊断;没有它们时 ARNO 退回 tree-sitter,并说明哪些结果是近似的。
安装
在 SourceWeft 中
- 打开 控制台中的 Jade,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
ARNO — Agent Repository Navigation & Operations
[ARNO — Agent Repository Navigation & Operations][ARNO MCP server – quality and maintenance score on Glama]
The IDE for agents
ARNO gives coding agents what an IDE gives you, served over MCP. Read by symbol, edit against a known revision, get the compiler's diagnostics back with the edit, validate with the repository's own commands, see what changed, and revert to a checkpoint — each step one tool call, none of it through the shell.
Symbol-aware reading is how ARNO finds its way around; the transaction is what it is for. Where the shell is still the better tool, use it — the question ARNO has to answer is whether an agent gets more done, at acceptable cost, with it than without (docs/benchmark.md).
Half the tokens, more issues fixed. Claude Code on 12 real closed issues from cobra (Go), ky (TypeScript), requests (Python) and ripgrep (Rust), judged by each upstream fix's own hidden tests:
Not just a shorter tool list: against a shell trimmed to Bash, Read, Edit and Write, ARNO still used 18–25% fewer tokens and fewer turns, in two separate runs. Sonnet 5, one run per task, four languages — results and caveats · how to set it up.
Status: 0.0.14 shipped, the first release without the Jade names; 0.0.11 and earlier were Jade — early, usable, and looking for feedback. Testing it? Start with the tester guide.
For macOS and Linux — Windows isn't supported (here's why, and where to upvote). Run it again to update. Other ways to install.
Table of contents
- Trying ARNO: a guide for testers
- Why ARNO exists
- Install
- Configure your MCP client
- Use it in a container
- The tools
- Repository commands
- Language support
- Design principles
- When the shell is still the right tool
- What ARNO does not do yet
- Stability and versioning
- Telemetry
- Reporting problems
- Development
Trying ARNO: a guide for testers
Thanks for testing. Half an hour gets you set up; the useful part is a week or two of your normal work with it switched on, and then telling us how it went — including if you turned it off.
1. Install ARNO and your language servers
macOS and Linux:
Windows isn't supported, sorry! If you'd like it to be, please 👍 issue #2 or tell us there why it matters to you. (WSL 2 runs Linux, so the Linux build may work there, but we don't test it or take bug reports for it.)
The script picks the build for your OS and CPU, checks it against the
release's checksums and installs it to /usr/local/bin, or ~/.local/bin
when that is not writable — no sudo, no Go toolchain. If that directory is
not on PATH, it offers to add it to your shell profile, and it prints the
absolute path to use as command in your MCP client config. On a first install it then opens
arno-mcp install, a menu that installs the language servers you pick, or
shows how to install them by hand; Enter skips it, and you can run it again
any time. Run the same command again to
update — ARNO tells you when a new release is out (see
Update check). (Prefer Go? go install github.com/julianbei/arno/cmd/arno-mcp@latest works too.) ARNO reads
structure in every language with nothing else installed; exact references,
cross-file rename and type errors on edit need the language's server —
arno-mcp install installs these for you, or by hand:
A missing server is never an error: ARNO says which answers are approximate.
2. Point your agent at a real repository
For Claude Code, put this in .mcp.json at the root of the repository you
work in (other hosts: Codex CLI, goose, OpenCode):
That keeps Claude Code's own tools too. For the clearest signal, run some
sessions with ARNO in place of them: claude --tools "" with the same
config (why and trade-offs). Restart
or reconnect the client (/mcp) after installing or upgrading ARNO.
3. Check it came up
Ask the agent: "call arno.capabilities". You should see your languages, each
with server … (not started) or no server (… not installed), plus the build
and test commands ARNO found (mvn, gradle, sbt, go test). If a server
you installed shows as not installed, that is a bug report.
4. What to try
Work as you normally would. If you want a checklist for the first sessions:
- Find and follow code: "where is X declared, and who calls it?" —
find,references. - Rename across files: a method or class used in several files —
rename(exact with gopls, jdtls or metals running). - A change in several places at once: "change the signature and update the
callers, then check it builds" —
applywithcheck. - Run the tests that matter:
run_testswith a file or test name, orapplywithcheck: "impact". - Repeatable commands: have the agent
declare_commandsomething you run often (./gradlew :core:test,sbt "testOnly *ParserSpec"); later sessions reuse it from.arno/commands.json. - Undo:
checkpointbefore something risky,revertif it goes wrong.
5. Tell us how it went
The templates ask for the output of arno.capabilities and, optionally,
arno.telemetry. Neither contains source code; telemetry is
local only and records no arguments or response text, so both are
safe to paste from a private repository.
Known rough edges on the JVM: no formatter runs for Java or Scala files; large Gradle builds can make jdtls's first answer much slower than 8.5s; Kotlin has no support yet.
Why ARNO exists
An agent that falls back to grep, sed and cat is operating outside any
tooling you control. No revision tracking, no guardrails, no telemetry, no way
to know what it did or why it chose to do it that way. Every shell fallback is
a hole in your visibility.
You cannot fix that by telling the model not to use the shell. The model uses the shell because the shell is cheaper — fewer tokens, fewer round trips, more flexible. So the only durable fix is to make the structural tool the cheaper option, and then measure whether you succeeded.
That is the entire bet, and it is testable. On this repository's own benchmark, ARNO answers seven realistic engineering questions in 0.85x the tokens of the equivalent shell commands. It was 5.63x before responses became plain text instead of JSON — see docs/response-style.md for what changed and why.
The counter-measurement matters as much. One question asked against an unrelated repository came out at 1.36x — worse than the shell — because an ambiguous symbol name forced an extra disambiguation call. Seven scenarios at home and one away disagree, both are honest, and the second is the one that predicts outside use. The 0.0.4 pilot on four outside repositories answers it at a larger scale: used in place of Claude Code's built-in tools, ARNO solved 12 of 12 real issues with 51% fewer tokens, and 18–25% fewer than a shell trimmed to four tools (docs/benchmark-results.md). ARNO is not finished.
ARNO's own development log (docs/feedback.md) records every time its author reached for bash instead, and why. The pattern it found was blunt: the fallbacks that survived longest each closed within two tasks of being named in the log — not when the tool shipped.
Install
With the install script
Downloads the latest release binary for your OS and
CPU, verifies it against checksums.txt, and installs it without sudo to
/usr/local/bin or ~/.local/bin. Run it again to update: a arno-mcp
already on PATH is replaced where it is, and nothing is downloaded when it
is already current. If the directory is not on PATH, it offers to add it to
your shell profile (ARNO_ADD_TO_PATH=1 does it without asking) and prints
the absolute path to use in your MCP client config. ARNO_VERSION pins a release tag;
ARNO_INSTALL_DIR picks the directory. Read it first if you like:
install.sh.
Windows isn't supported — see issue #2, and give it a 👍 if you'd like that to change.
Language servers: arno-mcp install
The menu lists each language server ARNO can use, whether it is installed, and
the exact command it would run — go install for gopls, brew install jdtls,
cs install metals, npm install -g for TypeScript and Pyright, rustup component add rust-analyzer, gem install ruby-lsp — and confirms before
running anything. A server with no installer on the machine gets instructions
for installing it by hand. The install script opens the menu after a first
install; ARNO_SKIP_SETUP=1 skips it.
For an agent, or any script — there is no terminal to answer a menu, so the same steps come without questions:
--list --json gives each server's key, whether it is installed and
where, the command that would install it on this machine, and manual
steps when there is none. arno.capabilities ends a missing server's line
with the command that installs it. Installing is deliberately not an MCP
tool: global package installs go through the agent's shell, where you approve
them.
Other ways to install
The install script above is the easiest way. These work too.
From Go
Lands in $GOBIN, or $(go env GOPATH)/bin if that is unset — which is
usually ~/go/bin, and is not on PATH by default. Add it if it is not
there, then confirm:
If you would rather not touch PATH, use the absolute path in your MCP client
config instead of the bare arno-mcp shown below.
From a release binary
Prebuilt binaries for linux and darwin on amd64 and arm64 are attached to each
GitHub release, with a
checksums.txt alongside them. Each is built natively on its own platform —
ARNO links tree-sitter through cgo, so the linux builds need a reasonably
current glibc. On an older distro, build from source or use the container
image, which is statically linked against musl.
As an MCP bundle, for Claude Desktop
Since 0.0.11, each GitHub release
also carries arno-mcp_<version>.mcpb, one bundle with the binaries for macOS
and Linux on Intel and ARM. Open it with Claude Desktop, pick the repository
ARNO should work on, and it runs with the core tools; no terminal and no
Docker. Language servers still come from arno-mcp install, or run without
them on tree-sitter alone.
From source
Optional: gopls
references and rename use gopls for their exact, compiler-resolved form.
Without it they still work — references degrades to a textual approximation
that says so in the response, and rename refuses rather than guessing.
The same goes for every language below: arno-mcp install shows which servers
are installed and installs the rest (Language servers).
Configure your MCP client
ARNO is a stdio MCP server. Point your client at the binary:
ARNO_WORKSPACE_ROOT is the repository ARNO inspects and edits. It does not
have to be the ARNO checkout — pointing it somewhere else is the entire point.
A --root /path/to/repo flag takes precedence over the environment variable,
and ARNO prints which of the three sources it used (flag, env, working
directory) at startup, so an agent can never quietly operate on the wrong
repository.
ARNO works on a non-git directory and on a repository with no commits yet. In
both cases it says what is degraded — changes, diff, history and
checkpoint need git — and everything else keeps working.
Let ARNO replace the built-in tools
ARNO saves tokens when it replaces the agent's own tools, not when it is added next to them. Every turn resends the whole tool list, and in Claude Code the built-in tools are about 38k tokens of it. In ARNO's pilot benchmark (12 real issues in cobra, ky, requests and ripgrep, one run each):
Trimming the built-in list is most of the saving on its own. ARNO on top of that used 25% fewer tokens and 24% less time than the trimmed shell, and solved the two tasks both shell setups failed. Given both ARNO and every built-in tool, the agent used Bash for four calls in five and paid for both lists. To run ARNO in place of the built-in tools:
with arno.json passing the core profile, which lists twelve tools — read,
edit, validate, and run the commands a repository declares — and keeps the
others callable:
The trade-off is real: without Bash the agent cannot run arbitrary commands.
run_tests, check and repository commands declared with declare_command
cover building, testing and repeatable scripts — a declaration lives in
.arno/commands.json, so later sessions reuse it; a task that needs git operations, network access
or ad-hoc scripts needs the shell back. The numbers above are one run per task
— see docs/benchmark-results.md for the results,
a rerun after the pilot's fixes, and the caveats.
Other hosts
Verified with a live session — find a declaration, insert beside it, run
check — using only ARNO's tools:
Codex CLI (0.154), in ~/.codex/config.toml:
Codex asks before every MCP tool call. With approval_policy = "never" it
refuses them outright; run codex exec --approve-for-me or approve ARNO's
tools interactively.
goose (1.50), for one run:
or permanently with goose configure → Add Extension → Command-line
Extension, command arno-mcp --root /absolute/path/to/the/repo --tools core.
Verified through goose's claude-code provider.
OpenCode (1.18), in opencode.json at the repository root or in
~/.config/opencode/opencode.json:
OpenCode prefixes tools with the server name, so they appear as
arno_arno_find and so on. Verified with the github-copilot provider
(Claude Sonnet 5).
Cline and Gemini CLI are not verified yet.
Three things that will confuse you once
Without "alwaysLoad": true, Claude Code may never use ARNO. Claude Code
hides MCP tools behind a tool search by default: the agent sees their names but
not their definitions, and has to search before it can call one. With its own
shell and file tools right there, it does not. In ARNO's benchmark, an agent
given both ARNO and the shell made no ARNO call in three of three runs; the
same setup with alwaysLoad called ARNO directly. Other hosts may have their
own equivalent — check that ARNO's tools are actually being called.
One server serves one repository, but any of its worktrees. ARNO is
pinned to the directory it was started in, and no cd in your shell reaches
it — MCP carries no per-call working directory. A session working in another
git worktree of the same repository says so once with
arno.workspace path=<worktree>; its subagents inherit that. A subagent in a
different worktree passes root=<path> on its own calls. For fleets, set
ARNO_REQUIRE_WORKSPACE=1 so a write from a session that never said which
worktree it works in is refused instead of landing in the shared checkout. See
docs/worktrees.md.
The MCP tool catalog is fixed at connection time. A newly added tool does not appear until the client reconnects. If you upgrade ARNO mid-session and a tool seems missing, reconnect before investigating.
Use the binary, not go run ./cmd/arno-mcp. A go run stanza recompiles at
every process start: measured here at 284–584ms to first handshake against 14ms
for the binary, with a warm build cache. A cold one is seconds. It also means
the server silently changes whenever the source does — useful while hacking on
ARNO itself, confusing everywhere else. This repository's own .mcp.json
deliberately still uses go run for that reason.
Environment variables
The install script reads its own:
Use it in a container
ARNO is a child process, not a service, so the useful shape is to copy the binary into your own image rather than run ARNO's:
Or build it yourself from the included Dockerfile.
The published image is distroless/static, so it carries no git, no gopls and
no language toolchains. ARNO detects each of those at runtime and degrades with
an explicit message rather than failing, so this still works — you get the
textual references fallback, and changes/diff/history/checkpoint are
off. If you want the full surface, install git and gopls in your image;
ARNO will find them.
The tools
31 tools, in four groups. Every response is plain text, shaped to lead with the decisive line — the answer first, the supporting detail after, raw output only when you ask for it.
Over MCP each one is registered as arno.<name> — arno.outline,
arno.replace_symbol, and so on. The tables below use the bare name for
readability. Most MCP clients show you the prefixed name already, often with
the dot rewritten (Claude Code displays mcp__arno__arno_find). Over the wire
ARNO accepts both arno.find and arno_find.
Inspect
Symbols are addressed as path::Name, or path::Name@line when a name is
ambiguous. An ambiguous read returns the candidates with their signatures
rather than guessing.
Modify
Every edit returns consequences, not "success": the revision transition, which
symbols moved, immediate diagnostics, and the IDs of any background validation
it started. Edits accept an expectedRevision precondition; supplying it makes
a stale edit fail loudly instead of silently clobbering a concurrent change.
Validate
Exit status is authoritative. A command that prints a success-looking line and exits non-zero fails.
State
Every tool above except workspace, events, telemetry, job_status and
job_output also takes an optional root=<path>: one of this repository's
git worktrees, to act in for that one call. See
docs/worktrees.md.
Project configuration
Discovery guesses how to build and test a repository from its manifests, and the
guess is sometimes wrong: a Makefile's python -m pytest picks the system
interpreter, npm run test runs lint and browser suites for a one-file check,
and a Go module with a TypeScript app beside it has two answers to "build". A
committed .arno/project.json states the answer once, the way an editor keeps
its settings in .vscode/:
- Areas are parts of the repository with their own language and commands,
each run inside its path.
checkruns a kind in every area that declares it;run_testswith a file uses the deepest area containing that file, with{file}relative to the area and{name}the test name. - Empty fields fall back to discovery, so a config can state only what discovery gets wrong. A config that does not parse, names an unknown field or a path outside the workspace fails the check instead of being ignored.
envputs the interpreter's directory first onPATHand adds the variables to every command.generatedpaths are skipped bygrep,findand the workspace tree.notes, with the list of areas, is sent to the agent when a session starts.checkwithdryRunsays when a command comesfrom .arno/project.json.
arno-mcp init --root /path/to/repo drafts the file from discovery, one area,
for you to review and commit; it never overwrites an existing one.
Repository commands
Beyond build and test, every repository has its own verbs — lint, codegen, migrate, release-gate — and an agent that does not know them reaches for the shell. So ARNO lets it record them instead:
They live in .arno/commands.json, which is meant to be committed. It becomes
the repository's declared command vocabulary — written once by whoever (or
whatever) worked out the incantation, replayed by name forever after. Calling
run_command with no name lists what the repository declares; calling it with
an unknown name answers with the commands that do exist, so a wrong guess
teaches rather than fails.
Both answers also list detected candidates: npm scripts and Makefile
targets ARNO can see in the repository's own manifests but nobody has
declared. Detection is read-only — nothing is written until declare_command
says so — and a script check already runs for build, typecheck or tests is
left off the list, since it is not a gap. capabilities shows the same
candidates alongside what it already reports. This closed a failure class the
2026-09-16 benchmark measured directly: an agent guessing run_command names
(test-unit, model_formsets_tests) against a repository that had declared
nothing, each guess a wasted call, when the manifest already answered it.
A validation chain
Repository rules — Semgrep, a custom linter, a licence check — belong in
validation, and they need no integration in ARNO. Declare one command that
runs the steps in order, joined with &&:
or, without editing the file, declare_command(name: "validate", run: "…").
run_command(name: "validate") runs it inside ARNO, so the run is part of the
session's record. Exit status decides: a rule that fails fails the run, the
steps after it do not run, and the summary leads with the failing output.
Use semgrep scan --error or the equivalent flag of your tool — a tool that
prints findings and exits 0 passes.
Language support
Structure comes from tree-sitter grammars compiled into the binary, so it
works with nothing installed. Semantics come from a real language server,
which you provide — arno-mcp install installs it for you — and ARNO starts
it on first use, reuses it for the session, and shuts it down on exit.
Every row is verified end-to-end by make conformance, which builds an image
containing all eight servers and runs ARNO against a real repository per
language.
Semantic requests wait for the server to finish indexing (its $/progress
tokens), because an indexing server answers wrongly rather than slowly. When
the primary server declines a rename, ARNO asks the language's installed
alternative: ruby-lsp renames classes but not methods, so Ruby method rename
needs solargraph installed alongside it. With ruby-lsp alone, method
rename refuses and repeats the server's reason.
Every edit response names what checked the file (checked: pyright-langserver)
or why nothing did (not checked: app.py: pyright-langserver is not installed).
Scala needs one opt-in. metals reports errors only after importing the sbt
build, and it asks permission first, because importing runs sbt and creates
.bloop/ and .metals/ in the repository. ARNO declines unless
ARNO_METALS_IMPORT=1 is set, and says so in the edit response. A repository
an editor has already imported needs no setting.
"Structure" is outline, symbol read, edit-by-symbol, grep and search.
"Semantics" is exact references, cross-file rename, and type-level
diagnostics on edit.
ARNO looks for servers on PATH and in the places toolchains actually install
them — ~/go/bin, ~/.cargo/bin, ~/.local/bin, ~/.coursier/bin — because
go install puts gopls somewhere that is not on PATH by default, and a
client that only checked PATH would report Go as unsupported on a machine
that has a working gopls.
A missing server is never an error. ARNO degrades to the behaviour above and says which answer you got.
Design principles
- Structure before source. Return the minimum sufficient representation first — outline before full source, summary before raw logs.
- Deterministic tools before model reasoning. ARNO orchestrates tree-sitter, git, gopls and the project's own build tooling. It does not reimplement them, and does not guess where they could answer.
- Every edit has a precondition and returns consequences. An edit can name the revision it expects and is refused if ARNO's revision has moved; it returns the revision transition, what changed and the diagnostics — not "success". Changes made outside ARNO do not yet move the revision (release plan Phase 5).
- Conclusions before logs. The verdict leads. Raw output expands on request.
- Semantic operations before textual ones. But textual escape hatches stay available, because the semantic path does not always exist.
- State is explicit. Revisions, checkpoints and change sets are objects, not implications.
- Validation waits by default, backgrounds on request.
check,run_testsandrun_commandreturn the verdict; a long run can return a job to poll instead. - An approximation must announce itself. When ARNO falls back to a text scan or a name-matched graph, the caveat travels with the data, in the response — not in documentation the agent will never read.
- ARNO is model- and harness-independent. MCP is an adapter, not the architecture.
- Measure agent outcomes, not infrastructure sophistication. Tokens and turns per completed task — and token reduction is worthless if the success rate drops with it.
- Repository-native execution. Builds, tests and lint run through the
repository's own commands — discovered, or declared in
.arno/commands.json— inside ARNO, so validation is part of the record instead of a shell side trip. - Cheaper than the escape hatch. If the shell is easier, faster and cheaper for a workflow, ARNO has failed that workflow. The benchmark, not opinion, says which (docs/benchmark.md).
The longer design document is docs/scope.md.
When the shell is still the right tool
ARNO does not try to match the shell's composability. Using the shell is a decision, not a leak, when the work is one of these:
- Git operations: commit, branch, rebase, push, blame. ARNO reads git
state (
changes,diff,history) and never moves it. - One-off probes:
curla local server, inspect a process, check a port, read an environment variable. - Debugging a script or a build system itself, where the question is what a shell command does rather than what the code says.
- Installing dependencies and toolchains:
npm install,go install,pip install. - Network access of any kind.
What stays on ARNO's side of the line, even though a shell could do it:
- Builds, typechecks, tests, lint and codegen. Run them with
check,run_testsor a declared command (declare_command, thenrun_command). Validation run from the shell is validation the change transaction cannot see: no verdict in the edit record, no scoped test runner, no failure summary. - Reading and searching code, and editing it. That is where ARNO's revisions, diagnostics and provenance apply.
A command you keep running from the shell for validation belongs in
.arno/commands.json, or in .arno/project.json as an area's build or test
command.
What ARNO does not do yet
Windows. ARNO is built and tested for macOS and Linux only, and we'd rather do those two really well than three halfway. Until further notice we don't build, test or look at Windows. If you'd like ARNO on Windows, please 👍 issue #2 — and if you think this is the wrong call, say so there; honest feedback is welcome. WSL 2 runs Linux, so the Linux build may work there, but it isn't tested.
This list is more useful than the feature list — it tells you what is worth reporting and what is already known. What is planned is in ROADMAP.md.
- Nine languages get a real grammar; the rest fall back to a text scan.
Go, TypeScript, TSX, JavaScript, Python, Ruby, Java, Scala and Rust are
parsed properly. Anything else (Kotlin, Swift, C/C++, C#, PHP, …) is served
by a heuristic that finds some declarations and misses others — and the
amount it misses varies enormously by language, so treat those outlines as
a hint rather than an inventory. ARNO always says which you got
(
! no kotlin grammar — …). - Semantic features need a language server installed for that language.
ARNO speaks LSP to whatever is on the machine (see
Language support). With a server,
referencesandrenameare compiler-exact and cross-file. Without one,referencesdegrades to a textual approximation that says so, andrenamerefuses rather than guessing — an approximate reference list is still useful to a reader, but an approximate edit is corruption. - No completion, hover or code actions. ARNO's LSP client implements what the tools need — references, rename, diagnostics — not the whole protocol.
- No blame, no cross-repo work, no remote execution.
- Formatting follows the project's own rules, and only for the files you
edited. gofmt and rustfmt always run. prettier (TypeScript/JavaScript),
black or ruff (Python) and scalafmt run only when the repository declares
them — a prettier config or
package.jsonkey,[tool.black],[tool.ruff.format]or a[format]section inruff.toml,.scalafmt.conf— using, for Node and Python, the project's own binary, because a formatter the project did not choose turns a one-line edit into a whole-file diff. rustfmt reads the nearestrustfmt.tomland the edition fromCargo.toml(or the workspace), and formats the one file: it does not followmoddeclarations into files you did not touch. Ruby, Java, JSON and Markdown are left as edited, and ARNO does not interpret.editorconfig. - Revision tracking is ARNO's own counter, not git's. It detects concurrent
edits within a session. It is not a VCS. A checkpoint snapshots the files ARNO
has edited and records git's
HEAD;revertrestores those files and nothing else, never moves git, and refuses once a commit has landed since the checkpoint — undoing committed work is git's job. Checkpoints do not survive a restart of the server. - Not hardened for untrusted input. It runs shell commands you declare and
edits files you point it at. Treat it as a development tool, and do not point
it at a repository you would not run
makein. What running ARNO inside a sandbox or container does and does not cover:- Covered by ARNO itself: reads and writes stay inside the workspace root,
symlinks included; dependency sources are read-only; a repository cannot
make ARNO launch a binary it ships (declared commands run through the
shell you already trust, and a
.arno/project.jsoninterpreter is a path you review in the diff). - Covered only by the sandbox: what a declared command, a Makefile
target, an npm script or a test suite does when
check,run_testsorrun_commandruns it — network access, files outside the workspace, credentials in the environment. ARNO runs the repository's own commands with your environment; a malicious repository'smake testis as dangerous under ARNO as in your shell. - Not covered at all: an agent asked to declare a harmful command, and language servers, which execute project configuration of their own (build scripts, plugins) when they index a workspace.
- Covered by ARNO itself: reads and writes stay inside the workspace root,
symlinks included; dependency sources are read-only; a repository cannot
make ARNO launch a binary it ships (declared commands run through the
shell you already trust, and a
Stability and versioning
Tool names and required arguments are frozen and enforced by a test. 0.0.3
added no tools and made two arguments optional (query on find, path on
read_range), both backward compatible. Schemas and server instructions are
still read once at connection time, so reconnect after upgrading.
docs/tool-contract.md has the full surface and the
policy on what counts as a breaking change.
What is not frozen: response wording, the .arno/* file formats, the
exact spelling of symbol IDs, and everything under internal/. Treat responses
as text for a model to read, not as a format to parse. ARNO_JSON=1 gives
machine-readable output if you need to parse something.
Telemetry
ARNO records how its own tools are used — call counts, response sizes, timing, and the failure classes that most often precede a caller giving up and using the shell.
It is written to .arno/telemetry.jsonl in your workspace and never
transmitted anywhere. It records no arguments, no response bodies and no
error text — only a 10-character hash of each call's target (path, symbol or
query), so the confusion report can tell a second tool asked about the same
thing. ARNO_TELEMETRY=0 turns it off; telemetry(reset: true) clears it.
ARNO tries not to leave files in a repository it was only asked to work in:
- In a git repository, before creating the log, ARNO adds it to
.git/info/exclude— the clone-local ignore file, never committed — unless git already ignores it..gitignoreis never touched. The log does not show up as untracked, so a harness that commits every untracked file does not commit it. ARNO_STATE_DIR=/some/dirmoves the log out of the workspace entirely, into a subdirectory per workspace. Use it when ARNO is rooted at a checkout that something else commits or reviews wholesale.- A call ARNO rejects outright (an unknown tool name) never creates the log.
.arno/commands.json is different: it is the repository's declared command
vocabulary, meant to be committed, and is only created when you declare a
command.
Update check
Separate from telemetry, ARNO looks up the newest release tag on GitHub — one
unauthenticated request for releases/latest, carrying nothing about your
workspace or how you use ARNO — at most once a day, in the background, with a
three-second timeout. A failed or offline check also waits a day. When a newer
release exists, it says so only where you asked what you are running:
and as the second line of arno.capabilities. It never appears in the server
instructions or in other tool responses. ARNO_UPDATE_CHECK=0 turns it off;
it is also off in CI (CI set) and for development builds.
It exists because response cost is invisible to whoever is reading the response. Its first live reading found a tool returning 4.6KB in 704ms on a routine call — something sixteen tasks of hand-written notes had never noticed.
Reporting problems
docs/reporting.md says what makes a useful report. There are four issue templates:
- feedback — how it went after some real use, or why you turned it off.
- bug — it did the wrong thing.
- friction — "I used the shell instead." This is the valuable one.
- feature wish — it should be able to do X.
If you are unsure which, pick friction. It is the cheapest to write and the easiest to act on, and "it was just habit" is a real answer — we want it. Every shell fallback is a place ARNO was not worth reaching for, and that is the only signal that reliably improves it.
Before filing a bug, check whether your client has reconnected since the version changed. A stale tool catalog explains a surprising share of "this tool does not exist" and "my fix did not take effect".
Development
The repository declares its own commands in .arno/commands.json, including
release-gate — build, vet, tests and a gofmt check, which is the gate a tag
has to pass. Run it the way an agent would: run_command(name: "release-gate").
Layout:
Contributions are welcome. The one hard rule is principle 8: if you add a code path that approximates, the response has to say so.
License
Apache License 2.0 — see LICENSE. Copyright 2026 Julian Amelung.
来源:README.md,提交 e73ab1c
工具
0版本历史
1- v0.0.11最新Sep 16, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分