{"id":27448477,"url":"https://github.com/nixin72/shan","last_synced_at":"2025-04-15T07:26:02.017Z","repository":{"id":44605886,"uuid":"408606013","full_name":"nixin72/shan","owner":"nixin72","description":"A declarative wrapper around your favourite system-wide package manager","archived":false,"fork":false,"pushed_at":"2022-03-20T19:04:39.000Z","size":3488,"stargazers_count":8,"open_issues_count":10,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-05-13T00:13:25.482Z","etag":null,"topics":["clojure","declarative","linux","macos","package-manager","windows"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nixin72.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-09-20T21:30:34.000Z","updated_at":"2024-01-23T21:11:04.000Z","dependencies_parsed_at":"2022-09-13T14:20:25.185Z","dependency_job_id":null,"html_url":"https://github.com/nixin72/shan","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixin72%2Fshan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixin72%2Fshan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixin72%2Fshan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nixin72%2Fshan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nixin72","download_url":"https://codeload.github.com/nixin72/shan/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249025524,"owners_count":21200317,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["clojure","declarative","linux","macos","package-manager","windows"],"created_at":"2025-04-15T07:26:01.334Z","updated_at":"2025-04-15T07:26:02.010Z","avatar_url":"https://github.com/nixin72.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Shan\n\nShan is a declarative wrapper around your favourite package manager.\n\n- Cross-platform: works on Linux, Windows and MacOS\n- Simple: shan harnesses existing package managers to do the heavy lifting\n- Declarative: sync to your config or let shan build it for you\n- Wide support: shan supports tons of package managers out of the box\n- Extensible: your package manager not supported? Add it in ~3 lines of code\n- Fast: shan is compiled using GraalVM to make it super fast - no JVM here.\n\n**NOTE:** Shan still isn't at 1.0 release, and as of now, it in fact does _not_\nsupport tons of package managers. My goal is, as of 1.0, to support:\n\n- [ ] dpkg\n- [x] yay\n- [x] paru\n- [ ] dnf\n- [x] brew\n- [ ] chocolatey\n- [ ] winget\n- [x] npm\n- [x] pip\n- [x] Gems\n\n## Table of Contents\n\n- [Why use shan?](#why-shan)\n- [Using shan](#usage)\n  - [Installing packages](#installing-packages)\n  - [Default package manager](#default-package-manager)\n  - [Removing packages](#removing-packages)\n  - [Listing packages](#listing-packages)\n  - [Temporarily installed packages](#temporary-packages)\n- [Contributing](#contributing)\n  - [Adding a package manager](#adding-a-package-manager)\n- [License](#license)\n\n## Why Shan?\n\nShan is for people who want to be able to manage their packages declaratively,\nbut don't want the complexity that comes with other systems like NixOS or Guix.\nIt's aim is to facilitate setting up new systems. If you've bought a new laptop\nand want to install everything you had with `brew` or you've decided you want to\ntry out Linux and want to install you had in `chocolatey`. Maybe you like\ndistro-hopping and want a way to get started quickly with all the packages you\nknow and love, or maybe you just broke your Arch install and decided it's easier\nto nuke your system than fix the issue (I know I've been there).\n\nIf you've ever been in any of these situations, try out shan. Shan works for\neveryone, no matter what operating system you're using, no matter what package\nmanagers you're using.\n\n## Usage\n\nAll the commands available at the moment are:\ninstall, add-repo\nremove, del-repo\nsync, rollback\nedit, default\npurge, merge\nlist, gen\n\n### Installing packages\n\nInstalling packages with shan is easily done through the `install` or `in`\nsubcommand.\n\n```sh\nshan install nodejs\n```\n\nFor example will install `nodejs` using the [default package manager](#your-config).\n\nYou can also specify to shan which package manager should be used to install a\npackage:\n\n```sh\nshan install nodejs -npm react\n```\n\nAnd this will install `nodejs` using the default package manager, and then `react`\nusing npm.\n\nYou can also mix and match things in any order and install as many packages as you\nwant in a single command:\n\n```sh\nshan install nodejs python -npm react react-native -pip PyYAML wakatime -npm expo\n```\n\nEvery time you install a package, the package will also be added to\n[your config file](#your-config) so that down the road, you'll have everything\navailable to you in a declarative config.\n\n### Package versions\n\nFor most package managers, you can specify which version of a package you want\nwhen installing a package:\n\n```sh\n$ shan install -npm react=17.0.2 -pip wakatime=13.1.0\n```\n\n### Default package manager\n\nMost people probably don't want to need to specify which package manager to use\nevery time they want to install something. Most people also probably use one\npackage manager more often than others, like `yay` or `brew`. For these\npurposes, shan allows you to set a default package manager to use.\n\n```sh\nshan default yay\n```\n\nThis will set `yay` to be the default package manager that shan should use. Now,\nwhen you install a package using `shan install \u003cpackage\u003e`, you don't need to tell\nshan that it should use `yay` to install it, shan will use the default.\n\n### Removing packages\n\nWhen removing a package using Shan, it's generally able to figure out which\npackage manager it should be using to remove a package. Let's say we have the\nfollowing packages installed:\n\n```clojure\nyay\nnodejs neovim atop\n\nnpm\nreact underscore atop\n```\n\nNow, if we want to remove `nodejs`, we simply have to do:\n\n```sh\nshan remove nodejs\n```\n\nAnd shan will figure out which package manager to remove nodejs using. Unlike\ninstalling, where it'll install using your default package manager, removing will\nsimply remove from where the package exists.\n\n```sh\nshan remove nodejs neovim react\n```\n\nWill remove `nodejs` and `neovim` using yay, and `react` will be removed using\n`npm`.\n\nWe do however have `atop` installed here in both yay _and_ npm. In this case,\nShan will prompt you for which package manager you want to uninstall `atop` from.\n\nYou can also specify instead if you'd like\n\n```sh\n$ shan rm -yay atop\n```\n\nBut for convenience sake, you don't have to.\n\nA package also doesn't need to be in your config to uninstall it.\n\n```sh\nshan rm emacs\n```\n\nIf you remove a package that isn't in your config, shan will look at which\npackage mangers are available on your system, then check if that package is\ninstalled using any of those package managers. If it is, then it'll remove the\npackage using that package manager, and let you know where it found it.\n\n### Listing packages\n\nKnowing which packages you have installed and being able to easily search for\nthem is important. That's why shan provides utilities for listing everything\nyou have installed in a variety of ways.\n\n```sh\n$ shan list\nyay\nneovim nodejs emacs\n\nnpm\nreact-native expo-cli\n\npip\nwakatime\n```\n\nYou can also add flags to the `list` command to get the data in a variety of formats.\n\n```sh\n$ shan list --json\n{\n    \"yay\": [\"neovim\", \"nodejs\", \"emacs\"],\n    \"npm\": [\"react-native\", \"expo-cli\"],\n    \"pip\": [\"wakatime\"]\n}\n$ shan list --parse\nyay neovim\nyay nodejs\nyay emacs\nnpm react-native\nnpm expo-cli\npip wakatime\n```\n\n### Temporary packages\n\nSometimes you want to quickly install a package to test it out, but you don't\nnecessarily want it to be added to your config. When installing or removing a\npackage, shan supports the ability to make \"temporary\" changes. This means that\nthe changes you make won't get added to your config file.\n\n```sh\nshan install -t nodejs -npm react\n```\n\nWill install nodejs using the default package manager and react using npm, however\nneither of these packages will get added to your config. Instead, the changes will\nbe saved in a separate file. This way, shan can act against that file independently\nof your config. For example if you want to uninstall everything temporary, you\ncan simply do\n\n```sh\nshan purge\n```\n\nAnd shan will delete everything temporarily installed. To protect you from\naccidentally purging your actual config, you can only purge your temporary one.\n\nIn addition to purging your temporary files, you can also _merge_ your list of\ntemporary packages with your config. This will take all packages installed\ntemporarily and add them to your `shan.edn` file.\n\n```sh\nshan merge\n```\n\n## Contributing\n\nAny and all contributions are more than welcome! If you have a feature request,\na question, or a bug to report, make an issue. If you think you can make the\nfeature or fix the bug, a PR would be awesome.\n\n### Adding a Package Manager\n\nshan doesn't support every package manager, but I would love it to! If you're\ninterested in adding a package manager, you can request it get added in an issue.\n\nIf you'd like to take a shot at adding one yourself, it's very simple though.\n\n1. Open `src/shan/managers.clj`\n2. In the `package-managers` map at the top of the file, add a new entry for\n   your package manager. Each value is a map, with at least 3 entries:\n   `:install`, `:remove`, `:installed?`.\n\n   1. For the `:install` value, put the command to install a package with your\n      package manager.\n   2. For the `:remove` value, put the command to remove a package.\n   3. For the `:installed?` value, put the command to check if a package is\n      locally installed.\n\n   There are other values that can and should be added if you want to get full\n   usage out of the given package manager. Other supported keys are `:type`,\n   `:list`, `:add-archive`, `:remove-archive`, `pre-install`.\n\n   1. The `:type` key should be what type of package manager it is. Possible\n      values are `:system` and `:language`. The default is `:system`.\n   2. `:list` is a little complicated. It should be present for all package\n      managers, but it's not required. If you don't know Clojure, feel free to\n      leave this one to the maintainers. If you do know it, take a look at the\n      `src/shan/managers/list.clj` file. The value for `:list` should be a\n      function that gets a list of all packages installed via that package\n      manager, and creates a list of all of them.\n   3. The `:add-archive` and `:remove-archive` keys are strings that contain the\n      command to add a new package archive for the package manager. Not all\n      package managers have package archives, so this isn't necessary for some.\n   4. `:pre-install` is something that will run before any packages get\n      installed using that package manager. This is useful for doing things like\n      updating the package archives so that packages you want that aren't in the\n      default archives become available.\n\nExample:\n\n```clojure\n{:pip {:install \"python -m pip install\"\n       :remove \"python -m pip uninstall -y\"\n       :installed? \"python -m pip show\"}}\n```\n\nQuestions? Put up an issue or make a PR with what you've got so far.\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2021 Philip Dumaresq\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnixin72%2Fshan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnixin72%2Fshan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnixin72%2Fshan/lists"}