Skip to content

fntune/turbobook

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

turbobook

Jupyter notebooks in the terminal. Real vim. Live Python kernel.

turbobook notebook.tb

No browser. No Electron. A 30ms keystroke-to-render notebook that works like an editor.


Why

Web notebooks are slow and mouse-dependent. Most "vim mode" add-ons are keybinding shims — they don't compose operators with motions. Jupyter's wire protocol is overkill for local work.

turbobook is a terminal-first notebook editor built from scratch:

  • Vim that actually composes. d2w, c$, yip, ct) — operators + motions work the way vim users expect, with correct inclusive/exclusive/linewise semantics.
  • Persistent Python kernel. A subprocess connected over a Unix socket keeps all your globals alive across cell executions.
  • Git-friendly format. .tb files are versioned JSON with stable UUID cell IDs (not execution counts). They diff cleanly.
  • Execute anywhere. Ctrl+Enter runs the focused cell from normal, insert, or visual mode — no mode switching required.

Installation

Requires Go 1.21+ and Python 3.10+.

git clone https://github.com/fntune/turbobook
cd turbobook
go build -o turbobook .
sudo mv turbobook /usr/local/bin/   # optional

Usage

turbobook notebook.tb   # open an existing notebook
turbobook               # splash screen with recent files

Key bindings

Navigation (normal mode)

Key Action
j / k Move focus between cells
Ctrl+Enter Execute focused cell
o / O Insert cell below / above
dd Delete cell
gg / G First / last cell
: Command mode

Editor (insert mode, inside a cell)

Full vim editing — all motions, operators, and text objects work:

Pattern Examples
Motions w b e B E 0 ^ $ gg G { }
Operators d c y with any motion (d2w, c$, yip)
Find/till f F t T + char, then ; / , to repeat
Visual v (char), V (line) — then any operator
Replace r (single char), ~ (toggle case)
Search / forward, ? backward, n / N to cycle
Join J joins next line

Commands

Command Action
:w Save (source only)
:w! Save with outputs
:q Quit

Format

Notebooks are stored as .tb files — plain JSON, designed to diff cleanly:

{
  "version": "1",
  "cells": [
    {
      "id": "3f2a1c8b-...",
      "type": "code",
      "source": "import pandas as pd\ndf = pd.read_csv('data.csv')",
      "outputs": [],
      "meta": { "exec_count": 1, "exec_ms": 42, "collapsed": false }
    }
  ]
}

Cell IDs are UUIDs — reordering cells doesn't rewrite the whole file.


Architecture

turbobook (Go binary)
├── bubbletea TUI                 event loop, terminal rendering
├── vim layer (pure functions)    VimState × Buffer → VimState × Buffer × Action
│   ├── normal mode               operators, motions, counts, registers
│   ├── insert mode               text input, ctrl sequences
│   └── visual mode               inclusive/exclusive selection
├── kernel client                 Unix socket IPC to Python subprocess
│   ├── execute / interrupt       cell execution, cancellation
│   └── status / ready            kernel lifecycle events
└── .tb format                    versioned JSON, UUID cells, MIME outputs

Python runtime (subprocess)
└── Unix socket server            JSON-RPC, Content-Length framing
    ├── execute handler           eval in shared namespace, captures stdout/stderr
    └── ready / shutdown          lifecycle handshake

The vim layer is entirely pure: every key event is a function from (VimState, Buffer, key) to (VimState, Buffer, Action). No side effects, no global state — the UI drives side effects based on the returned Action.


Status

Working alpha. Core vim editing, kernel execution, cell management, and .tb format are complete. Planned: LSP code completion, SQL cells with remote DB connections, AI generation and fix commands.

About

Terminal notebook editor with vim keybindings and a live Python kernel

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors