Skip to main content

A Textual TUI coding workspace with file explorer and syntax highlighting

Project description

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, and Git 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 as not on remote, and marks branches whose changes are already present on the default branch as in 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 Branch button.

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 Commit to Sync Changes when 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/file from 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 switcher
  • recent_actions.json: recent command-palette actions
  • sessions.json: per-workspace open tabs, active tab, explorer state, selected sidebar panel, and terminal visibility
  • keybindings.json: app-level keybinding overrides
  • settings.json: app-level editor settings such as format_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.

Project details


Release history Release notifications | RSS feed

This version

0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nanoc-0.tar.gz (114.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nanoc-0-py3-none-any.whl (117.4 kB view details)

Uploaded Python 3

File details

Details for the file nanoc-0.tar.gz.

File metadata

  • Download URL: nanoc-0.tar.gz
  • Upload date:
  • Size: 114.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nanoc-0.tar.gz
Algorithm Hash digest
SHA256 18bda9a773f34c06aec05c79718d9922309e5ab50693178352c923d93a9af4ea
MD5 31358e8e6804efd8ce7b1db6ab7dd514
BLAKE2b-256 47da55ab905893bc5f19965db4e4a00661d5a15757cc83b81bbba405d45f1df8

See more details on using hashes here.

Provenance

The following attestation bundles were made for nanoc-0.tar.gz:

Publisher: publish.yml on mmcguffi/nanoCode

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nanoc-0-py3-none-any.whl.

File metadata

  • Download URL: nanoc-0-py3-none-any.whl
  • Upload date:
  • Size: 117.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nanoc-0-py3-none-any.whl
Algorithm Hash digest
SHA256 5ddd7d454729b9a7acb553ba8ea1a346f41cc32c781e176780d853b97e3d4a7c
MD5 58d3b95f816d5c0de6b3d01ff5ae01d2
BLAKE2b-256 8e1754c17c9b5afcd857d0184df1fd13304784f9936786c06bdfd6fb93a858f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for nanoc-0-py3-none-any.whl:

Publisher: publish.yml on mmcguffi/nanoCode

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page