p.enthalabs

GitHub - garritfra/cell: A terminal spreadsheet editor with Vim keybindings

GitHub - garritfra/cell: A terminal spreadsheet editor with Vim keybindings · GitHub

Skip to content

Navigation Menu

Toggle navigation

[](https://github.com/)

Sign in

Appearance settings

* Platform

* AI CODE CREATION

- GitHub Copilot Write better code with AI

- GitHub Spark Build and deploy intelligent apps

- GitHub Models Manage and compare prompts

- MCP Registry New Integrate external tools

* DEVELOPER WORKFLOWS

- Actions Automate any workflow

- Codespaces Instant dev environments

- Issues Plan and track work

- Code Review Manage code changes

* APPLICATION SECURITY

- GitHub Advanced Security Find and fix vulnerabilities

- Code security Secure your code as you build

- Secret protection Stop leaks before they start

* EXPLORE

- Why GitHub

- Documentation

- Blog

- Changelog

- Marketplace

View all features

* Solutions

* BY COMPANY SIZE

- Enterprises

- Small and medium teams

- Startups

- Nonprofits

* BY USE CASE

- App Modernization

- DevSecOps

- DevOps

- CI/CD

- View all use cases

* BY INDUSTRY

- Healthcare

- Financial services

- Manufacturing

- Government

- View all industries

View all solutions

* Resources

* EXPLORE BY TOPIC

- AI

- Software Development

- DevOps

- Security

- View all topics

* EXPLORE BY TYPE

- Customer stories

- Events & webinars

- Ebooks & reports

- Business insights

- GitHub Skills

* SUPPORT & SERVICES

- Documentation

- Customer support

- Community forum

- Trust center

- Partners

View all resources

* Open Source

* COMMUNITY

- GitHub Sponsors Fund open source developers

* PROGRAMS

- Security Lab

- Maintainer Community

- Accelerator

- GitHub Stars

- Archive Program

* REPOSITORIES

- Topics

- Trending

- Collections

* Enterprise

* ENTERPRISE SOLUTIONS

- Enterprise platform AI-powered developer platform

* AVAILABLE ADD-ONS

- GitHub Advanced Security Enterprise-grade security features

- Copilot for Business Enterprise-grade AI features

- Premium Support Enterprise-grade 24/7 support

- Pricing

Search or jump to...

Search code, repositories, users, issues, pull requests...

Search

Clear

Search syntax tips

Provide feedback

We read every piece of feedback, and take your input very seriously.

- [x] Include my email address so I can be contacted

Cancel Submit feedback

Saved searches

Use saved searches to filter your results more quickly

Name

Query

To see all available qualifiers, see our documentation.

Cancel Create saved search

Sign in

Sign up

Appearance settings

Resetting focus

You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert

{{ message }}

garritfra/**cell**Public

- NotificationsYou must be signed in to change notification settings

- Fork 5

- Star 193

- Code

- Issues 26

- Pull requests 2

- Discussions

- Actions

- Projects

- Security and quality 0

- Insights

Additional navigation options

- Code

- Issues

- Pull requests

- Discussions

- Actions

- Projects

- Security and quality

- Insights

[](https://github.com/garritfra/cell)

garritfra/cell

main

BranchesTags

[](https://github.com/garritfra/cell/branches)[](https://github.com/garritfra/cell/tags)

Go to file

Code

Open more actions menu

Folders and files

| Name | Name | Last commit message | Last commit date | | --- | --- | --- | --- | | ## Latest commit ## History 165 Commits [](https://github.com/garritfra/cell/commits/main/)165 Commits | | [.claude](https://github.com/garritfra/cell/tree/main/.claude ".claude") | [.claude](https://github.com/garritfra/cell/tree/main/.claude ".claude") | | | | [.github](https://github.com/garritfra/cell/tree/main/.github ".github") | [.github](https://github.com/garritfra/cell/tree/main/.github ".github") | | | | [assets](https://github.com/garritfra/cell/tree/main/assets "assets") | [assets](https://github.com/garritfra/cell/tree/main/assets "assets") | | | | [crates](https://github.com/garritfra/cell/tree/main/crates "crates") | [crates](https://github.com/garritfra/cell/tree/main/crates "crates") | | |

| [docs/superpowers](https://github.com/garritfra/cell/tree/main/docs/superpowers "This path skips through empty directories") | [docs/superpowers](https://github.com/garritfra/cell/tree/main/docs/superpowers "This path skips through empty directories") | | | | [examples](https://github.com/garritfra/cell/tree/main/examples "examples") | [examples](https://github.com/garritfra/cell/tree/main/examples "examples") | | | | [.gitignore](https://github.com/garritfra/cell/blob/main/.gitignore ".gitignore") | [.gitignore](https://github.com/garritfra/cell/blob/main/.gitignore ".gitignore") | | | | [AGENTS.md](https://github.com/garritfra/cell/blob/main/AGENTS.md "AGENTS.md") | [AGENTS.md](https://github.com/garritfra/cell/blob/main/AGENTS.md "AGENTS.md") | | | | [BENCH.md](https://github.com/garritfra/cell/blob/main/BENCH.md "BENCH.md") | [BENCH.md](https://github.com/garritfra/cell/blob/main/BENCH.md "BENCH.md") | | | | [CHANGELOG.md](https://github.com/garritfra/cell/blob/main/CHANGELOG.md "CHANGELOG.md") | [CHANGELOG.md](https://github.com/garritfra/cell/blob/main/CHANGELOG.md "CHANGELOG.md") | | | | [CLAUDE.md](https://github.com/garritfra/cell/blob/main/CLAUDE.md "CLAUDE.md") | [CLAUDE.md](https://github.com/garritfra/cell/blob/main/CLAUDE.md "CLAUDE.md") | | | | [CONTRIBUTING.md](https://github.com/garritfra/cell/blob/main/CONTRIBUTING.md "CONTRIBUTING.md") | [CONTRIBUTING.md](https://github.com/garritfra/cell/blob/main/CONTRIBUTING.md "CONTRIBUTING.md") | | | | [Cargo.lock](https://github.com/garritfra/cell/blob/main/Cargo.lock "Cargo.lock") | [Cargo.lock](https://github.com/garritfra/cell/blob/main/Cargo.lock "Cargo.lock") | | | | [Cargo.toml](https://github.com/garritfra/cell/blob/main/Cargo.toml "Cargo.toml") | [Cargo.toml](https://github.com/garritfra/cell/blob/main/Cargo.toml "Cargo.toml") | | | | [LICENSE](https://github.com/garritfra/cell/blob/main/LICENSE "LICENSE") | [LICENSE](https://github.com/garritfra/cell/blob/main/LICENSE "LICENSE") | | | | [README.md](https://github.com/garritfra/cell/blob/main/README.md "README.md") | [README.md](https://github.com/garritfra/cell/blob/main/README.md "README.md") | | | | View all files |

Repository files navigation

- README

- Contributing

- MIT license

cell

[](https://github.com/garritfra/cell#cell)

A terminal spreadsheet editor with Vim keybindings, written in Rust.

![Image 1: cell screenshot](https://github.com/garritfra/cell/blob/main/assets/cell.png)

Install

[](https://github.com/garritfra/cell#install)

From crates.io:

undefinedshell cargo install cell-sheet-tui undefined

Pre-built binaries for Linux, macOS, and Windows are available on the GitHub Releases page.

Build from source

[](https://github.com/garritfra/cell#build-from-source)

undefinedshell git clone https://github.com/garritfra/cell.git cd cell cargo build --release

Binary at target/release/cell

undefined

Usage

[](https://github.com/garritfra/cell#usage)

undefinedshell cell # empty sheet cell data.csv # open CSV cell data.tsv # open TSV cell sheet.cell # open native format cell data.psv --delimiter '|' # open with a custom field delimiter cat data.csv | cell # read from stdin (pipe input) undefined

To explore an example sheet with formulas, ranges, and IF logic:

undefinedshell cell examples/demo.cell undefined

The CSV/TSV delimiter is auto-detected from file content; pass `--delimiter` to override. The native `.cell` format is auto-detected via its `# cell v` magic header.

Headless mode

[](https://github.com/garritfra/cell#headless-mode)

For shell pipelines, Makefiles, and CI, `cell` can read from and write to a file without launching the TUI:

undefinedshell cell sales.cell --read A1 # print one cell's computed value cell sales.cell --read B1:B10 # print a range as TSV cell sales.cell --eval '=SUM(B1:B10)' # evaluate a formula (no save) cell sales.cell --write A1 42 # set a cell, recalc, save in place cell sales.cell --write A1 42 --write B1 7 # batch multiple writes into one save cell sales.cell --write Total '=SUM(B:B)' --read Total # write a formula, then print it cat data.csv | cell --read A1 # read from stdin cell data.psv --delimiter '|' --read A1 # custom delimiter undefined

- Cell references are 1-indexed and Excel-style (`A1`, `AA10`, `A1:B3`).

- The `=` prefix on `--eval` is optional.

- Writes whose value starts with `=` are stored as formulas; others are auto-typed (number vs text).

- Operations apply in a fixed order per invocation: writes → save → reads → evals.

- Errors print to stderr; the process exits non-zero on bad refs, parse errors, or missing files.

- Stdin input supports CSV, TSV, and the native `.cell` format. The delimiter is auto-detected; pass `--delimiter` to override (CSV/TSV only). `--write` requires a file argument when reading from stdin.

Keybindings

[](https://github.com/garritfra/cell#keybindings)

If you know Vim, you know cell.

All motions and operators accept a `[count]` prefix (`5j`, `10G`, `3dd`, `4yy`, `2w`). Counts also work between an operator and its motion (`d3j`, `y2k`); outer and inner counts multiply (`5d2j` clears 10 rows). The in-progress count and operator render in the status line as you type.

Normal Mode

[](https://github.com/garritfra/cell#normal-mode)

#### Motion

[](https://github.com/garritfra/cell#motion)

| Key | Action | | --- | --- | | `h``j``k``l` | Move cursor (one cell) | | `gg` | First row (or row N with `[count]gg`) | | `G` | Last row (or row N with `[count]G`) | | `0` | First column | | `$` | Last column | | `w` / `b` | Next / previous non-empty cell in row | | `Ctrl-D` / `Ctrl-U` | Half-page down / up | | `Ctrl-F` / `Ctrl-B` | Full page down / up | | `{` / `}` | Previous / next block boundary in column | | `H` / `M` / `L` | Cursor to top / middle / bottom of viewport | | `zz` / `zt` / `zb` | Recenter / scroll-to-top / scroll-to-bottom around cursor | | `Ctrl-e` / `Ctrl-y` | Scroll viewport one row without moving cursor | | `Ctrl-o` / `Ctrl-i` (or Tab) | Jump back / forward in jump list |

#### Marks

[](https://github.com/garritfra/cell#marks)

| Key | Action | | --- | --- | | `m{a-z}` | Set mark at cursor | | `'{a-z}` | Jump to marked row (column 0) | | ``{a-z}` | Jump to exact marked cell |

#### Editing

[](https://github.com/garritfra/cell#editing)

| Key | Action | | --- | --- | | `i` / `a` / `Enter` | Edit cell (Insert mode) | | `x` | Clear cell | | `dd` | Delete row (`[count]dd` for N rows) | | `d{motion}` | Clear cells along motion (`dj`, `d3l`, `dh`, `dk`) | | `yy` | Yank row (`[count]yy` for N rows) | | `y{motion}` | Yank cells along motion (`yj`, `y3l`, `yh`, `yk`) | | `p` / `P` | Paste below / above | | `Ctrl-A` / `Ctrl-X` | Increment / decrement number in cell (`[count]` accepted) | | `~` | Toggle case of first character, advance cursor | | `guu` / `gUU` | Lowercase / uppercase entire cell | | `g~~` | Toggle case of every character in cell | | `.` | Repeat last change | | `u` | Undo | | `Ctrl-R` | Redo |

#### Selection & search

[](https://github.com/garritfra/cell#selection--search)

| Key | Action | | --- | --- | | `v` | Visual selection | | `V` | Visual line (full-row) selection | | `Ctrl-V` | Visual block selection | | `gv` | Re-enter previous visual selection | | `/` / `?` | Search forward / backward (incremental) | | `n` / `N` | Next / previous match | | `*` / `#` | Search for current cell's value forward / backward | | `f<char>` / `F<char>` | Jump to next / prev cell in row starting with `<char>` | | `;` / `,` | Repeat last `f`/`F` (same / reversed direction) | | `:` | Command mode |

Insert Mode

[](https://github.com/garritfra/cell#insert-mode)

Type to edit the cell. `ESC` or `Enter` confirms. Arrow keys, `Home`, `End`, `Backspace`, and `Delete` work as expected within the cell.

Visual Mode

[](https://github.com/garritfra/cell#visual-mode)

Extend the selection with `hjkl` (or `[count]j` etc.), then:

| Key | Action | | --- | --- | | `y` | Yank selection | | `d` | Delete selection | | `c` | Change selection (clear and enter Insert mode) | | `u` / `U` / `~` | Lowercase / uppercase / toggle case of selection (formula cells skipped) | | `Esc` | Cancel selection |

Commands

[](https://github.com/garritfra/cell#commands)

| Command | Action | | --- | --- | | `:w` | Save | | `:w file.csv` | Save as CSV | | `:w file.cell` | Save as native format | | `:w!` | Force save (flatten formulas, override warnings) | | `:q` | Quit | | `:q!` | Quit without saving | | `:wq` | Save and quit | | `:e file` | Open file | | `:sort A asc` | Sort by column A ascending | | `:sort B desc` | Sort by column B descending | | `:set delimiter=|` | Change CSV/TSV delimiter for the next save | | `:help` / `:help <topic>` | Open the in-app help screen / jump to a topic |

In the `:` prompt, `↑` / `↓` cycle through previously executed commands.

Formulas

[](https://github.com/garritfra/cell#formulas)

Formulas start with `=` and support Excel-compatible syntax:

``` =A1+B1 =SUM(A1:A10) =AVERAGE(B1:B5) =IF(A1>100, "high", "low") ```

Supported Functions (v1)

[](https://github.com/garritfra/cell#supported-functions-v1)

`SUM`, `AVERAGE`, `COUNT`, `MIN`, `MAX`, `IF`

Formula compliance with the ODF (OpenDocument Formula) spec is tracked and will expand over time.

File Formats

[](https://github.com/garritfra/cell#file-formats)

- **CSV/TSV** -- Opens and saves standard comma/tab-separated files. Formulas are flattened to their computed values on CSV export.

- `**.cell`** -- Native format that preserves formulas. Plain text, human-readable, inspired by sc-im.

When saving a CSV that contains formulas, cell warns you and suggests saving as `.cell` instead. Use `:w!` to force a CSV save.

Comparison with sc-im

[](https://github.com/garritfra/cell#comparison-with-sc-im)

sc-im is a battle-tested terminal spreadsheet built on the classic `sc` (Spreadsheet Calculator, 1981). It inspired cell's native `.cell` format. Here's how the two tools compare:

| | cell | sc-im | | --- | --- | --- | | **Language / TUI** | Rust + ratatui | C + ncurses | | **Editing model** | True Vim modal editing (`i` → Insert, `ESC` → Normal) | Vim-inspired navigation; `=` to enter a value, `e`/`E` to edit | | **Formula syntax** | Excel-compatible (`=SUM(A1:A10)`, `=IF(...)`) | `@`-prefix style (`@sum(A1:A10)`, `@avg(...)`) | | **Built-in functions** | SUM, AVERAGE, COUNT, MIN, MAX, IF | Extensive (@sum, @avg, @min, @max, @abs, @sqrt, ...) | | **File formats** | CSV, TSV, `.cell` | CSV, TSV, XLSX/XLS/ODS import, Markdown export, `.sc` | | **Cell formatting** | not yet | Bold, italic, underline, RGB colors | | **Scripting** | Headless CLI mode (`--read` / `--write` / `--eval`, stdin pipe) | Lua scripting, external C modules, non-interactive mode | | **Charting** | not yet | GNUPlot integration | | **Windows support** | ✓ (pre-built binaries) | Limited | | **Clipboard** | Built-in | Requires tmux / xclip / pbpaste | | **Config file** | not yet | `~/.config/sc-im/scimrc` |

Choose cell if…

[](https://github.com/garritfra/cell#choose-cell-if)

- You want editing that works exactly like Vim (`i` to insert, `ESC` to return, `/` to search)

- You prefer Excel-compatible formula syntax (`=SUM`, `=IF`, `=AVERAGE`)

- You need a working binary on Windows without extra setup

- You value a modern, memory-safe codebase with minimal dependencies

Choose sc-im if…

[](https://github.com/garritfra/cell#choose-sc-im-if)

- You need XLSX, ODS, or Markdown support right now

- You need Lua scripting or GNUPlot charting right now

- You need cell-level formatting (colors, bold, italic) right now

- You want a highly configurable, feature-rich tool with decades of history behind it

Architecture

[](https://github.com/garritfra/cell#architecture)

``` cell/ crates/ cell-sheet-core/ # Data model, formula engine, file I/O (no TUI dependency) cell-sheet-tui/ # Ratatui rendering, Vim modes, event loop ```

The core library is independent of the terminal UI and can be tested without a terminal.

Releasing

[](https://github.com/garritfra/cell#releasing)

1. Update the version in `Cargo.toml` (workspace version) 2. Update `CHANGELOG.md` with the new version's changes 3. Commit: `git commit -am "release: bump to vX.Y.Z"` 4. Tag and push:

undefinedshell git tag vX.Y.Z git push origin main --tags undefined

Pushing a `v*` tag triggers the release workflow, which:

- Builds binaries for Linux (x86_64, aarch64), macOS (x86_64, aarch64), and Windows (x86_64)

- Creates a GitHub Release with the binaries attached

- Publishes `cell-sheet-core` and `cell-sheet-tui` to crates.io via trusted publishing

Contributing

[](https://github.com/garritfra/cell#contributing)

Contributions are welcome. See CONTRIBUTING.md for the development setup, project conventions, and pull request workflow.

License

[](https://github.com/garritfra/cell#license)

MIT

About

A terminal spreadsheet editor with Vim keybindings

Topics

[vim](https://github.com/topics/vim "Topic: vim")[rust](https://github.com/topics/rust "Topic: rust")[spreadsheet](https://github.com/topics/spreadsheet "Topic: spreadsheet")[spreadsheets](https://github.com/topics/spreadsheets "Topic: spreadsheets")

Resources

Readme

License

MIT license

Contributing

Contributing

Uh oh!

There was an error while loading. Please reload this page.

Activity

Stars

**193** stars

Watchers

**1** watching

Forks

**5** forks

Report repository

Releases 10

v0.4.0 Latest Apr 28, 2026

+ 9 releases

Packages 0

Uh oh!

There was an error while loading. Please reload this page.

Uh oh!

There was an error while loading. Please reload this page.

Contributors

* * *

Uh oh!

There was an error while loading. Please reload this page.

Languages

- Rust 100.0%

Footer

[](https://github.com/) © 2026 GitHub,Inc.

Footer navigation

- Terms

- Privacy

- Security

- Status

- Community

- Docs

- Contact

- Manage cookies

- Do not share my personal information

You can’t perform that action at this time.