Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ Ghostty, and platform notes.

## Development Environment

`selfishell install` sets up one consistent environment: Zsh, Git, Vim,
Starship, Zinit, Neovim, mise-managed runtimes, CLI tools, and build tooling.
See [Environment](docs/ENVIRONMENT.md) for tool management and editor behavior.
See [Environment](docs/ENVIRONMENT.md) for managed tools, prompt behavior,
and the Neovim workflow.

## Everyday Commands

Expand Down
39 changes: 16 additions & 23 deletions docs/ENVIRONMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,15 @@ Selfishell installs one development environment. `packages.conf` declares
its packages: Zsh, Git, Vim, Starship, Zinit, Neovim, CLI tools, language
runtimes, compiler tooling, and optional macOS terminal fonts.

Selfishell installs a pinned mise binary and activates it for
interactive Zsh. Selfishell keeps its defaults in
`${XDG_CONFIG_HOME:-$HOME/.config}/selfishell/mise/selfishell.toml` (which is symlinked to `~/.config/mise/conf.d/selfishell.toml` so it is automatically loaded by `mise`); a project's
`mise.toml` can select different tool versions.

Developer tools managed by mise use exact reviewed versions pinned in
`config/shared/mise.toml`, the single source of truth for these versions. This
includes Starship, FZF, Zoxide, Ripgrep, Eza, Bat, jq, Neovim, Tree-sitter CLI, Node.js,
Python, uv, and GitHub CLI on both macOS and Ubuntu. Eza and Bat remain optional;
failure to install either does not stop setup. Projects remain free to override
the defaults in a local `mise.toml`. Updating the defaults requires a normal
Selfishell release and never happens during shell startup.
Selfishell installs a pinned mise binary and activates it for interactive Zsh.
Its defaults live under `${XDG_CONFIG_HOME:-$HOME/.config}/selfishell/mise/`,
linked into mise's `conf.d/selfishell.toml`. Project-local `mise.toml` files
can override these defaults.

`config/shared/mise.toml` pins the reviewed versions of Starship, FZF, Zoxide,
Ripgrep, Eza, Bat, jq, Neovim, Tree-sitter CLI, Node.js, Python, uv, and GitHub
CLI on both macOS and Ubuntu. These defaults change through Selfishell releases;
shell startup never updates them.

Mise manages the Starship executable and its version; Selfishell still manages
`starship.toml` and prompt initialization.
Expand Down Expand Up @@ -43,24 +40,20 @@ Install the environment:
selfishell install --yes
```

`selfishell update` uses `packages.conf` to install missing Apt, Homebrew, and directly
managed tools and synchronize mise tools before updating configuration. Apt and
Homebrew retain responsibility for packages still declared through them.
Copies of a tool left from an older release are not removed
automatically; after mise activation, its pinned tool version takes precedence.
See [Updates and rollback](UPDATES.md) for synchronization and cleanup behavior.
Copies of tools left from older package managers are preserved; after mise
activation, its pinned versions take precedence.

Package requirements have two failure policies:

- `required` packages must be available and install successfully;
- `optional` packages are recommended and attempted automatically, but an
unavailable package or installation failure does not stop the rest of setup.

`optional` does not mean that Selfishell asks about each package. Ghostty is the
separate interactive installation choice on macOS.

On macOS, interactive installation separately asks whether to install Ghostty
and manage its configuration. `--yes` accepts that choice automatically. The
choice is saved and reused by `selfishell update`.
Eza and Bat are optional. Only Ghostty has a separate installation choice:
on macOS, interactive setup asks whether to install it and manage its
configuration. `--yes` accepts that choice automatically. The choice is saved
and reused by `selfishell update`.

## Neovim workflow

Expand Down
36 changes: 14 additions & 22 deletions docs/PERFORMANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ SELFISHELL_BENCHMARK_PROFILE=full bash scripts/benchmark.sh
```

Each metric reports the mean, median (`p50`), 95th percentile (`p95`), and
maximum duration in milliseconds. `interactive-cached` starts a complete
interactive Zsh through the platform `.zshrc`.
maximum duration in milliseconds. `interactive-cached` loads the platform
`.zshrc` and exits; it does not measure a visible prompt, command-to-prompt
latency, or deferred plugin readiness. Measure those separately in a terminal.

### Base mode

Expand All @@ -37,21 +38,14 @@ checkout.

### Full-environment mode

Full mode additionally provisions the pinned mise, Starship, fzf, zoxide, and Zinit -- with
its pinned Zsh plugins -- into the benchmark's own isolated `HOME`, via the
same code path the real installer uses, so `interactive-cached` reflects a
real full-environment startup rather than whatever happens to already be on
the runner's `PATH`. It:

- uses an isolated, temporary `HOME`; the real user `HOME` is never read or
changed;
- uses that home as its working directory and gives mise an isolated global
config;
- installs the pinned mise and Zinit (with its pinned plugins), plus Starship,
fzf, and zoxide through mise using the release's exact pins;
- needs network access to provision those tools, so it is not part of the
regular (network-free) unit test suite, or run in CI -- run it locally
when needed.
Full mode provisions pinned mise, Starship, fzf, zoxide, Zinit, and its Zsh
plugins through the production installers into the temporary `HOME`. It uses
the release's exact pins and an isolated mise configuration, so measurements
include the managed shell integrations without changing the developer's tools
or plugin checkouts. Provisioning requires network access; run it locally when
needed, outside CI and the network-free test suite.

## Startup caches

Interactive startup audits completion directories on first use and once daily.
The `.zcompdump.audit` marker records the audit separately from `.zcompdump`,
Expand Down Expand Up @@ -89,11 +83,9 @@ SELFISHELL_BENCHMARK_ZPROF_FILE=/tmp/selfishell-startup.zprof \
bash scripts/benchmark.sh --mode full
```

The report ranks initialization functions by time and is intended for finding
expensive startup paths. The benchmark loads Zsh's built-in `zsh/zprof` module
only for this additional diagnostic startup, after every reported metric and
budget check has completed. It adds no code or dependency to ordinary shell
startup and does not enforce a performance threshold.
The report ranks initialization functions by time. The profiler runs once after
all timed measurements and budget checks; it adds no overhead to ordinary
startup and enforces no threshold.

## Budgets

Expand Down
36 changes: 13 additions & 23 deletions docs/PYTHON.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
# Python Development with Selfishell

Selfishell manages Python runtimes and packages using a modern, fast toolchain powered by **`mise`** and **`uv`**. This workflow ensures high performance, reproducibility, and clean environment isolation.

## Toolchain Overview

* **Runtime Manager (`mise`)**: Handles the installation of global and local Python versions.
* **Package & Virtualenv Manager (`uv`)**: Handles dependencies, virtual environments, and project bootstrapping at near-instant speed.
* **Auto-Activation**: When configured, entering a uv project directory (one with a `uv.lock` file) will automatically manage and activate its virtual environment.

---
Selfishell uses `mise` for Python versions and `uv` for packages and virtual
environments. Project settings can enable automatic virtualenv activation.

## Getting Started

### 1. Creating a Virtual Environment

Navigate to your Python project directory and run `uv venv` to create a virtual environment. It will be created in a `.venv` folder by default.
Create a `.venv` in your project directory:

```bash
cd /path/to/project
Expand All @@ -29,30 +22,30 @@ uv venv --python 3.12

### 2. Auto-Activation

`python.uv_venv_auto` integrates mise with uv to manage a project's virtual environment, but it applies to uv projects that have a `uv.lock` file, not simply any directory containing a `.venv`. A `uv.lock` is normally created as part of a uv project workflow, for example by `uv lock` or `uv sync`.
`python.uv_venv_auto` requires a uv project with a `uv.lock` file, created by
`uv lock` or `uv sync`; a `.venv` directory alone is insufficient.

Add the setting to the `[settings]` section of your project's local `mise.toml` file:
Add this setting to your project's `mise.toml`:

```toml
[settings]
python.uv_venv_auto = "create|source"
```

`"source"` activates an existing virtual environment; `"create|source"` also creates one when necessary before activating it.
`"source"` activates an existing virtual environment; `"create|source"` also
creates one when necessary.

Once configured, entering the uv project directory will activate it:

```bash
cd /path/to/project
# Your shell prompt (Starship) will show the active virtual environment (.venv)
# Run which to verify
which python
# Should output: /path/to/project/.venv/bin/python
# Expected: /path/to/project/.venv/bin/python
```

### 3. Installing Packages

Use `uv pip` to install packages inside the active virtual environment at high speeds:
Install packages in the virtual environment:

```bash
uv pip install requests
Expand All @@ -70,11 +63,8 @@ To generate a pinned lock file from dependency specifications:
uv pip compile pyproject.toml -o requirements.txt
```

---

## Editor Integration (Neovim)

Selfishell's built-in Neovim configuration integrates with Python LSP and tools.

To ensure Neovim can resolve your project dependencies, always run `nvim` from the project root after the virtual environment has been created and packages have been installed.
Once auto-activation is configured, `mise` will automatically activate the uv project's `.venv` when entering its directory, allowing Neovim to inherit the correct path to the local virtualenv Python interpreter.
Create the virtual environment and install dependencies before launching
`nvim` from the project root. With auto-activation configured, Neovim inherits
the uv project's virtualenv Python path for its Python tooling.
7 changes: 1 addition & 6 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,4 @@ Review the diff and CI results, merge when ready, then publish a normal patch
release by creating the next release tag. Use `scripts/next-patch-version.sh`
when you want the helper to calculate that patch version.

Every release asset receives signed build provenance through GitHub Artifact
Attestations before publication. Verification requires GitHub CLI:

```bash
gh attestation verify PATH_TO_ARCHIVE --repo jiminu/selfishell
```
For manual archive verification, see the [security model](SECURITY.md).
3 changes: 2 additions & 1 deletion docs/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ release provenance and preservation of existing files are security boundaries.
checksums or stronger provenance when supported by the selected backend.
- Git dependencies use an approved tag or commit.
- Existing configuration is backed up and tracked before managed replacement.
- Interactive shell startup performs no network update.
- Shell startup never installs updates; release metadata can refresh in the
background. See [update notices](UPDATES.md#status-and-update-notices).
- LSP servers added with `:LspInstall` are not version-approved the way the
default servers (lua_ls, pyright, bashls, jsonls, yamlls, tombi,
marksman) are: they install from the Mason registry, unpinned, the
Expand Down
Loading