{"id":13646391,"url":"https://github.com/CyberShadow/term-keys","last_synced_at":"2025-04-21T18:30:57.849Z","repository":{"id":44443407,"uuid":"109795265","full_name":"CyberShadow/term-keys","owner":"CyberShadow","description":"Lossless keyboard input for Emacs","archived":false,"fork":false,"pushed_at":"2024-09-06T16:40:01.000Z","size":186,"stargazers_count":120,"open_issues_count":3,"forks_count":11,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-21T13:54:56.464Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Emacs Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CyberShadow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-11-07T06:22:09.000Z","updated_at":"2025-04-18T17:30:31.000Z","dependencies_parsed_at":"2024-08-02T01:38:31.478Z","dependency_job_id":null,"html_url":"https://github.com/CyberShadow/term-keys","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberShadow%2Fterm-keys","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberShadow%2Fterm-keys/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberShadow%2Fterm-keys/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CyberShadow%2Fterm-keys/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CyberShadow","download_url":"https://codeload.github.com/CyberShadow/term-keys/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250110824,"owners_count":21376542,"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":[],"created_at":"2024-08-02T01:02:54.410Z","updated_at":"2025-04-21T18:30:57.610Z","avatar_url":"https://github.com/CyberShadow.png","language":"Emacs Lisp","funding_links":[],"categories":["Emacs Lisp"],"sub_categories":[],"readme":"# term-keys - lossless keyboard input for Emacs\n\nThis package allows configuring Emacs and a supported terminal emulator to handle keyboard input involving any combination of keys and modifiers.\n\n## Table of Contents\n\n  * [Introduction](#introduction)\n  * [Installation](#installation)\n  * [Setup](#setup)\n    * [Configuring Emacs](#configuring-emacs)\n    * [Configuring `term-keys`](#configuring-term-keys)\n    * [Terminal Emulators](#terminal-emulators)\n      * [urxvt (rxvt-unicode)](#urxvt-rxvt-unicode)\n      * [xterm](#xterm)\n      * [kitty](#kitty)\n      * [wezterm](#wezterm)\n      * [Alacritty](#alacritty)\n      * [Konsole](#konsole)\n      * [Yakuake](#yakuake)\n      * [Linux console](#linux-console)\n      * [st](#st)\n      * [macOS Terminal](#macos-terminal)\n      * [Windows Terminal](#windows-terminal)\n      * [Unsupported terminals](#unsupported-terminals)\n  * [Similar projects](#similar-projects)\n\n## Introduction\n\nGenerally, terminal emulators and applications running in a terminal cannot reliably transmit and receive certain keystrokes (keys in combination with modifiers).\nFor some key combinations, there is no consensus on how these events should be encoded on the wire (F-keys and movement keys plus modifiers);\nsome other key combinations cannot be represented at all (such as \u003ckbd\u003eCtrl\u003c/kbd\u003e\u003ckbd\u003e1\u003c/kbd\u003e or \u003ckbd\u003eCtrl\u003c/kbd\u003e\u003ckbd\u003eShift\u003c/kbd\u003e\u003ckbd\u003eA\u003c/kbd\u003e).\nThis can be an impediment for Emacs users, especially when you've already configured your Emacs in an environment unrestricted by these limitations (X11) and now wish to use it in the terminal as well.\n\nThe `term-keys` package allows solving this problem by giving these key combinations a custom, unique encoding, overcoming the limitations of the protocol implemented by the terminal emulators.\n\n## Installation\n\nTo install `term-keys`, first add my ELPA package archive. Add this to your `init.el` and evaluate it:\n\n```elisp\n(require 'package) ; you may already have this line\n(add-to-list 'package-archives\n             '(\"cselpa\" . \"https://elpa.thecybershadow.net/packages/\"))\n```\n\nThen, install it like any ELPA package (\u003ckbd\u003eM-x\u003c/kbd\u003e`package-install`\u003ckbd\u003eRET\u003c/kbd\u003e`term-keys`).\n\n## Setup\n\nSetting up `term-keys` is a three-part process:\n\n1. Configure Emacs;\n2. Configure `term-keys` (optional);\n3. Configure your terminal emulator.\n\nSee the sections below for more information.\n\n### Configuring Emacs\n\nSetting up `term-keys` is as easy as:\n\n```elisp\n(require 'term-keys)\n(term-keys-mode t)\n```\n\nThis will automatically set up current and new TTY frames to decode `term-keys` key sequences.\nIf you prefer to enable it for each frame manually, you can do so by invoking `(term-keys/init)`.\n\n### Configuring `term-keys`\n\n`term-keys` is very configurable. Most things can be changed via Emacs' `customize` interface - use \u003ckbd\u003eM-x\u003c/kbd\u003e`customize-group`\u003ckbd\u003eRET\u003c/kbd\u003e`term-keys` to access it.\n\nSome of the supplementary code for terminal emulator configuration can be configured as well.\nBecause it's not loaded by default (as it's only necessary for initial configuration), you need to load it explicitly before configuring it, e.g. using \u003ckbd\u003eM-:\u003c/kbd\u003e`(require 'term-keys-konsole)`, and only then invoking Emacs' `customize` interface.\nSee the terminal's section in this file for more information.\n\nThe only part of `term-keys` which cannot be configured via the `customize` interface is the set of key combinations to support, as (counting all possible keys plus combinations of modifier keys) their total number is very large.\nFor this purpose, `term-keys` allows specifying the name of a function to invoke, which shall implement this logic.\nSee the documentation of `term-keys/want-key-p-func` and `term-keys/want-key-p-def` (as well as the definition of the latter) for more information.\n\n### Terminal Emulators\n\nEach terminal emulator has its own method of configuration. Consult the section corresponding to your terminal emulator of choice below.\n\nNote that you will need to update the terminal emulator configuration every time you change the `term-keys` configuration.\n\n#### urxvt (rxvt-unicode)\n\nThere's three ways to configure `urxvt` with `term-keys`: via command-line parameters, via X resources, or by invoking a `term-keys` function from Emacs.\n\n##### Command-line parameters\n\nCommand-line configuration consists in adding the key bindings to the `urxvt` invocation directly.\nYou can use `term-keys/urxvt-script` to create a shell script in this manner:\n\n```elisp\n(require 'term-keys-urxvt)\n(with-temp-buffer\n  (insert (term-keys/urxvt-script))\n  (write-region (point-min) (point-max) \"~/launch-urxvt-with-term-keys.sh\"))\n```\n\nAfterwards, you can run e.g.:\n\n```bash\n$ sh ~/launch-urxvt-with-term-keys.sh -e emacs -nw\n```\n\nThis will launch Emacs under an `urxvt` instance configured for `term-keys`.\n\n##### X resources\n\nX resource configuration consists in adding the `term-keys` configuration to the X resources.\nThe X resources are global (per X session), and will apply to all newly-started `urxvt` instances.\nYou can use `term-keys/urxvt-xresources` to create the necessary configuration in this manner:\n\n```elisp\n(require 'term-keys-urxvt)\n(with-temp-buffer\n  (insert (term-keys/urxvt-xresources))\n  (append-to-file (point-min) (point-max) \"~/.Xresources\"))\n```\n\nThen use `xrdb` to load the file into memory:\n\n```bash\n$ xrdb -merge ~/.Xresources\n```\n\n##### Direct invocation\n\nIn addition to generating a static configuration as a shell script or X resources, you can ask `term-keys` to invoke `urxvt` directly.\nThis has the benefit that it will always use the up-to-date `term-keys` configuration, but the downside that it must be done by invoking `emacs` or `emacsclient`.\nFor example:\n\n```bash\n$ emacsclient --eval '(term-keys/urxvt-run-emacs)'\n```\n\nSee the `term-keys/urxvt-*` definitions for more urxvt-specific help code.\n\nYou may also want to disable some default `urxvt` shortcuts which may interfere with using Emacs.\nConsider adding something like this to your `~/.Xresources`:\n\n```\nURxvt*iso14755: 0\nURxvt.keysym.Shift-Insert: builtin-string:\nURxvt.keysym.M-S: builtin-string:\n```\n\n#### xterm\n\n`xterm` is configured nearly identically as `urxvt`;\nthus, this section will be very similar to the `urxvt` section above.\n\nNote: `xterm` supports an extended input mode; see `modifyOtherKeys` et al in the `xterm(1)` man page.\nYou may find it sufficient for your use case even without `term-keys`.\n\nAs with `urxvt`, there's two ways to configure `xterm`: via command-line parameters or X resources.\nCommand-line configuration consists in adding the key bindings to the `xterm` invocation directly.\nYou can use `term-keys/xterm-script` to create a shell script in this manner:\n\n```elisp\n(require 'term-keys-xterm)\n(with-temp-buffer\n  (insert (term-keys/xterm-script))\n  (write-region (point-min) (point-max) \"~/launch-xterm-with-term-keys.sh\"))\n```\n\nAfterwards, you can run e.g.:\n\n```bash\n$ sh ~/launch-xterm-with-term-keys.sh -e emacs -nw\n```\n\nThis will launch Emacs under an `xterm` instance configured for `term-keys`.\n\nX resource configuration consists in adding the `term-keys` configuration to the X resources.\nThe X resources are global (per X session), and will apply to all newly-started `xterm` instances.\nYou can use `term-keys/xterm-xresources` to create the necessary configuration in this manner:\n\n```elisp\n(require 'term-keys-xterm)\n(with-temp-buffer\n  (insert (term-keys/xterm-xresources))\n  (append-to-file (point-min) (point-max) \"~/.Xresources\"))\n```\n\nThen use `xrdb` to load the file into memory:\n\n```bash\n$ xrdb -merge ~/.Xresources\n```\n\nIn addition to generating a static configuration as a shell script or X resources, you can ask `term-keys` to invoke `xterm` directly.\nThis has the benefit that it will always use the up-to-date `term-keys` configuration, but the downside that it must be done by invoking `emacs` or `emacsclient`.\nFor example:\n\n```bash\n$ emacsclient --eval '(term-keys/xterm-run-emacs)'\n```\n\nSee the `term-keys/xterm-*` definitions for more xterm-specific help code.\n\nYou may also want to disable the `eightBitInput` `xterm` option, e.g. with `-xrm 'XTerm*eightBitInput: false'`.\n\n#### kitty\n\n[kitty](https://sw.kovidgoyal.net/kitty/) is configured via its `kitty.conf` configuration file.\n\nTo configure kitty for `term-keys`, use `term-keys/kitty-conf` to generate a `kitty.conf` fragment:\n\n```elisp\n(require 'term-keys-kitty)\n(with-temp-buffer\n  (insert (term-keys/kitty-conf))\n  (write-region (point-min) (point-max) \"~/kitty-for-term-keys.conf\"))\n```\n\nThen, add the output to your main `kitty.conf` file.\n\nYou can customize kitty's mapping of GLFW modifiers to Emacs modifiers in the generated configuration using the respective `customize` group, i.e.: \u003ckbd\u003eM-:\u003c/kbd\u003e`(progn (require 'term-keys-kitty) (customize-group 'term-keys/glfw))`\n\n#### wezterm\n\n[wezterm](https://wezfurlong.org/wezterm/index.html) is configured via its `wezterm.lua` configuration file.\n\nTo configure wezterm for `term-keys`, use `term-keys/wezterm-conf` to generate a `wezterm.lua` fragment:\n\n```elisp\n(require 'term-keys-wezterm)\n(with-temp-buffer\n  (insert (term-keys/wezterm-conf))\n  (write-region (point-min) (point-max) \"~/wezterm-for-term-keys.lua\"))\n```\n\nThen, add the output to your main `wezterm.lua` file.\n\nYou can customize wezterm's mapping of GLFW modifiers to Emacs modifiers in the generated configuration using the respective `customize` group, i.e.: \u003ckbd\u003eM-:\u003c/kbd\u003e`(progn (require 'term-keys-wezterm) (customize-group 'term-keys/glfw))`\n\n#### Alacritty\n\n[Alacritty](https://github.com/alacritty/alacritty) is configured via its `alacritty.yml` configuration file.\n\nTo configure alacritty for `term-keys`, use `term-keys/alacritty-config` to generate a `alacritty.yml` fragment:\n\n```elisp\n(require 'term-keys-alacritty)\n(with-temp-buffer\n  (insert (term-keys/alacritty-config))\n  (write-region (point-min) (point-max) \"~/alacritty-for-term-keys.yml\"))\n```\n\nThen, add the output to your main `alacritty.yml` file.\n\nYou can customize Alacritty's mapping of its supported modifiers to Emacs modifiers in the generated configuration using the respective `customize` group, i.e.: \u003ckbd\u003eM-:\u003c/kbd\u003e`(progn (require 'term-keys-alacritty) (customize-group 'term-keys/alacritty))`\n\n#### Konsole\n\nKonsole provides an interface for adding new and editing existing escape sequences for key combinations \n(Settings \u0026rarr; Edit current profile... \u0026rarr; Keyboard \u0026rarr; Edit).\n`term-keys` can generate a Konsole keyboard profile according to its settings.\n\nTo do so:\n\n1. Create a new keyboard profile, based on the default one.  \n   (Select \"Default (XFree 4)\", and click \"New...\".)  \n   Name it e.g. `Emacs`.\n2. Append the output of `term-keys/konsole-keytab` to the newly created `.keytab` file, e.g.:\n\n   ```elisp\n   (require 'term-keys-konsole)\n   (with-temp-buffer\n\t (insert (term-keys/konsole-keytab))\n\t (append-to-file (point-min) (point-max) \"~/.local/share/konsole/Emacs.keytab\"))\n   ```\n   \n3. Assign the keyboard profile to a new or existing Konsole profile.\n\nYou can customize the mapping of Konsole (Qt) modifiers to Emacs modifiers using the respective `customize` group, i.e.: \u003ckbd\u003eM-:\u003c/kbd\u003e`(progn (require 'term-keys-konsole) (customize-group 'term-keys/konsole))`\n\nYou may also want to disable some default Konsole shortcuts (Settings \u0026rarr; Configure Shortcuts...),\nas they may interfere with standard Emacs commands.\n\n#### Yakuake\n\nYakuake seems to share much with Konsole, and can be configured in the same way.\nSee the section above for details.\n\n#### Linux console\n\nThe Linux console can be customized using `.keymap` files and the `loadkeys` program.\nYou can configure it for `term-keys` as follows:\n\n1. Use `term-keys/linux-keymap` to create a `.keymap` file:\n\n   ```elisp\n   (require 'term-keys-linux)\n   (with-temp-buffer\n\t (insert (term-keys/linux-keymap))\n\t (write-region (point-min) (point-max) \"~/term-keys.keymap\"))\n   ```\n\n2. Load the created `.keymap` file:\n\n   ```bash\n   $ sudo loadkeys ~/term-keys.keymap\n   ```\n\nTo reset the layout to the default one, run `sudo loadkeys -d`.\n\nYou will need to invoke `loadkeys` after every boot; alternatively, on\nsystemd distributions, you can add a `KEYMAP=` line to\n`/etc/vconsole.conf`.\n\nYou can customize some settings affecting the generated `.keymap` files using the respective `customize` group, i.e.: \u003ckbd\u003eM-:\u003c/kbd\u003e`(progn (require 'term-keys-linux) (customize-group 'term-keys/linux))`\n\nNote that the `.keymap` files generated by `term-keys/linux-keymap` assume a QWERTY keyboard layout.\nIf you use another layout (AZERTY, Dvorak, Colemak...), you will need to customize `term-keys/mapping` and set the alphanumeric keynumbers accordingly.\n\nNote also that Linux has a limitation on the number of customized keys. Custom key strings need to be assigned to \"function keys\", for which there are 256 slots by default (which includes the default strings for the F-keys and some other keys like Insert/Delete). This leaves about 234 slots for `term-keys`, which is sufficient for the default configuration, but may not be sufficient for a custom one, especially if you enable support for additional modifiers.\n\n#### st\n\n[st](https://st.suckless.org/) is configured by editing its `config.h` and recompiling. The key sequences can be configured in this way as well.\n\nYou can configure st for `term-keys` as follows:\n\n1. Generate the initial `config.h`, e.g. by building `st` once.\n2. Use the `term-keys/st-config-*` functions to create header files:\n\n   ```elisp\n   (require 'term-keys-st)\n   ;; Assuming st is checked out in ~/st\n   (with-temp-buffer\n\t (insert (term-keys/st-config-key))\n\t (write-region (point-min) (point-max) \"~/st/config-term-keys-key.h\"))\n   (with-temp-buffer\n\t (insert (term-keys/st-config-mappedkeys))\n\t (write-region (point-min) (point-max) \"~/st/config-term-keys-mappedkeys.h\"))\n   ```\n\n3. Update the definition of `mappedkeys` in `config.h` as follows:\n\n   ```c\n   static KeySym mappedkeys[] = {\n   #include \"config-term-keys-mappedkeys.h\"\n\t   -1\n   };\n   ```\n\n4. Update the definition of `key` in `config.h` as follows:\n\n   ```c\n   static Key key[] = {\n   #include \"config-term-keys-key.h\"\n\t   /* keysym           mask            string      appkey appcursor crlf */\n\t   /* ( ... original definitions follow ... ) */\n   ```\n\n5. Rebuild st.\n\nYou can customize st's mapping of X11 modifiers to Emacs modifiers in the generated configuration using the respective `customize` group, i.e.: \u003ckbd\u003eM-:\u003c/kbd\u003e`(progn (require 'term-keys-st) (customize-group 'term-keys/x11))`\n\n#### macOS Terminal\n\nThe standard macOS Terminal.app allows, to a certain extent, customizing escape sequences sent by key combinations\n(Terminal \u0026rarr; Preferences... \u0026rarr; Profiles \u0026rarr; (select a profile) \u0026rarr; Keyboard).\n`term-keys` can generate a configuration XML file, which can be injected into Terminal.app's preferences plist file.\n\nTo do so:\n\n1. Create a new profile. Name it e.g. `Emacs`.\n2. Enable the \"Use Option as Meta key\" option on the Keyboard tab.\n3. Export the `term-keys` keymap XML file:\n\n   ```elisp\n   (require 'term-keys-terminal-app)\n   (with-temp-buffer\n     (insert (term-keys/terminal-app-keymap-xml))\n     (append-to-file (point-min) (point-max) \"~/term-keys.xml\"))\n   ```\n\n4. Import the keymap into Terminal.app's preferences file:\n\n   ```bash\n   $ plutil -replace 'Window Settings.Emacs.keyMapBoundKeys' \\\n       -xml \"$(cat ~/term-keys.xml)\" \\\n       ~/Library/Preferences/com.apple.Terminal.plist\n   ```\n\n   (If you named your profile something other than `Emacs`, substitute its name in the command above.)\n\n5. Restart Terminal.app.\n\nNote that the application's settings UI only allows configuring a small set of keys.\nThis limitation does not carry over to the underlying configuration file format, and thus does not apply to `term-keys` -\nthe generated keymap file will contain definitions for all keys that generate a Unicode key code on macOS.\nThese entries will appear (displayed with the key's hex code instead of the key name) in the terminal emulator's configuration, but cannot be edited there.\n\nYou can customize the mapping of Terminal.app modifiers to Emacs modifiers using the respective `customize` group, i.e.: \u003ckbd\u003eM-:\u003c/kbd\u003e`(progn (require 'term-keys-terminal-app) (customize-group 'term-keys/terminal-app))`\n\n#### Windows Terminal\n\nTo configure Windows Terminal for `term-keys`, use `term-keys/windows-terminal-json` to generate a json file.\n\n```elisp\n(require 'term-keys-windows-terminal)\n(with-temp-file \"~/windows-terminal.json\"\n  (insert (term-keys/windows-terminal-json)))\n```\n\nThen, add the contents to Windows Terminal settings.\n\n#### Unsupported terminals\n\nThese terminals don't (directly) support customizing key bindings, and thus cannot be used with `term-keys`:\n\n- **PuTTY** - Custom key mappings are [a known frequently-requested feature](https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/key-mapping.html).\n- **GNOME Terminal** - Uses the [Gnome VTE widget](https://github.com/GNOME/vte), which doesn't seem to support key binding customization.\n- **tilix**, **Guake**, **tilda** - Use the same widget as GNOME Terminal.\n- **GNOME Terminator** - Uses the same widget as GNOME Terminal, however has a plugin system. Perhaps writing a plugin is possible?\n- **termite** - Uses the same widget as GNOME Terminal, however, it has a `modify_other_keys` option, similar to xterm's `modifyOtherKeys`.\n- **mintty** - No support for customizing key bindings, however, it already [has some support](https://github.com/mintty/mintty/wiki/CtrlSeqs) for xterm's `modifyOtherKeys` protocol extensions.\n- **Bitvise SSH Client** - No support for customizing key bindings. Supports a custom extended protocol (bvterm), which seems to allow lossless keyboard input (including key-up events), however it is full of Windows-isms (much of the protocol uses the same data types as used by the Windows API), and getting Emacs to speak it would be a non-trivial task that's not likely to be achievable using just Emacs Lisp code.\n- **Terminology** - No support for customizing key bindings at runtime (via a configuration file), however, this terminal generates its key/string translation tables using another terminal emulator (i.e. by sending keyboard events with `xdotool` to another terminal emulator and recording the resulting strings). Therefore, it may be possible to configure Terminology with `term-keys` by running its configuration script through another terminal pre-configured with `term-keys` (e.g. `xterm`), then rebuilding Terminology using the resulting configuration.\n\n## Similar projects\n\n* [xterm-keybinder](https://github.com/yuutayamada/xterm-keybinder-el) is an Emacs package similar to this one. `term-keys` improves upon xterm-keybinder by supporting more terminals, better documentation, customizability, and extensibility, and improved wire efficiency.\n\n* [notty](https://github.com/withoutboats/notty) is an experimental terminal emulator which also aims at achieving lossless keyboard input by extending the ANSI protocol. `term-keys` does not use notty's protocol because its escape sequence prefix (`^[{`) conflicts with a default Emacs command binding (`backward-paragraph`).\n\n* [Fix Keyboard Input on Terminals](http://www.leonerd.org.uk/hacks/fixterms/) is a proposal to improve input in terminals, which is to some extent implemented in `xterm` and Emacs. Unfortunately, the proposed protocol is vague and incomplete, as it does not cover modifier keys and many PC keyboard keys.\n\n* The [kitty terminal emulator](https://github.com/kovidgoyal/kitty) (the one written in Python, not [the PuTTY fork](http://www.9bis.net/kitty/)) implements [its own protocol extensions for keyboard handling](https://github.com/kovidgoyal/kitty/blob/master/protocol-extensions.asciidoc#keyboard-handling) (though it can also be simply configured with term-keys as [described above](#kitty)).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCyberShadow%2Fterm-keys","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCyberShadow%2Fterm-keys","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCyberShadow%2Fterm-keys/lists"}