Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
137020a
Overhaul documentation with Diataxis structure and VHS demos
jezdez Apr 10, 2026
219b3d6
Rewrite motivation page with project history and design rationale
jezdez Apr 10, 2026
062298e
Add intersphinx cross-references to conda documentation
jezdez Apr 10, 2026
1f813f9
Fix update demo to show actual conda upgrade
jezdez Apr 10, 2026
de148fb
Record demos in fresh Miniforge instead of pixi dev env
jezdez Apr 10, 2026
5c29d52
Fix exception messages to render package names as strings, not lists
jezdez Apr 10, 2026
59e71b7
Use single quotes instead of backticks in user-facing messages
jezdez Apr 10, 2026
31c0c5f
Re-record demos with --quiet base-protection fix and message fixes
jezdez Apr 10, 2026
170920b
Pre-update conda in hidden setup for install and quickstart demos
jezdez Apr 10, 2026
1c7fdb7
Improve user-facing messages: singular/plural, tone, quiet flag
jezdez Apr 10, 2026
3247dd0
Fix indentation and quoting in base-protection check message
jezdez Apr 13, 2026
8fd9b4e
Re-record all 6 demos with latest code changes
jezdez Apr 13, 2026
6dbb6e1
Fix quickstart and update demos to show real plugin updates
jezdez Apr 13, 2026
cee7cea
Re-record affected demos for post-#122 reset and #133 --force
jezdez Apr 23, 2026
e10cfdf
Fix stale 'essentials only' wording in reset messaging and docs
jezdez Apr 23, 2026
a216559
Apply ruff format to main_reset.py
jezdez Apr 23, 2026
c128543
Fix incorrect claim that conda-self ships with conda 26.1.1+
jezdez May 4, 2026
56ef19a
Pin libmambapy <2.6 in test fixtures to work around Windows DLL failure
jezdez May 4, 2026
4e421d3
fix: persist libmambapy pin so conda self update respects it
jezdez May 5, 2026
1c0317c
fix: pin libmambapy <2.6 in test_reset_base_protection env
jezdez May 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 14 additions & 15 deletions conda_self/cli/main_reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,20 @@ def file_path(self) -> Path | None:
"""
).lstrip()

WHAT_TO_EXPECT = dedent(
WHAT_TO_EXPECT_ESSENTIALS = dedent(
"""
This will reset your `base` to ONLY contain `conda`, its plugins,
This will reset your 'base' to ONLY contain 'conda', its plugins,
and their dependencies.
"""
).lstrip()
SUCCESS = dedent(
WHAT_TO_EXPECT_SNAPSHOT = dedent(
"""
SUCCESS!
Reset the `base` environment to only the essential packages and plugins.
"""
).lstrip()
SUCCESS_SNAPSHOT = dedent(
"""
SUCCESS!
Reset the `base` environment to {snapshot_name} snapshot.
This resets your 'base' to the {snapshot_name} snapshot
and removes any packages outside of it.
"""
).lstrip()
SUCCESS = "Reset the 'base' environment to only the essential packages and plugins.\n"
SUCCESS_SNAPSHOT = "Reset the 'base' environment to {snapshot_name} snapshot.\n"


def configure_parser(parser: argparse.ArgumentParser) -> None:
Expand All @@ -121,9 +117,6 @@ def execute(args: argparse.Namespace) -> int:
from ..query import permanent_dependencies
from ..reset import names_from_explicit, reset

if not context.quiet:
print(WHAT_TO_EXPECT)

snapshot: Snapshot | None = args.snapshot
reset_file: Path | None = None

Expand All @@ -139,9 +132,15 @@ def execute(args: argparse.Namespace) -> int:

if reset_file is not None and not reset_file.exists():
raise FileNotFoundError(
f"Failed to reset to `{snapshot}`.\nRequired file {reset_file} not found."
f"Failed to reset to '{snapshot}'.\nRequired file {reset_file} not found."
)

if not context.quiet:
if snapshot is not None:
print(WHAT_TO_EXPECT_SNAPSHOT.format(snapshot_name=snapshot.display_name))
else:
print(WHAT_TO_EXPECT_ESSENTIALS)

prompt = "Proceed with resetting your 'base' environment"
if snapshot is not None:
prompt += f" to the {snapshot.display_name} snapshot"
Expand Down
15 changes: 13 additions & 2 deletions conda_self/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,25 @@
from pathlib import Path


def _plural(word: str, count: int) -> str:
return word if count == 1 else f"{word}s"


class NotAPluginError(CondaError):
def __init__(self, specs: list[str]):
super().__init__(f"The following requested specs are not plugins: {specs}.")
names = ", ".join(specs)
if len(specs) == 1:
msg = f"The requested package is not a plugin: {names}"
else:
msg = f"The requested packages are not plugins: {names}"
super().__init__(msg)


class PluginRemoveError(CondaError):
def __init__(self, specs: list[str]):
super().__init__(f"Packages '{specs}' can not be removed.")
names = ", ".join(specs)
noun = _plural("package", len(specs))
super().__init__(f"{noun.capitalize()} can not be removed: {names}")


class NoDistInfoDirFound(CondaError):
Expand Down
14 changes: 7 additions & 7 deletions conda_self/health_checks/base_protection.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def check(prefix: str, _verbose: bool) -> None:
print(f"{OK_MARK} Base environment is protected (frozen).\n")
else:
print(f"{X_MARK} Base environment is not protected.\n")
print(" Run `conda doctor --fix` to protect it.\n")
print("Run 'conda doctor --fix' to protect it.\n")


def fix(prefix: str, args: Namespace, confirm: ConfirmCallback) -> int:
Expand Down Expand Up @@ -90,12 +90,12 @@ def fix(prefix: str, args: Namespace, confirm: ConfirmCallback) -> int:

if not context.quiet:
print(f"This will clone 'base' to '{default_env}', reset base, and freeze it.")
if env.external_packages:
print(
f" Warning: Base environment contains {len(env.external_packages)} "
"non-conda package(s) that will become non-functional after reset.\n"
f" They are preserved in the cloned '{default_env}' environment."
)
if env.external_packages:
print(
f" Warning: Base environment contains {len(env.external_packages)} "
"non-conda package(s) that will become non-functional after reset.\n"
f" They are preserved in the cloned '{default_env}' environment."
)
confirm("Proceed?")

# Prefer the installer snapshot for resetting base so that
Expand Down
15 changes: 15 additions & 0 deletions demos/_settings.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Set Shell "bash"
Set FontFamily "JetBrains Mono"
Set FontSize 20
Set Width 1200
Set Height 600
Set Margin 20
Set MarginFill "#19191b"
Set Padding 20
Set Theme "Dark+"
Set TypingSpeed 40ms
Set WaitTimeout 300s

Env BAT_OPTS "--color=always --paging=never --plain"
Env BAT_THEME "Visual Studio Dark+"
Env CONDA_PLUGINS_USE_SHARDED_REPODATA "1"
24 changes: 24 additions & 0 deletions demos/_setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Sourced by VHS tapes to create a fresh Miniforge with conda-self installed.

MINIFORGE_DIR="/tmp/miniforge-demo"
INSTALLER="/tmp/miniforge.sh"
INSTALLER_URL="https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname -s)-$(uname -m).sh"
CONDA_SELF_SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

unset CONDA_PREFIX CONDA_DEFAULT_ENV CONDA_SHLVL CONDA_PROMPT_MODIFIER
unset PIXI_HOME PIXI_PROJECT_MANIFEST

if [[ ! -f "$INSTALLER" ]]; then
curl -fsSL -o "$INSTALLER" "$INSTALLER_URL"
fi

rm -rf "$MINIFORGE_DIR"
bash "$INSTALLER" -b -p "$MINIFORGE_DIR" > /dev/null 2>&1
"$MINIFORGE_DIR/bin/pip" install -q -e "$CONDA_SELF_SRC" > /dev/null 2>&1

eval "$("$MINIFORGE_DIR/bin/conda" shell.bash hook)"
conda activate base

export PS1="\[\e[1;38;2;67;176;42m\]\$\[\e[0m\] "
export CONDA_CHANNELS=conda-forge
Binary file added demos/base-protection.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demos/base-protection.mp4
Binary file not shown.
40 changes: 40 additions & 0 deletions demos/base-protection.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Source demos/_settings.tape

Output demos/base-protection.gif
Output demos/base-protection.mp4

Hide
Type `source demos/_setup.sh`
Enter
Wait /\$/
Type "clear"
Enter
Wait /\$/
Show

Type "# Check if your base environment is protected"
Enter
Sleep 500ms

Type@80ms "conda doctor base-protection"
Enter
Wait /\$/
Sleep 3s

Type "# Enable protection: clone base, reset, freeze"
Enter
Sleep 500ms

Type@80ms "conda doctor base-protection --fix --yes"
Enter
Wait /\$/
Sleep 3s

Type "# Verify protection status"
Enter
Sleep 500ms

Type@80ms "conda doctor base-protection"
Enter
Wait /\$/
Sleep 3s
Binary file added demos/install-plugin.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demos/install-plugin.mp4
Binary file not shown.
35 changes: 35 additions & 0 deletions demos/install-plugin.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Source demos/_settings.tape

Output demos/install-plugin.gif
Output demos/install-plugin.mp4

Hide
Type `source demos/_setup.sh`
Enter
Wait /\$/
# Pre-update conda so the install step only shows the plugin
Type `conda update --yes --quiet --override-frozen conda 2>&1 | tail -1`
Enter
Wait /\$/
Type "clear"
Enter
Wait /\$/
Show

Type "# Install a conda plugin into the base environment"
Enter
Sleep 500ms

Type@80ms "conda self install --yes conda-index"
Enter
Wait /\$/
Sleep 3s

Type "# Inline channel specs are rejected"
Enter
Sleep 500ms

Type@80ms "conda self install conda-forge::some-plugin"
Enter
Wait /\$/
Sleep 3s
Binary file added demos/quickstart.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demos/quickstart.mp4
Binary file not shown.
44 changes: 44 additions & 0 deletions demos/quickstart.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Source demos/_settings.tape

Output demos/quickstart.gif
Output demos/quickstart.mp4

Hide
Type `source demos/_setup.sh`
Enter
Wait /\$/
# Pre-update conda so the install step only shows the plugin
Type `conda update --yes --quiet --override-frozen conda 2>&1 | tail -1`
Enter
Wait /\$/
Type "clear"
Enter
Wait /\$/
Show

Type "# Check base environment protection"
Enter
Sleep 500ms

Type@80ms "conda doctor base-protection"
Enter
Wait /\$/
Sleep 2s

Type "# Install a plugin"
Enter
Sleep 500ms

Type@80ms "conda self install --yes conda-index"
Enter
Wait /\$/
Sleep 3s

Type "# Reset base to the installer-provided snapshot"
Enter
Sleep 500ms

Type@80ms "conda self reset --yes"
Enter
Wait /\$/
Sleep 3s
Binary file added demos/remove.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demos/remove.mp4
Binary file not shown.
44 changes: 44 additions & 0 deletions demos/remove.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Source demos/_settings.tape

Output demos/remove.gif
Output demos/remove.mp4

Hide
Type `source demos/_setup.sh`
Enter
Wait /\$/
# Install a plugin so we can demonstrate removing it
Type `conda self install --yes --quiet conda-index 2>&1 | tail -1`
Enter
Wait /\$/
Type "clear"
Enter
Wait /\$/
Show

Type "# Remove a plugin from the base environment"
Enter
Sleep 500ms

Type@80ms "conda self remove --yes conda-index"
Enter
Wait /\$/
Sleep 3s

Type "# Essential packages like conda itself are protected"
Enter
Sleep 500ms

Type@80ms "conda self remove conda"
Enter
Wait /\$/
Sleep 3s

Type "# Override protection with --force (use with care)"
Enter
Sleep 500ms

Type@80ms "conda self remove --force --dry-run conda"
Enter
Wait /\$/
Sleep 3s
Binary file added demos/reset.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demos/reset.mp4
Binary file not shown.
26 changes: 26 additions & 0 deletions demos/reset.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Source demos/_settings.tape

Output demos/reset.gif
Output demos/reset.mp4

Hide
Type `source demos/_setup.sh`
Enter
Wait /\$/
# Install a plugin so reset has something to clean up
Type `conda self install --yes --quiet conda-index 2>&1 | tail -1`
Enter
Wait /\$/
Type "clear"
Enter
Wait /\$/
Show

Type "# Reset base to the installer-provided snapshot"
Enter
Sleep 500ms

Type@80ms "conda self reset --yes"
Enter
Wait /\$/
Sleep 3s
Binary file added demos/update.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demos/update.mp4
Binary file not shown.
27 changes: 27 additions & 0 deletions demos/update.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Source demos/_settings.tape

Output demos/update.gif
Output demos/update.mp4

Hide
Type `source demos/_setup.sh`
Enter
Wait /\$/
# Install an older plugin so the update has something to upgrade
# (use raw conda install to avoid pinning the version in history)
Type `conda install --yes --quiet --override-frozen conda-index=0.6.0 2>&1 | tail -1`
Enter
Wait /\$/
Type "clear"
Enter
Wait /\$/
Show

Type "# Update conda and all plugins"
Enter
Sleep 500ms

Type@80ms "conda self update --yes --all"
Enter
Wait /\$/
Sleep 3s
1 change: 1 addition & 0 deletions docs/_static/css/custom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* conda-self custom styles */
6 changes: 6 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Changelog

## Unreleased

- Added comprehensive documentation with Diataxis structure
- Added VHS terminal demos
Loading
Loading