{"id":21813529,"url":"https://github.com/loggerhead/easy-karabiner","last_synced_at":"2025-04-13T23:27:42.059Z","repository":{"id":57425130,"uuid":"52837199","full_name":"loggerhead/Easy-Karabiner","owner":"loggerhead","description":"A tool to simplify key-remapping configuration for Karabiner","archived":false,"fork":false,"pushed_at":"2017-03-17T03:30:47.000Z","size":154,"stargazers_count":34,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-27T13:45:17.714Z","etag":null,"topics":["macos","tool"],"latest_commit_sha":null,"homepage":"","language":"Python","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/loggerhead.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-01T01:08:49.000Z","updated_at":"2021-05-26T00:28:59.000Z","dependencies_parsed_at":"2022-09-19T05:21:04.890Z","dependency_job_id":null,"html_url":"https://github.com/loggerhead/Easy-Karabiner","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loggerhead%2FEasy-Karabiner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loggerhead%2FEasy-Karabiner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loggerhead%2FEasy-Karabiner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loggerhead%2FEasy-Karabiner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/loggerhead","download_url":"https://codeload.github.com/loggerhead/Easy-Karabiner/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248795639,"owners_count":21162810,"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":["macos","tool"],"created_at":"2024-11-27T14:29:48.331Z","updated_at":"2025-04-13T23:27:42.037Z","avatar_url":"https://github.com/loggerhead.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Easy-Karabiner\n\n[![Travis Build Status](https://travis-ci.org/loggerhead/Easy-Karabiner.svg?branch=master)](https://travis-ci.org/loggerhead/Easy-Karabiner)\n[![Code Health](https://landscape.io/github/loggerhead/Easy-Karabiner/master/landscape.svg?branch=master)](https://landscape.io/github/loggerhead/Easy-Karabiner/master)\n[![Coverage Status](https://coveralls.io/repos/github/loggerhead/Easy-Karabiner/badge.svg)](https://coveralls.io/github/loggerhead/Easy-Karabiner)\n[![PyPI version](https://img.shields.io/pypi/v/easy_karabiner.svg)](https://pypi.python.org/pypi/easy_karabiner)\n\n[Karabiner](https://pqrs.org/osx/karabiner/index.html.en) is a great tool and I love it! But it's configuration is too complicated for newbies. For making life simpler, I have invented Easy-Karabiner, which is a tool to generate xml configuration for Karabiner from simple python script.\n\n# Installation\n\n```bash\npip install easy_karabiner\n```\n\nOr you can install manually\n\n```bash\ngit clone https://github.com/loggerhead/Easy-Karabiner.git\ncd Easy-Karabiner\npython setup.py install\n```\n\n# Usage\n\nGenerate xml configuration from default path (`~/.easy_karabiner.py`), save it to `~/Library/Application Support/Karabiner/private.xml`, and reload Karabiner.\n\n```bash\neasy_karabiner\n```\n\nSame as above, except generating xml configuration from `./myconfig.py`.\n\n```bash\neasy_karabiner myconfig.py\n```\n\nPrint generated xml configuration from a specific file.\n\n```bash\neasy_karabiner -s myconfig.py\n```\n\nSee `easy_karabiner --help` for detailed options.\n\n# How to write `~/.easy_karabiner.py`\n\nEasy-Karabiner attempts to simplified the most commonly used configurations of Karabiner as well as possible, but there still exists some things you should know first.\n\nOr if you don't care about it and/or want to try it right now, [examples](https://github.com/loggerhead/Easy-Karabiner/tree/master/examples) are a good start :-)\n\n## Basics\n\nKarabiner is a context-aware key-remapping software, and Easy-Karabiner has simplified it's context and key-remapping to the combination of three components:\n\n* Map\n* Definition\n* Filter\n\nLet me show you a simple example.\n\n```python\nMAPS = [\n    # Remap 1 press of 'Left Command'+'K' to 30 press of 'Up'\n    # only when the active application is 'Google Chrome'\n\t['cmd K', 'up '   * 30, ['Google Chrome']],\n    ['cmd J', 'down ' * 30, ['Google Chrome']],\n\t# Swap 'Left Alt' to 'Left Command' only\n    # when the input keyborad is 'Cherry G80-3494'\n    ['alt', 'cmd', ['CHERRY_GmbH_0011']],\n    # You can get the peripheral name from `easy_karabiner -l`\n    ['cmd', 'alt', ['CHERRY_GmbH_0011']],\n    # Press 'Left Alt'+'C' to open 'Google Chrome'\n\t['alt C', 'Google Chrome'],\n]\n```\n\nIn most simple situation, you don't need to define any thing, just write a `MAPS` by your intuition.\n\n## Map\n\n`Map` is consist of three parts: `Map_Command`, `KeyCombo`, `Filter`, none of these parts are necessary.\n\n```python\n['_Map_Command_', 'KeyCombo1', 'KeyCombo2', ..., ['Filter1', 'Filter2', ...]]\n```\n\nThe number of `KeyCombo` could be changed if  `Map_Command` changed, but in most situations, there are only one or two `KeyCombo`; and if you ignored `Map_Command`, then only two `KeyCombo` is allowed.\n\n### Map_Command\n\n`Map_Command` is used to tell Karabiner what kind of key-remapping it is. For example\n\n```python\n# Remapping double pressed 'fn' to 'F12'\n# it keeps unchanged when single pressed\n['_double_', 'fn', 'F12'],\n# Remapping 'esc' to 'cmd_r ctrl_r alt_r shift_r' when holding it\n# it keeps unchanged when single pressed or other situations\n['_holding_', 'esc', 'cmd_r ctrl_r alt_r shift_r']\n```\n\nEasy-Karabiner provide some aliases to help you remeber Karabiner `Map_Command`, include\n\n| Alias            | Original              |\n| ---------------- | --------------------- |\n| `double`         | `DoublePressModifier` |\n| `holding`        | `HoldingKeyToKey`     |\n| `press_modifier` | `KeyOverlaidModifier` |\n\nYou can also use the original Karabiner `Map_Command`, For example\n\n```python\n# Reverse scroll direction if not Apple trackpad\n['__FlipScrollWheel__', 'flipscrollwheel_vertical', ['!APPLE_COMPUTER', '!ANY']]\n```\n\n### KeyCombo\n\n`KeyCombo` has the same format, they are composed by space-separated `Key`, and used to represent a combo of normal keys or actions. Easy-Karabiner predefined some aliases for reducing tedious typing. You can found the predefined aliases [here](https://github.com/loggerhead/Easy-Karabiner/blob/master/easy_karabiner/alias.py).\n\nHere is some example about `KeyCombo`\n\n```python\n# A single key\n'alt'\n# A shortcut\n'alt C'\n\n# A special key-combo which represent one action--open application\n'Google Chrome'\n\n# A special key-combo which represent one action--exectue script\n# script must start with '#! ' to tell Easy-Karabiner it's a script\n'#! osascript /usr/local/bin/copy_finder_path'\n\n# A special key-combo which represent two actions:\n#   1. Click left mouse button\n#   2. Execute script\n# NOTICE: if a action contain space, you should use quote to tell\n#         Easy-Karabiner that is a entirety.\n'mouse_left \"#! osascript /usr/local/bin/copy_finder_path\"'\n```\n\nBecause Easy-Karabiner verify a `Key` by check predefined XML file, but there exists some predefined `Key` not exists in any data file, so Easy-Karabiner will not prevent you to use a unknown `Key` but give you a warning.\n\n### Filter\n\n`Filter` is used to tell Karabiner when/where the key-remapping working or not working. For example\n\n```python\n# Remapping works only when current application is NOT\n# 'Skim' or any applications defined in 'EMACS_IGNORE_APP' predefined replacement\n['ctrl P', 'up', ['!EMACS_IGNORE_APP', '!Skim']]\n# '!' before a filter means NOT, otherwise means ONLY\n# NOTICE: How you define a thing, then how you use it in Easy-Karabiner.\n#\t\t  So, you don't need add '{{' and '}}' around a replacement.\n\n# Remapping works only when 'Skim' or 'Kindle'\n# NOTICE: You don't need to define a filter if it is application filter,\n#\t\t  Easy-Karabiner will do this job for you.\n['ctrl cmd F', 'cmd_r shift_r F cmd_r shift_r -', ['Skim', 'Kindle']]\n```\n\nTo distinguish `KeyCombo` and `Filter`, you must use brackets to tell Easy-Karabiner whether last part of a `Map` is a list of `Filter` or not.\n\n## Definition\n\n`Definition` is used to define `Filter` or `Key`, so you can use it in `Map`. Because Easy-Karabiner auto-defined most things for you, so you don't need it in most situation. `Definition` has several forms\n\n```python\nDEFINITIONS = {\n    # `NAME` is a symbol to represent the ground-truth value which used in `MAPS`\n    'NAME': 'VALUE',\n    # A `NAME` can represents multiple values\n    'NAME': ['VALUE1', 'VALUE2', ...],\n    # Same as above, except `DEF_TYPE` specified `Definition` type\n    'DEF_TYPE::NAME': 'VALUE',\n    'DEF_TYPE::NAME': ['VALUE1', 'VALUE2', ...],\n}\n```\n\nThe key of `Definition` is how you define it, how you use it; So you don't need to around a defined replacement with `{{` and `}}`.\n\nFor your convenience, Easy-Karabiner would use predefined `Definition`, so you don't need to define everything and just use it in `Filter`.\n\n### Replacement\n\n`Replacement` is a special `Definition` which will replaced by values when used. It has the form below\n\n```python\n'NAME': ['VALUE1', 'VALUE2', ...]\n```\n\nIf Easy-Karabiner cannot guess `DEF_TYPE` from `VALUE`, then a `Definition` with above form will be defined as a `Replacement`. Easy-Karabiner will try to define any undefined values in `Replacement` to keep consistency with other parts, for example\n\n```python\n# Two keymap will be defined\n'LAUNCHER_MODE_V2_EXTRA': [\n    ['__KeyDownUpToKey__', 'C', 'Maps'],\n    ['__KeyDownUpToKey__', 'V', 'FaceTime'],\n]\n\n# 'Sublime Text' and 'Visual Studio Code' will be defined\n'emacs_ignore_app': [\n    'ECLIPSE', 'EMACS', 'TERMINAL',\n    'REMOTEDESKTOPCONNECTION', 'VI', 'X11',\n    'VIRTUALMACHINE', 'TERMINAL', 'Sublime Text',\n    'Visual Studio Code',\n]\n```\n\n# LICENSE\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floggerhead%2Feasy-karabiner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Floggerhead%2Feasy-karabiner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floggerhead%2Feasy-karabiner/lists"}