Skip to content

Proposal to Simplify OH-MY-ZSH #377

sorin-ionescu opened this Issue May 30, 2011 · 87 comments

Organising code inside of OH-MY-ZSH is becoming unnecessarily complex. For a while, there has been the /custom directory to dump files that override or append to the functionality of /lib, /plugins, and /themes.

Then the ability to override /plugins via /custom/plugins was added (#89). Now, a new proposal has been submitted to allow the overriding of /themes (#376) and /lib (in the comments to #376) via /custom/themes and /custom/lib respectively.

Additionally, there is the /functions directory (b865f2a) for dumping miscellaneous functions and the /completions directory (#351) for dumping miscellaneous completions.

These directories are unnecessary for we already have a software configuration management (SCM) tool called Git. We should use Git exclusively.

I propose that we get rid of /custom, and edit /lib, /plugins, and /themes directly. We also get rid of /functions, and /completions to encourage the creation of plugins instead of dumping random code in those directories.

Pulling updates while retaining customisations is easy by recursively merging conflicting hunks by favouring our version.

git pull --no-commit --strategy=recursive -X ours robbyrussell master

Updates should always be checked for dangerous code (rm -rf /). Hence we use pull --no-commit to stop Git from auto-committing to let us check the files even when there is a clean merge.

git status
*** Check the files listed. ***
git commit

Lastly, if we use Git exclusively, the /tools directory becomes unnecessary and should be removed.

Keep It Simple!

vguerci commented May 31, 2011

I mostly agree with this, KISS ftw.

The only opposable argument I see to this is that using git is less "user-friendly" than dropping a file to "custom".
But this is a reasonable assumption that people wanting to "override" plugins has the git skills required...

About the /tools I'm not sure about, the installer could be moved to a gist, the uninstaller is not that important, but I like the auto-upgrade feature... Hmm could it be extracted as plug-in? (Fyi, I use a local branch with a modified autoupdate, which shows diff stats and then rebase, every day)


The SHELL is not user friendly. We do what we can to mitigate 40 years of baggage. Responsible users keep their dotfiles under version control. In my case OMZ is a submodule which points to my fork. So, whether a file with new functions is dropped into /custom or new functions are appended to /lib/functions.zsh, either operation must be committed. What is not easy is not learning version control and having the changes go 'POOF!' There is no fun in writing déjà vu code.

Yes, the installer can be moved into a Gist, and auto-upgrade can be moved into a plugin. In any case, auto-upgrade only reliably works if the core is never modified for no chance of merge conflicts to arise, and the core has not changed significantly to break code in /custom, /functions, and /completions.

I have never used the upgrade script. Since I write plugins and fix OMZ, I have rarely have had a non-eventful manual upgrade.

You cannot use rebase if you want to share your OMZ fork. You have to merge.

I am almost done creating a simplified OMZ for my own use.



I'm of the opinion that there are different user groups of ohmyzsh. There are people who wouldn't lose any sleep if their zsh config disappeared... and they had to start over and there are those who are much more invested into their custom configuration. I'm not sure who ohmyzsh is entirely best fit for. In many ways, I see it as a huge stepping stone from a stock zsh configuration to something easy to get going more than I see it as a tool for advanced users.

Having said that... could ohmyzsh be organized in a way to help lead people through the novice to "expert" phases? Definitely... where do I want OMZ to focus it's attention? On the early adopter/novice phase. I want to keep that initial process as easy/simple for someone to get going. As people want to customize/optimize... I think there is a lot we can do to facilitate that journey, but want to make sure this project honors our novices as first class citizens.

The experts don't need this project as much. Once we start getting into more complicated git configurations... we could start to overwhelm novices (and myself for that matter). I'm hardly a git expert and would want to see OMZ provide useful scripts to handle a lot of the proposed features. Perhaps we can chat further once I see how you've setup things in your simplified version and we can share some thoughts together.

A former novice

gutenye commented Jun 6, 2011

I love the idea. where can I give a try and report issues?

meh commented Jun 6, 2011

+1 on this, just make some wrapping scripts for noobs and everyone's happy.

giddie commented Sep 19, 2011

I like this very much; I already maintain a personal fork with modified libs & plugins for use on several machines. I do use the custom directory, but it's for aliases or tweaks that are specific to that account / machine. I wouldn't really want to lose that, but I see no need for a custom plugins or function directory, as I modify the standard ones in my fork.


see also #79 where I introduced a git approach

jedahan commented Jan 26, 2012

Sorin's fork works very well so far, @robbyrussell what set of feature coverage would you ideally want before reconsidering his approach? Even better if you could list the most important first. I have already implemented a rough upgrade plugin that works similarly to the current upgrade_oh_my_zsh() and submitted to zsh-syntax-highlighting support for the fork's method of plugin loading.


I intended to write an extensive post documenting all the changes. I wanted to commit a few more changes before announcing that I have pushed my fork to GitHub for public scrutiny, but @jedahan found it first.

vguerci commented Jan 26, 2012

Only that! Good job :)


looking forward to the extensive post though. :)

jedahan commented Jan 26, 2012

Ahh sorry for busting the door open before the table was set @sorin-ionescu !


My OMZ fork has been seven months in the making. I have started it because OMZ has a very bad reputation with the Zsh developers because users join #zsh on FreeNode to whine that something is broken.

Shell scripting is hard; it has 40 years of baggage. Not to mention, most of the code on the Internet is full of bashisms. While said bashisms may be supported, Zsh is closer to KSH than BASH, and it often has a more efficient way of completing tasks than BASH.

A large portion of OMZ has been copied/pasted and assumed to work. While a pull request may work or half-work for a submitter, it may not work for everybody. A green 'this pull request can be automatically merged' bar is not enough to accept a pull request.

@robbyrussell has asked for help in the past. This is it.

While I do not have a scientific metric, probably 90-95% of the core (what used to be /lib) I have thrown away and rewritten. Plugins have also been cleaned up, have had portions rewritten, or in some cases removed.

I encourage you to go through all files and compare my fork with the original as well as reading the Git log.

$EDITOR **/*~(completions)/*(.)


Pulling updates while retaining customisations is easy by recursively merging conflicting hunks by favouring our version.

not sure if that's a good idea. I think for each merge conflict, you should just look at your own changes and the upstream changes and figure out which make most sense. Sometimes you want to keep your own changes, sometimes you want the upstream version, sometimes a bit of both. It's impossible to say in advance.

2) merge conflicts are not a "bad thing which must be avoided at all costs". see my detailed explanation @ #79 (comment)

3) OMZ has AFAIK never had a policy which explains how things should go, maybe we should make a list of rules for our version, such as:

  • leverage git, don't use 'custom' directories and the likes, encourage git branches and "the right way"
  • prefer (highly commented) zsh code over bashims and posix-isms where they make sense.
  • prefer opt-in features over opt-out. especially for things which may not be beneficial for everyone. (examples: i strongly dislike some default things like bindkey -s '\e.' "..\n" and the time output for commands which take a bit longer, I also don't like how plugins pollute my alias namespace with aliases I'll never use)

Pulling updates while retaining customisations by recursively merging conflicting hunks by favouring our version is the only way for auto-update to work if such functionality is to be added. Personally, I do not like auto-update, but I do have a branch where I am toying with an implementation.


  • I have cleaned up and organised OMZ by using a non-written list of rules.
  • I leverage Git over a directory hierarchy.
  • I prefer Zsh code over bashims. I have added comments where appropriate, but I do not have a high comment density.


  • An opt-in system would make configuration and implementation overly complicated. OMZ should provide sane defaults. If you do not like a particular set of key bindings nor aliases, edit or delete them. I do not think that I have that particular key binding nor have I defined a particular time format. Have you actually read the code or used my fork?
  • high comment density is my suggestion not because of ideological goals, but merely because I assume most people trying to hack on [your fork of] OMZ aren't that experienced zsh scripters. high comment density may get in the way of experienced contributors, but the gates it opens for other people to more easily get involved should be worth it.
  • if with autoupdating you mean "starting the update process automatically" and "deal with all conflicts automatically", that just cannot work, period. Both with the standard OMZ methods (different files in custom dirs), as well as with the improved git method, if a user changes a certain behavior/functionality, and upstream changes that same bit as well, it's just impossible to automatically know which version should be preferred. The user is the only person who can know and manual intervention is needed. manual intervention should happen, it's the only right way and it makes no sense to try to avoid it.
  • I started using your fork now, the examples i gave are with robby's version.
  • I agree there should be sane defaults. Let's just try it your way and if I encounter anything I consider insane, I'll shout.

Feel free to add comments where needed and open a pull request. Be forewarned that I am a grammar Nazi. :)



I notice that your fork of OMZ doesn't have all of the plugins currently available for OMZ. What would be the best way of including some of my favorites, like extract (ironically enough, something that you wrote), using your fork?

Would it be as simple as copying over the plugin and renaming the file to be loaded to 'init.zsh'?


@cruser Rename old plugins to init.zsh. The names of the plugins are deceiving. Some plugins have been renamed while others have been merged. A few were indeed deleted. extract is there under archive.


@robbyrussell @eddorre Have you had a look at this?


I've switched to sorin-ionescu's version on two machines and so far so good. It definitely feels a bit more responsive.

my two cents.


@sorin-ionescu's fork fixed some weird issues with oh-my-zsh, tmux and OS X.


@sorin-ionescu (and fans of his fork)

I've taken a few, brief reviews of your branch to see what sort of major differences I could spot. In general, I'm liking the direction that you're trying to take this with regard to introducing a slightly more zsh-esque approach to configuration. This definitely isn't an area that I'm strong at and have relied on the community to help evolve off of my initially offered toolset.

Having said that, I have a number of small concerns that would need to be addressed before I could fully accept the changes, which I think we can work together on.

Taking a quick step back, I want to be re-state/clarify my position on the "philosophy" behind OMZ from my perspective.

1 - Needs to be amazingly simple to get going

oh-my-zsh needs to be focused on helping people adopt zsh as easily and painless as possible. We should assume that an overwhelming majority of people who use OMZ will be coming from bash/sh and this will be the first introduction to zsh. We shouldn't assume that they:

a. know git
b. know too much bash/zsh/sh (they've probably barely scratched the surface here)

Knowing these are nice-to-have, not pre-requisites. I want to take care of these people, first and foremost. OMZ needs to hold their hand as long as we can. When they feel comfortable to run further ahead (advanced shit), we can try our best to accommodate.

2 - Auto-update will be, by default, on

While I agree that we don't want everything to be opt-out, I do feel like auto-updating should be, by default... on. I may want to reconsider how often it auto-updates though. Personally feel that once a week, is too often at the moment. This is a great way to ensure that most people are getting performance updates and bug fixes. We've received a lot of positive feedback about this feature and would like to keep it around.

People can opt-out, if they find it unnecessary.

People shouldn't have to review every change upon update. Those who care enough to check all that out, can opt-in. Again, most people aren't going to be config/zsh/git experts... so let's not throw stuff in front of them that'll they'll be thinking, "wtf am i looking at?"

3 - It needs to ship with a healthy collection of community developed themes and plugins

I don't think we've figured out where the sweet spot is here. It's not 5, it's not 100... it's somewhere in between. As you'll have seen over the past few months, I've stopped auto-accepting new themes until I can sort this out. We're going to introduce a new approval process where people will need to get enough votes from the community for it to get merged into my master branch. Details to come on this front.

Plugins, on the other hand, I don't think we've hit that "too many" point yet. We definitely could though, so suspect we'll likely introduce a similar approach as we do with themes.

I would like to keep the base install full of awesome goodies for people to choose from. I really want to avoid breaking themes and plugins out of the main repository... as I feel like that will just make it harder for people to use the damn thing. (back to point 1, I don't want people to need to know how to use slightly more complicated git features in order to load a plugin for their shell). I also don't want to have to manage multiple repositories (ie., a oh-my-zsh-themes and oh-my-zsh-plugins repos)... that just sounds messy.

4 - It needs to stay/feel fun for people

At the end of the day, oh-my-zsh should be taking some of the pain out of sitting in front of terminal screens each day. Each time we consider introducing more complexity, features, instructions... if it's not simple and friendly... with a dash of fun... then it has no place in the project. I want to be crystal clear on this point. If it's not fun/engaging/friendly... then what's the point? There's plenty of boring zsh documentation for people to dive into if they want to do their own thing.

Having said that... that doesn't mean that we can't find a healthy middle-ground. I definitely don't want to be frustrating the zsh experts with people who are hitting odd problems from time to time with this project. I appreciate that you've taken it upon yourself to try and pull OMZ closer to that realm... and in response, I'm happy to outline some thoughts on how we might get to where we both want to be.


Having had some time to think over stuff, I feel like your branch calls for a version bump. It's not entirely backwards compatible and I don't want to cause problems for people who are content/happy with how things work today.

Let's take a quick walk down a possible plan... (as I see it so far)

We create a v2 branch (name TBD) that is based off of your branch. Within this branch, I'd like to see the following:

  • A simple installation path for people. We can modify our install script to run things behind the scenes. I don't want people to need to copy/paste git commands... if they want to know what is happening, we can provide a link to that file in the installation documentation.
  • A community-driven effort to update a bunch of their favorite themes to work with v2. We'd automatically accept any themes that were updated prior to the official release date.
  • Figure out how we'll update/upgrade people in a seamless fashion. Given that we don't have an easy way to interact with all of our users without the auto update feature, I think we'll need to get creative about how we interact with people here. We could, one week, release an update for the update script... so that the next week, it'd prompt them to upgrade to 2.0. (again, think we need to get creative here for how we can help thousands of people migrate without a lot of headaches)... to be discussed further.
  • Ensure that most of our plugins are ported. (if people are using plugins that don't get ported, we need to let them know somehow)

Further to this, can you (@sorin-ionescu) writeup an overview of how you, currently, see the workflow for someone who wants to do more advanced things based on your branch/approach? (ie., have their own plugins/custom configuration)

So, yes, I would welcome this approach, but we'll need to tackle some of the warm and fuzzy stuff prior to rolling it out.

In short, oh-my-zsh needs to be extremely simple to use out-of-the-box... fairly simple to maintain and customize.

Would love to hear your thoughts here...


@robbyrussell robbyrussell was assigned Mar 6, 2012

We'll sit on this until we hear back from @sorin-ionescu



You wrote over 1000 words. So, it's only fair that I write 2000. I kid. I kid. :)

I wrote a response to this last week, but I still have to spell, grammar, and diction check it. It's always better to wait a few days to parse the words on the screen, not the ones in short-term memory.

I'll post it later this week.


...wouldn't expect anything less!


How about creating a omz github organization to evolve from 1.0 to 2.0?


@acasajus, @paulmillr We have a zsh-users organisation. I would not call it toxic, but I would also not call it absolutely needed.


Oh My Zsh Next

@robbyrussell, in the following text, I will address your version of Oh My Zsh as OMZ Robby and mine as OMZ Sorin.


I absolutely agree that it needs to be simple. I am a Mac user. I do not like complicated things.

OMZ Sorin has been simplified a lot through the removal of an abundance of directory hierarchies for code and the merging or removal of duplicate plugins and themes. Furthermore, completion plugins have been removed in favour of @nicoulaj's zsh-completions project.

However, a minimum level of user knowledge is still expected to use this project. It will never be point-and-click.

Users not knowing Git can be easily addressed through Git wrapper functions or scripts.

Users not knowing shell scripting is not as easily addressed. The majority of the noise in #zsh on Freenode is generated by OMZ users complaining that something is broken and that they do not know how to fix it.

OMZ Robby is broken by me too pull requests from people who do not know enough Zsh, or for the matter, enough shell scripting. Often, the offending code is introduced through a copy-paste from a blog or a wiki without comprehension nor knowing its full consequences.

Bad pull requests have to be rejected even if it hurts people's feelings. One person may feel good that his pull request has been approved but then 50 complain that OMZ is broken.

OMZ Robby fails the requirement to be simple because the installation script requires Git. Mac OS X does not come with Git by default; so, it fails to install. The installation script should use curl (Mac) and wget (Linux). I like how Pow handles this.

OMZ Sorin fails the requirement to be simple for not having an installation script at all, which can be added, but, in order to do that, the completions submodule may have to be changed to a subtree since GitHub does not include submodule content in the generated archives in Downloads. I have emailed @github support to ask them to remedy this problem.

Auto Update

I do not like auto updating because it is very easy to sneak in obfuscated code in the initial pull request of a massive plugin or completion that will steal passwords or files. Zsh has a built-in interface to low-level system features, a built-in FTP client, and it supports the manipulation of TCP sockets. These features are documented in man zshmodules.

Completions are reviewed by @nicoulaj in his zsh-completions project. The OMZ project should only have to review plugins.

Being aware that some people, including you, want auto updating, I am toying with a simple implementation in the module-update branch.

However, very few people know how to use git reflog or git reset to return to the previous commit after an update. An OMZ culture based on the if it ain't broke, don't fix it principle should be developed because there is a probability of it being broke after fixing it.

If auto updating is ultimately added, I strongly advocate that it should be turned off by default. Those who want it will see its settings in zshrc and turn it on.

It only takes one security incident before there is a plethora of OMZ Considered Harmful posts on Hacker News and the blogosphere.

Themes and Plugins

Converting themes from OMZ Robby to the Zsh native format used by OMZ Sorin is time consuming. Thus far only 4 themes I like have been converted. However, there are, at the time of this writing, 20 themes in OMZ Sorin, not 4. Zsh is shipped with 16 themes.

Themes can be listed with the following command.

prompt -l

In OMZ Robby, many themes are broken because of missing scripts and the assumption of certain plugins being loaded. Many themes are also repetitive, meaning, they are identical to other themes with only a colour change. With the exception of a few popular themes, the rest are just used by their authors and no one else.

With the native Zsh theming system, repetitive themes need not exist since the prompt command accepts arguments that in turn will be passed to the theme setup function. Themes can be written to accept colours when initialised.

prompt adam2 green blue white

Such themes should define a help function to inform the user on how they need to initialised.

prompt -h adam2

Though some are advocating the splitting of plugins and themes into their own repositories, I have never done so. Instead, we should not merge anything that will be used by just one or two people.

We must avoid including the kitchen sink.


OMZ can be more frustrating to beginners than advanced Zsh users (experts do not exist) since they do not know how to fix whatever is broken.

If we are careful of what we merge in, and OMZ just works, the project should be satisfying to both camps.

Sometimes, I comment on a pull request to inform the contributor that there is a better way to write a particular piece of code. The reply is positive, the author is thankful and makes the changes I recommend or informs me that while my recommendation is good, it will not work in all instances, and I adjust accordingly. There is fun in learning.

Asking contributors to respect the coding style or to write comments in complete sentences does not kill the fun, but it does keep frustration away when trying to fix broken code.

Moving Forward

Since the zshrc is no longer compatible, it absolutely calls for a version bump. Ever since I have switched to zstyle, I have always known that my fork will either be OMZ v2.0 or a competing project.

We should not make a TBD branch:

  • It will have less exposure. It is much harder to install a branch. People will have to learn GitHub to switch branches or tags before clicking the download button. Those who know Git will have to remember to switch away from master to the TBD branch. The installation script will have to know of TBD to fix all the aforementioned problems, which is a needless complication.

  • We do not want v2.0 issues mixed in with the hundreds of v1.0 issues. It will make development harder.

  • Git is bad at switching branches that have diverged a lot. It leaves files and directories behind that are listed as untracked.

It is much simpler to add a link to this issue and to my fork at the top of your README and to inform users that it is v2.0 and whomever wants to test it before it is merged into master should do so.

There should be a community-driven effort to update themes, but updated themes should be up to a vote for re-inclusion. The first theme pull request in my fork was broken from the start by missing a battery script dependency and containing unused code. No theme should be auto-accepted.

A script that will update OMZ from v1.0 to v2.0 will ultimately fail no matter how creative we are. We have no control over what people put in their .zshrc. The best we can do is to rename the current .zshrc to .zshrc.v1.bak and .oh-my-zsh to .oh-my-zsh.v1.bak, copy the new template .zshrc to ~/.zshrc, and inform the user of the change. Even Apple, who have a draconian control over their software and hardware, which we do not have, fail their upgrades often. Hoping for anything other than the above, I believe, is wishful thinking.


There is no special workflow. Anyone who wants to customise OMZ Sorin should do so in place. The update function or script, if integrated, will not overwrite local changes. A manual update, however, will require the usage of the following Git command to avoid manual merges.

git pull -s recursive -X ours remote branch

The above command tells Git to pull using the recursive strategy (default), but if there is a conflict, to favour the local version and continue. The user will never have to manually resolve conflicts. Of coarse, if the user prefers the upstream, he should use -X theirs instead of -X ours, and Git will favour the remote version. He who knows how to merge conflicts should use the classic command.

git pull remote branch

It would be helpful if you make time for a thorough review. Switch to OMZ Sorin for a week and merge your personal changes. That way you will get a feel for how it works.


For everyone like me to whom this was not obvious, you may need to update like this:

git pull -s recursive -X ours remote branch
git submodule update

I just updated sorin/oh-my-zsh without the above command and started running into autocompletion errors until I executed git submodule update because I had the old, broken, upstream code in my submodule directories.


You have to restart your shell after an update.

Update submodules with git submodule update --init --recursive or gSU if you have the Git plugin enabled.


Guys, what about startup speed, can it be somehow tweaked in 2.0? I'm using nehalem 2.4ghz and it takes up to 15 seconds to launch new tab with oh-my-zsh. And there are not many plugins loaded.

zstyle ':omz:load' plugin 'archive' 'git' 'node' 'osx' 'python' 'ruby' 'z'


It only takes 1-2 seconds on my system. Add zmodload zsh/zprof at the top of your zshrc and zprof at the bottom. See where it's slow.


It seems that it's slow on compinit / compaudit. Also this (slow loading) occurs only sometimes.

num  calls                time                       self            name
 1)    2        3366.81  1683.40   94.68%   3366.81  1683.40   94.68%  compaudit
 2)    1        3480.64  3480.64   97.88%    113.84   113.84    3.20%  compinit

 2)    1        3480.64  3480.64   97.88%    113.84   113.84    3.20%  compinit
       1/2      3366.81  3366.81   94.68%      0.83     0.83             compaudit [1]


       1/2      3366.81  3366.81   94.68%      0.83     0.83             compinit [2]
       1/2      3365.98  3365.98   94.66%   3365.98  3365.98             compaudit [1]
 1)    2        3366.81  1683.40   94.68%   3366.81  1683.40   94.68%  compaudit
       1/2      3365.98  3365.98   94.66%   3365.98  3365.98             compaudit [1]

Have you or your distribution added massive completions? In any case, this is not the place to discuss this. Open an issue in my fork.


Right, sorry, opening.

nsp commented Mar 16, 2012

Just throwing this out there: OMZ 2.0 could be called my-zsh, because it's 'my zsh configuration'

iandol commented Mar 29, 2012

As someone who only ever uses git to simply pull stuff to consume off github (I use another dCVS), I really hope wrappers will be simple to use or documentation provides the minimum to get going. OMZ has so far been very helpful to me and I think many others who are not zsh ninjas, I hope it still will retain the path of least resistance to get people who may not be git gurus to try out zshtopia from bashlandia...

homebrew as an example runs off git, but it is so well abstracted that the end user doesn't need to be a git user. I hope OMZ can keep that same balance...


@iandol There will be a balance.


Due to recent discussions (#23) about what should be in the core and should be in plugins, I'm working on a completely modular (rebased often) OMZ.

  1. You do not want aliases? Don't load it.
  2. You do not want utility functions? Don't load it.
  3. You do not want key bindings? Don't load it.
  4. You do not want environment variables? Don't load it.
  5. You do not want prompt themes? Don't load it.

My idea of what are essential modules may not be your idea of what are essential modules. However, for those who like my idea of what should be considered essential modules, there will be a core meta-module that will load the rest.


@iandol I agree and I think that at some point having OMZ bundled and installed from package managers could be a nice solution.


+1 for autoupdate turned off by default
+1 for treating OMZ as dotfiles to customize: a good starting point but fork it, customize it to your liking in your own repo, and pull/cherry-pick larger fixes or features you like from upstream. Your dotfiles are very personal thing.

Maybe a thorough README or wiki outlining a suggest git workflow to pull and cherry-pick from upstream would keep less experienced git users happy. Or taken a step further wrappers or aliases that run the git commands for users.

giddie commented Mar 31, 2012

I'd actually like to see at auto-update feature available, though. I'd like the feature so that when / if I install my OMZ setup on the CLI of friends & family, they can get updates that I push to my repo with a simple keystroke.


That's what I did with my fork : contains my custom files and is a plain copy of the original repo (sorin's) (there are branches for new features/themes but that's it)

But that's where there is a huge difference in opinions. @sorin-ionescu wants OMZ to be modified in place, so you don't need to maintain those files and it's "easier" for you to customise your config.

I prefer to have a "vanilla" OMZ and do everything that's related to my configuration in my own files.

So far you can use both solutions, depending on what you prefer, and there is no official policy (except what @sorin-ionescu said) on what is the best way to deal with that.

I try as much as I can to keep things clean in OMZ so my way of doing things still work. There are some slight issues though. For example the way $path is handled forces me to declare $path in my .pre.zshrc and my .post.zshrc.


OMZ Sorin is now fully modular. Load what you need. Ignore what you don't. Please help with module documentation. See osx and tmux modules README examples.

saimn commented Apr 10, 2012

@sorin-ionescu I just switched to your repository and It is really great ! The only criticism I can made is that you have changed git aliases. It is quite confusing as I am used to gcm (checkout master), gst (status) or gba (show all branches). I understand your logic for naming aliases but IMO it would be better to keep old aliases.


@saimn you can either override the aliases in your .zshrc (or another custom file, that's what I would do), or simply rewrite the git module for your needs (that's what @sorin-ionescu would do).

saimn commented Apr 10, 2012

sure I can do that, but I think that it would be better to keep the compatibility with robbyrussel's branch for these kind of things, it will be less disturbing for OMZ/git users. (this may also be true for other plugins, I don't know).


@saimn OMZ Sorin is a fresh start. It has been rewritten almost from scratch. I will not add the old Git aliases.


Quick update to everyone. Been focusing on some business stuff lately (travel and such)... so this has been on the backburner. I'm still due to follow up with @sorin-ionescu at some point. As far as next steps... we're disagreeing on the auto-update functionality, so that has ramifications. Regardless of whether it's the less popular approach. it's the approach that I'm going to insist upon for the time being. (for the reasons I outlined previously)

We'll catch up on pull requests for 1.0 OMZ in the near future and continue to see how we can bridge @sorin-ionescu's work into my branch as he's done a lot of great work.


OMZ should ship only the core plus a reduced number of essencial plugins/themes which can be consistently maintained by the people in charge. This allows pull requests to be reviewed thoroughly taking care of the security issue, making it less dangerous to (auto)update OMZ.

All the other themes/plugins should be maintained by their creators in their own repositories, be collected on a central gallery (with voting/download count), and be installable with the help of a utility (pretty much like, for example: homebrew, npm, sublime package manager or adiumextras)

This would increase the fun of it, and distribute the responsibility of the code maintenance and quality by more people.
At the same time users could chose which plugins are worth of being installed and create alternative plugins for those who suck, letting them be voted/downloaded by the people who appreciate them. Don't like those git aliases? Create you own and share them in the gallery, allowing other people to enjoy them and vote.

This is a better model then having to issue a pull request to the main OMZ repository in order to change/modify the code of a plugin/theme, leaving the decision of merge in the hands of a reduced number of people who are not the original creators of that particular plugin, possibly hurting the intent and vision of the original creator of the plugin. Or not doing it at all, labeling useful changes as personal customizations (possibly keeping "diamonds" away from the community).


@aristidesfl It's exactly what this post is about, and what @sorin-ionescu's fork does. If you want your theme you can keep it on your fork. If you want a custom plugin, go ahead and create your own.

The upsteam version only contains essential plugins and common plugins (git, osx, screen/tmux), plus a few themes (3 or 4).

Regarding the package manager idea, I'm not so sure that OMZ is (or will be) big enough to require this kind of technology, and it would be really painful to add this kind of tool to a simple shell configuration (after all, that's what OMZ is).

Actually, I'm not even sure that there will be a lot of plugins that don't only consist of a few aliases, and aliases are most of the time only used by their author, so even the gallery idea is (IMHO) already too much.

And themes are, most of the time, identical to another already existing theme, with a few colour changes or different symbols for VCS statuses. So unless it's a radically different kind of theme (in which case it could/should be included in the upstream repo), there is no need to "show it to everyone".

And finally when it comes to the actual interesting plugins, we try on OMZ2, to keep files mentioning the author(s) of the said plugin so they're always in the loop whenever a modification to the plugin is done.


@robbyrussell I kind of agree with @sorin-ionescu on the auto-update system. Recently his fork had a major change which implied a mandatory modification of the .zshrc file, and auto update wouldn't have taken care of that and could possibly have make ZSH unusable. (And basically if you intend at some point to merge @sorin-ionescu work in your repository, the current auto update will make a huge mess for everyone).

Without even mentioning potential security issues and conflicts with the upstream, a blind auto-update could lead to serious issues and unexpected behaviour when plugins are renamed/removed/merged (so unsync'd with the .zshrc configuration).

Basically there are different kind of users, but in the most common ones we have:

  • one time users, which will download OMZ just to have a basic configuration and that's it. So basically they don't need auto updates because they only needed a "better than the default" configuration and updating it won't change anything.
  • I want a template for my configuration users, as their name state, they only want a template for their configuration so they can customise their settings based on an actual configuration. They will probably be the most interested in the auto-update system, but unfortunately, this means that if a conflict happens during the update they will have to deal with it. So it's not really an auto update but a "fetch and attempt to merge" with the possibility of it not working and the OMZ configuration left as-is. In their case, if some options have changed in the plugins they're using they won't notice until OMZ does unexpected things.
  • "Advanced user", basically they're already up to date, and the auto-update is just a PITA for them.

Of course some people will prefer to have an auto-update (mostly because they're not aware of the danger of the said auto-update) and to satisfy them @sorin-ionescu is making an auto-update module. So if you're really sure you want to risk issues with updates, you can use an auto-update system. But, I think this module should be disabled by default, maybe commented in the zshrc template with a link to the of the auto-update module explaining the potential danger of auto-update in OMZ, this way OMZ developers aren't responsible for any issue due to auto-update.


I agree with @robbyrussell on the auto-update issue: it should be there for casual users (such as myself) so that they are up to date with the latest "goodness" and bugfixes of OMZ. I think the security issue here is overrated.

I also prefer the /custom folder over editing the OMZ files directly. Now I am aware that OMZ is in essence "just" a configuration of ZSH so the fact that OMZ has its own configuration gives two layers of configuration. (You configure OMZ which in turn configures ZSH)
But I think OMZ should be considered as an "app" or library in itself (which is what it feels like right now) and hence should have its own means of customization (the /custom folder). This "app" feel is exactly what makes OMZ easy and understandable for newcomers right now.

The Janus project explicitly discourages configuration through customization of the Janus source itself which I think is the sane choice for OMZ as well.



What good does it do to have the late "goodness" if you don't know what it is?
With auto updates you receive things on your machine and have no idea what changed or what new tools there are.
Potentially they could be performance improvements, true, but what about unexpected behavior, bloat and malware?


The customization issue it's a harder decision imo.

Directly in the source

You take advantage of OMZ's topology to introduce customizations in a organized fashion in the places where they belong. For example, if you want to add/modify some aliases for git you would make them on the git module, next to other git stuff; and so on.

Imo the bigger, and perhaps only advantage of this, happens when updating OMZ: if changes are introduced in the same place you made some customizations, you get a merge conflict, and that's good because they are probably modifications about something you really care about (otherwise wouldn't have customized), and probably want to review to make sure they are not silently overridden or breaking something.

Separate File

You get separation. You don't have all your changes spread all over OMZ, something which would introduce complexity and overhead to perform most of the operations. The customization is faster and maintenance is lower.

You can use other VCS than git to maintain and backup your customizations, or no VCS at all. The entrance cost is lower for unexperienced users, but, on the other hand, if you don't know how to use a VCS, maybe you don't need zsh in the first place; and git is popular.


I love the way @sorin-ionescu organized OMZ, it becomes very clear where everything is located and remove some unnecessary abstractions, but I have to disagree with the way he designed customizations.



Customization should be allowed by the user, he should be able to override any of the modules or by loading new modules, but IMO it should be done outside of OMZ's folder, take my dotfiles for example, I hate to commit code that isn't mine and prefer to use submodules whenever it's possible, this way I do not have to worry about maintaing a healthy code, that is not mine, myself. And because of the way OMZ work (in the master branch) I have to manually symlink (recursive symlink) all my extensions back inside OMZ submodule.

But of course you are now thinking, why the hell I don't use the wonderful Git and Github and just fork OMZ and use my fork for the submodule and just add any custom plugin to it? Well actually this would work, but first I won't be able to auto-update my OMZ and I have to resort to manual merging of upstream changes, which of course is not a hard task but it does take more time to maintain.


You could resort to what I've done for Janus where the user can maintain a separate submodule, or just a folder it doesn't need to be a Git folder and when the user requests a plugin, Janus will look in that folder first and if not found, it will look inside the bundled plugins. This will help the user keep using upstream repository and just worrying about maintaining what he added to it.

Now from what I have seen in the code, you are already half-way through making this work that way, in the omodload() you do check if the module has already been loaded and if it has you skip it, so just make it check in ~/.omz for example first and then look inside the modules/ folder if not found, if it were found in both folders, well the ~/.omz version will be loaded first and this way the user may be able to add or override any module.

Please don't hesitate to ask if you need more clarification on how it's done by Janus but I do believe it is the best way to go, for advanced users as well as for novices because none would have to maintain OMZ fork themselves.


My main motivation behind my Oh My Zsh fork is the KISS principle. What you want, what used to be the custom directory, does not work well in practice, at least it has not for me.

Oh My Zsh is dot files. When code in custom goes out of sync with code in the main OMZ, issues arise. Additionally, Zsh code is not C. There is a performance penalty in having override code because both have to be parsed and potentially executed. The symptom is that opening a terminal tab takes 2-3 seconds.

You intend to copy a module from the modules directory and put it in ~/.omz and change omdload to look for it. Periodically, you'll have to diff your custom module with the main OMZ. Manual intervention is lousy when git pull --no-commit --strategy=recursive -X ours sorin master can do that for you.

Different people want different ways of doing things, including me. The way I have set it up right now works very well with a little Git knowledge.

I have tilde, which pulls my entire $HOME environment via submodules. I don't have directories all over the place. All my environment-related work, including Oh My Zsh occurs inside of tilde.

I can cd to a submodule and push it, or I can push all of them at the same time using foreach.

.tilde git:master ❯ git submodule foreach --recursive 'git config --get remote.origin.url'
Entering 'dot'
Entering 'dot/oh-my-zsh'
Entering 'dot/oh-my-zsh/modules/completion/functions'
Entering 'dot/oh-my-zsh/modules/history-substring-search/external'
Entering 'dot/oh-my-zsh/modules/syntax-highlighting/external'
Entering 'opt'

I agree with you on one thing, adhering to the KISS principle would make it great for newbies but what about us power users ? I work 10 maybe 12 hours a day so the last thing I need is to have to spend more time on maintaing my fork of OMZ, of course I could keep it this way, because it does work and I do not write much plugins myself (or override others)

As for the performance time, having it check for modules in ~/.omz does not affect performance in any way, of course that is if you write it well, consider the following:

your ~/.zshrc:

zstyle ':omz:load' omodule \
  'environment' \

your home:

  | environment

  | environment
  | terminal

Now consider the following omoload function

# Loads Oh My Zsh modules.
function omodload {
  local -a omodules
  local omodule

  # $argv is overridden in the anonymous function.

  function {
    local ofunction

    # Extended globbing is needed for listing autoloadable function directories.

    # Add functions to fpath.
    fpath=(${omodules:+${OMZ}/modules/${^omodules}/functions(/FN)} $fpath)

    # Load Oh My Zsh functions.
    for ofunction in \
      autoload -Uz "$ofunction"

  for omodule in "$omodules[@]"; do
    if zstyle -t ":omz:module:$omodule" loaded; then
    elif [[ -d "$HOME/.omz/$omodule" ]]; then
      if [[ -s "$HOME/.omz/modules/$omodule/init.zsh" ]]; then
        source "$HOME/.omz/modules/$omodule/init.zsh"

      if (( $? == 0 )); then
        zstyle ":omz:module:$omodule" loaded 'yes'
        zstyle ":omz:module:$omodule" loaded 'no'
    elif [[ ! -d "$OMZ/modules/$omodule" ]]; then
      print "$0: no such module: $omodule" >&2
      if [[ -s "$OMZ/modules/$omodule/init.zsh" ]]; then
        source "$OMZ/modules/$omodule/init.zsh"

      if (( $? == 0 )); then
        zstyle ":omz:module:$omodule" loaded 'yes'
        zstyle ":omz:module:$omodule" loaded 'no'

The function above will load the environment module once and only once because if it is found in ~/.omz it will be loaded from there, if not it will be loaded from ~/.oh-my-zsh so as you can see, the only performance hit is one extra call to -d which we all know, on UNIX it is insignificant, and no conflicts will ever arise because you are loading it only once.

So yes I do vote for this structure and if you want to keep it your way, that's fine by me, but please do add this function, even gated it doesn't matter...


Oh and here's the performance proof:

Benchmark script:

#!/usr/bin/env zsh

for i in $(seq 1 10000); do
  if [ $(( $i % 2 )) -eq 0 ]; then
    if [ -d "${HOME}/Code" ]; then
    if [ -d "${HOME}/not-existing" ]; then


$ time /tmp/
/tmp/  0.11s user 0.06s system 98% cpu 0.167 total

as you you can see, this script tests for an existing folder 5000 times and for an not existing folder another 5000 times, and it runs insanely fast and this timing does count the odd/even calculation so in reality it's even more faster.


I am requesting volunteers to tackle the remaining open documentation issues.

jgosmann commented Jun 9, 2012

My 2 cents: I really like @sorin-ionescu's approach which seems much more structured and simpler (it also feels a bit more faster). Actually, I switched over to his fork. Concerning tha main points of discussion:

Auto update

The auto update of OMZ Robby was annoying for me as I am using different PCs and quite to often I had to dismiss the auto update question. Updating without confirming the update is no option for me as it could break things without having a clue what's going on. Therefore I prefer to trigger an update manually from time to time and if something doesn't work afterwards I know that it was probably the update.

Custom plugins

I think, it would be nice to have a folder for custom plugins. But in fact, I do not really care at the moment, because I have no need right now to add custom plugins (the plugins shipped with OMZ Sorin cover my needs).
However, I want to use my own prompt theme. Luckily this is really easy:

  1. Write your theme and save it in a folder foo
  2. Add this before you source the OMZ init script:
fpath=(path/to/foo $fpath)
autoload -Uz prompt_yourtheme_setup
  1. Select your theme like every other theme: zstyle ':omz:module:prompt' theme 'yourtheme'

@jgosmann, why don't you just add your theme to the prompt module functions directory?


I track my zshrc file and theme in its own git repository and include OMZ as submodule. Otherwise I would also need to fork OMZ which seems to complicate the update process a bit ...


@jgosmann I also track OMZ in my dot-files repository, and I track my dot-files repository in my tilde repository. It works fine.


The problem isn't tracking OMZ in the dot-files repository and that's also what I do (dotzshrc). But I want to be able to track my own theme without forking OMZ. Doing that just to add this file seems to make it unnecessarily complicated to synchronize changes to to theme:

Process right know
  1. Change the theme on one computer and commit.
  2. Push changes.
  3. Pull changes on all other computers.
Process with forked OMZ

(as I imagine it, I haven't actually tried it; maybe there is an easier solution I do not know?)
1. Change the theme on one computer and commit
2. Push changes to forked OMZ repository.
3. Commit the change of the version of the submodule in the dot-files repository
4. Push those changes
5. Pull those changes on all other computers
6. git submodule update


You have to do the following once.

  1. Fork my OMZ
  2. Replace my OMZ with your OMZ in your dot files.

Then do the following.

  1. Do your changes inside your dot files OMZ.
  2. Commit.
  3. Push
  4. Pull your changes on all computers

Played a bit around and the result so far: If I only commit the changes to the OMZ submodule, the parent (local) dot-files repository will show uncommitted changes as long as I do not commit to that repository, too. Moreover, if I clone the (remote) dot-files repository in that stage it will not checkout the most current version of the OMZ submodule. I have to do another pull in the OMZ submodule and I have even to specify the branch as the working copy will be on no branch.

Sure it works somehow. But to me it feels not so clean and simple.


There is a giant aliases file in the Git module. Just type gSU at the top of the hierarchy to update all submodules.

If you do not like the fact that you have to commit in the parent repository, you can use git subtrees. There is a git-subtree script in the contrib folder of Git that makes things very easy.

Yes, it's a little bit of an initial pain until you get the hang of it, but it's better. Creating convoluted directory hierarchies to not modify third-party dot files directly creates nothing but problems in the long run.


I didn't know about subtrees, they might be an option. Probably I have to think about all of this a bit more ...



You lost me at "you can use git subtrees." (speaking on behalf of a lot of OMZ users who don't know how git works that much...)

@ColinHebert : RE: "Recently his fork had a major change which implied a mandatory modification of the .zshrc file, and auto update wouldn't have taken care of that and could possibly have make ZSH unusable"

Hmm, I don't believe that has been an issue with my version of OMZ... because we've always ensured that new updates don't BREAK existing config files. (i vaguely recall a small issue we had once, but we caught it within a few hours and fixed it before most people would have had an auto-update run)

I'm still open for exploring a 2.0, but it sounds like @sorin-ionescu and I have a difference of opinion on who the target audience is. From my perspective, what has been proposed looks too complex for people who aren't that comfortable with a shell already. (please refer back to this comment for my reasons).

From what I can tell... OMZ has an increasingly growing fan base and the biggest problem we have is that I, personally, can't keep up with all the pull-requests, which I'm addressing by tapping a few shoulders to aid me... but having gone back and forth over default conventions and philosophies, I'm going to stick to my guns on this one. I think @sorin-ionescu presents a great option for people who want to get a bit more clever, but I think my approach is best suited for the folks that I've been catering to all this time.

My approach is...

  • people run a shell command, it switches you over
  • they edit a config file
  • they select a theme (seem to be the most popular thing people want... personalization)
  • maybe look into plugins (maybe... doubt most are)

all of this without needing to know much/if anything about git.

Anyhow.. back to looking at pull requests.


Am going to close this issue for now as I don't believe OMZ suffers from being the opposite of simple (to use) at the moment. If we want to discus performance concerns, let's do those on a case-by-case basis.

Perhaps I'm not the average OMZ user... maybe I'm completely wrong, but I don't get the sense that many people know how to use some of the more advanced features... which might indicate a lack of learning resources/knowledge base. Until I'm convinced otherwise, I'm going to go about organizing and managing things in a similar manner and will always favor small/incremental updates to the project/framework over proposals to re-engineer the entire thing. (but am glad that open source makes it so easy for some people to do so!)

Onwards we march!


There is a communication issue here.


@robbyrussell, you are confused. @jgosmann has added OMZ as a submodule in his dot files. Whether he customises OMZ or just updates it via whatever mechanism, he has to commit in the parent project. That's how Git submodules work. I gave him the option to use subtrees if he does not like that. My OMZ fork does not require the use of subtrees. I also do not use subtrees.

Your fork is dependent on Git. It is dependent on Git to install, and it is depended on Git to update. If there is no Git, it cannot be installed with the script, and if there is a merge problem during the update, it leaves the user holding the problem.


I have always considered my fork as a work in progress until all the README files are done (there a few more to go). This was not a secret. I have communicated this. I am not sure to which breaking change you are referring, the merging of the alias and utility modules is not a breaking change. It does give a warning about the alias module not being found, which informs the user to remove it from zshrc. That issue has been up there for two months.

There was a partial breaking change some weeks ago, which was absolutely necessary because using the five rc files is what Zsh expects, and it's the only way for it to work properly. The change went well. I believe that there was only one issue opened claiming that something didn't work.

Almost all bugs have been fixed in a few hours.

Your OMZ used to break all the time when I used to use it because whatever I have had in custom used to go out of sync with /lib and /plugins. It may have changed in the last year, but based on the amount of issues opened, I would argue that is not the case. Config files are easy to fix. Code buried inside OMZ is not.

Why do you have so many pull requests? Because it's broken, and many people are trying to fix the same thing. There are many duplicate pull requests. Also, there are a lot of me too pull requests that benefit no other person.

That said, the configuration files in my fork have stabilised.

Auto-update can migrate the zshrc using regular expressions and search and replace.

Philosophy Between Our Forks

  • Users run a shell command, which switches them over (there is no install script yet).
  • Users edit a config file (same).
  • Users select a theme (same)
  • Users look into plugins/modules (same).

If users don't customise, as you claim, they don't need to know Git to use my fork either. Nevertheless, the amount of forks begs to differ, and since GitHub gives no other metric than the number of watchers and forks, it's the only metric we can use.

My fork has been a year in the making. It didn't drop over night. I have used incremental updates myself whenever I had time.

Have you ever used my fork for at least a week?

Sideways we march! :)

skwp commented Jun 14, 2012

I want to speak up that I am the maintainer of a 700+ watcher dotfiles project and I have recommended omz-sorin to my users since a few months back. To be honest, I am not an expert ZSH user and my first motivation for upgrading to sorin's branch was the fact that he had not included the somewhat annoying (my opinion) weekly update feature :).

It also struck me that sorin really knew what he was doing with regard to zsh, and was producing a very zsh-specific project. As I learned more about the differences, I could see that sorin's version is likely to be more maintainable by people who really know zsh.

From a usability standpoint, I see a lot less "stuff" in sorin's fork, and so I believe it's easier to comprehend. Rather than plugins/libs/modules/templates, there are really only modules, and they're well organized as directories. Being relatively new to ZSH, it's easy for me to understand the organization of this codebase.

I don't know what else to add other than I understand that sorin's branch has grown very slowly over time to become a very clean and modularized set of plugins, yet it has greatly diverged from robby's. I can understand that robby would have a hard time merging something that was drastically different from what he has come to maintain. At the end of the day, that would mean that robby would be responsible for dealing with the change requests, and clearly there's already a crazy overrun of pull requests on this project.

My proposal is @sorin-ionescu , don't worry so much about this project, and go ahead and develop your fork without worrying about trying to merge back with robby's version. You have a dedicated support base, and we don't need everyone to switch over to it. In fact, it may cause the same pull request chaos that robby has to deal with. I'd rather keep the omz-sorin secret all to myself :) I will continue promoting it to my users. Thanks @sorin-ionescu for an awesome implementation and thanks @robbyrussell for the original inspiration. Both of you have done tremendous work for getting lazy bash users like myself to see the enlightenment of zsh.


@skwp, the motivation for my fork was to help the users of Oh My Zsh, not to take over @robbyrussell's project. That said, I will not keep it as a shadow of its parent. If it's not going to be merged into the parent project, I would have to ask @github to separate the two projects, and I would have to rename and rebrand it. I have not thought of clever name besides zsh.d akin to other dot d directories in /etc.

skwp commented Jun 14, 2012

I would agree with this. I almost did my dotfiles project as a fork of Janus but I was not happy with how they organized things, so I took my own path. I don't think there's anything wrong with that, and probably less load on Robby to try to merge these things. I like that you're trying to do a good thing, and I think users in the end care less than you or Robby do about the way your projects are handled. People will be happy either way :)


Fans, contribute to the renaming and rebranding of the project.

febs commented Oct 11, 2012

I got a 404 following that link.


The project has been since renamed into prezto


Hello. I don't know if the omz project is dead but I've started hacking on it since it has a very clean base for the evolution (mainly new plugin) I need. Does this project still maintained?

skwp commented Feb 14, 2013

Prezto => is actively maintained

hotpxl commented Nov 26, 2013

This debate is awesome..


@kevinleeone It's called Prezto — Instantly Awesome Zsh.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.