Package Control

The official Sublime Text package manager.

ClaudeSublime

By petr.jakub
Created June 26, 2026, last updated July 29, 2026.

JulJunMayAprMarFebJan Dec2025 NovOctSepAug 2026-W34 | installs: 6 | removals: 2 | upgrades: 0 2026-W34 | installs: 6 | removals: 2 | upgrades: 0 2026-W34 | installs: 6 | removals: 2 | upgrades: 0 2026-W33 | installs: 3 | removals: 0 | upgrades: 0 2026-W33 | installs: 3 | removals: 0 | upgrades: 0 2026-W33 | installs: 3 | removals: 0 | upgrades: 0 048 WeeklyInstalls 024 WeeklyUpgrades 2026-W31 1.0.3 / 1.0.2 2026-W30 1.0.1 / 1.0.0 / ... 1.0.1 / 1.0.0 / 0.1.6 2026-W29 0.1.5 / 0.1.4 2026-W28 0.1.3 2026-W27 0.1.2 / 0.1.1 / ... 0.1.2 / 0.1.1 / 0.1.0 / 0.0.2 / 0.0.1
Installations: recent average 3 per week, 10 in total
Installations minus removals
Upgrades

Links

Versions

1.0.3 (>ST4106) ·
2026-07-29 10:08

More

ClaudeSublime

A Sublime Text plugin for Claude Code, written in Claude Code — the tool wrote its own editor integration. (Yes, it's turtles all the way down. And yes, that means you can now blame the AI for its own plugin.)

A Sublime Text plugin with two features:

  1. rsync sync — push/pull the project to/from a remote host over SSH, from the sidebar context menu, plus an optional watchdog auto-sync on change.
  2. Claude Code panel — run Claude Code in a Terminus output panel rooted at the project, with live highlighting of the files Claude changes, change navigation, and interaction notifications.

Requirements

Install

This repo isn't in the default channel, so add it as a custom repository once and Package Control then installs/updates it like any package:

  1. Package Control: Add Repository (Command Palette, cmd/ctrl+shift+P), paste:
    https://gitlab.com/petr.jakub/claudesublime/-/raw/main/repository.json
    
  2. Package Control: Install Package → pick ClaudeSublime.

Package Control installs the latest tagged release. Updates come with Package Control: Upgrade Package. If Terminus is missing, ClaudeSublime offers to install it on first panel open.

Private fork? If you point the repository at a private GitLab repo, Package Control's http_basic_auth won't work (GitLab's API rejects basic auth), and the archive download can't be authenticated — so PC install only works with a public repo. For a private one, use the manual/dev install below.

Manual

Copy this folder into your Sublime Text Packages directory, named exactly ClaudeSublime (open it via Preferences → Browse Packages…):

~/Library/Application Support/Sublime Text/Packages/ClaudeSublime        (macOS)
%APPDATA%\Sublime Text\Packages\ClaudeSublime                            (Windows)
~/.config/sublime-text/Packages/ClaudeSublime                            (Linux)

Sublime loads it automatically. To verify, open the Command Palette and type ClaudeSublime — the commands should be listed. To remove it, delete that folder (or remove it via Package Control if installed that way).

Enabling watchdog (optional — only for auto-sync)

watchdog affects auto-sync only (highlighting is log-driven and never uses it). Without watchdog, auto-sync runs only while the Claude panel is open (it rides a polling loop) plus ST "sync on save". With it, auto-sync uses real OS file events and runs whenever Sublime is open — and on macOS deletions/creations (including files Claude writes in the terminal) are picked up promptly. If you don't use rsync sync, you don't need watchdog at all.

The catch: Sublime Text 4 plugins run on a bundled Python 3.8, so the library must be installed into ST's own Lib/python38 folder, and on macOS the wheel must match Python 3.8 and your CPU. Use a watchdog 4.x wheel — 5.0+ drops Python 3.8 (a too-new watchdog simply fails to import and is ignored).

This package ships a .python-version file (3.8) so ST runs it on the 3.8 host — that's also what puts Lib/python38 on the import path. Without it ST would use the legacy 3.3 host, where neither watchdog nor os.scandir exist. If you ever see module 'os' has no attribute 'scandir' in the console, the package is running under 3.3 — make sure .python-version is present and restart Sublime Text.

macOS (Apple Silicon shown; for Intel swap the platform — see note):

# 1. Locate ST's 3.8 lib folder
LIB="$HOME/Library/Application Support/Sublime Text/Lib/python38"

# 2. Download a 3.8 wheel for your arch (arm64 here; uname -m to check)
cd /tmp
pip3 download 'watchdog<5' --only-binary=:all: \
  --python-version 3.8 --implementation cp --abi cp38 \
  --platform macosx_11_0_arm64 -d watchdog-dl

# 3. Drop it into ST's lib (remove any older/mismatched copy first)
rm -rf "$LIB"/watchdog "$LIB"/watchdog-*.dist-info "$LIB"/_watchdog_fsevents*.so
unzip -o /tmp/watchdog-dl/watchdog-*.whl -d "$LIB"

# 4. Restart Sublime Text (required — Lib is read at startup)

Intel Mac: replace --platform macosx_11_0_arm64 with --platform macosx_10_9_x86_64. Run uname -m (arm64 vs x86_64) if unsure.

Linux — watchdog uses inotify (pure Python, no compiled extension), so a plain install into ST's lib works regardless of your system Python version:

LIB="$HOME/.config/sublime-text/Lib/python38"
pip3 install --target "$LIB" 'watchdog<5'
# then restart Sublime Text

Windows — watchdog uses ReadDirectoryChangesW (also pure Python). In PowerShell:

$LIB = "$env:APPDATA\Sublime Text\Lib\python38"
pip install --target "$LIB" "watchdog<5"
# then restart Sublime Text

On Linux/Windows there's no per-CPU C extension to match (the compiled part, _watchdog_fsevents, is macOS-only), so any watchdog 4.x is fine — keep the <5 pin so it still imports under Python 3.8. If pip pulls a .dist-info for a newer dep that won't import, just reinstall with the pin.

Verify: restart ST, open View → Show Console, and run:

from watchdog.observers import Observer; print("watchdog OK:", type(Observer()).__name__)

An observer name — FSEventsObserver/KqueueObserver (macOS), InotifyObserver (Linux), WindowsApiObserver (Windows) — means it loaded. The ClaudeSublime status bar then shows Auto-sync 🟢 (instead of the panel-tied polling fallback). On macOS, if FSEvents can't load, watchdog automatically falls back to kqueue — still fine for normal projects.

Developing the plugin? Instead of copying, symlink your working copy into Packages so edits apply live — see CLAUDE.md. The symlink is a dev convenience only, not the way end users activate the plugin.

Per-project configuration — ClaudeSublime.json

Put a ClaudeSublime.json at a project folder root (see ClaudeSublime.example.json). // comments and trailing commas are allowed.

The fastest way to create one is the Command Palette entry ClaudeSublime: Generate Project Config (also under Tools → ClaudeSublime and in the sidebar right-click menu — there it targets the project folder of the clicked item). It writes a ClaudeSublime.json with the required fields (host, remote_path) left empty and the optional ones pre-filled with their defaults, then opens it for editing. If the file already exists it just opens it instead of overwriting.

{
    "rsync": {
        "enabled": true,                   // optional, set false to disable all rsync
        "host": "server.example.com",      // required (when enabled)
        "remote_path": "/srv/www/app",     // required (when enabled)
        "user": "jakub",                   // optional (default: ssh config / current user)
        "port": 22,                        // optional
        "connect_timeout": 30,             // optional
        "keepalive": 300,                  // optional (ServerAliveInterval)
        "ssh_key_file": "~/.ssh/id_rsa",   // optional
        "ssh_config_file": "~/.ssh/config",// optional
        "extra_ssh_options": [],           // optional, raw ssh -o flags
        "extra_rsync_options": [],         // optional, raw rsync flags (e.g. "--rsync-path=sudo rsync")
        "ignore_regexes": []               // optional, merged with built-in defaults
    },
    "claude": {
        "session": ""                      // optional session UUID to --resume
    }
}

claude.session is filled in automatically: when you open the panel and a new session is started — because none was pinned yet, or a --resume couldn't find the saved one — the plugin writes the new session's UUID back here, so the next open resumes right where you left off. You can still set/replace it manually via ClaudeSublime: Save Session ID for This Project.

To use only the Claude Code panel without any remote sync, set "rsync": { "enabled": false } (the other rsync fields can be omitted). All sync commands — Sync ↑/↓ and Toggle Auto-Sync — then stay disabled, and auto-sync never starts.

Windows

rsync sync does not work on Windows: the runner streams rsync through a pseudo-terminal using Python's pty module, which is Unix-only, and Windows has no native rsync. So on Windows Generate Project Config writes a minimal, disabled rsync block:

{
    "rsync": { "enabled": false },
    "claude": { "session": "" }
}

rsync is treated as unavailable on Windows regardless of the config — even if you hand-write a full rsync section, the sync commands stay disabled, auto-sync never starts, and the indicator shows (a manual trigger just says "not supported on Windows"). No error spam. The Claude panel, highlighting and auto-open all work normally. If you need remote sync there, run it yourself via WSL (wsl rsync … with /mnt/c/… paths).

FreeIPA / JumpHost / ControlMaster

rsync uses your ~/.ssh/config verbatim, so the cleanest setup is to define the JumpHost / ControlMaster there:

Host server.example.com
    ProxyJump jump.example.com
    ControlMaster auto
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 600

With ControlMaster the first connection authenticates once; subsequent syncs reuse the master socket and won't re-prompt. If rsync/ssh does ask for a password, passphrase, or host-key confirmation, ClaudeSublime shows it as a Sublime input panel (note: input is not masked, same as ST's rename input).

Ignore patterns

ignore_regexes are regexes matched against the project-relative path and are also converted to rsync --exclude rules (so they apply in both sync directions). Generate Project Config pre-fills a sensible default set — VCS metadata (.git/, .svn/, .hg/, …), OS cruft (.DS_Store, Thumbs.db, …), editor/IDE state (*.sublime-*, sftp-config.json, .idea/, .vscode/, vim swap files, ClaudeSublime.json), and dependency/build caches (node_modules/, __pycache__/, *.pyc, venv/, .pytest_cache/, .gradle/, …). Because they live in the config (not hard-wired), you can delete any entry to start syncing it — e.g. drop \.git/ to sync the .git folder — or add your own.

(If a config has no ignore_regexes key at all — e.g. a minimal hand-written one — the same built-in defaults are used as a fallback. Setting the key, even to [], takes over completely.)

Usage

Sidebar right-click → ClaudeSublime:

Local and remote stay 1:1 (a true mirror), except ignored paths. With sync_delete on (the default), rsync --delete is used so a file you remove on one side is removed on the other:

  • Auto-sync pushes the whole project on every change and removes anything on the remote that no longer exists locally (deletions and renames of files and folders propagate). This includes files Claude creates/edits/deletes directly from the panel. With watchdog installed it works whenever ST is running; without it, auto-sync falls back to polling the project and so only runs while the Claude panel is open.
  • Manual sync mirrors in both directions — whole project, or a selected folder (a selected single file never triggers deletions).

Ignored paths (ignore_regexes, e.g. .git/, node_modules/) are always protected — never pushed and never deleted just because they're missing on the other side. Set sync_delete to false to make every sync add/update only (stale files then linger, as in the old behaviour).

Editor right-click → ClaudeSublime:

All commands (Command Palette — type "ClaudeSublime")

Caption Command What it does
Show / Hide Claude Panel claude_sublime_toggle Open the panel, or toggle its visibility
Toggle Focus (editor ⇄ panel) claude_sublime_focus_toggle Move focus between the editor and the Claude panel (opens/shows it if needed)
New Claude Session claude_sublime_new_session Stop the current session, start a fresh one (its id is auto-saved)
Save Session ID for This Project claude_sublime_save_session Manually pin a session UUID into ClaudeSublime.json
Generate Project Config claude_sublime_init_config Create a ClaudeSublime.json (also in the sidebar menu)
Enable Interaction Notifications claude_sublime_enable_notifications Add the Notification + Stop hooks (globally, in ~/.claude) so you're pinged when Claude needs you / finishes
Go to Changed File claude_sublime_goto_changed_file Quick-panel list of files with Claude marks (+/− counts); jump to one
Next / Previous Change (this file) claude_sublime_goto_change {"direction": …, "scope": "file"} Jump between Claude's change blocks in the active tab
Next / Previous Change (all tabs) claude_sublime_goto_change {"direction": …, "scope": "global"} Same, continuing across all open tabs (wraps)
Send Selection to Claude claude_sublime_send_selection Send the selection/line to Claude and submit
Add File to Context claude_sublime_add_context {"include_selection": false} Insert @file into the prompt (no submit)
Add File + Selection to Context claude_sublime_add_context {"include_selection": true} Insert @file + the selection (no submit)
Sync local → remote claude_sublime_sync_up rsync push (whole project, or selected paths)
Sync remote → local claude_sublime_sync_down rsync pull
Toggle Auto-Sync claude_sublime_toggle_autosync Turn auto-sync on/off for this window

Sidebar-only: claude_sublime_add_context_sidebar (Add File to Context from the tree).

The status bar shows an auto-sync indicator: Auto-sync 🟢 (on), Auto-sync 🔴 (off), Auto-sync 🟠 (syncing now), or Auto-sync ⚪ (N/A — rsync disabled or not configured). Sublime status items have no hover tooltip, hence the legend here. Hide it with show_autosync_status: false.

After each successful sync, a short note appears next to it — Synced: file1, file2 (basenames, up to two) or Synced: 15 files — since rsync is often too quick to catch the 🟠. Turn it off with show_synced_files: false.

Suggested keybindings (opt-in — nothing is bound by default)

ClaudeSublime ships no active key bindings, so it never clashes with keys your other packages use. Every command is in the Command Palette (type ClaudeSublime:). The bindings below are provided as a ready-to-copy template in Example.sublime-keymap. Open Preferences → Package Settings → ClaudeSublime → Key Bindings (a split view of the template and your user keymap) and copy the ones you want into the right-hand pane. The ctrl+alt+… combos can clash with AltGr on some keyboard layouts.

Suggested shortcut Action
ctrl+alt+c Show / hide Claude panel
ctrl+alt+j Toggle focus (editor ⇄ panel)
ctrl+alt+shift+c New Claude session
ctrl+alt+a Add file + selection to context
ctrl+alt+shift+a Send selection to Claude
ctrl+alt+s Sync local → remote
ctrl+alt+shift+s Toggle auto-sync
ctrl+alt+shift+o Go to changed file (quick panel)
ctrl+alt+. / ctrl+alt+, Next / previous change (this file)
ctrl+alt+shift+. / ctrl+alt+shift+, Next / previous change (all tabs)

How highlighting works

Highlighting is driven entirely by the Claude session log (~/.claude/projects/<enc>/<id>.jsonl), not by watching the filesystem. Each Edit/Write Claude makes is recorded there (as a structuredPatch or full content); the plugin tails the log and turns those into markers. Consequences:

Markers:

Interaction notifications (sound + focus)

Get pinged when Claude needs you (a permission prompt / idle wait) and when a prompt finishes — like iTerm2's bell. Run ClaudeSublime: Enable Interaction Notifications once: it adds two Claude Code hooks to your user-global ~/.claude/settings.json (merged into any existing settings; idempotent):

It's a personal, global setting: nothing is written into any project (so it never lands in a repo or affects teammates who don't want it), and it applies to every project you open. Each hook writes its event to a per-project sentinel file under ~/.claude that the plugin watches on a fast ~250 ms loop (notify_poll_ms), so the ping is near-immediate. (Enabling also removes any hook an older version of the plugin had put in the project's .claude/settings.local.json.) Settings:

Restart Claude (or send one prompt) after enabling so the CLI loads the hooks.

Platform support

Primarily developed on macOS. The core — Claude panel, live highlighting, change navigation, auto-open, status bar, session pinning, Generate Project Config, focus toggle — works the same everywhere. Platform differences:

Feature macOS Linux Windows
Claude panel, highlighting, navigation, auto-open
Suggested keybindings (opt-in) ✅ (ctrl+alt+… can clash with AltGr on some layouts)
rsync sync (manual + auto-sync) ❌ not supported (needs the Unix-only pty; config generation disables it)
watchdog / auto-sync backend FSEvents/kqueue inotify ReadDirectoryChangesW
Interaction notifications — hook fires ⚠️ the hook is a POSIX shell command; works under Git Bash, likely not under cmd/PowerShell
Notification sound afplay canberra-gtk-play/paplay MessageBeep
Notification banner (notify_banner) terminal-notifier / osascript notify-send (if installed) PowerShell balloon (best-effort)

The macOS-specific bits are guarded, so nothing crashes on other platforms — worst case a notification degrades to just panel focus + status.

Known limitation — panel height

Sublime Text has no API to set output-panel height. The Claude panel opens at ST's default height; drag its top border to resize — ST remembers it per window.

Panel scrollback (history)

By default Claude Code runs as a full-screen TUI (the alternate screen buffer, like vim/less), where terminals keep no scrollback — anything that scrolls off is gone. To avoid that, the plugin launches Claude with CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1 (setting disable_alternate_screen, on by default), so Claude renders inline and the conversation stays in the panel's scrollback — scroll back through it with the mouse wheel like any terminal. Terminus keeps the last scrollback_history_size lines (its own setting, default 10000).

Set disable_alternate_screen: false to get the original full-screen TUI (no scrollback). Either way, the full transcript is always on disk at ~/.claude/projects/<encoded-cwd>/<session-id>.jsonl (claude --resume).

Settings

See ClaudeSublime.sublime-settings (Preferences → Package Settings → ClaudeSublime → Settings) for highlighting, auto-sync, and rsync flag options.

By default the sync does not preserve file owner/group: -a would copy the local numeric uid/gid to the remote, where it usually maps to a non-existent user or wrong group (e.g. uid 501 / group games). With sync_preserve_ownership off (the default) rsync gets --no-owner --no-group, so remote files are owned by the ssh user. Turn it on only if you sync as root on both ends.

Results

Packages