Skip to content

Latest commit

 

History

History
403 lines (332 loc) · 18 KB

File metadata and controls

403 lines (332 loc) · 18 KB

Runtime Notes

These notes preserve runtime details that are too specific for the README but matter when changing launch, config, editor, shell, or popup behavior.

Config UI

yzx config validates the optional root config and seeds cursors.toml from the child-owned template when that file is missing. Runtime preparation uses the same one-time cursor seed.

The UI leaves these sparse sources absent until you save a field:

~/.config/yazelix/config.toml
~/.config/yazelix/mars/config.toml
~/.config/yazelix/zellij/config.kdl
~/.config/yazelix/starship.toml

yzx launch may create mars/config.toml containing only the managed appearance projection before Mars starts.

The Helix and advanced native files stay lazy. Opening a file-action row creates its starter file. Activating either Steel row creates both helix/helix.scm and helix/init.scm.

While editing a text field, Ctrl+e opens the staged value in the configured editor environment and returns the edited text to the row. Enter saves.

Appearance Projection

Root appearance.mode is the managed dark/light authority. Ratconfig uses it for its own palette. When Mars is included and ~/.config/yazelix/mars/config.toml is a writable regular file, a global save or reset updates only mars.appearance.preset; Mars's existing directory watcher reloads that change. Before yzx launch, the runtime performs the same reconciliation and removes any inherited MARS_APPEARANCE that could override the file.

A store-backed, symlinked, or otherwise read-only Mars file is never replaced. In that case, launch sets MARS_APPEARANCE to the validated root value and the change applies to the new process. yzx enter, SSH use, and no-Mars packages do not project terminal appearance. Direct edits to the native Mars field may affect a running window, but the next global save or managed launch restores the root value.

Yazelix passes only the root dark/light mode to each new managed Zellij session. Zellij resolves the matching theme_dark or theme_light member. A managed session ignores ambient terminal appearance reports so the explicit root mode remains authoritative. A root appearance save from inside that session calls set-dark-theme or set-light-theme against that exact session. Zellij's host-theme event switches the top bar between its child-owned dark and light palettes. A bar loaded by a later tab receives the session's current mode even when no new host-theme transition occurs. Ratconfig keeps the saved root value when either component projection fails and reports that the next launch will retry it.

Each managed Yazi launch reads the current root mode before materializing its config. Yazelix selects the matching native flavor.dark or flavor.light, using Yazi Bistro's Bluloco Light default when the light side is absent. An absent dark side uses Yazi's native preset; Ratconfig exposes that state as the first dark choice, default, without writing it as a flavor name. When a flavor is selected, both runtime flavor keys receive it so ambient detection cannot choose the opposite side. The source theme.toml is never rewritten, and an existing Yazi process keeps its current theme until it is reopened.

Sessions

yzx enter and yzx launch pass the managed config and --new-session-with-layout to packaged Zellij before forwarding caller arguments. Zellij owns session creation, attachment, switching, process lifetime, and native failure messages. Plain launch creates an independent session. --session NAME requests a fresh named session, while attach NAME requires a live target. Attach and switching preserve the target state without reapplying the managed layout.

The managed Zellij config sets default_layout "layout" and points layout_dir at the directory containing the active layout.kdl and layout.swap.kdl. Runtime appearance, shell, or widget projection rewrites that directory to the materialized state path. Zellij lists the configured default first, so native type-to-create selects the Yazelix layout before it creates the named session.

Use full names for supported attach behavior. Native unique-prefix matching, rename, and structural resurrection remain Zellij surfaces outside the Nova v1 continuity contract. Yazelix adds no registry or second session owner.

Zellij Sidecars

zellij/config.kdl is a guarded sidecar for scalar preferences such as paired dark/light themes, pane frames, mouse mode, scrollback size, copy behavior, styled underlines, startup tips, and ui.pane_frames.rounded_corners. Ratconfig uses the same 41 identities from the pinned Zellij assets for both theme fields, with a flake check keeping the inventory aligned. The inherited pair is theme_dark "ansi" and theme_light "gruvbox-light"; resetting a field removes only its sparse override. Custom names found on either member join the shared pool shown by both pickers.

The former static theme field is not part of the managed model. An existing assignment remains untouched in the user sidecar and is reported as ignored, while runtime materialization omits it so the complete pair has one clear authority.

When yzx config runs inside a managed session (ZELLIJ_SESSION_NAME or YAZELIX_ZELLIJ_SESSION_NAME, plus YAZELIX_STATE_DIR), saving a Zellij tab field also patches $YAZELIX_STATE_DIR/zellij/config.kdl so the running Zellij watcher can pick up scalars without rewriting integration patches. Editing the active theme-pair member applies live; editing the other member takes effect on the next appearance change or managed session launch. Ratconfig labels pane frames, rounded corners, copy-on-select, and clipboard target as now when that active runtime file is addressable. Mouse mode, scrollback size, styled underlines, and startup tips say next session; outside an active managed session, every Zellij field is next-session. Quoted custom theme names without KDL escapes remain accepted; richer string syntax stays preserved but native-file-only.

Ratconfig scopes sidecar diagnostics instead of marking every Zellij field invalid. Safe untyped top-level leaves stay unchanged across unrelated saves and resets without a synthetic field or informational diagnostic for each leaf. The exact native-file action opens the sidecar for those settings. Invalid known fields affect only their own row and remain repairable. Advanced diagnostics report ignored legacy settings, malformed or structured native nodes, structural KDL comments or continuations, extra metadata on managed blocks, and integration-owned nodes. Unsafe source state blocks writes, and each guarded diagnostic names its Yazelix owner.

The runtime rejects uncommented top-level ownership nodes in that sidecar:

keybinds
default_shell
default_layout
layout_dir
layout
plugins
load_plugins
support_kitty_keyboard_protocol
env
session_name
attach_to_session

Use zellij/plugins.kdl for extra plugin declarations. It accepts only plugins and load_plugins blocks:

plugins {
    my_plugin location="file:/home/me/.config/zellij/plugins/my_plugin.wasm"
}

load_plugins {
    my_plugin
}

Plugin ids owned by Yazelix, such as yzpp and yazelix_pane_orchestrator, cannot be redeclared. Plugin keybindings are not managed by this sidecar.

Popup Lifecycle

Opening or revealing a managed popup shows Zellij's tab-wide floating layer. Toggling the focused popup off or explicitly closing it hides that layer after closing or suppressing the managed pane. This returns directly to the tiled workspace instead of exposing a session manager, terminal, or other floating pane underneath. Suppressed keep-alive popups and unrelated floating panes continue running; their explicit keybindings can show them again.

Agent Popup

The packaged agent launcher gives the pane its initial agent terminal title, then replaces itself with [agent].command. The default auto chooses a provider once per state directory. On first launch it checks PATH in this order:

codex resume
grok
opencode
pi
claude --resume

It stores the selected provider at:

${YAZELIX_STATE_DIR}/agent/provider

Later launches use that stored provider. If the stored provider is unknown or missing from PATH, the popup prints a diagnostic and tells the user to remove the provider file so Yazelix can choose again.

Any other agent.command value is executed directly by the same launcher for new sessions, so custom commands receive the same initial title. Put argv-style arguments in agent.args, not in agent.command.

Yazi Popup

Alt Shift Y asks the pane orchestrator to toggle the packaged yazi popup with the active tab's canonical workspace root as its explicit request cwd. The popup uses toggle_close_behavior "hide", so the popup plugin preserves the live Yazi process and navigation state while that requested root still matches. It remembers the launch root separately from Yazi's changing process cwd. If the canonical root changes, the next ordinary toggle closes the stale process and launches a fresh one at the new root. yzx reveal sends one configured replace request to the popup owner with the absolute target as a launch argument. Yazi reveals that target during normal startup, so reveal does not wait for or address a partially started process. This deliberately resets the popup's navigation state while leaving the canonical workspace unchanged. Managed Yazi owns Alt r locally and passes no hovered path. The popup role sends one explicit hide to the popup owner, preserving the live Yazi process and navigation state and returning to the underlying pane. Tiled Yazi asks the pane orchestrator to focus the existing editor and remains visible. Neither role opens the hovered item or changes editor cwd, canonical workspace, or sidebar state; Enter remains the explicit file-open action. Helix owns its reveal binding locally as well. Zellij does not intercept or reroute the chord, so hiding the popup cannot replay it as a Helix reveal.

The popup runs the same yzx-yazi launcher and layered config as the tiled sidebar with the private workspace-popup role. Packaged Yazi initialization omits sidebar registration and sidebar-status for that role. Popup navigation and ordinary opens retain their existing local and canonical-workspace semantics.

Shell History, Nushell, And Starship

When shell.program = "nu", Yazelix does not read normal Nushell config. It generates runtime Nu files that source packaged Yazelix config first and then optional user files:

~/.config/yazelix/nu/env.nu
~/.config/yazelix/nu/config.nu

If host mise is available on the inherited PATH, managed Nu inserts mise activate nu output after packaged config.nu and before user nu/config.nu. Missing or failing mise is skipped.

shell.atuin = true sources Nova's build-generated Atuin integration after the selected shell's user startup layer. yzx-nu composes Nushell after user nu/config.nu; yzx-shell uses ~/.bashrc, the effective Zsh .zshenv and .zshrc, or Fish's config.fish. An existing shell-specific Atuin search function skips the managed source. Nova uses the locked packaged binary, binds contextual history search to Ctrl+r, leaves Up-arrow with native history, and disables Atuin AI bindings. ATUIN_NOBIND suppresses managed bindings while retaining lifecycle hooks. A managed init failure reaches stderr without preventing shell startup. shell.atuin = false omits Nova's hooks and bindings without changing either history store. See Configuration for explicit one-time imports and the native-config ownership boundary.

Managed Nu always sets STARSHIP_CONFIG to a runtime-effective file. That file starts with Nova's sparse [character].format = ":: " marker and recursively merges optional native overrides from ~/.config/yazelix/starship.toml. Top-level format stays unset by default, so Starship retains its native $all layout, including directory, Git, environment, and tool modules. Normal ~/.config/starship.toml does not affect the managed Nu prompt.

Helix

yzx-hx builds the effective Helix config on each launch from the packaged default plus optional managed user files under:

~/.config/yazelix/helix/

helix/config.toml is deep-merged over the packaged TOML default. The generated effective file is ${YAZELIX_STATE_DIR}/helix/config.toml. Yazelix reserves Alt r for reveal, so the generated config enforces:

[keys.normal]
A-r = ':sh yzx reveal "%{buffer_name}"'

helix/languages.toml is loaded by the managed Helix config dir when present. helix/helix.scm and helix/init.scm load through a private HELIX_STEEL_CONFIG overlay once both files exist. The overlay keeps the user command module and init while retaining the packaged bridge startup. Without a user Steel pair, the packaged module provides :yzx-new-shell, which opens a new Yazelix terminal pane at the current file directory or workspace.

Tab Workspace

The pane orchestrator owns one canonical workspace root per tab. The first managed open resolves the containing Git worktree, or the opened directory or file parent outside Git, and publishes it as explicit state. Later ordinary Yazi opens preserve that root while passing the requested absolute target to Helix. This includes ignored files, nested repositories, and non-Git descendants. A managed open also resets a drifted Helix cwd to the canonical root. After success, only the originating managed Yazi follows the primary target's directory; the canonical workspace, shell panes, and hidden agent stay unchanged.

Yazi Alt z is the explicit retarget operation. It updates the orchestrator and managed editor together; an editor failure restores the prior root and its bootstrap or explicit provenance. Git and agent popup requests carry the canonical root explicitly. A hidden agent is reused across pane focus and local navigation changes, and is replaced only after the canonical root changes.

Yazi

Managed Yazi accepts native TOML, optional Lua and keymap sidecars, and a user-owned asset tree:

~/.config/yazelix/yazi/yazi.toml
~/.config/yazelix/yazi/theme.toml
~/.config/yazelix/yazi/package.toml
~/.config/yazelix/yazi/starship.toml
~/.config/yazelix/yazi/init.lua
~/.config/yazelix/yazi/keymap.toml
~/.config/yazelix/yazi/plugins/*.yazi/
~/.config/yazelix/yazi/flavors/*.yazi/

Native TOML tables merge recursively. User scalars and arrays replace packaged values; only plugin.prepend_fetchers uses replace-plus-managed-Git semantics, which keeps user fetchers while restoring the two sidebar Git fetchers exactly once. Broken config paths, invalid TOML, and incomplete flavors stop Yazi launch. The managed edit opener is always restored. Normal ~/.config/yazi is not read.

Optional yazi/starship.toml is a complete replacement for Nova's packaged compact Starship header config, not a merge layer. Its presence alone activates materialization. The materializer requires readable TOML and links it into the effective config as yazelix_starship.toml; omission retains the packaged file. Both the normal sidebar and workspace popup use that same effective path.

Automation can materialize that config without starting Yazi, Zellij, Mars, an editor, or the full Yazelix runtime:

effective_config="$(
  yzx yazi-config materialize \
    --user-config-dir "$PWD/yazi" \
    --state-dir "$PWD/state"
)"
YAZI_CONFIG_HOME="$effective_config" yazi --debug

--user-config-dir names the exact directory that contains yazi.toml, init.lua, plugins/, and the other native Yazi entries. --state-dir names the isolated state root. Callers must pass both flags; the command does not use YAZELIX_CONFIG_HOME or YAZELIX_STATE_DIR as defaults. The selected Yazelix package supplies the packaged config, including for no-yazi variants and Home Manager installations. Root appearance.mode and the packaged Yazi Bistro light default are supplied internally; the public command takes no appearance flags. The Home Manager module adds no materializer option.

Successful calls print one absolute effective config directory and a newline to stdout, with no stderr output. In dark mode, a user directory with no managed entries returns the package's read-only config directory and leaves the state path absent. Light mode materializes runtime theme.toml even without user entries so it can select the packaged light default. Other inputs replace only <state-dir>/yazi through a staging directory. Bad command usage exits 64. Materialization failures exit 1; validation failures leave an existing effective directory intact.

The materializer validates paths, TOML syntax and merge structure, required integration fields, plugin and flavor shapes and collisions, appearance projection, source/state overlap, and output construction. Yazi remains responsible for semantic config checks, Lua and plugin behavior, and external commands. Run yazi --debug with the printed YAZI_CONFIG_HOME when automation needs those checks.

Plugin and flavor directories activate materialization independently of init.lua and are linked into the runtime config. Packaged plugin names cannot be overridden. A user flavor with a packaged name takes precedence over the packaged copy. Yazi Bistro supplies the packaged flavor catalog and its dark/light classification. User-installed, unclassified flavors join both Ratconfig pools. theme.toml remains the native source for explicit choices and unrelated theme settings; the materializer copies it only when runtime appearance projection is required. Ratconfig renders its simple values and the sparse yazi.toml layer in the Yazi tab. package.toml passes through as opaque ya pkg metadata, but Yazelix never runs the package manager. Create asset directories in this tree or symlink them from another checkout.

Example managed Yazi plugin layout:

~/.config/yazelix/yazi/plugins/foo.yazi/main.lua
~/.config/yazelix/yazi/flavors/foo.yazi/flavor.toml
~/.config/yazelix/yazi/init.lua
~/.config/yazelix/yazi/theme.toml
require("foo"):setup()
[flavor]
dark = "foo"
light = "foo"

Managed Yazi refreshes sidebar git decorations on setup, directory changes, tab changes, and managed popup close or hide hooks.