NotebookVim
notebookvim is a Vim-inspired terminal workspace for Jupyter notebooks and
data engineering projects. Navigate and edit notebooks or source files, run
cells in a persistent kernel, explore data with local SQL and profiling tools,
and manage an entire project without leaving the command line. Python and SQL
are supported today, with Scala and R support planned for future releases. The
workspace also includes an integrated terminal, AI assistance powered by Codex,
Claude, or Ollama, and connectivity for data platforms such as Databricks, with
a provider-neutral foundation designed to support platforms such as Microsoft
Fabric.
I hope you enjoy this programmer-focused CLI for the world of data—and that it makes working with data feel a little more at home in the terminal.
Install
Install the published package with pip:
python -m pip install notebookvim
For an isolated command-line installation, use pipx:
pipx install notebookvim
The package installs the notebookvim command.
Development setup
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e '.[dev]'
Use
cd path/to/project
notebookvim
notebookvim new experiment.ipynb
notebookvim experiment.ipynb
notebookvim path/to/project
Opening notebookvim without a path starts a project workspace in the current
directory. Use Ctrl+E to toggle the project tree and Ctrl+P to fuzzy-find a
file. Selecting a notebook or supported UTF-8 text file opens it without leaving
the application. Python, Markdown, JSON, TOML, YAML, SQL, shell, and other common
source files receive syntax highlighting; use Ctrl+S to save and Ctrl+Q to
quit from the text editor. Generated
directories such as .git, .venv, node_modules, and __pycache__ are
hidden from the navigator.
Selecting a .parquet, .parq, or .pq file opens a read-only preview of its
first 25 rows followed by Spark-style count, mean, stddev, min, and
max summary statistics. Statistics are calculated directly with PyArrow;
Spark is not started.
Parquet and Delta inspection
With a Parquet file open, typing :inspect prioritizes contextual
inspect parquet … completions. Available metadata views are:
:inspect parquet describe
:inspect parquet profile
:inspect parquet partitions
:inspect parquet rowgroups
:inspect parquet schema
:inspect parquet files
:inspect parquet history
Describe shows physical format, dimensions, compression, producer, and metadata
size. Schema includes nested fields and field metadata; row groups include row
counts and sizes; partitions recognize Hive-style key=value paths. Plain
Parquet has no transaction history, so its history view reports filesystem
modification information and explains that limitation.
If the open Parquet file is below a Delta table root containing _delta_log,
Delta completions are added automatically:
:inspect delta describe
:inspect delta profile
:inspect delta version
:inspect delta schema
:inspect delta partitions
:inspect delta rowgroups
:inspect delta history
:inspect delta files
:inspect delta properties
:inspect delta cdf
:inspect delta time travel 12
The inspector reconstructs snapshots from retained JSON commits and Parquet checkpoints, including multipart checkpoints and referenced V2 sidecars. It replays add/remove actions for current or historical versions and exposes table metadata, protocol versions, active files, per-file statistics, commit operations, properties, and change-data-file actions. Reports are read-only and limited to 500 rows where a table may contain many files or row groups.
Delta profiling uses DuckDB over the active snapshot files. It deliberately refuses snapshots containing deletion vectors because a direct Parquet scan would otherwise include logically deleted rows.
Inspection metadata opens in a scrollable overlay by default. Press Escape
to close it and return to the same file and cursor context; inspection does not
create or switch document tabs. Append side or below to keep a report next
to the source while working, and close a pinned report with Escape or
:inspect close:
:inspect parquet schema side
:inspect parquet rowgroups below
:inspect delta history side
:inspect close
The terminal, AI assistant, and inspection report share the auxiliary split area, so opening one closes the others instead of squeezing the source into three panes.
Local SQL and dataset profiles
Open a syntax-highlighted, entirely local DuckDB workspace with :sql. Enter
SQL, press Escape, and use these commands:
:sql Open the existing SQL tab, or create one
:sql new Open another SQL tab
:sql run Run the current query (up to 200 displayed rows)
:sql explain Show the DuckDB query plan
:sql history Show recent session queries
:sql save Save the query under queries/
:sql cancel Cancel a running query (Ctrl+C also works)
DuckDB can query project data directly without starting Python, Spark, or a
server—for example, SELECT * FROM read_parquet('data/sales.parquet') or
SELECT * FROM read_csv_auto('data/sales.csv'). Results remain attached to the
SQL tab and include execution time and a truncation marker when more rows exist.
From a Parquet preview or SQL workspace, use :profile (or :profile current)
to open a profile tab. It shows shape, types, null rates, approximate distinct
counts, min/max, mean, standard deviation, quartiles, common values, inferred
identifier/timestamp/categorical roles, and available Parquet metadata. Use
:profile save or Ctrl+S from the profile tab to export the result as JSON in
the project root. Profiling uses DuckDB summaries and bounded top-value checks;
it does not load the whole dataset into application memory.
Project editing shortcuts:
Ctrl+Tab Move between the file browser and active editor
Option+Enter Open the selected browser file in a new tab (Alt+Enter in terminals)
Shift+Tab Move to the next open tab
Ctrl+Shift+Tab Move to the previous open tab
Ctrl+W Close the active tab (`:tab close` also works)
Escape, then q Close the active file/tab
Ctrl+E, then t Terminal-safe way to focus the browser and open a file in a tab
Escape, then ]/[ Terminal-safe next / previous tab
u / Ctrl+R Undo / redo in Normal mode
: Open commands in Normal mode
The status bar keeps the essential controls visible: : for commands,
:help, Ctrl+E for files, i to edit, Ctrl+S to save, and Ctrl+Q to
exit. Closing the final tab leaves the project browser and command system open
and shows the NotebookVim welcome screen. From there, open another file or use
Esc, then : to enter a command, just as you would return to commands in Vim.
Python text files and Python notebook cells receive local Jedi completions;
press Tab to accept a displayed completion. Markdown and other supported text
files retain syntax highlighting without Python completions.
Editable files open in Vim-style Normal mode and cannot be changed until you
press i, a, I, A, o, or O. The status bar shows NORMAL, INSERT,
or VISUAL. In a text file, Normal mode supports h/j/k/l, w/b,
0/$, gg/G, dd, yy, x, p/P, u, Ctrl+R, and character-wise
Visual mode with v. Press Escape to return to Normal mode. Python files
keep local completions in Insert mode, and Tab accepts a suggestion.
Platform-style cursor shortcuts work alongside Vim motions. On macOS,
Command+Left/Right goes to the start/end of a line and
Command+Up/Down goes to the start/end of the document. On Windows and Linux,
Ctrl+Left/Right moves by word and Ctrl+Up/Down moves to the start/end of the
document. Add Shift to extend the selection. Option+Left/Right also moves by
word on macOS. Command-key delivery depends on the terminal exposing enhanced
keyboard events; Home/End and the Vim motions remain available everywhere.
Notebook cells use the same modal idea. Press Enter on a selected cell to
open it in cell-Normal mode, then i to edit. The first Escape returns from
Insert to cell-Normal mode; a second Escape commits the cell and returns to
notebook navigation. Pressing i from notebook navigation remains a shortcut
that opens the cell directly in Insert mode. Use j/k to select cells,
o/O to create and edit a cell below/above, dd to delete, yy to copy,
p/P to paste below/above, u/Ctrl+R to undo/redo, gg/G for the
first/last cell, J/K to move a cell, m to switch code/Markdown, and
r/R to run or run-and-advance. Arrow keys remain available. Enter does
not enter Insert mode.
Press : in navigation mode for commands. Selected-cell commands include:
:cell run :run cell 2
:cell output clear
:cell add above :cell add below
:cell delete :cell duplicate
:cell move up :cell move down
:cell type code :cell type markdown
Displayed cell numbers are one-based and include every code and Markdown cell.
For example, :run cell 2 selects and executes the second cell when it is a
code cell.
Notebook and kernel commands include :notebook run all, :notebook save,
:kernel info, :kernel interrupt, :kernel restart, and :kernel shutdown.
Use :help in the application for the complete list. :q closes the active
file/tab—including the final tab—while :wq saves and closes it. :exit exits notebookvim after the usual
unsaved-work confirmation. Other short aliases include :run,
:output clear, and :w.
The command bar shows matching commands in a selectable list as you type. Use
Up/Down to choose an option, Tab to fill it, and Enter to run it. This includes
command arguments such as every available option after :theme. Open a project
file by its workspace-relative path with :file open reports/sales.py, or open
it in a new tab with :tab open reports/sales.py; both commands complete file
paths from the current project, including subdirectories.
Create an empty file with :file new reports/summary.py or the equivalent
:file create reports/summary.py. You can also right-click a folder in the file
explorer and enter a filename; right-clicking a file uses its parent folder.
Run notebookvim with no argument to start with no project open; use notebookvim . to
open the current folder. Switch projects without leaving notebookvim using :project open foldername or its
alias :folder open foldername. Both commands complete folders inside the
current project; you may also type an absolute path or a relative path such as
../another-project. Unsaved files must be saved or closed before switching.
Use :project close or :folder close to clear the active project and return
to the welcome screen.
Initialize a Databricks-oriented medallion project in the current folder with
:project scaffold init data-engineering. It adds Bronze, Silver, and Gold
starter notebooks alongside src, sql, and tests folders, a README,
requirements, and a .gitignore. Existing files are always preserved, so the
command is safe to run again.
file/tab, :wq saves and closes it, and :exit exits notebookvim after the usual
unsaved-work confirmation. Other short aliases include :run,
:output clear, and :w.
Open a workspace terminal beside the active document with :terminal,
:terminal open, or :terminal open side. Use :terminal open below for a
lower split and hide either layout with :terminal close. The terminal keeps
its current directory and command history while hidden. Submitted lines are
forwarded to a running process, so prompts, confirmations, and interactive CLIs
work. Use Up/Down for history, Ctrl+L to clear its output, Ctrl+C to interrupt a
running command, and Escape to return focus to the editor. It uses a VS
Code-style dark terminal background, foreground, and 16-color ANSI palette.
Full-screen programs that require complete terminal-screen emulation should be
launched with a non-alternate-screen option when available.
Commands run through the configured macOS login shell in interactive mode, so
normal shell startup files and aliases are loaded. ANSI and true-color output
is preserved inside the terminal frame.
AI assistants
Open the AI side pane with :ai or :ai open, or place it beneath the document
with :ai open below. It streams answers and includes
the active file plus a bounded snapshot of the selected notebook cell, text
file, or SQL query. Ctrl+C cancels a request and Escape returns to the
document.
:ai status Show which provider CLIs are installed
:ai provider codex Use Codex CLI
:ai provider claude Use Claude Code
:ai provider ollama qwen2.5-coder:7b
Use Ollama with a specific installed model
:ai ask Explain this cell Open the pane and send a prompt
:ai interrupt Stop the running AI request and keep the pane open
:ai close Close the pane
The selected provider and Ollama model are saved in user settings. If the model
is omitted, NOTEBOOKVIM_OLLAMA_MODEL or llama3.2 is used. Provider runs use safe
analysis modes: Codex uses a read-only sandbox and Claude Code uses plan mode.
Ollama receives prompt context without shell or file-editing tools.
Databricks
Authenticate with the Databricks CLI, then connect the current notebookvim session:
:databricks connect
:databricks connect MyProfile
:databricks connect https://your-workspace.cloud.databricks.com
:databricks status
Passing a workspace URL opens browser-based OAuth, which is the easiest route for Databricks Free Edition. With no argument, notebookvim uses default unified authentication; a non-URL argument selects a named Databricks profile.
After connecting, Python notebook cells automatically receive workspace (a
Databricks WorkspaceClient) and dbutils. Local use of dbutils supports the
utility groups exposed by the Databricks SDK, including fs, secrets,
widgets, and jobs. For example:
for item in dbutils.fs.ls("/"):
print(item.path)
Credentials remain in the standard Databricks authentication configuration and are not written into notebook files. This connection provides workspace utilities; notebook cells still execute in the local Python kernel.
Remote notebook synchronization
After connecting to Databricks, map the active local notebook or source file to a workspace notebook:
:databricks sync set /Workspace/Users/me@example.com/Analysis
:databricks sync set /Workspace/Users/me@example.com/Analysis --strip-outputs
:databricks sync status
:databricks sync diff
:databricks sync pull
:databricks sync push
Supported working-copy formats are .ipynb, .py, .sql, .scala, and .r.
Mappings and the last synchronized content hash live under .notebookvim/, which is
hidden from the project browser. Jupyter notebooks use the native Jupyter
workspace format so notebook and cell metadata survive round trips. Source
notebooks use the matching Databricks language.
Safety rules are deliberately strict:
- Pull never overwrites unsaved editor changes.
- Pull also stops when the saved local file changed since synchronization.
- Push stops when the remote content changed since synchronization.
:databricks sync diffdisplays source changes by notebook cell.- Resolve a reviewed conflict with
:databricks sync resolve local(force push) or:databricks sync resolve remote(force pull). Both require saved local work. --strip-outputsremoves code outputs and execution counts from uploaded Jupyter notebooks while leaving the local file unchanged.
You may also provide the mapping on the first operation, such as
:databricks sync push /Workspace/Users/me@example.com/Analysis.
Remote jobs and logs
Databricks jobs use the same authenticated connection:
:databricks jobs
:databricks jobs running
:databricks run 12345 --param date=2026-08-19 --param region=eu
:databricks logs 98765
:databricks logs follow 98765
:databricks cancel 98765
:databricks rerun 98765
The job and run views show identifiers, state, result, start time, duration,
parameters, compute ID, and the Databricks run link. A run ID can be omitted
from logs, cancel, and rerun immediately after :databricks run; notebookvim remembers
the most recently started run. Follow mode refreshes every two seconds until a
terminal state is reported.
Databricks returns standard-stream driver logs for supported non-notebook task types and notebook exit values or failures for notebook tasks. It does not return notebook driver stdout through the Jobs output endpoint; complete cluster logs require a log destination configured on the Databricks job.
This initial remote provider is Databricks. The synchronization and report models are provider-neutral, but Microsoft Fabric authentication, definition conversion, job execution, and log retrieval still require a Fabric adapter.
Git profiles
Named Git profiles keep commit identity and provider account selection together. Credentials remain in GitHub CLI, Git Credential Manager, or the operating system credential store; notebookvim never stores access tokens or passwords.
:git profile add personal github layanwije me@example.com "My Name"
:git profile add work azure me@company.com me@company.com "My Name"
:git profile list
:git profile use personal
:git login personal
:git status
:git pull
:git push
GitHub browser login requires gh or Git Credential Manager. Azure DevOps
browser login requires Git Credential Manager and uses Microsoft OAuth. Profile
selection writes the profile's author name and email to the current repository,
so it does not change the identity of unrelated projects.
Other commands:
notebookvim run experiment.ipynb
notebookvim info experiment.ipynb
notebookvim --help
Development
pytest
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file notebookvim-0.1.0.tar.gz.
File metadata
- Download URL: notebookvim-0.1.0.tar.gz
- Upload date:
- Size: 90.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f61fe2bc2c02586f7387940e25861524e2d4f9d4ce9024b4cadcec0bcd3350f3
|
|
| MD5 |
91f58a89416b67386a6b0bd821706e60
|
|
| BLAKE2b-256 |
754a1eb6ec6ea4189fcba771cd41dde34fa790b565bf13834f6c94100ed2f34a
|
File details
Details for the file notebookvim-0.1.0-py3-none-any.whl.
File metadata
- Download URL: notebookvim-0.1.0-py3-none-any.whl
- Upload date:
- Size: 83.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54e642b4a4c55b2086cf22a022be5c640ca1c252761049c7d53d0dad13970342
|
|
| MD5 |
1cbc63055dff48897078c743d524b46e
|
|
| BLAKE2b-256 |
9febc152c641bf748ba748110c05b3d9268ca68d6f2fd183f64e8e492730d42a
|