Skip to content
xucklessPublic

About

Modeless terminal code editor in Rust. Neovim’s alternative, Micro’s keys, Zed’s Features. LSP, git, a real terminal, AI Agents (ACP) and your $EDITOR over SSH. One small binary.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Skink

A modeless terminal editor with a seat for every AI agent.
Micro's keys and config, tree-sitter highlighting, LSP diagnostics, a real terminal emulator in a tab, and an ACP client for coding agents. One static Rust binary, about 22 MB with 10 languages built in and the rest as packages, that uses under 10 MB of RAM when idle.



Rust 1.90+ ratatui tree-sitter Linux · macOS · Windows
Binary about 22 MB First frame under 4 ms Idle RSS about 8 MB No unsafe code Status: alpha 0.9.0 License: MIT OR Apache-2.0



Docs · Why · How it solves it · Install · Quick start · Everything is a tab · AI agents · How it fits together · Status · Develop · Credits



Skink editing a Rust file: file tree, file and terminal tabs, tree-sitter colours and the status line

A real frame from the editor (Ghostty-style tab bar with file and terminal tabs, file tree, Tokyo Night, Nerd Font icons).

✦ Sound familiar?

  1. VS Code feels heavy. An Electron app, an extension host and a language server or three, just to fix a typo. Startup takes seconds and the fan spins up.
  2. You want proper git in your editor. Stage a hunk, read the blame, resolve a conflict, without switching to another app or memorising git add -p.
  3. You like the idea of Neovim, but not the motions. The speed, the terminal, the keyboard focus, yes. Weeks of learning modes and building a config before it feels like home, no.
  4. Remote development in a GUI editor is painful. The remote server component wants a gigabyte of RAM and a supported glibc (no Alpine). The GUI must run on your machine. And it all breaks on the box you SSH into from a jump host.
  5. nano is easy but stops there. No language server, no multiple cursors, no project search. Once the file is real code, you're on your own.
  6. Your AI agent lives in another window. You copy errors from the terminal into the chat, paste code back, and hope the agent didn't quietly rewrite five files you never looked at.
  7. Copy over SSH doesn't reach your clipboard. You select text in a remote editor, press copy, and it never leaves the server.
  8. Your tmux layout is the IDE. One pane for the editor, one for the shell, one for the agent, and you're the glue between them.
  9. Config fatigue. Plugin managers, dotfile repos, a setup that breaks on update, and a fresh server that has none of it.
  10. "Permission denied" on save. You edited /etc/something for ten minutes, then find out you needed sudo.
  11. No root on the server. You can't apt install your editor, and the one that's there is vi.

✦ How Skink solves them

Skink is a modeless code editor that runs in your terminal. Think Neovim's reach, Micro's keys, Zed's features: you type, you select with Shift or the mouse, Ctrl+S saves, Ctrl+Q quits. It is small on purpose. No async runtime, no plugin host, no GUI toolkit, and every language server and grammar loads only when you open that language.

The problem What Skink does
1 Heavy editors One static Rust binary (about 22 MB), a first frame in under 4 ms, about 8 MB of RAM when idle. Budgets are checked in CI on every push.
2 Git in the editor Gutter change marks, stage / unstage / revert a hunk from an inline peek, inline blame, a git panel (commit, branches, stash, push / pull), side-by-side diffs and click-to-resolve merge conflicts.
3 Neovim without the motions No modes. Micro's default keys and its settings.json / bindings.json formats, so Micro users change nothing. The mouse and trackpad just work: click, drag, sideways scroll, Alt+click for another cursor.
4 Remote development It is the remote editor: SSH in and run skink .. Nothing to install on your machine, no server component, no GUI. Works over mosh and tmux too.
5 nano with more Language servers (completion, hover, go to definition, references, rename, code actions, format), tree-sitter colours for 10 languages built in and more as packages, multiple cursors, project search and replace, structural search with ast-grep, a refactor preview for every multi-file change.
6 Agent in another window A real terminal as a tab runs claude, gemini or codex next to your file. Over the Agent Client Protocol, Ctrl+G rewrites a selection as an inline diff you accept line by line, an agent panel shows its tool calls, and files an agent writes are staged for review before they touch disk.
7 Clipboard over SSH Every copy is also sent as OSC 52, so it lands on your local clipboard through SSH (inside tmux, with set -g set-clipboard on).
8 tmux as the IDE Everything is a tab: files, shells, help, diffs, search results, command output. Split panes, a shell docked at the bottom, and a session that reopens your layout and shells next time.
9 Config fatigue Useful with zero config. Settings live in one Micro-format JSON file, and :help explains everything inside the editor.
10 Permission denied Skink offers sudo and saves through sudo tee in a terminal tab, where sudo can ask for your password. Saves are atomic either way.
11 No root The installer puts the binary in ~/.local/bin after checking its SHA-256. No sudo, no package manager, Linux x86_64 / aarch64 (static musl), macOS and Windows.

Read the docs: skink.cc, with a search box that answers plain questions ("how do I exit", "make the text bigger", "set up Claude Code"), recorded demos, every shortcut and honest comparisons with Neovim, Vim, nano, Micro, Helix and Zed.

✦ Install

PlatformCommand
Linux · macOS
curl -fsSL https://skink.cc/install.sh | sh
Windows
PowerShell 5.1+ or 7+
irm https://skink.cc/install.ps1 | iex
From source
any OS, Rust 1.90+
cargo install --git https://github.com/xuckless/skink skink

The installers download the right prebuilt binary for your machine (Linux x86_64 and aarch64 static musl, macOS Apple Silicon and Intel, Windows x86_64), check its SHA-256 and refuse to install on a mismatch, then put it in ~/.local/bin (%LOCALAPPDATA%\Programs\skink\bin on Windows). No sudo, no admin prompt. They add that folder to your PATH if it is missing.

skink --version                                       # check it worked
curl -fsSL https://skink.cc/install.sh | sh -s -- --uninstall
Installer options
Variable Effect
SKINK_VERSION=v0.1.0 Install a specific release instead of the latest
SKINK_INSTALL_DIR=DIR Install somewhere else
SKINK_NO_MODIFY_PATH=1 Leave your shell startup files alone (--no-modify-path on Unix)
SKINK_UNINSTALL=1 PowerShell only: remove the binary and the PATH entry (Unix: sh -s -- --uninstall)
SKINK_BASE_URL=URL Download from a mirror instead of GitHub

Prefer to do it by hand? Grab skink-<target>.tar.gz (or .zip on Windows) and its .sha256 from the releases page, then verify with shasum -a 256 -c.

Note

The binaries are not code-signed yet. The installers verify checksums, and on macOS they clear the quarantine flag for you. If you download an archive in a browser instead, macOS Gatekeeper may block it (xattr -d com.apple.quarantine skink) and Windows SmartScreen may warn (More info, then Run anyway).

For the best look, use a terminal with truecolor and a Nerd Font. scripts/install-nerd-font.sh installs one on Linux. No Nerd Font? Set SKINK_ICONS=ascii.

✦ Quick start

skink                    # empty scratch buffer
skink src/main.rs        # open a file
skink src/main.rs:42:7   # jump to line 42, column 7
skink .                  # open a folder: file tree on the left
skink --install kotlin   # a package: grammar, language server, ...
skink --install .        # what this project needs

Make it your $EDITOR for git, Claude Code / Codex (Ctrl+G), crontab -e and your shell. Files handed over by a tool open lean (one buffer, about 2 ms); inside a Skink terminal tab they open as a tab of that Skink. More.

git config --global core.editor skink
export EDITOR=skink VISUAL=skink      # Ctrl-G in Claude Code / Codex, crontab -e, edit-command-line
Key Does Key Does
Ctrl+S Save Alt+P Quick open (tabs, recent, project files)
Ctrl+Q Close tab (quit on the last) Ctrl+E Command line (help explains everything)
Ctrl+Z / Y Undo / redo F12 Jump between your file and a terminal
Ctrl+F Find (Ctrl+N / P next / previous) Shift+F12 Open another terminal
Ctrl+C / X / V Copy / cut / paste (no selection copies the line) F8 File tree
Alt+↑ / ↓ Move line Alt+1…9 Jump to tab N

The mouse works: click to place the cursor, drag to select, click a tab to switch, middle-click to close. Type help in the command line for the full tour and the complete key table.

✦ Everything is a tab

Files, terminals, help, diffs and command output all live in one tab bar, the way terminal-first people already work. Nothing opens a modal window you have to dismiss.

Quick open (Alt-P): open tabs first, then recent and project files, matched on the file name

Tab How you get it What it is
File skink FILE, Ctrl+O, Alt+P A rope-backed buffer with undo history, CRLF-safe saves, syntax colours, diagnostics and indent guides
Terminal Shift+F12, :term CMD A real terminal emulator in a pty. Its tab title follows the program inside, like Ghostty
Help :help [topic] The built-in manual, searchable like any other file
Diff :diff The working tree against git
Conflicts :conflicts Every conflicted file at its first marker. :ours / :theirs / :both resolve the block under the cursor, and it is undoable
Run :run CMD Command output, in a tab, not scrolled off your screen
Settings :settings, :bindings Micro-format JSON, created with defaults on first open. :reload applies it

Config lives in ~/.config/skink (or $SKINK_CONFIG_DIR). A binding can chain actions: "Copy|CopyLine" runs the first that works, "Escape,Deselect" runs both, and "command-edit:goto " opens the command line pre-filled.

✦ AI agents

Skink does not ship an agent. It gives yours a good place to run.

skink .
# Shift-F12 opens a terminal tab (F12 flips back to your file). In it:
claude            # or: gemini, opencode, goose ...
# or straight from the command line (Ctrl-E):
:term claude

Under that sits skink-ai, an Agent Client Protocol client with no async runtime: one reader thread per agent, plus a prompter for the workflows you would want in an editor (rewrite a selection, search the project, one tracked worker task). The agent panel in the UI is the next piece. The wire subset and the seams are written up in docs/ACP.md.

Running inside EveryAI

Every external capability in Skink (LSP, agents, terminals) sits behind a trait with two implementations: local, where Skink does the work, and delegated, where a host does it. When EveryAI starts Skink in its terminal it sets two environment variables, and Skink hands LSP and agent control over to it. It talks MCP over loopback HTTP, with nothing for you to configure. Without them, Skink runs standalone and never contacts anything.

Variable Meaning
SKINK_HOST_URL The host's MCP endpoint, for example http://127.0.0.1:41234/mcp
SKINK_HOST_TOKEN The bearer token for this session

The full contract is in docs/HANDOVER.md.

✦ How it fits together

Nine crates, split along the seams that matter. Dependencies point down, and skink-core never touches the UI, so the whole editing engine tests headless.

flowchart TB
    BIN["<b>skink</b><br/>the binary<br/>path:line:col · host detection"]

    subgraph front["🖥️ Front end"]
        UI["<b>skink-ui</b><br/>ratatui · tabs · tree · quick open<br/>command line · themes · screen tests"]
    end

    subgraph caps["🔌 Capabilities (each behind a trait: local or delegated)"]
        LSP["<b>skink-lsp</b><br/>thin LSP client<br/>lazy server per language"]
        AI["<b>skink-ai</b><br/>ACP client<br/>AgentController seam"]
        TERM["<b>skink-term</b><br/>pty + vt100 emulator"]
        HOST["<b>skink-host</b><br/>EveryAI handover<br/>MCP over loopback HTTP"]
    end

    subgraph engine["⚙️ Engine (no UI, headless-testable)"]
        SYN["<b>skink-syntax</b><br/>tree-sitter · lazy grammars"]
        CFG["<b>skink-config</b><br/>Micro keys · settings · bindings"]
        CORE["<b>skink-core</b><br/>ropey buffer · selection · undo<br/>find · command registry"]
    end

    BIN --> UI
    UI --> LSP & AI & TERM & SYN & CFG & CORE
    HOST -. "takes over" .-> LSP
    HOST -. "takes over" .-> AI
    LSP & AI & SYN & CFG --> CORE

    style BIN fill:#7aa2f7,stroke:#3d59a1,color:#1a1b26
    style UI fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
    style CORE fill:#1f2335,stroke:#73daca,color:#c0caf5
    style HOST fill:#2a2438,stroke:#bb9af7,color:#c0caf5
Loading
Crate What it owns
skink-core Rope buffer on ropey, selections, undo/redo history, CRLF-safe saves, find, and the Micro-style command registry that the palette, key bindings and (later) scripting all share
skink-config Micro key names and Micro's default bindings, plus the settings and bindings file formats
skink-syntax tree-sitter highlighting, one lazily loaded grammar per language
skink-lsp A thin LSP client: JSON-RPC transport and server lifecycle, trimmed from Lapce
skink-term The terminal pane: portable-pty plus a vendored vt100. Built to stand alone as its own crate
skink-ai The ACP client, a 99-style prompter, and the AgentController seam
skink-host The EveryAI handover: an MCP client over a plain loopback TcpStream
skink-ui The ratatui front end, with screen-snapshot tests on a TestBackend
skink The binary

✦ Status

Skink is alpha. It is a real editor you can write code in today, and the bigger pieces are still landing.

✅ Working Editing with multiple cursors, auto-pairs, smart indent, comment toggle, syntax-aware selection · find bar (regex, case, whole word, replace, in-selection) · atomic saves, external-change reload, crash backups · tabs for files, terminals, help and previews · quick open over the whole project, command palette, symbol search · file tree (create, rename, trash, filter, .gitignore) · tree-sitter highlighting with injections, parsed incrementally: 10 languages built in and the rest as packages · LSP: diagnostics, completion with snippets, hover, signature help, go-to-definition, references, format, code actions, inlay hints · Markdown and SVG previews · skink --upgrade · AI: a 99-style prompt box (Ctrl-G) over ACP with model choice, an agent panel with permission prompts, and a refactor preview (checkboxes, per-file diff) for every multi-file change, including rename symbol · split panes, project-wide search and replace, session restore, folding, sticky scroll, rulers, docks, jump list · :agents with a health check on settings save · git: gutter change marks, stage / unstage / revert hunks with an inline peek, blame (inline and as a tab), a git panel (status, commit, branches, stash, push / pull in a terminal), side-by-side diff, clickable conflict resolution, status colours in the tree · refactors: structural search and replace (ast-grep), safe delete, move file with import updates, extract variable / function · tasks (tasks.json + detected cargo, npm, go, zig, pytest, make) with problem matchers · terminal history search, file:line links, prompt jumps · macros · EveryAI handover (tested against a fake host) · debugger (DAP): gdb, lldb-dap, CodeLLDB, debugpy, delve; breakpoints with conditions and logpoints, call stack, variables, watch, console, inline values, launch.json + preLaunchTask · as your $EDITOR: commit messages, rebase lists and Claude Code / Codex Ctrl-G prompts open lean (one buffer, :cq aborts), and inside a Skink terminal they open as a tab of that Skink · configuration: per-project .skink/settings.json and "[lang]" sections, settings checked as you save (unknown keys, types, ranges) with key completion and a JSON schema, custom language servers ("lsp.<lang>"), keymap presets (Micro, VS Code, Sublime) under bindings.json · themes: Tokyo Night (night, storm, moon, day), Catppuccin, Gruvbox, high contrast, your own JSON themes and Micro colorschemes, "auto" light/dark from the terminal, :theme with live preview · shell integration (prompt marks) in terminal tabs for bash, zsh, fish and PowerShell · Lua scripts (init.lua; project scripts only once trusted): commands, events, status items, pickers · persistent undo across restarts · big files highlight a window around the view · remote: skink ssh host:~/app runs the editor on another machine over your own ssh, installs itself there without the remote needing internet, and forwards ports that dev servers open in its terminals (saved "remotes", :ports, :port) · packages: skink --install kotlin (verified short names), owner/repo releases or a folder; WASM grammars loaded on first use, language servers downloaded and checksum-checked, themes, fonts, Lua; skink --install . installs what a project needs
🚧 Next Publish the first-party packages and the package index on the docs site
🧭 Planned Autonomous abuse-testing pass (v1.0)

Measured on Linux, release build with fat LTO and strip, by scripts/profile.py in a real pty:

Result Target
Binary 21.9 MB (tree-sitter grammars and wasmtime for package grammars, which cost disk, not RAM; Lua is 0.4 MB) under 25 MB (owner decision 2026-11-10)
Start to first frame 2.0 ms plain text · 3.2 ms Markdown · 3.9 ms Rust (colours arrive a moment later) under 50 ms
Idle RSS, project open about 8 MB under 15 MB
RSS with a 1 MB Rust file open about 30 MB under 120 MB

scripts/profile.py --budget checks these in CI on every push.

These will be re-measured as LSP, the terminal and the agent panel grow, with CI budgets set from the real numbers.

✦ Develop

cargo test --workspace                                # unit + screen-snapshot tests
cargo clippy --workspace --all-targets -- -D warnings
cargo deny check                                      # licences: permissive only
scripts/measure.py [path]                             # cold start + peak RSS in a real pty (Linux/macOS)

CI runs on Linux, macOS and Windows. Releases are tag-driven: pushing v* builds all five targets, writes SHA256SUMS, publishes the GitHub release and then installs it with the public one-liner on four OSes to prove it works. unsafe is forbidden workspace-wide.

Where the code comes from. The rule is copy-first from permissive projects, and every adapted chunk carries a header naming its source, commit and changes. cargo-deny blocks GPL, AGPL and LGPL, and treats MPL-2.0 as banned. Zed (GPL/AGPL) and Helix (MPL-2.0) are design references only: no code, no query files. The full ledger is in THIRD_PARTY_NOTICES.md.

✦ Credits

Skink stands on a lot of good work, most of it permissively licensed, and says so in the source:

Micro (key bindings and config formats) · Lapce (LSP transport and lifecycle) · ropey · ratatui · tree-sitter and nvim-treesitter queries · lsp-types · portable-pty · vt100 · tui-textarea (the undo-history idea) · tui-term (the painting approach) · Tokyo Night, Catppuccin and Gruvbox (theme palettes) · the Agent Client Protocol. The prompter's shape is inspired by ThePrimeagen/99; it has no licence, so only the ideas were used, never the code.

An aside on the name: a skink is a small, quick lizard that sheds its tail to get away. Like Anole, it is named for a lizard that's light on its feet. Built by @xuckless.

✦ License

Dual-licensed under MIT or Apache-2.0, at your option.

Skink is part of the same family as EveryAI, where it will be the default editor, and runs fine without it.
Third-party notices ship in every release archive.

About

Modeless terminal code editor in Rust. Neovim’s alternative, Micro’s keys, Zed’s Features. LSP, git, a real terminal, AI Agents (ACP) and your $EDITOR over SSH. One small binary.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages