{"id":45979354,"url":"https://github.com/hainet50b/homeos","last_synced_at":"2026-06-07T06:00:55.895Z","repository":{"id":336797454,"uuid":"1150298194","full_name":"hainet50b/homeos","owner":"hainet50b","description":"An AI-agent-driven CLI for keeping install scripts reproducible across machines","archived":false,"fork":false,"pushed_at":"2026-05-31T07:11:28.000Z","size":1234,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T09:22:16.948Z","etag":null,"topics":["linux","macos","rust","windows"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hainet50b.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-05T05:36:25.000Z","updated_at":"2026-05-31T07:10:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"dcf776d5-5198-493c-b7a5-7be1c2151876","html_url":"https://github.com/hainet50b/homeos","commit_stats":null,"previous_names":["hainet50b/homeos"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/hainet50b/homeos","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hainet50b%2Fhomeos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hainet50b%2Fhomeos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hainet50b%2Fhomeos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hainet50b%2Fhomeos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hainet50b","download_url":"https://codeload.github.com/hainet50b/homeos/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hainet50b%2Fhomeos/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34010556,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-07T02:00:07.652Z","response_time":124,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["linux","macos","rust","windows"],"created_at":"2026-02-28T17:24:29.270Z","updated_at":"2026-06-07T06:00:55.852Z","avatar_url":"https://github.com/hainet50b.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# homeos\n\n![Build](https://github.com/hainet50b/homeos/actions/workflows/build.yml/badge.svg)\n![Release](https://img.shields.io/github/v/release/hainet50b/homeos)\n![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue)\n\n**Making install script hell feel like *home*.**\n\n*homeos* (ho-mee-os) — named after *homeostasis*, a layer above your install scripts, managed from a single Git repository.\n\n\u003e [!IMPORTANT]\n\u003e **Built for AI agents** *(since v0.3.0)*. A generated `AGENTS.md` (mirrored as `CLAUDE.md` for Claude Code) teaches your AI agent how to drive homeos and keep your repository self-documenting through an agent-maintained `README.md` at the root.\n\n## Features\n\n- **Source of truth in a single Git repo** — Everything in your *home* is visible and under your control. Nothing happens beyond what you write.\n- **One interface, any provider** — Manage custom scripts and package providers alike through one interface and one config file.\n- **Install in the right order** — When packages depend on each other, homeos respects dependencies in every operation, executing scripts in the correct order.\n- **Nothing runs without confirmation** — A plan is always shown before execution. If it's not in the plan, it doesn't run.\n- **Run anywhere: Linux, macOS, Windows** — Built with Rust. Works on any OS.\n\n[Quick Tour](#quick-tour) | [Install](#install) | [Reference](#reference) | [Official Plugins](#official-plugins) | [Using with AI agents](#using-with-ai-agents) | [Plugin Development Guide](#plugin-development-guide)\n\n## Quick Tour\n\n### With an AI agent — the new standard\n\nThe fastest way to use homeos is to let your AI coding agent drive it.\n\n```sh\n$ homeos init\nInitialized homeos at /home/\u003cusername\u003e/.local/share/homeos\n\n$ homeos cd\n# A new shell drops you inside the homeos data directory.\n\n$ claude   # or codex, aider, cursor, ...\n```\n\nThen, in the agent's chat, describe what you want:\n\n\u003e Install Neovim for me\n\nThe agent reads the `AGENTS.md` that `homeos init` generated in the data directory, picks the right plugin for your OS, shows you a plan, applies it after your approval, updates the repository README, and commits the change. See [Using with AI agents](#using-with-ai-agents) for what happens under the hood.\n\n### Manual walk-through\n\nIf you prefer to drive homeos directly, here is the same flow without an agent.\n\n1. Initialize a new repository\n\n```sh\n$ homeos init\nInitialized homeos at /home/\u003cusername\u003e/.local/share/homeos\n```\n\n2. Add a package\n\n```sh\n$ homeos package add rustup\nAdded package 'rustup'\n```\n\n3. Move to a package directory and edit its install scripts\n\n```sh\n# Open a new shell in the package directory\n$ homeos package cd rustup\n$ ls\ninstall.ps1  install.sh  uninstall.ps1  uninstall.sh  update.ps1  update.sh\n\n# Edit the scripts you need, remove the ones you don't\n\n# Return to the previous shell\n$ exit\n```\n\n4. Verify the scripts\n\n```sh\n$ homeos package cat rustup\n=== install.sh ===\n#!/usr/bin/env sh\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n\n=== install.ps1 ===\n(not found)\n\n=== update.sh ===\n#!/usr/bin/env sh\nrustup update\n\n=== update.ps1 ===\n(not found)\n\n=== uninstall.sh ===\n#!/usr/bin/env sh\nrustup self uninstall\n\n=== uninstall.ps1 ===\n(not found)\n```\n\n5. Apply, review the plan and install\n\n```sh\n$ homeos apply\nThe following packages will be installed:\n  rustup\n\nProceed? [y/N] y\nInstalling rustup...\n(rustup installer output)\ndone\n\n$ rustup --version\nrustup 1.29.0 (28d1352db 2026-03-05)\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eUsing a plugin\u003c/summary\u003e\n\n1. Browse official plugins\n\n```sh\n$ homeos plugin list-remote\nName      Description                                  URL\n--------  -------------------------------------------  ---------------------------------------------------\napt       APT package manager plugin for homeos.       https://github.com/hainet50b/homeos-plugin-apt\ndnf       DNF package manager plugin for homeos.       https://github.com/hainet50b/homeos-plugin-dnf\nhomebrew  Homebrew package manager plugin for homeos.  https://github.com/hainet50b/homeos-plugin-homebrew\nwinget    WinGet package manager plugin for homeos.    https://github.com/hainet50b/homeos-plugin-winget\n```\n\n2. Add a plugin to your repository\n\n```sh\n$ homeos plugin add dnf\nPlugin 'dnf' added successfully\n```\n\n3. Create a package using the plugin — the plugin's templates render automatically, no script editing needed\n\n```sh\n$ homeos package add neovim --plugin dnf --param name=neovim\nAdded package 'neovim'\n```\n\n4. Apply\n\n```sh\n$ homeos apply\nThe following packages will be installed:\n  neovim (plugin: dnf)\n\nProceed? [y/N] y\nInstalling neovim...\n(dnf output)\ndone\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eComposing packages with a repo (e.g., COPR, tap, bucket)\u003c/summary\u003e\n\nSetup steps that several packages share — enabling a COPR repository, adding a Homebrew tap, registering a Scoop bucket — are best expressed as their own package, with dependents declaring `depends_on`. The setup runs once before any dependent and can be uninstalled cleanly.\n\n1. Add the required plugins — both the setup plugin (e.g., `dnf-copr`, `homebrew-tap`, `scoop-bucket`) and the package manager plugin used by the dependent\n\n```sh\n$ homeos plugin add dnf-copr\nPlugin 'dnf-copr' added successfully\n$ homeos plugin add dnf\nPlugin 'dnf' added successfully\n```\n\n2. Add a setup package using the setup plugin\n\n```sh\n$ homeos package add dnf-copr-mise --plugin dnf-copr --param name=jdxcode/mise\nAdded package 'dnf-copr-mise'\n```\n\n3. Add the actual package depending on it\n\n```sh\n$ homeos package add mise --plugin dnf --param name=mise --depends-on dnf-copr-mise\nAdded package 'mise'\n```\n\n4. Apply — the COPR enable runs first, then the package install\n\n```sh\n$ homeos apply\nThe following packages will be installed:\n  dnf-copr-mise (required by mise)\n  mise (plugin: dnf)\n\nProceed? [y/N]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSetting up a new machine from your repo\u003c/summary\u003e\n\nAfter installing homeos (see [Install](#install)), restore your environment from your existing homeos repository in two commands.\n\n1. Clone your repository\n\n```sh\n$ homeos init https://github.com/\u003cusername\u003e/\u003crepo\u003e\nInitialized homeos at /home/\u003cusername\u003e/.local/share/homeos (cloned from https://github.com/\u003cusername\u003e/\u003crepo\u003e)\n```\n\n2. Apply — installs everything declared in `homeos.yml`\n\n```sh\n$ homeos apply\nThe following packages will be installed:\n  ...\n\nProceed? [y/N] y\nInstalling ...\ndone\n```\n\n\u003c/details\u003e\n\n## Install\n\n### Prerequisites\n\n- **Git 2.28 or newer.** `homeos init` runs `git init --initial-branch=main`, which requires Git 2.28+.\n\n### Linux / macOS\n\n```sh\ncurl -sSf https://raw.githubusercontent.com/hainet50b/homeos/main/install.sh | sh\n```\n\nInstalls to `~/.local/bin/homeos`. Ensure `~/.local/bin` is in your `PATH`.\n\n### Windows\n\n```powershell\nirm https://raw.githubusercontent.com/hainet50b/homeos/main/install.ps1 | iex\n```\n\nInstalls to `%USERPROFILE%\\.homeos\\bin\\homeos.exe` and adds the directory to your user `PATH`.\n\nThe install scripts also set up shell completion for your detected shell. If your shell needs an additional manual step, the script prints the exact instruction to follow.\n\nAlternatively, download the prebuilt binary directly from [GitHub Releases](https://github.com/hainet50b/homeos/releases) and place it on your `PATH` manually. In that case, see [Shell completion](#shell-completion) to set up completion yourself.\n\n## Reference\n\n### Directory Structure\n\nThe data directory depends on the operating system:\n\n| OS      | Data directory                         |\n|---------|----------------------------------------|\n| Linux   | `~/.local/share/homeos`                |\n| macOS   | `~/Library/Application Support/homeos` |\n| Windows | `%LOCALAPPDATA%/homeos`                |\n\n```\n\u003cdata_dir\u003e/\n├── homeos.yml\n├── state.yml\n├── .gitignore\n├── packages/\n│   └── neovim/\n│       ├── install.sh\n│       ├── update.sh\n│       └── uninstall.sh\n└── plugins/\n    └── dnf/\n```\n\n- `homeos.yml` — package and plugin definitions.\n- `state.yml` — tracks installed packages. Machine-specific, excluded from version control via `.gitignore`.\n- `packages/` — action scripts (`install.sh`, `update.sh`, `uninstall.sh` for Linux/macOS; `.ps1` for Windows).\n- `plugins/` — plugin files.\n\n### Overriding the data directory\n\nSet `HOMEOS_DATA_DIR` to use an alternate data directory:\n\n```sh\nexport HOMEOS_DATA_DIR=\"$HOME/.config/homeos-work\"\nhomeos apply\n```\n\nPriority: `HOMEOS_DATA_DIR` overrides the OS default. If unset, the default from the table above applies.\n\n#### Maintaining multiple configurations\n\nYou can keep more than one homeos repository on the same machine and switch between them with `HOMEOS_DATA_DIR`. A common case: your personal homeos repo lives at the OS default location, and a separate repository holds **your team's shared setup** (onboarding scripts, standardized developer tools, internal package definitions). Maintain and apply each independently:\n\n```sh\n# Your personal repo — the OS default, no override needed:\nhomeos apply\n\n# Switch to your team's shared repo:\nexport HOMEOS_DATA_DIR=\"$HOME/.config/homeos-team\"\nhomeos init https://github.com/\u003cteam\u003e/\u003chomeos-repo\u003e\nhomeos apply\n```\n\nEach repository is fully isolated — its own `homeos.yml`, packages, plugins, and installation state.\n\n### Configuration (homeos.yml)\n\n```yaml\npackages:\n  claude:\n    depends_on: [bubblewrap, sandbox-runtime, socat]\n    script_aliases: { update: install }\n  bubblewrap:\n    plugin: dnf\n    params:\n      name: bubblewrap\n  sandbox-runtime:\n    plugin: npm\n    params:\n      name: \"@anthropic-ai/claude-code-sandbox-runtime\"\n  socat:\n    plugin: dnf\n    params:\n      name: socat\n  ollama:\n    script_aliases: { update: install }\n    enabled: false\n\nplugins:\n  dnf:\n    url: https://github.com/hainet50b/homeos-plugin-dnf\n  npm:\n    url: https://github.com/hainet50b/homeos-plugin-npm\n```\n\n- `depends_on` — declare dependencies on other packages.\n- `script_aliases` — map an action to another script (e.g., run `install.sh` for `update`).\n- `enabled` — `true` by default. Set to `false` to skip the package in operations.\n- `plugin` — plugin name to use for script generation.\n- `params` — values passed to the plugin's templates.\n\n### Core Commands\n\n#### `homeos init`\n\nCreate the initial homeos structure at the data directory. Without arguments, creates an empty structure with a skeleton `homeos.yml`. With a URL, clones the remote repository into the data directory.\n\n```\nUsage: homeos init [OPTIONS] [URL]\n\nArguments:\n  [URL]  Remote URL to clone\n\nOptions:\n      --strip-git  Remove .git directory after cloning\n```\n\n#### `homeos cd`\n\nLaunch a shell in the data directory.\n\n```\nUsage: homeos cd [OPTIONS]\n\nOptions:\n      --print  Print the data directory path to stdout and exit, without launching a shell\n```\n\n#### `homeos apply`\n\nInstall new packages and update installed ones.\n\n```\nUsage: homeos apply [OPTIONS]\n\nOptions:\n      --dry-run  Display the plan without executing scripts or prompting\n```\n\nA confirmation prompt is shown before execution.\n\n```\n$ homeos apply\nThe following packages will be installed:\n  bubblewrap\n  socat\n  claude\nThe following packages will be updated:\n  neovim\nThe following packages will be skipped:\n  zed (disabled)\n\nProceed? [y/N]\n```\n\n\u003e [!NOTE]\n\u003e Packages are installed in dependency order based on `depends_on`.\n\n### Manage packages\n\nPackages can be **enabled** or **disabled**. Disabled packages are skipped by `apply`, `install`, and `update`. `uninstall` runs regardless of the enabled status. Newly added packages are enabled by default.\n\nPackages can declare **dependencies** on other packages. homeos handles them in the right order.\n\n#### `homeos package list`\n\nList all packages.\n\n```\nUsage: homeos package list\n```\n\nAlso available as `homeos package ls`.\n\nDisplays a table with package name, enabled status, installed status, backing plugin, and dependencies.\n\n```\n$ homeos package list\nPackage  Enabled  Installed  Plugin  Dependencies\n-------  -------  ---------  ------  -----------------\nneovim   yes      yes        dnf     -\nclaude   yes      yes        -       bubblewrap, socat\ndocker   no       no         dnf     -\n```\n\n#### `homeos package add`\n\nAdd a new package. Creates a package directory under `packages/` and adds an entry to `homeos.yml`. Skeleton scripts are generated for all OS (both `.sh` and `.ps1`).\n\n```\nUsage: homeos package add [OPTIONS] \u003cPACKAGE\u003e\n\nArguments:\n  \u003cPACKAGE\u003e  Package name\n\nOptions:\n      --depends-on \u003cDEPENDENCY\u003e    Add a dependency (can be repeated)\n      --script-alias \u003cALIAS\u003e       Add a script alias as target=source (can be repeated)\n      --plugin \u003cPLUGIN\u003e            Plugin to use for generating scripts\n      --param \u003cPARAM\u003e              Plugin parameter as key=value (can be repeated)\n```\n\nTo generate scripts from a plugin instead of default skeletons:\n\n```\n$ homeos package add neovim --plugin dnf --param name=neovim.x86_64\n```\n\n#### `homeos package remove`\n\nRemove package entries from `homeos.yml`. The package directory is not deleted unless `--purge` is specified.\n\n```\nUsage: homeos package remove [OPTIONS] \u003cPACKAGES\u003e...\n\nArguments:\n  \u003cPACKAGES\u003e...  Package names\n\nOptions:\n      --purge  Also delete the package directory\n```\n\n#### `homeos package rename`\n\nRename a package. Renames the package directory on disk, updates the entry key in `homeos.yml`, updates `state.yml` if the package is installed, and updates any `depends_on` references in other packages to point to the new name.\n\n```\nUsage: homeos package rename \u003cOLD\u003e \u003cNEW\u003e\n\nArguments:\n  \u003cOLD\u003e  Current package name\n  \u003cNEW\u003e  New package name\n```\n\n#### `homeos package add-dep`\n\nAdd dependencies to an existing package.\n\n```\nUsage: homeos package add-dep \u003cPACKAGE\u003e \u003cDEPENDENCY\u003e...\n\nArguments:\n  \u003cPACKAGE\u003e        Package name\n  \u003cDEPENDENCY\u003e...  Dependencies to add\n```\n\n#### `homeos package remove-dep`\n\nRemove dependencies from an existing package.\n\n```\nUsage: homeos package remove-dep \u003cPACKAGE\u003e \u003cDEPENDENCY\u003e...\n\nArguments:\n  \u003cPACKAGE\u003e        Package name\n  \u003cDEPENDENCY\u003e...  Dependencies to remove\n```\n\n#### `homeos package add-alias`\n\nAdd script aliases to an existing package.\n\n```\nUsage: homeos package add-alias \u003cPACKAGE\u003e \u003cALIAS\u003e...\n\nArguments:\n  \u003cPACKAGE\u003e    Package name\n  \u003cALIAS\u003e...   Aliases as target=source pairs (e.g., update=install)\n```\n\n#### `homeos package remove-alias`\n\nRemove script aliases from a package.\n\n```\nUsage: homeos package remove-alias \u003cPACKAGE\u003e \u003cALIAS\u003e...\n\nArguments:\n  \u003cPACKAGE\u003e    Package name\n  \u003cALIAS\u003e...   Alias targets to remove (e.g., update)\n```\n\n#### `homeos package enable`\n\nEnable packages.\n\n```\nUsage: homeos package enable \u003cPACKAGES\u003e...\n\nArguments:\n  \u003cPACKAGES\u003e...  Package names\n```\n\n#### `homeos package disable`\n\nDisable packages.\n\n```\nUsage: homeos package disable \u003cPACKAGES\u003e...\n\nArguments:\n  \u003cPACKAGES\u003e...  Package names\n```\n\n#### `homeos package info`\n\nDisplay package details.\n\n```\nUsage: homeos package info \u003cPACKAGE\u003e\n\nArguments:\n  \u003cPACKAGE\u003e  Package name\n```\n\nShows enabled/installed status, plugin, dependencies, dependents, and script aliases.\n\n```\n$ homeos package info claude\nPackage: claude\nEnabled: yes\nInstalled: yes\nPlugin: -\nDependencies:\n  bubblewrap\n  sandbox-runtime\n  socat\nDependents:\n  (none)\nScript aliases:\n  update → install\n```\n\n#### `homeos package cat`\n\nDisplay all scripts for a package.\n\n```\nUsage: homeos package cat \u003cPACKAGE\u003e\n\nArguments:\n  \u003cPACKAGE\u003e  Package name\n```\n\nDisplays all script files for both Linux/macOS (`.sh`) and Windows (`.ps1`) regardless of the current OS. If a script does not exist, `(not found)` is shown.\n\n```\n$ homeos package cat rustup\n=== install.sh ===\n#!/usr/bin/env sh\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n\n=== install.ps1 ===\n(not found)\n\n=== update.sh ===\n#!/usr/bin/env sh\nrustup update\n\n=== update.ps1 ===\n(not found)\n\n=== uninstall.sh ===\n(not found)\n\n=== uninstall.ps1 ===\n(not found)\n```\n\n#### `homeos package cd`\n\nLaunch a shell in the package root or specific package directory.\n\n```\nUsage: homeos package cd [OPTIONS] [PACKAGE]\n\nArguments:\n  [PACKAGE]  Package name (optional — defaults to packages root)\n\nOptions:\n      --print  Print the resolved path to stdout and exit, without launching a shell\n```\n\n### Operate packages\n\nhomeos tracks which packages are installed on this machine in `state.yml`. This file is machine-specific and managed automatically — you don't need to edit it. The behavior of `install`, `update`, and `uninstall` depends on the package's enabled status and whether it is in `state.yml`.\n\nA confirmation prompt is shown before execution. On script failure, the error is reported and execution continues to the next package.\n\n| State                       | install                  | update                  | uninstall               |\n|-----------------------------|--------------------------|-------------------------|-------------------------|\n| enabled + not in state      | Execute                  | Skip (not installed)    | Skip (not installed)    |\n| enabled + in state          | Skip (already installed) | Execute                 | Execute                 |\n| disabled + not in state     | Skip (disabled)          | Skip (disabled)         | Skip (not installed)    |\n| disabled + in state         | Skip (disabled)          | Skip (disabled)         | Execute                 |\n\n\u003e [!NOTE]\n\u003e `uninstall` ignores the enabled/disabled status — its only concern is whether the package is in `state.yml`. After a successful uninstall, the package is automatically disabled in `homeos.yml`.\n\n#### `homeos package install`\n\nExecute install scripts. Records installed packages in `state.yml`.\n\n```\nUsage: homeos package install [OPTIONS] \u003cPACKAGES\u003e...\n\nArguments:\n  \u003cPACKAGES\u003e...  Package names\n\nOptions:\n      --dry-run  Display the plan without executing scripts or prompting\n```\n\n#### `homeos package update`\n\nExecute update scripts.\n\n```\nUsage: homeos package update [OPTIONS] \u003cPACKAGES\u003e...\n\nArguments:\n  \u003cPACKAGES\u003e...  Package names\n\nOptions:\n      --dry-run  Display the plan without executing scripts or prompting\n```\n\n#### `homeos package uninstall`\n\nExecute uninstall scripts. Disables packages in `homeos.yml` and removes them from `state.yml`. The package directory is not deleted.\n\n```\nUsage: homeos package uninstall [OPTIONS] [PACKAGES]...\n\nArguments:\n  [PACKAGES]...  Package names\n\nOptions:\n      --all      Uninstall all installed packages (from state.yml)\n      --dry-run  Display the plan without executing scripts or prompting\n```\n\n### Manage plugins\n\n#### `homeos plugin list`\n\nList all plugins.\n\n```\nUsage: homeos plugin list\n```\n\nAlso available as `homeos plugin ls`.\n\nDisplays a table with plugin name, description, and URL. `Description` is loaded from each plugin's `plugin.yml`.\n\n```\n$ homeos plugin list\nName  Description                              URL\n----  ---------------------------------------  ----------------------------------------------\ndnf   DNF package manager plugin for homeos.   https://github.com/hainet50b/homeos-plugin-dnf\n```\n\n#### `homeos plugin list-remote`\n\nList official plugins available from GitHub.\n\n```\nUsage: homeos plugin list-remote\n```\n\nAlso available as `homeos plugin ls-remote`.\n\nDisplays name, description, and URL for each official plugin.\n\n```\n$ homeos plugin list-remote\nName      Description                                  URL\n--------  -------------------------------------------  ---------------------------------------------------\napt       APT package manager plugin for homeos.       https://github.com/hainet50b/homeos-plugin-apt\ndnf       DNF package manager plugin for homeos.       https://github.com/hainet50b/homeos-plugin-dnf\nhomebrew  Homebrew package manager plugin for homeos.  https://github.com/hainet50b/homeos-plugin-homebrew\nwinget    WinGet package manager plugin for homeos.    https://github.com/hainet50b/homeos-plugin-winget\n```\n\n#### `homeos plugin add`\n\nAdd a plugin. Without a URL, resolves the official repository automatically. See [Plugin Development Guide](#plugin-development-guide) for `--local` usage.\n\n```\nUsage: homeos plugin add [OPTIONS] \u003cPLUGIN\u003e [URL]\n\nArguments:\n  \u003cPLUGIN\u003e  Plugin name\n  [URL]   Remote URL to clone (defaults to official repository)\n\nOptions:\n      --local  Create an empty plugin skeleton for local development\n```\n\n#### `homeos plugin remove`\n\nRemove a plugin. The plugin directory is not deleted unless `--purge` is specified.\n\n```\nUsage: homeos plugin remove [OPTIONS] \u003cPLUGIN\u003e\n\nArguments:\n  \u003cPLUGIN\u003e  Plugin name\n\nOptions:\n      --purge  Also delete the plugin directory\n```\n\n#### `homeos plugin refresh`\n\nRefetch a plugin's templates from its registered URL. Useful when the upstream plugin has been updated and you want the new templates locally.\n\n```\nUsage: homeos plugin refresh [OPTIONS] [PLUGIN]\n\nArguments:\n  [PLUGIN]  Plugin name (required unless --all)\n\nOptions:\n      --all      Refresh every registered plugin\n      --dry-run  Show what would change without writing\n      --yes      Skip the confirmation prompt\n```\n\nThe diff is computed file by file (added / modified / removed). Local edits to a plugin's templates are overwritten by the refresh — review the summary before confirming. Plugins added via `plugin add --local` are skipped (they have no upstream URL).\n\n#### `homeos plugin info`\n\nDisplay plugin details.\n\n```\nUsage: homeos plugin info \u003cPLUGIN\u003e\n\nArguments:\n  \u003cPLUGIN\u003e  Plugin name\n```\n\nShows description, URL (or `(local)`), parameters, and action templates.\n\n```\n$ homeos plugin info dnf\nPlugin: dnf\nDescription: DNF package manager plugin for homeos.\nURL: https://github.com/hainet50b/homeos-plugin-dnf\nParameters:\n  name\nTemplates:\n  install.sh.tmpl (/home/\u003cusername\u003e/.local/share/homeos/plugins/dnf/install.sh.tmpl)\n  install.ps1.tmpl (not found)\n  update.sh.tmpl (/home/\u003cusername\u003e/.local/share/homeos/plugins/dnf/update.sh.tmpl)\n  update.ps1.tmpl (not found)\n  uninstall.sh.tmpl (/home/\u003cusername\u003e/.local/share/homeos/plugins/dnf/uninstall.sh.tmpl)\n  uninstall.ps1.tmpl (not found)\n```\n\n#### `homeos plugin cat`\n\nDisplay `plugin.yml` and all template files for a plugin.\n\n```\nUsage: homeos plugin cat \u003cPLUGIN\u003e\n\nArguments:\n  \u003cPLUGIN\u003e  Plugin name\n```\n\nExample:\n\n```\n$ homeos plugin cat dnf\n=== plugin.yml ===\nparams:\n  - name\n\n=== install.sh.tmpl ===\n#!/usr/bin/env sh\nsudo dnf install -y {{name}}\n\n=== update.sh.tmpl ===\n#!/usr/bin/env sh\nsudo dnf install -y {{name}}\n\n=== uninstall.sh.tmpl ===\n#!/usr/bin/env sh\nsudo dnf remove -y {{name}}\n```\n\n#### `homeos plugin cd`\n\nLaunch a shell in the plugins root or specific plugin directory.\n\n```\nUsage: homeos plugin cd [OPTIONS] [PLUGIN]\n\nArguments:\n  [PLUGIN]  Plugin name (optional — defaults to plugins root)\n\nOptions:\n      --print  Print the resolved path to stdout and exit, without launching a shell\n```\n\n### Shell completion\n\nPrint a shell completion script for the given shell to stdout.\n\n```\nUsage: homeos completion \u003cSHELL\u003e\n\nArguments:\n  \u003cSHELL\u003e  Target shell [possible values: bash, zsh, fish, powershell, elvish]\n```\n\nRedirect the output to the shell-specific location:\n\n```sh\n# bash\nhomeos completion bash \u003e ~/.local/share/bash-completion/completions/homeos\n\n# zsh\nhomeos completion zsh \u003e ~/.local/share/zsh/site-functions/_homeos\n\n# fish\nhomeos completion fish \u003e ~/.config/fish/completions/homeos.fish\n\n# PowerShell\nhomeos completion powershell \u003e\u003e $PROFILE\n\n# Elvish\nhomeos completion elvish \u003e ~/.config/elvish/lib/homeos.elv\n```\n\n\u003e [!NOTE]\n\u003e `install.sh` / `install.ps1` set up completion automatically for the detected shell.\n\n## Official Plugins\n\nOfficial plugins are available. See each plugin's repository for details.\n\n| Name | Description |\n|------|-------------|\n| [apt](https://github.com/hainet50b/homeos-plugin-apt) | APT package manager plugin for homeos. |\n| [dnf](https://github.com/hainet50b/homeos-plugin-dnf) | DNF package manager plugin for homeos. |\n| [dnf-copr](https://github.com/hainet50b/homeos-plugin-dnf-copr) | DNF COPR plugin for homeos. |\n| [homebrew](https://github.com/hainet50b/homeos-plugin-homebrew) | Homebrew package manager plugin for homeos. |\n| [homebrew-cask](https://github.com/hainet50b/homeos-plugin-homebrew-cask) | Homebrew cask plugin for homeos. |\n| [homebrew-tap](https://github.com/hainet50b/homeos-plugin-homebrew-tap) | Homebrew tap plugin for homeos. |\n| [npm](https://github.com/hainet50b/homeos-plugin-npm) | npm package manager plugin for homeos. |\n| [scoop](https://github.com/hainet50b/homeos-plugin-scoop) | Scoop package manager plugin for homeos. |\n| [scoop-bucket](https://github.com/hainet50b/homeos-plugin-scoop-bucket) | Scoop bucket plugin for homeos. |\n| [winget](https://github.com/hainet50b/homeos-plugin-winget) | WinGet package manager plugin for homeos. |\n\nBuilt a community plugin? [Open an issue](https://github.com/hainet50b/homeos/issues/new) and we'll list it here.  \nWant a plugin that doesn't exist yet? [Request it](https://github.com/hainet50b/homeos/issues/new) — we'd love to hear what you need.\n\n## Using with AI agents\n\n`homeos` ships with an `AGENTS.md` guide that AI coding agents (Claude Code, Codex, Aider, Cursor, etc.) can read to learn how to operate `homeos` on the user's behalf. The guide is generated by the binary itself, so its content is always in sync with the version you have installed. `homeos init` writes it to the data directory, and `homeos cd` keeps it refreshed across binary upgrades.\n\nThe canonical workflow:\n\n1. Run `homeos cd` to launch a shell in the data directory.\n2. Start your AI agent from that shell.\n3. Ask the agent for what you want. The agent reads `AGENTS.md` at the working directory (or `CLAUDE.md`, which is a symlink to the same file on Linux/macOS, or a content copy refreshed alongside `AGENTS.md` on Windows) and proceeds.\n\nFor example, asking *\"Install Neovim for me\"* on a Fedora machine:\n\n1. The agent runs `homeos package list --json` to see what is currently declared, then `homeos plugin list-remote --json` to find the right package manager plugin (e.g. `dnf` on Fedora, `homebrew` on macOS, `winget` on Windows).\n2. It proposes a plan in chat: add the `dnf` plugin, add a `neovim` package using that plugin, then apply.\n3. After your approval, it runs the corresponding `homeos plugin add` / `homeos package add` commands, then `homeos apply --dry-run --json` to confirm the plan, and finally `homeos apply --yes` to execute.\n4. It updates the repository `README.md` to reflect what's now installed, then commits everything together with `git add -A \u0026\u0026 git commit -m \"Add Neovim\"`.\n\nThe plan and confirmation steps mean the agent cannot run anything you haven't seen. The `--json` output mode and the `--yes` flag let agents read structured state and execute approved plans on your behalf.\n\n\u003e [!NOTE]\n\u003e Action scripts under `packages/` work best when **non-interactive**: pass `-y` / `--noconfirm` / `--accept-*` flags so the underlying tool doesn't prompt. The agent's subprocess has no controlling terminal, and a script that tries to read from stdin will fail immediately.\n\u003e\n\u003e `sudo` is the one operation that can't be made non-interactive — it always needs your password (unless you configure `NOPASSWD` in sudoers). When a script in the plan invokes `sudo`, the agent hands off: it asks you to run the equivalent `homeos package install \u003cname\u003e` (or `homeos apply`) in your own terminal, where you have a real tty and can type the password.\n\n\u003e [!TIP]\n\u003e Once you push the homeos repository to GitHub, `gh browse` from inside the data directory opens the agent-maintained `README.md` in your browser — a convenient way to review your installation state, or share your setup with teammates.\n\n### Local customizations\n\nFor extra guidance specific to your setup — naming conventions, machines you've opted out, sensitive operations to double-check — drop a file at `\u003cdata_dir\u003e/AGENTS.local.md`. The generated `AGENTS.md` instructs the agent to read it alongside the main guide. `homeos` itself never touches `AGENTS.local.md`; it is hand-written and yours to maintain.\n\n## Plugin Development Guide\n\nA plugin consists of a parameter list (`plugin.yml`) and template files (`*.tmpl`). When a user runs `homeos package add` with a plugin, the templates are rendered with the user's parameters.\n\nBelow is a step-by-step guide to creating a plugin.\n\n### 1. Create a plugin\n\n```sh\n$ homeos plugin add --local my-provider\nPlugin 'my-provider' created locally\n\n$ homeos plugin cd my-provider\n$ ls\ninstall.ps1.tmpl  plugin.yml          uninstall.sh.tmpl  update.sh.tmpl\ninstall.sh.tmpl   uninstall.ps1.tmpl  update.ps1.tmpl\n```\n\n### 2. Define parameters\n\nEdit `plugin.yml` to set a `description` (a one-line summary of the plugin's purpose) and define the parameters that users must provide when using your plugin:\n\n```yaml\ndescription: My provider plugin for homeos.\nparams:\n  - name\n```\n\n### 3. Write templates\n\nEdit the template files for each action. `.sh.tmpl` files are for Linux/macOS, `.ps1.tmpl` files are for Windows. You can provide both, or only the ones relevant to your plugin's purpose — unused templates can be deleted.\n\nTemplates use `{{key}}` placeholders. When a user runs `homeos package add` with your plugin, each `{{key}}` is replaced with the corresponding value from the user's `params`.\n\nFor example, `install.sh.tmpl`:\n\n```sh\n#!/usr/bin/env sh\nsudo dnf install -y {{name}}\n```\n\nWhen a user adds a package with `--param name=neovim.x86_64`:\n\n```sh\n$ homeos package add neovim --plugin my-provider --param name=neovim.x86_64\n\n$ homeos package cat neovim\n=== install.sh ===\n#!/usr/bin/env sh\nsudo dnf install -y neovim.x86_64\n```\n\n\u003e [!TIP]\n\u003e Downloaded plugins can be freely edited locally. Changes only affect your machine and are not pushed upstream.\n\n## License\n\nLicensed under either of\n\n * Apache License, Version 2.0\n   ([LICENSE-APACHE](LICENSE-APACHE) or \u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e)\n * MIT license\n   ([LICENSE-MIT](LICENSE-MIT) or \u003chttp://opensource.org/licenses/MIT\u003e)\n\nat your option.\n\n## Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall be\ndual licensed as above, without any additional terms or conditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhainet50b%2Fhomeos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhainet50b%2Fhomeos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhainet50b%2Fhomeos/lists"}