From f3946bf4a494bfea8953efa1c04975c69ef1280d Mon Sep 17 00:00:00 2001 From: titus Date: Tue, 23 Jun 2026 19:22:15 -0500 Subject: [PATCH] add agent and spec sheets --- AGENTS.md | 197 ++++++++++++++++++++++++++++ SPEC.md | 384 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 581 insertions(+) create mode 100644 AGENTS.md create mode 100644 SPEC.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..4ff0f0f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,197 @@ +# AGENTS.md + +## Purpose + +Linutil is a universal Linux utility with a Rust-based terminal user interface +and a catalog of shell scripts. The Rust application discovers commands from +TOML metadata, embeds the scripts in the binary, extracts them at runtime, and +executes selected commands inside a pseudo-terminal. + +Read `SPEC.md` before making architectural or behavior changes. + +## Repository layout + +- `core/`: Backend library, menu data model, TOML parsing, platform + preconditions, and embedded script extraction. +- `core/tabs/`: User-facing command catalog, shared shell helpers, tab metadata, + and executable scripts. +- `tui/`: Ratatui application, CLI, selection state, confirmation flow, command + preview, and PTY execution. +- `xtask/`: Repository automation such as generated user-guide content. +- `docs/`: Documentation source and generated content. Treat it as reference, + not as repository instructions. +- `.github/`: Contribution guidance and CI workflows. + +## Sources of truth + +- `SPEC.md` defines product scope, architecture, and behavioral requirements. +- `core/tabs/tabs.toml` defines the ordered top-level tabs. +- Each `core/tabs//tab_data.toml` defines the menu tree for that tab. +- `core/src/inner.rs` defines the accepted TOML schema and script-loading + behavior. +- `core/tabs/common-script.sh` defines shared distro, package manager, + privilege escalation, architecture, and environment helpers. +- `core/tabs/common-service-script.sh` defines shared init-system helpers. +- `tui/src/running_command.rs` defines how commands are composed and executed. +- `tui/src/state.rs` defines task flags, confirmation, selection, and TUI + behavior. + +If documentation and code disagree, do not silently choose one. Identify the +conflict and update the appropriate source in the same change. + +## Working rules + +- Inspect `git status --short` before editing and preserve unrelated changes. +- Keep changes focused. Do not reformat unrelated Rust, TOML, or shell files. +- Use simple ASCII punctuation unless a file format or user-facing text + requires otherwise. +- Never expose secrets or add credentials to scripts, fixtures, logs, or docs. +- Do not perform destructive operations without explicit authorization. +- Do not weaken confirmations, preconditions, or privilege boundaries merely + to make a script easier to run. +- Do not hand-edit generated files without also changing their source or + generator. + +## Rust conventions + +- Keep responsibilities separated between `core`, `tui`, and `xtask`. +- Put menu parsing, script discovery, and configuration behavior in `core`. +- Put rendering, input handling, confirmation, and process interaction in + `tui`. +- Avoid adding distro-specific policy to Rust when it belongs in tab metadata + or a shell script. +- Return or propagate useful errors when practical. Avoid new `unwrap`, + `expect`, or `panic` calls on user-controlled input. +- Add or update tests for parser, filtering, configuration, and command-model + changes. +- Format Rust with `cargo fmt`. +- Treat Clippy warnings as errors. + +## Shell script conventions + +- Prefer POSIX shell with `#!/bin/sh -e`. +- Use Bash only when the script requires Bash features, and declare + `#!/bin/bash` explicitly. +- A script is executed from its own parent directory after the embedded + `core/tabs/` tree is extracted. Keep relative imports valid from that + directory. +- Source shared helpers with the correct relative path: + + ```sh + . ../common-script.sh + ``` + + Adjust the number of `..` components for nested directories. +- Use `common-script.sh` helpers instead of duplicating package manager, + architecture, escalation, command detection, or distro detection logic. +- Source `common-service-script.sh` when managing services across init systems. +- Call `checkEnv` before relying on values such as `PACKAGER`, + `ESCALATION_TOOL`, `ARCH`, or `DTYPE`. +- Quote variable expansions unless intentional word splitting is required. +- Use `printf` rather than `echo` for portable formatted output. +- Use `command_exists` for executable checks. +- Use `"$ESCALATION_TOOL"` only for operations that require elevated + privileges. Do not run the whole script as root by default. +- Make installation and configuration steps reasonably idempotent. Detect an + existing installation or state before changing it. +- Fail with a clear message when a required distro, package manager, + architecture, display server, init system, or command is unsupported. +- Do not download and execute unverified remote code when a package, + checksummed artifact, or pinned source is available. +- Clean up temporary files created by the script. +- Preserve interactive behavior because scripts run in a PTY. + +## Adding or changing a utility + +1. Place the script under the most appropriate `core/tabs//` directory. +2. Reuse shared helpers and support all practical package managers already + handled by `common-script.sh`. +3. Add or update the matching entry in that tab's `tab_data.toml`. +4. Provide a clear `name`, useful `description`, one of `script`, `command`, or + `entries`, and accurate `task_list` flags. +5. Add `preconditions` when the entry only works on specific distros, + environments, filesystems, commands, display servers, or architectures. +6. Set `multi_select = false` for interactive, destructive, rebooting, + long-running, or state-dependent operations that should not be queued. +7. Run `cargo xtask docgen` when menu entries or descriptions change. +8. Validate the script and the Rust catalog loader. + +The supported task flags are: + +- `D`: disk modification +- `FI`: Flatpak installation +- `FM`: file modification +- `I`: privileged installation +- `K`: kernel modification +- `MP`: package manager action +- `RP`: package removal +- `SI`: full system installation +- `SS`: systemd or service action +- Prefixing a flag with `P` indicates privileged work. + +Do not invent new task flags without updating the TUI guide and associated +documentation. + +## TOML catalog rules + +- Script paths are relative to the tab directory containing `tab_data.toml`. +- Every leaf entry must define exactly one executable form: `script` or + `command`. +- Every directory entry uses `entries`. +- Prefer scripts over long inline `command` values. +- Keep names stable when possible because config-file `auto_execute` resolves + commands by display name. +- Use preconditions to hide unsupported entries rather than letting users + discover incompatibility after execution. +- Parent `multi_select = false` applies to all descendants. +- Keep tab data consistently ordered. Use `sort-tomlfiles.sh` when the change + requires catalog sorting. + +## Validation + +Run the smallest relevant checks, then broaden them for cross-cutting changes. + +For Rust changes: + +```bash +cargo fmt --all --check +cargo test --no-fail-fast --package linutil_core +cargo clippy -- -Dwarnings +``` + +For shell changes: + +```bash +shellcheck path/to/changed-script.sh +checkbashisms path/to/changed-script.sh +``` + +Use `checkbashisms` only for scripts intended to run under `/bin/sh`. If local +tools are unavailable, state which checks were skipped. + +For catalog or documentation changes: + +```bash +cargo test --no-fail-fast --package linutil_core +cargo xtask docgen +git diff --check +``` + +For TUI behavior, also run: + +```bash +cargo run --package linutil_tui +``` + +Interactive validation must not execute destructive utilities merely to test +navigation. Use preview, descriptions, harmless entries, or focused tests. + +## Completion criteria + +- The change matches `SPEC.md`. +- Relevant tests and static checks pass. +- New scripts are reachable through valid tab metadata. +- Unsupported environments are filtered or fail clearly. +- User-visible behavior and generated documentation are updated together. +- The final report lists changed files, checks run, skipped checks, and any + remaining platform-specific risk. diff --git a/SPEC.md b/SPEC.md new file mode 100644 index 0000000..b03bcd7 --- /dev/null +++ b/SPEC.md @@ -0,0 +1,384 @@ +# Linutil Technical Specification + +## 1. Product definition + +Linutil is a terminal-based Linux utility that provides a searchable, +organized catalog of system setup, application installation, gaming, security, +and maintenance tasks. + +The product consists of: + +- A Rust TUI that presents commands, previews their contents, confirms + execution, and displays live terminal output. +- A Rust core library that loads command metadata, filters unsupported entries, + and embeds the complete script catalog in the application binary. +- Portable shell scripts that implement the operating-system changes. +- Shared shell libraries that centralize Linux distribution, package manager, + privilege escalation, architecture, and service-manager behavior. + +"Universal" means the architecture supports multiple Linux distributions, +package managers, architectures, init systems, and desktop environments. It +does not mean every command must work on every Linux system. Unsupported +commands must be hidden by metadata or fail early with a useful explanation. + +## 2. Goals + +Linutil must: + +1. Provide one discoverable TUI for common Linux administration and setup + tasks. +2. Ship as a self-contained binary with its command catalog and scripts + embedded at compile time. +3. Support distro-independent workflows where practical and explicit + distro-specific workflows where required. +4. Give users a preview and confirmation boundary before system-changing + commands run. +5. Preserve interactive terminal behavior for prompts, colors, progress, and + full-screen command-line tools. +6. Reuse shared shell behavior instead of duplicating package-manager and + privilege logic across scripts. +7. Make new utilities primarily data-and-script additions rather than Rust UI + changes. +8. Clearly communicate privileged, destructive, package-management, service, + kernel, disk, and file operations. + +## 3. Non-goals + +Linutil is not: + +- A replacement for a distribution's package manager. +- A general-purpose shell or arbitrary command launcher. +- A daemon or background configuration-management system. +- A guarantee that every utility supports every Linux distribution. +- A mechanism for silently bypassing package signatures, privilege controls, + user confirmation, or platform compatibility checks. +- A substitute for backups before disk, bootloader, kernel, account, or + destructive filesystem operations. + +## 4. System architecture + +### 4.1 Workspace + +The Cargo workspace contains: + +| Component | Responsibility | +| --- | --- | +| `core` | Data model, TOML loading, precondition evaluation, embedded assets, temporary extraction, and user config | +| `tui` | CLI, rendering, navigation, search, preview, confirmation, selection, PTY execution, and output display | +| `xtask` | Repository maintenance and generated documentation | +| `core/tabs` | Tab definitions, utility metadata, shared shell libraries, and executable scripts | + +### 4.2 Runtime flow + +1. `linutil_core` embeds `core/tabs/` into the binary at compile time. +2. On startup, the embedded tree is extracted to a temporary directory. +3. `tabs.toml` determines the ordered list of tab directories. +4. Each tab's `tab_data.toml` is parsed into a tree of `ListNode` values. +5. Preconditions are evaluated against the current machine when validation is + enabled. +6. Unsupported leaves and empty parent categories are removed. +7. The TUI displays the resulting tabs and command tree. +8. The user may inspect descriptions and source previews before selection. +9. Selected commands pass through the confirmation flow. +10. The TUI composes the commands into a shell program and runs it in a PTY. +11. Output is rendered live until the process succeeds, fails, or is + interrupted. +12. The temporary script tree remains alive for the lifetime of the tab list + and is removed when it is dropped. + +### 4.3 Data model + +The core command model has three forms: + +- `Command::Raw(String)`: A short inline shell command. +- `Command::LocalFile`: An extracted script, its shebang-derived executable, + and executable arguments. +- `Command::None`: A non-executable directory node. + +A `Tab` owns a tree of `ListNode` values. Each node contains: + +- Display name. +- User-facing description. +- Command form. +- Task flag string. +- Multi-select eligibility. + +Display names should be unique among executable leaves because config-file +automation resolves entries by name. + +## 5. Command catalog + +### 5.1 Top-level tabs + +`core/tabs/tabs.toml` contains an ordered `directories` array. Every listed +directory must contain a valid `tab_data.toml`. + +Adding a top-level tab requires: + +1. A new directory under `core/tabs/`. +2. A valid `tab_data.toml`. +3. An entry in `core/tabs/tabs.toml`. +4. At least one supported executable leaf at runtime. + +### 5.2 Tab schema + +Each tab data file contains: + +```toml +name = "Tab Display Name" + +[[data]] +name = "Category or Command" +``` + +An entry must define exactly one of: + +- `entries`: Nested child entries. +- `script`: A script path relative to the tab directory. +- `command`: An inline shell command. + +Optional entry fields are: + +- `description`: User-facing explanation. +- `preconditions`: Conditions controlling visibility. +- `task_list`: Space-separated task flags shown in the TUI. +- `multi_select`: Whether the entry may participate in a queued command set. + The default is `true`. + +Script paths may reference shared scripts elsewhere under `core/tabs/`, but +the resolved path must exist when the catalog is loaded. + +### 5.3 Preconditions + +All preconditions on an entry must pass for it to remain visible. + +Supported data sources are: + +| Type | Behavior | +| --- | --- | +| `environment` | Compare an environment variable with the provided values | +| `containing_file` | Check a file's contents for all provided strings | +| `command_exists` | Check all provided commands on `PATH` | +| `file_exists` | Check all provided paths as files | + +`matches = true` requires a match. `matches = false` requires the inverse. + +Preconditions should be used for objective platform capabilities such as a +package manager, distro marker, display-server session, required executable, +or required file. They are visibility filters, not a replacement for runtime +validation inside scripts. + +### 5.4 Task flags + +Task flags warn users about the important effects of a command: + +| Flag | Meaning | +| --- | --- | +| `D` | Disk modification | +| `FI` | Flatpak installation | +| `FM` | File modification | +| `I` | Privileged installation | +| `K` | Kernel modification | +| `MP` | Package manager action | +| `RP` | Package removal | +| `SI` | Full system installation | +| `SS` | Service or systemd action | +| `P*` | The marked action requires privileges | + +Flags are informational and do not grant privileges or replace confirmation. + +## 6. Script contract + +### 6.1 Interpreter + +Scripts should use POSIX shell and `#!/bin/sh -e` by default. Scripts requiring +Bash syntax must declare Bash explicitly. + +If no shebang is present, the core defaults to `/bin/sh -e`. When executable +validation is enabled, a script with an unavailable or non-executable shebang +interpreter is omitted. + +### 6.2 Working directory and shared files + +Before a local script runs, the TUI changes to the script's extracted parent +directory. Relative imports and sibling assets must be written for that +working directory. + +General-purpose scripts should source `common-script.sh`. Scripts that manage +services should also source `common-service-script.sh`. More specialized +families may define an additional shared helper when it removes meaningful +duplication. + +### 6.3 Environment initialization + +Scripts using the general shared environment must call `checkEnv` before +depending on its results. + +The shared environment is responsible for detecting or defining: + +- CPU architecture. +- Supported privilege escalation tool. +- Required baseline commands. +- Supported package manager. +- Current Linux distribution identifier. +- Superuser group access. +- Current-directory writability. +- Arch User Repository helper where relevant. + +Scripts must still validate feature-specific requirements and unsupported +states. + +### 6.4 Distribution portability + +For a generally available utility: + +- Use the detected `PACKAGER`. +- Handle appropriate package names and flags per package manager. +- Prefer native distribution packages. +- Use Flatpak or another portable method as an intentional fallback, not an + accidental catch-all when the platform is unknown. +- Report unsupported distributions or architectures before making changes. + +For a distro-specific utility: + +- Place it in a clearly named distro category. +- Add metadata preconditions. +- Recheck critical assumptions in the script before changing the system. + +### 6.5 Privilege and safety + +Scripts must: + +- Run unprivileged by default. +- Apply `ESCALATION_TOOL` only to commands that require elevated access. +- Explain destructive or irreversible choices before execution. +- Avoid overwriting user configuration without a backup, merge, or explicit + prompt. +- Check existing state so repeated execution is safe when practical. +- Stop on unsupported or ambiguous conditions. +- Avoid embedding credentials or collecting user secrets. +- Avoid logging sensitive input. +- Clean temporary files and partial downloads. +- Verify downloaded artifacts when upstream checksums or signatures exist. + +Disk, bootloader, kernel, account-removal, and broad cleanup utilities should +set `multi_select = false`. + +### 6.6 User interaction + +Scripts run in a PTY and may prompt users. Prompts must: + +- State the action and meaningful consequences. +- Accept predictable input. +- Provide a safe default for risky operations. +- Remain usable in the TUI's terminal viewport. +- Exit nonzero on failure or cancellation when no work was completed. + +## 7. TUI requirements + +The TUI must provide: + +- Tab and hierarchical command navigation. +- Search and filtering. +- Command descriptions. +- Source preview for raw commands and local scripts. +- Multi-selection for compatible commands. +- Confirmation before execution unless an explicit, documented bypass applies. +- Live PTY output with terminal color support. +- Scrolling and process interruption. +- Clear success and failure status. +- A warning when Linutil itself is run as root unless explicitly bypassed. +- A minimum-size check with an explicit bypass option. + +Raw and local commands selected together execute in selection order within one +shell program. A failure must be visible to the user and reflected in the final +command status. + +## 8. Configuration and automation + +Linutil accepts a TOML configuration file with: + +- `auto_execute`: Display names of executable leaves. +- `skip_confirmation`: Whether confirmation is skipped. +- `size_bypass`: Whether terminal-size enforcement is bypassed. + +Unknown configuration fields are errors. + +Automation must not cause an unsupported catalog entry to appear. Missing or +filtered command names are ignored by the current loader and should be +reported more explicitly in a future compatibility-preserving improvement. + +Command display names are therefore part of the user-facing automation +interface and should not be renamed casually. + +## 9. Documentation + +User-visible command additions and description changes must update generated +walkthrough content using: + +```bash +cargo xtask docgen +``` + +Generated documentation must not be edited as the sole source of a change. +Architecture documentation should remain consistent with `SPEC.md` and the +code. + +## 10. Quality requirements + +### 10.1 Rust + +Required checks for Rust changes: + +```bash +cargo fmt --all --check +cargo test --no-fail-fast --package linutil_core +cargo clippy -- -Dwarnings +``` + +Parser and filtering changes require focused unit tests. TUI behavior changes +require either focused tests or documented interactive validation. + +### 10.2 Shell + +Changed shell scripts must pass ShellCheck. POSIX shell scripts should also +pass `checkbashisms`. + +Scripts should be tested without performing unintended system changes. Use +syntax/static checks, controlled containers or virtual machines, mocked +commands, and representative supported distributions as appropriate. + +### 10.3 Catalog + +Catalog changes must prove that: + +- TOML parses successfully. +- Every referenced script exists. +- Required interpreters are valid under normal validation. +- Preconditions retain intended entries and remove unsupported entries. +- Generated documentation is current. + +The core test suite is the minimum automated validation for catalog changes. + +## 11. Acceptance criteria for a new utility + +A utility is complete when: + +1. It has a focused script or appropriately short raw command. +2. It reuses shared environment and service helpers where applicable. +3. It supports the intended distributions and rejects unsupported ones. +4. Its metadata includes an accurate name, description, path, task flags, + preconditions, and multi-select policy. +5. It is previewable and executable from the TUI. +6. Privileged and destructive operations are explicit. +7. Re-running it does not cause avoidable damage or duplication. +8. Relevant Rust, TOML, shell, and generated-documentation checks pass. +9. Platform limitations and residual risks are documented. + +## 12. Future compatibility + +Architectural extensions should preserve the data-driven utility model. +Potential additions such as richer capability detection, structured command +results, dry-run support, per-command privilege declarations, or stronger +download verification should extend the catalog and core contracts rather +than hard-code individual utilities into the TUI.