nanoCode
A Textual-based TUI editor/workspace with tabs, project search, git controls, markdown preview, and an integrated terminal.
Features
- File explorer sidebar with git-aware decorations and context-menu file actions
- Project text search sidebar with clickable file/line results
- Git control sidebar for staging, unstaging, discard, commit, sync, and branch checkout
- Tabbed editor with preview tabs, persistent tabs, and git status badges
- Markdown source/rendered preview workflow
- External formatter framework with Ruff-backed Python formatting
- Footer language selector for syntax overrides and footer branch selector for quick checkout
- Integrated PTY terminal with session handoff support
- Quick switcher for open tabs and recent files
- Workspace session restore for open files and key UI state
- Mouse support for splitters, tabs, search results, recent files, and git controls
Installation
Install from PyPI:
pip install nanoc
This installs the nanoc command and textual[syntax], which includes tree-sitter support for syntax highlighting.
Usage
Launch the app from the current directory:
nanoc
Launch against a specific workspace:
nanoc /path/to/project
Run through the Python module entry point:
python -m nanocode.app /path/to/project
Keyboard Shortcuts
| Key | Action |
|---|---|
Ctrl+S |
Save file |
Ctrl+Shift+S |
Save file as |
Ctrl+P |
Quick open files and tabs |
Ctrl+Shift+P |
Open command palette |
Ctrl+Shift+M |
Toggle Markdown preview |
Ctrl+/ |
Toggle line comment |
Ctrl+Shift+F |
Format document |
Ctrl+O |
Focus file tree |
Ctrl+E |
Focus editor |
Ctrl+Option+Left |
Switch to tab on the left |
Ctrl+Option+Right |
Switch to tab on the right |
Ctrl+T |
Toggle terminal |
Ctrl+N |
New untitled file |
Ctrl+Q |
Quit |
Additional actions such as Editor: Format Document, Editor: Toggle Format On Save, View: Search, View: Git, Settings: Keybindings, and theme switching are available from the command palette.
App-level shortcuts can be overridden with ~/.config/nanoCode/keybindings.json.
Only NanoCode app bindings are configurable; widget and modal bindings keep their built-in defaults.
Use the command palette and run Settings: Keybindings to create or open that file in the editor.
Modifier names in overrides use Textual syntax; macOS-friendly aliases like command and option are also accepted.
Example:
{
"bindings": {
"file.save": "ctrl+alt+s",
"view.files": "ctrl+shift+o"
}
}
UI Overview
- Sidebar tabs switch between
Explorer,Search, andGit Control. - The editor area shows recent files when no tabs are open.
- Files normally open as preview tabs first; editing or double-clicking promotes them to regular tabs.
- The bottom panel hosts the integrated terminal and can be toggled with
Ctrl+T. - The footer exposes the current branch and language mode. Both controls are clickable.
- The footer branch selector labels local-only branches as
local, labels same-name tracking branches that are no longer on the remote asnot on remote, and marks branches whose changes are already present on the default branch asin main. If the remote cannot be reached, it falls back to local tracking state such as Git's[gone]marker. - The footer branch selector hides old branch groups by default, can show them on demand, asks before switching to one, and can create and switch to a new branch from its
New Branchbutton.
Search, Git, and Markdown Workflows
- Project search scans the workspace, skips common generated directories, and jumps the cursor to the selected match.
- The git sidebar shows staged and unstaged changes, supports file-level and bulk actions, and can switch its primary button from
CommittoSync Changeswhen the tree is clean but ahead of remote. - Some discard operations are intentionally destructive and may remove untracked files as part of restoring the worktree.
- Clicking a changed file in the git sidebar opens it and can show an inline fullscreen diff view.
- Markdown preview opens a rendered companion tab for Markdown files rather than replacing the source tab.
Terminal
The terminal is a built-in PTY emulator based on pyte.
Features:
- Interactive shell support (
bash,zsh, etc.) - 256-color ANSI rendering
- Mouse tracking support
- Running interactive terminal programs
- Session handoff: when a file is opened with
nanoc path/to/filefrom inside the integrated terminal, the request is forwarded into the already-running app session instead of spawning a second instance
Persistence & Config
nanoCode stores user state under ~/.config/nanoCode/.
Current files:
recent.json: recent files shown on startup and used by the quick switcherrecent_actions.json: recent command-palette actionssessions.json: per-workspace open tabs, active tab, explorer state, selected sidebar panel, and terminal visibilitykeybindings.json: app-level keybinding overridessettings.json: app-level editor settings such asformat_on_save
Workspace restore intentionally skips untitled tabs, but it does restore file-backed tabs and rendered Markdown tabs.
Supported Languages
Syntax highlighting is supported for Textual's built-in languages:
- Bash (
.sh,.bash,.zsh,.command) - Go (
.go) - Java (
.java) - JavaScript (
.js,.mjs,.cjs,.jsx) - Python (
.py) - HTML (
.html,.htm) - CSS (
.css) - JSON (
.json) - Markdown (
.md) - Regex (
.regex,.regexp) - Rust (
.rs) - YAML (
.yaml,.yml) - TOML (
.toml) - SQL (
.sql) - XML (
.xml,.xsd,.xsl,.xslt,.svg)
Use the footer language selector to override the active tab's language for the current tab session.
Choose Auto to return to extension-based detection, or Plain Text to disable syntax highlighting.
Comment toggling is implemented for common languages including Bash, Go, HTML, Java, JavaScript, Markdown, Python, Rust, SQL, TOML, XML, and YAML.
Formatting is provided through external tools. Python formatting uses Ruff to organize imports and then run ruff format, so install Ruff separately and make sure ruff is on PATH before running Editor: Format Document or pressing Ctrl+Shift+F. Format-on-save is off by default and can be toggled from the command palette with Editor: Toggle Format On Save.
Development
Install development dependencies:
pip install -e ".[dev]"
Run the full test suite:
python -m pytest
Run a focused test module while iterating:
python -m pytest tests/test_workspace_sessions.py -q
Publishing
The PyPI project and distribution name is nanoc; the app name remains nanoCode, the import package remains nanocode, and the installed command is nanoc.
PyPI releases are published by .github/workflows/publish.yml using PyPI Trusted Publishing. Configure a pending GitHub Actions publisher on PyPI with:
- PyPI project name:
nanoc - Owner:
mmcguffi - Repository name:
nanoCode - Workflow name:
publish.yml - Environment name:
pypi
Version numbers use a major-only scheme: 0, 1, 2, and so on. The first release is 0.
Create the initial 0 release manually after the major-only version and publishing workflow changes are on main. After version 0 is available on PyPI, .github/workflows/release.yml handles normal releases without bypassing branch rules. When a non-release pull request is merged into main, GitHub Actions opens a release/N pull request that bumps version in pyproject.toml and nanocode.__version__ to the next major number. When that release pull request is merged, GitHub Actions creates a GitHub release with the same numeric tag and generated notes, then dispatches publish.yml.
The repository Actions setting must allow workflows to read and write repository contents so the release workflow can create release branches, open release pull requests, create releases, and dispatch publish runs. If GitHub Actions pull request creation is disabled in repository settings, the workflow leaves the release/N branch in place and logs a warning instead of failing. publish.yml runs the tests, builds the source and wheel distributions, and uploads them to PyPI without a PYPI_TOKEN secret. It can also be run manually from GitHub Actions if a failed publish needs to be retried before files have reached PyPI.
Metadata
Release files for nanoc 0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| nanoc-0.tar.gz | 114.1 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nanoc-0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 231.5 kB
Release files / nanoc-0.tar.gz
| Download URL | nanoc-0.tar.gz |
|---|---|
| Size | 114.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
18bda9a773f34c06aec05c79718d9922309e5ab50693178352c923d93a9af4ea
|
|
BLAKE2b-256 checksum How to use checksums |
47da55ab905893bc5f19965db4e4a00661d5a15757cc83b81bbba405d45f1df8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 26, 2026.
Transparency logRelease files / nanoc-0-py3-none-any.whl
| Download URL | nanoc-0-py3-none-any.whl |
|---|---|
| Size | 117.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5ddd7d454729b9a7acb553ba8ea1a346f41cc32c781e176780d853b97e3d4a7c
|
|
BLAKE2b-256 checksum How to use checksums |
8e1754c17c9b5afcd857d0184df1fd13304784f9936786c06bdfd6fb93a858f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 26, 2026.
Transparency logSecurity for nanoc 0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for nanoc-0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 26, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.