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.
Docs · Why · How it solves it · Install · Quick start · Everything is a tab · AI agents · How it fits together · Status · Develop · Credits
A real frame from the editor (Ghostty-style tab bar with file and terminal tabs, file tree, Tokyo Night, Nerd Font icons).
- 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.
- 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. - 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.
- 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.
- 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.
- 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.
- Copy over SSH doesn't reach your clipboard. You select text in a remote editor, press copy, and it never leaves the server.
- 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.
- Config fatigue. Plugin managers, dotfile repos, a setup that breaks on update, and a fresh server that has none of it.
- "Permission denied" on save. You edited
/etc/somethingfor ten minutes, then find out you neededsudo. - No root on the server. You can't
apt installyour editor, and the one that's there isvi.
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.
| Platform | Command |
|---|---|
| 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 -- --uninstallInstaller 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.
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 needsMake 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.
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.
| 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.
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 claudeUnder 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.
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.
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
| 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 |
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.
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.
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.
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.
