{"id":13549378,"url":"https://github.com/b3nj5m1n/xdg-ninja","last_synced_at":"2025-05-14T12:09:57.804Z","repository":{"id":37091597,"uuid":"491527855","full_name":"b3nj5m1n/xdg-ninja","owner":"b3nj5m1n","description":"A shell script which checks your $HOME for unwanted files and directories.","archived":false,"fork":false,"pushed_at":"2025-05-11T14:55:03.000Z","size":641,"stargazers_count":2832,"open_issues_count":37,"forks_count":155,"subscribers_count":17,"default_branch":"main","last_synced_at":"2025-05-11T15:34:47.427Z","etag":null,"topics":["linux","shell","terminal","xdg","xdg-basedir","xdg-compliance"],"latest_commit_sha":null,"homepage":"","language":"Haskell","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/b3nj5m1n.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2022-05-12T13:35:20.000Z","updated_at":"2025-05-11T14:55:06.000Z","dependencies_parsed_at":"2024-02-29T03:32:42.803Z","dependency_job_id":"ac19f539-696f-46c6-b760-59a6ea2539c5","html_url":"https://github.com/b3nj5m1n/xdg-ninja","commit_stats":{"total_commits":426,"total_committers":172,"mean_commits":"2.4767441860465116","dds":0.7676056338028169,"last_synced_commit":"4496cde743c4313c91f1840ccab5bdd845612a60"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b3nj5m1n%2Fxdg-ninja","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b3nj5m1n%2Fxdg-ninja/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b3nj5m1n%2Fxdg-ninja/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/b3nj5m1n%2Fxdg-ninja/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/b3nj5m1n","download_url":"https://codeload.github.com/b3nj5m1n/xdg-ninja/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254140746,"owners_count":22021219,"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":["linux","shell","terminal","xdg","xdg-basedir","xdg-compliance"],"created_at":"2024-08-01T12:01:21.205Z","updated_at":"2025-05-14T12:09:52.787Z","avatar_url":"https://github.com/b3nj5m1n.png","language":"Haskell","funding_links":[],"categories":["Haskell","Terminal","terminal","Tools"],"sub_categories":["Apps and Tools","Ansible"],"readme":"\u003c!-- markdownlint-disable MD041 --\u003e\n\u003c!-- markdownlint-configure-file { \"no-inline-html\": { \"allowed_elements\": [div, h1, h4, p, i, img] } } --\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003exdg-ninja\u003c/h1\u003e\n  \u003ch4\u003e\n    Because you wouldn't let just anyone into your \u003ci\u003e$HOME\u003c/i\u003e\n  \u003c/h4\u003e\n\u003c/div\u003e\n\nA shell script that checks your `$HOME` for unwanted files and directories.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://s11.gifyu.com/images/68747470733a2f2f73382e67696679752e636f6d2f696d616765732f5065656b2d323032322d30352d31332d31362d30372e676966.gif\" width=\"500\" alt=\"xdg-ninja command output\" /\u003e\n\u003c/p\u003e\n\nWhen `xdg-ninja` encounters a file or directory it knows about, it will tell you whether it's possible to move it to the appropriate location, and how to do it.\n\nThe configurations are from the [arch wiki page on XDG_BASE_DIR](https://wiki.archlinux.org/title/XDG_Base_Directory), [antidot](https://github.com/doron-cohen/antidot) (thanks to Scr0nch for writing a conversion tool), and crowdsourced by other users.\n\n## Installing\n\n### Manual Installation\n\nClone the repository, then run the [`./xdg-ninja.sh`](./xdg-ninja.sh) script.\n\n```sh\ngit clone https://github.com/b3nj5m1n/xdg-ninja\ncd xdg-ninja\n./xdg-ninja.sh\n```\n\nThis will run every test in the default configuration.\n\n### [Nix](https://nixos.org)\n\nTurn on [flakes](https://nixos.wiki/wiki/Flakes), then run the following command:\n\n```sh\nnix run github:b3nj5m1n/xdg-ninja\n```\n\n### [Homebrew](https://brew.sh)\n\n\u003e [!NOTE]\n\u003e Due to how `xdg-ninja` is developed, releases are not cut, so Homebrew ships a stale version, therefore you have to install and upgrade `xdg-ninja` from the git HEAD. ref: [#204](https://github.com/b3nj5m1n/xdg-ninja/issues/204)\n\u003e\n\u003e Homebrew will not upgrade `xdg-ninja` when running a generic `brew upgrade`, you must specifically upgrade `xdg-ninja` from the git HEAD, _see below_\n\nInstall:\n\n```sh\nbrew install xdg-ninja --HEAD\n```\n\nUpgrade:\n\n```sh\nbrew upgrade xdg-ninja --fetch-HEAD\n```\n\n### Other Package Managers\n\n`xdg-ninja` is available in many other package managers.\n\nThe full list is available on the [repology page](https://repology.org/project/xdg-ninja/versions).\n\nFollow the instructions for your package manager to install `xdg-ninja`.\n\n## Contributing\n\n### Dependencies\n\n- Your favorite POSIX-compliant shell ([bash](https://repology.org/project/bash/packages), [zsh](https://repology.org/project/zsh/packages), [dash](https://repology.org/project/dash-shell/packages), etc.)\n- [jq](https://repology.org/project/jq/packages) for parsing the json files\n- [find](https://repology.org/project/findutils/versions)\n\n#### Optional\n\n- [glow](https://repology.org/project/glow/packages) for rendering Markdown in the terminal ([bat](https://repology.org/project/bat-cat/packages), [pygmentize](https://repology.org/project/pygments/versions) or [highlight](https://repology.org/project/highlight/packages) can be used as a fallback, but glow's output is clearer therefore glow is recommended)\n\n### Configuration\n\nThe configuration is done in the [`./programs/`](./programs/) directory, which should be located in the same working directory as the [`xdg-ninja.sh`](./xdg-ninja.sh) script. This can be overridden with the `XN_PROGRAMS_DIR` environment variable.\n\nYou define a program, and then a list of files and directories which that program ruthlessly puts into your `$HOME` directory.\n\nFor each file/directory, you specify if it can be (re)moved.\n\nIf this is the case, you also specify instructions on how to accomplish this in Markdown.\n\nFiles in this directory can have any name, but using the name of the program is recommended.\n\n### Automatically Generating Configuration\n\nFor x86_64 Linux systems, you can download the `xdgnj` binary from the [releases page](https://github.com/b3nj5m1n/xdg-ninja/releases).\n\nAlternatively, you can build it from source using `cabal` or `stack`, use the nix flake or use the provided docker image.\n\n\u003e To be clear, this is just a tool that will help you automatically generate the config files, you still only need your shell to run the tests\n\n#### Available commands\n\n```sh\nxdgnj add # Adds a new configuration\nxdgnj prev programs/FILE.json # Preview the configuration for a program\nxdgnj edit programs/FILE.json # Edit the configuration for a program\nxdgnj run # Mostly the same as running the shell script\n```\n\n#### Prebuilt Binaries\n\n\u003e [!IMPORTANT]\n\u003e The binaries only run on x86_64 Linux systems.\n\n```sh\ncurl -fsSL -o xdgnj https://github.com/b3nj5m1n/xdg-ninja/releases/latest/download/xdgnj\nchmod +x xdgnj\n```\n\n#### Building from source\n\nYou can use `cabal build` or `stack build`\n\n#### Nix\n\n```sh\nnix run github:b3nj5m1n/xdg-ninja#xdgnj-bin ...\n```\n\n#### Docker\n\nUse the provided dockerfile in [`./haskell/build/`](./haskell/build/).\n\n### Manually Creating Configuration\n\nWe're going to use `git` as an example.\n\nBy default, it puts the file `.gitconfig` into `$HOME`.\n\nLuckily, the XDG spec is supported by git, so we can simply move the file to `$XDG_CONFIG_HOME/git/config`.\n\nWe can use that last sentence as our instructions. In this case, there are no newlines, so escaping this string for use in json is trivial, however, this is how you should generally approach it:\n\n```sh\necho \"Luckily, the XDG spec is supported by git, so we can simply move the file to _$XDG_CONFIG_HOME/git/config_.\" | jq -aRs .\n```\n\nLet's see what the output of this command looks like for something a little more sophisticated.\n\nHere's an example file:\n\n```sh\ncat example.md\n```\n\n```text\nCurrently not fixable.\n\n_(But you can probably just delete the dir)_\n```\n\nHere's what catting this file into `jq` produces:\n\n```sh\ncat example.md | jq -aRs .\n```\n\n```text\n\"Currently not fixable.\\n\\n_(But you can probably just delete the dir)_\\n\"\n```\n\nNow, we can assemble our final json file:\n\n```json\n{\n    \"name\": \"git\",\n    \"files\": [\n        {\n            \"path\": \"$HOME/.gitconfig\",\n            \"movable\": true,\n            \"help\": \"Luckily, the XDG spec is supported by git, so we can simply move the file to _$XDG_CONFIG_HOME/git/config_.\\n\"\n        }\n    ]\n}\n```\n\nSaving this as `git.json` in the [`./programs/`](./programs/) directory will result in the script picking it up and checking the file.\n\nIf you've created a configuration for a file that isn't in the official repository yet, make sure to create a pull request so that other people can benefit from it as well.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb3nj5m1n%2Fxdg-ninja","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fb3nj5m1n%2Fxdg-ninja","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fb3nj5m1n%2Fxdg-ninja/lists"}