Jump to content

Find, filter, open Git repositories

Recommended Posts

Alfred Git Repos Workflow
Browse, search and open Git repositories from within Alfred.
Get the workflow from GitHub or Packal.
This workflow requires some configuration before use. See Configuration for details.

  • repos [<query>] — Show a list of your Git repos filtered by <query>
    • — Open selected repo in app_1 (see configuration)
    • ⌘+↩ — Open selected repo in app_2 (see configuration)
    • ⌥+↩ — Open selected repo in app_3 (requires configuration)
    • ^+↩ — Open selected repo in app_4 (requires configuration)
    • ⇧+↩ — Open selected repo in app_5 (requires configuration)
    • fn+↩ — Open selected repo in app_6 (requires configuration)
    • reposettings — Open settings.json in default JSON editor
  • reposupdate — Force workflow to update its cached list of repositories. (By default, the list will only be updated every 3 hours.)
  • reposhelp — Open this file in your browser

Before you can use this workflow, you have to configure one or more folders in which the workflow should search for Git repos. The workflow uses find to search for .git directories, so you shouldn't add huge directory trees to it, and use the depth option to restrict the search depth. Typically, a depth of 2 will be what you want (i.e. search within subdirectories of specified directory, but no lower). Add directories to search to the search_dir array in settings.json (see below).
The default settings.json file looks like this:

  "app_1": "Finder",             // ↩ to open in this/these app(s)
  "app_2": "Terminal",           // ⌘+↩ to open in this/these app(s)
  "app_3": null,                 // ⌥+↩ to open in this/these app(s)
  "app_4": null,                 // ^+↩ to open in this/these app(s)
  "app_5": null,                 // ⇧+↩ to open in this/these app(s)
  "app_6": null,                 // fn+↩ to open in this/these app(s)
  "global_exclude_patterns": [],      // Exclude from all searches
  "search_dirs": [
  "path": "~/delete/this/example",   // Path to search. ~/ is expanded
  "depth": 2,                        // Search subdirs of `path`
  "name_for_parent": 1,              // Name Alfred entry after parent of `.git`. 2 = grandparent of `.git` etc.
  "excludes": [                      // Excludes specific to this path
    "tmp",                           // Directories named `tmp`
    "bad/smell/*"                    // Subdirs of `bad/smell` directory

This is my settings.json:

  "app_1": "Finder",
  "app_2": ["Finder", "Sublime Text", "SourceTree", "iTerm"],
  "app_3": "Sublime Text",
  "app_4": "SourceTree",
  "app_5": "iTerm",
  "app_6": "GitHub",
  "global_exclude_patterns": [],
  "search_dirs": [
      "path": "~/Code"
      "path": "~/Sites"

Search Directories
Each entry in the search_dirs list must be a mapping.
Only path is required. depth will default to 2 if not specified. excludes are globbing patterns, like in .gitignore.
name_for_parent defaults to 1, which means the entry in Alfred's results should be named after the directory containing the .git directory. If you want Alfred to show the name of the grandparent, set name_for_parent to 2 etc.

This is useful if your projects are structured, for example, like this and src is the actual repo:


Open in Applications
The applications specified by the app_N options are all called using open -a AppName path/to/directory. You can configure any application that can open a directory in this manner. Some recommendations are Sublime Text, SourceTree, GitHub or iTerm.

Note: As you can see from my settings.json, you can also set an app_N value to a list of applications to open the selected repo in more than one app at once:

  "app_2": ["Finder", "Sublime Text", "SourceTree", "iTerm"],

You can also use on a result to access Alfred's default File Actions menu.
License, Thanks
This workflow is released under the MIT Licence.
It uses the Alfred-Workflow and docopt libraries (both MIT Licence).
The icon is by Jason Long, from git-scm.com, released under the Creative Commons Attribution 3.0 Unported Licence.

Edited by deanishe
Link to comment

Cheeky update today.


It's very handy being able to open your Git repos in your editor, terminal, Finder and SCM app from Alfred. Now you can open the repo in all of them at once!


Just set an app_N option to a list of applications.


Also fixed a bug with app_6 / fn+↩ not working.

Link to comment

Is it normal if it takes long time to initialise the database? It says few seconds but it is still on that step.

Debug information:

Starting debug for 'Git Repos'
[ERROR: alfred.workflow.input.scriptfilter] Code 0: 17:10:19 repos.py:89 DEBUG    args: {u'--edit': False,
 u'--helpfile': False,
 u'--open': False,
 u'--update': False,
 u'<appnum>': None,
 u'<path>': None,
 u'<query>': u''}
17:10:19 background.py:215 DEBUG    Calling [u'/usr/bin/python', 'XXXXXXXXXXXXXXXX/background.pyc', u'update'] ...
17:10:19 background.py:220 DEBUG    Executing task `update` in background...
I've updated the settings file
Link to comment

Another update today.


Now you can specify an arbitrary level of the file tree after which a repo is named in Alfred, e.g.:


If your directory looks like this:

    Project 1
    Project 2

You can set name_for_parent to 2, so the workflow shows "Project 1", "Project 2" etc. in Alfred, not "htdocs", "htdocs", "htdocs" etc.

Link to comment

Indeed, it didn't follow symlinks (which is find's default behaviour).


I've added a new version (1.3) that does follow symlinks. Give that one a go.


v1.3 follow symlinks, but global_exclude_pattern doesn't work. 


I set 'global_exclude_patterns": ["old*"] '  in settings.json, but old.jmjeong.com repo still appears. In the previous version, it doesn't

Link to comment
~/Dropbox/Apps/Alfred.alfredpreferences/workflows/user.workflow.BAF71062-A6BA-40A6-A1A0-09B8628D42E5 $ python update.py 

Excludes setting - [u'tmp', u'bad/smell/*', u'old*']

20:46:17 update.py:89 DEBUG    repo `alfred-extension` at `/Users/jmjeong/git/alfred-extension`

20:46:17 update.py:89 DEBUG    repo `bobby` at `/Users/jmjeong/git/bobby`

20:46:17 update.py:89 DEBUG    repo `CCMask` at `/Users/jmjeong/git/CCMask`

20:46:17 update.py:89 DEBUG    repo `cocos-samples` at `/Users/jmjeong/git/cocos-samples`

20:46:17 update.py:89 DEBUG    repo `django-appsales` at `/Users/jmjeong/git/django-appsales`

20:46:17 update.py:89 DEBUG    repo `Hyde` at `/Users/jmjeong/git/Hyde`

20:46:17 update.py:89 DEBUG    repo `ihd2` at `/Users/jmjeong/git/ihd2`

20:46:17 update.py:89 DEBUG    repo `iLink` at `/Users/jmjeong/git/iLink`

20:46:17 update.py:89 DEBUG    repo `jmjeong.com` at `/Users/jmjeong/git/jmjeong.com`

20:46:17 update.py:89 DEBUG    repo `old.jmjeong.com` at `/Users/jmjeong/git/old.jmjeong.com`

20:46:17 update.py:89 DEBUG    repo `old.jmjeong.github.com` at `/Users/jmjeong/git/old.jmjeong.github.com`

20:46:17 update.py:89 DEBUG    repo `PlanBeQuickAdd` at `/Users/jmjeong/git/PlanBeQuickAdd`

20:46:17 update.py:89 DEBUG    repo `todo.txt-ios` at `/Users/jmjeong/git/todo.txt-ios`

20:46:17 update.py:89 DEBUG    repo `vitae` at `/Users/jmjeong/git/vitae`

20:46:17 update.py:89 DEBUG    repo `weatherrecord.new` at `/Users/jmjeong/git/weatherrecord.new`

20:46:17 update.py:94 DEBUG    15 repos found in `/Users/jmjeong/git` in 3.95 s

20:46:17 workflow.py:970 DEBUG    Cached data saved at : /Users/jmjeong/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/net.deanishe.alfred-git-repos/repos.cache

20:46:17 update.py:141 INFO     15 repos found in 4.03 s

20:46:17 update.py:142 INFO     Update finished


old.jmjeong.com and old.jmjeong.github.com is not symbolic link. 

I thought these directories is not included in the result set because of 'excludes' setting. 

Link to comment
  • 3 weeks later...

Somehow I can't get it to recognise a simple git repo. My settings are:

  "app_1": "Finder", 
  "app_2": "Terminal", 
  "app_3": null, 
  "app_4": null, 
  "app_5": null, 
  "app_6": null, 
  "global_exclude_patterns": [], 
  "search_dirs": [
      "path": "~/develop/_sites/_webhook/aesite"
      "path": "~/_arm-new/arm_lib/"

It just sits there and says No known git repos..


Any idea? Thanks!

Link to comment

Yes, I did a reposupdate a few times. Here is the last log snippet, which says no repos found..

15:34:17 repos.py:90 DEBUG    args: {u'--edit': False,
 u'--helpfile': False,
 u'--open': False,
 u'--update': True,
 u'<appnum>': None,
 u'<path>': None,
 u'<query>': None}
15:34:17 background.py:215 DEBUG    Calling [u'/usr/bin/python', '/Users/ae/Library/Application Support/Alfred 2/Alfred.alfredpreferences/workflows/user.workflow.A4C6E503-62A4-476D-8B6D-80CF94FE0DC8/workflow/background.pyc', u'update'] ...
15:34:18 background.py:259 DEBUG    Task `update` running
15:34:18 background.py:260 DEBUG    cmd : [u'/usr/bin/python', u'update.py']
15:34:18 background.py:220 DEBUG    Executing task `update` in background...
15:34:18 update.py:94 DEBUG    0 repos found in `/Users/ae/_arm-new/arm_lib/` in 0.02 s
15:34:18 update.py:94 DEBUG    0 repos found in `/Users/ae/develop/_sites/_webhook/aesite` in 0.04 s
15:34:18 workflow.py:970 DEBUG    Cached data saved at : /Users/ae/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data/net.deanishe.alfred-git-repos/repos.cache
15:34:18 update.py:139 INFO     0 repos found in 0.10 s
15:34:18 update.py:140 INFO     Update finished
15:34:18 background.py:270 DEBUG    Task `update` finished
Link to comment

Can you run these commands:

find -L /Users/ae/_arm-new/arm_lib -type d -name .git -depth 1
find -L /Users/ae/develop/_sites/_webhook/aesite -type d -name .git -depth 1

Those are the commands the workflow will use to find your repos.

You might need to adjust the depth setting if the repos aren't direct subdirectories of the search_dirs.

Link to comment

Ok, one good one error. The first one finds the .git directory, the second my mistake, no repos in there. I removed the erronous path and setting the depth to 2 made of course no diff as it found the repos.. Any other ideas? Thanks for looking into this!

Link to comment

Is the git repo actually /Users/ae/_arm-new/arm_lib, not a subdirectory thereof?
The workflow only searches subdirectories of the search_dirs. It won't match the search_dirs themselves.
Can you change the path to /Users/ae/_arm-new instead, or is that directory tree too big?

Link to comment
  • 4 months later...

Awesome workflow, found a "bug" though. If your json file is incorrect the workflow completely stops working without any visible errors. What's worse, you can't open the settings anymore since that also crashes ;)

Here's the backtrace:

[ERROR: alfred.workflow.action.script] Code 1: Traceback (most recent call last):
  File "repos.py", line 232, in <module>
  File "workflow/workflow.py", line 944, in __init__
  File "workflow/workflow.py", line 2168, in check_update
    if not force and not self.settings.get('__workflow_autoupdate', True):
  File "workflow/workflow.py", line 1378, in settings
  File "workflow/workflow.py", line 802, in __init__
  File "workflow/workflow.py", line 813, in _load
    for key, value in json.load(file_obj, encoding='utf-8').items():
  File "json/__init__.py", line 290, in load
  File "json/__init__.py", line 351, in loads
    return cls(encoding=encoding, **kw).decode(s)
  File "json/decoder.py", line 365, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "json/decoder.py", line 383, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Create New...