Skip to content

Activate projects' Python environments, and show their tool versions - #12

Merged
srozen merged 4 commits into
mainfrom
project-environments
Nov 5, 2026
Merged

srozen merged 4 commits into
mainfrom
project-environments

Conversation

@srozen

@srozen srozen commented Nov 5, 2026

Copy link
Copy Markdown
Owner

When you cd into a project, Codec now activates its uv .venv (after asking once) and shows which tool versions the pane is using: from mise, the other common version managers, or conda. Each command in the Commands sidebar records what it ran with, and Explain passes it to the model.

Screenshots

Going into a project with a .venv: Codec asks at the top of the pane, and the status bar counts what's in effect.

The activation question, and the environments chip

A project with a .venv and seven mise tools, one pinned but not installed: one chip, which opens the list.

The environment list

Settings › Shell › Project environments: the answers, a project per row, missing ones flagged.

The answers in Settings

Python environments

  • Going into a folder with a .venv, or below one, asks: Always, This Time, Never, or × (not now). Asking first matters because a downloaded folder can ship its own .venv/bin/python.
  • Once allowed, the zsh integration activates it on the way in (from a chpwd hook, so cd app && python already uses it) and deactivates it on the way out. It sets VIRTUAL_ENV and PATH as activate would, without touching the prompt. deactivate works and keeps it off until you leave. An environment activated by hand or by mise is left alone. If mise's hook moves the PATH, the environment is put first again at each prompt.
  • This Time activates it in that pane only, through a new private key sequence, and remembers nothing.
  • Answers live in venv-decisions beside the shell scripts. The shell reads the file and Codec writes it. Settings lists them: switch Activate/Never, forget one, flag projects whose folder or .venv is gone, Remove Missing. Changes reach panes already in the project at their prompt.

Tool versions

  • The shell reports a new OSC 6973 toolchain event only when something may have changed: the folder, mise's __MISE_DIFF, or a mise, uv, pyenv, nvm, conda (…) command ran. Toolchain and VersionManagers live in CodecCore.
  • mise, while it's active: mise ls --current --json (about 13 ms).
  • Otherwise, the files and variables of pyenv, rbenv, nodenv, asdf, nvm, fnm, chruby, read without running them. nvm, fnm and chruby only switch when told, so the version in use is compared with what the project asks for.
  • Conda: the active environment, except base.
  • A version that isn't installed, or isn't the one asked for, gets a warning. The list offers the manager's install or switch command (mise install, nvm use…), run in the pane.
  • The status bar shows a single chip (8 environments). The first version had a chip per tool, which crowded out the folder and the command when a project used many tools.

Testing

  • swift build -j 2 --build-tests, swift test -j 2 --skip-build: 542 tests pass. New: ToolchainTests, VersionManagersTests, VenvActivationTests (a real zsh: asking, activating with the cd, This Time, deactivate, environments activated elsewhere, refusing later, reporting only on change), ToolchainUITests (a real pane end to end, Settings, the status bar chip, the Commands heading).
  • ARCHS="arm64 x86_64" scripts/build-app.sh release: builds a universal app.
  • make screenshots: retaken. The tour uses a stand-in mise, so its images don't depend on the machine.
  • Not tried with the real tools other than mise and uv. pyenv, rbenv, nodenv, asdf, nvm, fnm, chruby and conda are covered by fake installs that follow each tool's documented layout. nvm's NVM_BIN path, fnm's per-shell link and FNM_DIR are worth a check on a machine that has them.

🤖 Generated with Claude Code

srozen and others added 3 commits November 5, 2026 12:18
Going into a folder with a .venv, or below one, now asks at the top of the
pane whether to activate it: Activate, Never, or not now. Once allowed,
Codec's zsh integration activates it on the way in and deactivates it on the
way out, from a chpwd hook so `cd app && python` already uses it. It sets
VIRTUAL_ENV and the PATH the way `activate` would, without touching the
prompt, defines a `deactivate` that keeps it off until you leave, and leaves
alone an environment activated by hand or by mise. The answers live in
venv-decisions beside the scripts, which the shell reads and Codec writes;
asking first matters because a downloaded folder can ship its own
.venv/bin/python.

At each prompt where something may have changed (the folder, mise's
__MISE_DIFF, or a mise or uv command just ran), the shell reports the
environment and, while mise is active, `mise ls --current --json` in a new
OSC 6973 toolchain event. Toolchain, in CodecCore, reads it and the
environment's pyvenv.cfg. The status bar shows a chip per tool, a pinned
version that isn't installed in the warning color, and a popover with where
each version comes from and Install with mise. Each command in the Commands
sidebar records what it ran with, a new heading starts where that changed,
and Explain passes it to the model.

Settings › Shell › Project environments turns activation off and forgets the
answers. The screenshot tour gains a shot of the question and the chips,
with a stand-in mise so it doesn't depend on the machine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without mise, the shell now tells Codec which version managers it has and
the variables they set, and VersionManagers reads their version files
without running them: pyenv, rbenv and nodenv (override, nearest file, then
the global version, a partial version resolved to the newest installed),
asdf (the nearest .tool-versions naming each tool), and nvm, fnm and chruby,
which only switch when told, so the version in use is compared with what
the project asks for. The active conda environment shows too, except base.
A tool that isn't installed or isn't the version asked for gets a warning,
and the list offers the manager's install or switch command.

The status bar now shows one chip counting the environments instead of a
chip per tool, which crowded out the folder and the command in projects
with many tools; it opens the list. The Commands heading keeps its folder
when the versions are long.

The question in a pane gains This Time, which activates the environment
until you leave the project through a new private key sequence and
remembers nothing. Settings › Shell lists the remembered answers a project
per row, to switch between Activate and Never or forget; projects whose
folder or .venv can't be found are flagged, and Remove Missing forgets
them, never automatically since a disk may just be unplugged. Changes reach
panes already in the project at their prompt.

The screenshot tour adds a project with many tools, its list, and the
Settings section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tests' run helper waited for zsh to be back at a prompt by counting
133;B marks against commands. A prompt redrawn by a widget (Codec's
refresh, or This Time's) draws one more mark, so after one the helper
returned as soon as the command's done event arrived, before the
toolchain report that follows it. On the slower CI runner the report then
came too late, and two tests read the previous one. The helper now waits
for the prompt's line count, which the shell sends right after the
report.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ALambot

ALambot commented Nov 5, 2026

Copy link
Copy Markdown

🍆

Both sides added a setting and a Settings section to the Shell tab:
Preferences keeps both keys, Settings shows Listing files then Project
environments, and SettingsView takes both the environment answers and the
command runner. The zsh tests keep both suites. The screenshots are
retaken with the merged tour, which has the listing shot and the
environment shots.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@srozen
srozen merged commit 6c37e51 into main Nov 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants