path_helper
Version, currently 1.0.110 versions
github.com/yb66/path_helper
Simple replacement for Apple's /usr/libexec/path_helper
50 stars
0 dependents
License: NOASSERTION
Nothing has been indexed for 1.0.1 yet. The tag is recorded, its shard.yml has not been read, so the manifest and dependency list below are empty because they are unknown rather than because they are absent.
Installation
# Add this to your shard.yml
dependencies:
path_helper:
github: yb66/path_helper
version: ~> 1.0.1Then run:
shards installshard.yml
No shard.yml has been indexed for 1.0.1. You can read it on the repository.
Dependencies
Unknown: the shard.yml for this version has not been read yet.
README
This README is the one indexed from the repository at its latest ref, not from the tag for this version.
# path_helper
## WHAT?
A replacement for Apple's `/usr/libexec/path_helper`.
## WHAT DOES THAT DO?
It helps set the PATH environment variable, among other things.
## WHY REPLACE IT?
Because Apple's one loads the system libraries to the front, which almost certainly isn't what you want. Have a look:
$ /usr/libexec/path_helper
PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
<snip!>
## WHAT ELSE DOES IT DO?
I'm glad you asked. Apple has some good ideas (lots of them, actually) that developers overlook for whatever reason. One of them is the [*framework bundle structures*](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html), but more on that in a moment.
Apple's `path_helper` helps organise the `PATH` and `MANPATH` by listing things you want added to the path in text files in well known locations (e.g. /etc/paths and /etc/paths.d/*) it's easy to create a PATH that works for you. Where the Apple `path_helper` falls down is:
- It puts them in /etc meaning you need elevated permissions
- Being in /etc also makes them system wide
- It's only for `PATH` and `MANPATH` but development and administration often need new installs' headers and libraries accessible in the same way too
- The string it returns is designed to be `eval`'d. I know that `eval` isn't *always* evil but why not just return the `PATH` string and allow it to be set to a variable - maybe there's more to be added? Just a thought.
This library fixes those problems by extending that to:
C_INCLUDE_PATH
DYLD_FALLBACK_FRAMEWORK_PATH
DYLD_FALLBACK_LIBRARY_PATH
and of course, `PATH` and `MANPATH`.
## DO I NEED TO BE ON APPLE TO USE IT?
No, it should work on any unix-like system.
## HOW DOES PATH_HELPER KNOW WHAT TO PUT IN THE PATH?
Apple has put paths in `/etc/paths` and further files are there for the user or apps to add under `/etc/paths.d/`. If you want to order them then prefixing a number works well, e.g.
$ tree /etc/paths.d
/etc/paths.d
├── 10-pkgsrc
└── MacGPG2
└── ImageMagick
The format of the file is simply a path per line, e.g.
$ cat /etc/paths.d/10-pkgsrc
/opt/pkg/bin
/opt/pkg/sbin
$ cat /etc/paths
/usr/local/bin
/usr/local/sbin
/usr/bin
/usr/sbin
/bin
/sbin
The order *within* the file matters as well as the order the files are read/concatenated.
### Note: ###
The `/etc/paths` file in Apple isn't set out fully or in the order I'd want so I changed mine, you may want to do the same.
## Per user paths ##
This is the bit I like best.
There's not really any help made for paths that might be local to the user, like `~/.rubies` or something like that so I've added two places the Ruby script will check for further paths:
- `~/Library/Paths/paths.d` and `~/Library/Paths/paths`, and
- `~/.config/paths.d/` and `~/.config/paths`
You can use the `--setup` to have the path_helper set up the directory layout and files, you just have to fill them!
The Ruby script will also allow use of the tilde `~` character in a path by replacing it with the `HOME` env variable. For example, if I install Haskell and want to put it in my path I can do the following.
### Way 1, Use the paths, Luke
$ echo '~/Library/Haskell/bin' > ~/Library/Paths/paths
$ tree ~/Library/Paths
/Users/iainb/Library/Paths
├── paths
└── paths.d
$ cat ~/Library/Paths/paths
~/Library/Haskell/bin
That puts `/Users/iainb/Library/Haskell/bin` at the front of my path and will only apply to my account's `PATH`.
### Way 2, paths.d/
$ touch ~/Library/Paths/paths.d/60-Haskell
$ tree ~/Library/Paths
/Users/iainb/Library/Paths
├── paths
└── paths.d
└── 60-Haskell
#### Why use the paths.d sub directory?
If I show you my actual set up it'll become clearer:
$ tree ~/Library/Paths
/Users/iainb/Library/Paths
├── paths
└── paths.d
├── 05-pkgsrc
├── 08-homebrew
├── 10-keybase
├── 30-oh-my-zshell
├── 50-ngrok
├── 55-Crystal-opt
├── 60-Crystal
├── 61-Opam
├── 62-Haskell
├── 63-Erlang
├── 63-Go
├── 64-Pyenv
├── 65-Rust
└── 66-Antigen
Once you start installing various things it make sense to keep their paths in their own file, it's easier to organise (and remove).
## The order
Library/Paths/paths.d ordered as the file system does
Library/Paths/paths
.config/paths.d (same again)
.config/paths
/etc/paths.d (same again)
/etc/paths
## Why Library/Paths/paths and not Library/paths ?
Because this is such a useful pattern that I've extended it for headers and includes, read on!
## Man paths and DYLD and C_INCLUDE ##
### Manpaths
Apple has already dictated that `/etc/manpaths` and `/etc/manpaths.d/` are the default paths for setting `MANPATH`, so the same pattern has been followed for that as with `PATH`, so just add `~/Library/Paths/manpaths` or `~/.config/manpaths` along with the `manpaths.d` sub directory if you wish.
- `~/Library/Paths/manpaths.d/`
- `~/.config/manpaths`
- `~/Library/Paths/manpaths.d/`
- `~/.config/manpaths`
- `/etc/manpaths.d/`
- `/etc/manpaths`
### DYLD ###
Same goes for DYLD_FALLBACK_LIBRARY_PATH and DYLD_FALLBACK_FRAMEWORK_PATH (if using the Ruby script):
- `~/Library/Paths/dyld_library_paths.d/`
- `~/.config/dyld_library_paths`
- `~/Library/Paths/dyld_library_paths.d/`
- `~/.config/dyld_library_paths`
- `/etc/dyld_library_paths.d/`
- `/etc/dyld_library_paths`
and:
- `~/Library/Paths/dyld_framework_paths.d/`
- `~/.config/dyld_framework_paths`
- `~/Library/Paths/dyld_framework_paths.d/`
- `~/.config/dyld_framework_paths`
- `/etc/dyld_framework_paths.d/`
- `/etc/dyld_framework_paths`
### C_INCLUDE ###
Same again for `C_INCLUDE`:
- `~/Library/Paths/include_paths.d/`
- `~/Library/Paths/include_paths`
- `~/.config/include_paths.d/`
- `~/.config/include_paths`
- `/etc/include_paths.d/`
- `/etc/include_paths`
(and the `include_paths.d` sub dir too, for the last two if you wish).
## HOW DO I GET THIS WONDERFUL JOYFUL EVENT MAKER INTO MY LIFE? ##
I was going to make this into a Ruby gem but that is such a faff. Here's the gist of it:
- Download it (use `git clone` or a download link, you can even just copy and past the [script](exe/path_helper))
- Make sure it has the correct permissions (`chmod +x`)
- Run the `--setup`
- Copy and paste the bit setup tells you to, and put it in your `~/.zshenv` or `~/.bashenv`
- Find your life is so much better now it's easy to manage your paths
For example:
# I put my path_helper in `/usr/local/libexec` because I'm the only person using this machine
# and I want my other accounts to be able to access its goodness.
sudo mkdir -p /usr/local/libexec
cd /usr/local/libexec
# ~/Projects/path_helper is where I keep the project
ln ~/Projects/path_helper/exe/path_helper .
chmod +x path_helper
# Look at the help because you're not like everyone else, you read instructions ;-)
path_helper --help
# You need sudo to add the folders in /etc, see the --help if you don't want that
sudo path_helper --setup
# See what's already there
path_helper --debug
Apple's path_helper is in `/usr/libexec`, this install won't touch it, you can always use it or return to it if you wish.
And checking its output:
$ path_helper
PATH="/opt/pkg/sbin:/opt/pkg/bin:/opt/X11/bin:/opt/ImageMagick/bin:/usr/local/MacGPG2/bin:/usr/local/git/bin:/opt/puppetlabs/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin"; export PATH;
## NOTE!
The script **doesn't set the PATH**, it *returns* a path, **you have to set the path** with it e.g. `PATH=$(/usr/local/libexec/path_helper.rb -p "")`. Call `/usr/local/libexec/path_helper -h` to see all the options.
## My actual system
$ tree ~/Library/Paths
/Users/iainb/Library/Paths
├── include_paths
├── manpaths.d
│ └── 30-oh-my-zshell
├── paths
└── paths.d
├── 05-pkgsrc
├── 08-homebrew
├── 10-keybase
├── 30-oh-my-zshell
├── 50-ngrok
├── 55-Crystal-opt
├── 60-Crystal
├── 61-Opam
├── 62-Haskell
├── 63-Erlang
├── 63-Go
├── 64-Pyenv
├── 65-Rust
└── 66-Antigen
$ tree /etc/paths.d/
/etc/paths.d/
├── 10-pkgsrc
├── 15-macports
├── 20-XCode
├── MacGPG2
├── go
└── mono-commands
## You know what else is helpful?
The --debug flag. For example:
$ exe/path_helper --debug
Path | Found in | Ignored duplicate
---- | -------- | -----------------
/opt/pkg/bin | ~/Library/Paths/paths.d/05-pkgsrc |
| /etc/paths.d/10-pkgsrc | ✗
/opt/pkg/sbin | ~/Library/Paths/paths.d/05-pkgsrc |
| /etc/paths.d/10-pkgsrc | ✗
/opt/pkg/gnu/bin | ~/Library/Paths/paths.d/05-pkgsrc |
~/homebrew/bin | ~/Library/Paths/paths.d/08-homebrew |
$HOME/gopath | ~/Library/Paths/paths.d/10-keybase |
$HOME/gopath/bin | ~/Library/Paths/paths.d/10-keybase |
~/.oh-my-zsh/custom/plugins/fzf/bin | ~/Library/Paths/paths.d/30-oh-my-zshell |
~/Applications/ngrok | ~/Library/Paths/paths.d/50-ngrok |
/opt/crystal/bin | ~/Library/Paths/paths.d/55-Crystal-opt |
/opt/crystal/embedded/bin | ~/Library/Paths/paths.d/55-Crystal-opt |
~/Library/Frameworks/Crystal.framework/Versions/Current/bin | ~/Library/Paths/paths.d/60-Crystal |
~/Library/Frameworks/Crystal.framework/Versions/Current/embedded/bin | ~/Library/Paths/paths.d/60-Crystal |
~/Library/Frameworks/Opam.framework/Programs | ~/Library/Paths/paths.d/61-Opam |
~/Library/Haskell/bin | ~/Library/Paths/paths.d/62-Haskell |
~/Library/Frameworks/Erlang.framework/Programs | ~/Library/Paths/paths.d/63-Erlang |
~/go/bin | ~/Library/Paths/paths.d/63-Go |
~/.pyenv/bin | ~/Library/Paths/paths.d/64-Pyenv |
~/.cargo/bin | ~/Library/Paths/paths.d/65-Rust |
~/bin | ~/Library/Paths/paths.d/66-Antigen |
/opt/local/bin | /etc/paths.d/15-macports |
/Library/Developer/CommandLineTools/usr/bin | /etc/paths.d/20-XCode |
| /etc/paths.d/20-XCode |
/usr/local/MacGPG2/bin | /etc/paths.d/MacGPG2 |
/usr/local/go/bin | /etc/paths.d/go |
/Library/Frameworks/Mono.framework/Versions/Current/Commands | /etc/paths.d/mono-commands |
/usr/local/bin | /etc/paths |
/usr/local/sbin | /etc/paths |
/usr/bin | /etc/paths |
/usr/sbin | /etc/paths |
/bin | /etc/paths |
/sbin | /etc/paths |
Current:
/Users/iainb/.gem/ruby/2.6.3/bin:/Users/iainb/Library/Frameworks/Ruby.framework/Versions/2.6.3/lib/ruby/gems/2.6.0/bin:/Users/iainb/Library/Frameworks/Ruby.framework/Versions/2.6.3/bin:/Users/iainb/.opam/4.06.1/bin:/Users/iainb/perl5/bin:/opt/pkg/bin:/opt/pkg/sbin:/opt/pkg/gnu/bin:/Users/iainb/homebrew/bin:$HOME/gopath:$HOME/gopath/bin:/Users/iainb/.oh-my-zsh/custom/plugins/fzf/bin:/Users/iainb/Applications/ngrok:/Users/iainb/Library/Frameworks/Crystal.framework/Versions/Current/bin:/Users/iainb/Library/Frameworks/Crystal.framework/Versions/Current/embedded/bin:/Users/iainb/Library/Frameworks/Opam.framework/Programs:/Users/iainb/Library/Haskell/bin:/Users/iainb/Library/Frameworks/Erlang.framework/Programs:/Users/iainb/go/bin:/Users/iainb/.pyenv/bin:/Users/iainb/.cargo/bin:/Users/iainb/bin:/opt/local/bin:/usr/local/MacGPG2/bin:/usr/local/go/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin
If you expected items you'd inserted in the path manually to
show up earlier then either clear the path before running this
and reinsert or add paths via:
(~/Library/Paths|~/config)/paths.d
(~/Library/Paths|~/config)/paths/*)
/opt/pkg/bin:/opt/pkg/sbin:/opt/pkg/gnu/bin:/Users/iainb/homebrew/bin:$HOME/gopath:$HOME/gopath/bin:/Users/iainb/.oh-my-zsh/custom/plugins/fzf/bin:/Users/iainb/Applications/ngrok:/opt/crystal/bin:/opt/crystal/embedded/bin:/Users/iainb/Library/Frameworks/Crystal.framework/Versions/Current/bin:/Users/iainb/Library/Frameworks/Crystal.framework/Versions/Current/embedded/bin:/Users/iainb/Library/Frameworks/Opam.framework/Programs:/Users/iainb/Library/Haskell/bin:/Users/iainb/Library/Frameworks/Erlang.framework/Programs:/Users/iainb/go/bin:/Users/iainb/.pyenv/bin:/Users/iainb/.cargo/bin:/Users/iainb/bin:/opt/local/bin:/Library/Developer/CommandLineTools/usr/bin:/usr/local/MacGPG2/bin:/usr/local/go/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin%
Everything you need to know! Very useful for working out when other things are manipulating the path too.
## Development
I'm happy to hear from you, email me or open an issue. Pull requests are fine too, try to bring me a spec or an example if you want a feature or find a bug.
Sorry the current specs aren't in such good shape, I hope to improve that.
## Licence
See the LICENCE file.
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This release
- Version
1.0.1- Tagged
- Nov 26, 2025
- Commit
2495840dee14- Indexed
- not yet
Dependents
No indexed shard depends on this one yet.
Repository
github.com/yb66/path_helper
Metadata
- Created
- Aug 12, 2026
- Updated
- Aug 12, 2026
- Synced
- Aug 12, 2026
- Versions
- 10