Skip to content

Repository files navigation

Chord based terminal code editor for humans and agents.
Language server enabled for one-shot CLI or interactive TUI edits.

ane editor


Installation

curl -s https://prettysmart.dev/install/ane.sh | sh

The installer detects your platform and puts ane on your PATH.

Other installation options

With cargo:

cargo install ane-editor

With mise — using the GitHub backend:

mise use -g github:prettysmartdev/ane

To pin to a specific version: mise use -g github:prettysmartdev/ane@0.1.0

From GitHub Releases — download the binary for your platform from GitHub Releases:

PlatformAsset
Linux (x86_64)ane-linux-amd64
Linux (ARM64)ane-linux-arm64
macOS (Intel)ane-macos-amd64
macOS (Apple Silicon)ane-macos-arm64

From source — requires Rust 1.75+ and make:

git clone https://github.com/prettysmartdev/ane.git
cd ane
sudo make install

ane

A New Editor / Agent Native Editor

ane is a new take on chord-based code editing in the terminal. By combining 1) one-shot code editing for scripts and code agents via ane exec, 2) language server and tree-sitter support by default, and 3) a language-server-aware chord system, ane aims to help with focused, efficient edits to source code for humans and code agents alike.

Note:ane is still early and everything including supported chords, languages, and TUI/CLI features are still a work in progress. There will be vim chords that don't have an equivalent (yet). If you have a desired chord component, language, or feature you'd like to see added to ane, issues and PRs are always welcome. ane is my daily driver editor already, and I will be working to improve it rapidly.

Goals

  1. Chord-native editing -- a 4-part chord system (action, positional, scope, component) for expressive, composable editing operations
  2. Agent-native interface -- a headless exec mode that lets AI code agents read and modify files with minimal token usage, outputting standard unified diffs
  3. LSP-integrated -- native language server integration for language-aware chords (Rust, Go, TypeScript/JavaScript, Python)

Non-goals

  1. Be a drop-in replacement for {favorite editor}. The chord system is intentionally different and the core featureset is small by design. It's an experiment in merging chords and language servers for humans and agents.
  2. Be the fastest or most memory-efficient editor. An embedded language server will always be slower than vim or emacs. ane sits between classic terminal editors and full desktop IDEs like Zed, VSCode, and JetBrains.
  3. Be extremely extensible (yet). The priority is nailing the core — chord engine, LSP integration, agent usability. Plugins would be great eventually, but not before the core reaches 1.0 quality.

Chord System

ane lets you edit source code very precisely using key chords via its chord engine. ane chords have 4 parts: action, positional, scope, component.

PartCodesDescription
Actionchange, delete, replace, yank, append, prepend, insert, jump, listWhat to do
Positionalinside, entire, after, before, until, to, outside, next, previous, first, lastWhere relative to scope
Scopeline, buffer, function, variable, struct, member, delimiterWhat language construct
Componentbeginning, contents, end, value, parameters, arguments, name, self, word, definitionWhich part of the scope

Examples:

  • cifc -- Change Inside Function Contents (short form)
  • ChangeInsideFunctionContents -- same chord, long form
  • cels(target:5, value:"new text") -- change line 5 to "new text"
  • jnfn -- Jump Next Function Name (move cursor to the next function)
  • lefn -- List Entire Function Names (explore all functions in a file)
  • cefd -- Change Entire Function Definition (change a signature without touching the body)

Chords that target language constructs (Function, Variable, Struct, Member) require an active LSP connection. Line, Buffer, and Delimiter scopes work without LSP.

See the Chord System reference for the full grammar and Chord Examples for worked before/after examples of every valid scope/component combination.

Frontend-Aware Execution

Chords behave differently depending on the frontend:

  • CLI (ane exec): accepts all arguments as parameters, returns a unified diff
  • TUI: manipulates editor state (cursor, mode) for interactive editing

This also means that not all chords are valid for both frontends, like j to jump the cursor - the CLI has no cursor and therefore rejects jump chords.

Usage

TUI Mode (interactive editing)

# Open current directory (file tree + editor)
ane .# Open a specific file
ane path/to/file.rs

ane TUI editor

Keybindings:

KeyAction
Ctrl-EToggle between Edit mode and Chord mode
Ctrl-TToggle file tree pane (creates tree if opened with single file)
Ctrl-SSave file (works in any mode)
Ctrl-RRecall previous chord (Chord mode). Press repeatedly to cycle backwards through chord history. Press Enter to execute the recalled chord
Ctrl-CExit ane (opens modal to confirm exit and/or save edited file if needed)
Arrow keysNavigate (Edit/Chord: move cursor; Chord with input: left/right move chord cursor)
EnterOpen file from tree / execute chord / newline (context-dependent)
EscReturn to Chord mode (Edit mode) / clear chord input (Chord mode)
ClickPosition cursor in editor
Click + dragSelect text and copy to clipboard (line numbers excluded)
Shift + dragNative terminal selection (fallback)

Modes:

  • Chord mode (default): type a chord in the command box and press Enter to execute. Short-form chords are executed without 'Enter' if they are valid for the current cursor's position (i.e. cifc will automatically execute if the cursor is resting within a recognized function).
  • Edit mode: direct text editing of the open buffer. Toggle with Ctrl-E or press 'Esc' to exit edit mode.

Top bar shows: cursor position, LOC count, total lines, and approximate token count — useful for estimating LLM context usage.

See Using the TUI for the full guide. See Mouse Selection for the full selection and clipboard reference.

Exec Mode (for code agents)

# Short form
ane exec --chord "cifc(target:foo, value:\"return 0;\")" path/to/file.rs
# Long form
ane exec --chord "ChangeInsideFunctionContents(target:foo, value:\"return 0;\")" path/to/file.rs
# Line operations (no LSP needed)
ane exec --chord "cels(target:5, value:\"new text\")" path/to/file.rs
ane exec --chord "dels(target:3)" path/to/file.rs
# Discover functions before editing
ane exec --chord "lefd" path/to/file.rs
# Read one function body (prefer over reading the whole file)
ane exec --chord "yefc(target:foo)" path/to/file.rs
# Pipe value from stdinecho"new body"| ane exec --chord "cifc(target:foo, value:-)" path/to/file.rs
# Append/Prepend on Line scope
ane exec --chord "aals(target:10, value:\"new line\")" path/to/file.rs # new line AFTER line 10
ane exec --chord "aels(target:10, value:\" // note\")" path/to/file.rs # inline at END of line 10
ane exec --chord "pbls(target:10, value:\"// above\")" path/to/file.rs # new line BEFORE line 10
ane exec --chord "pels(target:10, value:\"/// \")" path/to/file.rs # inline at START of line 10

Exec mode outputs a unified diff to stdout showing what changed. Yank chords output the selected text. Prefer narrow scopes (yefc/cifc for one function) over broad ones (yebs/cebs for the whole file) to minimize output and reduce errors.

See Exec Mode for the full guide.

Embedded via Crate

ane's chord engine, LSP engine, and buffer management are available as a Rust library. Disable the default frontends feature to drop CLI/TUI dependencies:

[dependencies]
ane-editor = { version = "0.1", default-features = false }
use ane::core::{parse_chord, execute_chord, tool_definition};let query = parse_chord("cifn(target:old, value:\"new\")")?;// ... execute against a buffer with the chord engine

ane::core::tool_definition() returns a ready-to-serialize tool definition for LLM tool-use APIs (Claude, OpenAI, etc.).

See Embedding via Crate for the full API reference.

LSP Integration

ane natively integrates with language servers for language-aware chord operations.

  • Auto-detection: detects the project language (e.g., Cargo.toml -> Rust) and starts the appropriate language server
  • Async startup: LSP starts in the background; non-LSP chords (Line, Buffer, Delimiter) work immediately
  • Status display: the TUI status bar shows LSP status (ready, starting, not installed, failed)
  • Chord gating: chords marked requires_lsp: true wait for LSP readiness; non-LSP chords execute immediately
  • Install assistance: if the language server isn't installed, ane automatically installs if possible
  • Syntax highlighting: tree-sitter provides immediate structural highlighting on open; LSP semantic tokens add type-aware colors once the server is ready

Supported languages:

LanguageLSP serverTree-sitterDetection
Rustrust-analyzerCargo.toml
Gogoplsgo.mod, go.work
TypeScript / JavaScriptvtslspackage.json, tsconfig.json
Pythonbasedpyrightpyproject.toml, pyrightconfig.json, setup.py
Markdown.md, .markdown
JSON.json, .jsonc
YAML.yaml, .yml
TOML.toml
DockerfileDockerfile, .dockerfile
XML.xml, .xsd, .xsl, .svg, .rss

Languages with LSP servers support language-aware chords (Function, Variable, Struct, Member). All languages include tree-sitter syntax highlighting. See Syntax Highlighting and Languages for details.

See LSP Integration for details.

Architecture

ane uses a strict 3-layer architecture with unidirectional dependencies:

Layer 2: Frontend (CLI + TUI + frontend traits)
| calls down to
Layer 1: Commands (chord engine + diff + LSP engine)
| calls down to
Layer 0: Data (buffers, file tree, state, chord types, LSP registry)
  • Layer 0 (data) -- all filesystem I/O, state, chord type definitions, LSP server registry/schemas/types
  • Layer 1 (commands) -- chord parsing/resolution/patching, diff generation, LSP client lifecycle and requests, LSP installation
  • Layer 2 (frontend) -- CLI argument parsing, TUI rendering/event handling, frontend action traits

Lower layers never import from higher layers. Violating this is an architectural error.

See Architecture Overview for the full design.

Documentation

The full user guide is in docs/:

#GuideWhat's covered
00Getting StartedInstallation, concepts, first edits
01Chord SystemFull 4-part grammar reference
02Chord ExamplesBefore/after examples for every combination
03Using the TUIModes, keybindings, file tree
04Exec ModeOne-shot CLI edits, agent patterns
05Embedding via CrateRust library API, feature flags
06LSP IntegrationLanguage server setup and status
07Architecture OverviewThree-layer design
08Compared to Other EditorsTrade-offs vs Vim, Emacs, Helix, etc.
09Syntax Highlighting and LanguagesTree-sitter + LSP pipeline, supported languages
10Mouse SelectionClick-to-position, drag-to-select, clipboard
11Listing, Words, and DefinitionsList action, Word/Definition components, First/Last

Building

cargo build # dev build
cargo build --release # release build (LTO + strip)
cargo test# all tests
cargo clippy -- -D warnings
cargo fmt --check

Using the dev container

docker build -f Dockerfile.dev -t ane-dev .
docker run -it -v $(pwd):/workspace ane-dev

About

A New Editor / Agent Native Editor

Resources

Stars

14 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages