{"id":15046123,"url":"https://github.com/chmouel/raffi","last_synced_at":"2026-02-25T16:04:48.726Z","repository":{"id":91815677,"uuid":"607637630","full_name":"chmouel/raffi","owner":"chmouel","description":"fuzzel/iced launcher based on yaml configuration","archived":false,"fork":false,"pushed_at":"2026-02-23T13:01:52.000Z","size":8846,"stargazers_count":77,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-23T21:36:13.559Z","etag":null,"topics":["fuzzel","iced","iced-rs","launcher","sway","wayland","yaml","yaml-config"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chmouel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-02-28T11:33:54.000Z","updated_at":"2026-02-23T13:01:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"92f13666-c063-4146-95d6-e2124ceb1986","html_url":"https://github.com/chmouel/raffi","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/chmouel/raffi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chmouel%2Fraffi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chmouel%2Fraffi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chmouel%2Fraffi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chmouel%2Fraffi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chmouel","download_url":"https://codeload.github.com/chmouel/raffi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chmouel%2Fraffi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29829411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-25T15:41:19.027Z","status":"ssl_error","status_checked_at":"2026-02-25T15:40:47.150Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["fuzzel","iced","iced-rs","launcher","sway","wayland","yaml","yaml-config"],"created_at":"2024-09-24T20:52:44.369Z","updated_at":"2026-02-25T16:04:48.720Z","avatar_url":"https://github.com/chmouel.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Raffi Application Launcher\n\nRaffi is an application launcher designed to sit on top of Fuzzel, or, if preferred, operate using its own built‑in interface. It allows commands and scripts to be defined in a YAML configuration file, with support for icons, arguments, conditional visibility, and script execution through configurable interpreters.\n\n![image](https://github.com/chmouel/raffi/assets/98980/04d6af0f-2a80-47d5-a2ec-95443a629305)\n\n*See more screenshots [below](#screenshots)*\n\n## Installation\n\nPrebuilt binaries are available from the GitHub releases page. Download the archive or package suitable for your platform. If you intend to use the default interface, Fuzzel must also be installed.\n\nOn Arch Linux, Raffi can be installed from the AUR using a helper such as:\n\n```sh\nyay -S raffi-bin\n```\n\nOn NixOS or using Nix (unstable channel):\n\n```sh\nnix-shell -p raffi\n```\n\nWith LinuxBrew or Homebrew:\n\n```sh\nbrew tap chmouel/raffi https://github.com/chmouel/raffi\nbrew install raffi\n```\n\nFrom crates.io:\n\n```sh\ncargo install raffi\n```\n\nTo build from source:\n\n```sh\ngit clone https://github.com/chmouel/raffi.git\ncd raffi\ncargo build --release\n```\n\nIf you only require Fuzzel integration and want a significantly smaller binary, build without the native UI:\n\n```sh\ncargo build --release --no-default-features\n```\n\nThis reduces the binary from roughly 15 MB to around 1.1 MB by removing the iced GUI dependency.\n\n## Usage\n\nRunning `raffi` launches configured entries through the selected interface. The chosen item is executed according to the configuration.\n\nCommon options include:\n\n`-p` or `--print-only` prints the command rather than executing it.\n`-c` or `--configfile \u003cFILE\u003e` selects a custom configuration file.\n`-r` or `--refresh-cache` refreshes cached icon paths.\n`-I` or `--disable-icons` disables icons for slightly faster startup.\n`-u` or `--ui-type \u003cTYPE\u003e` selects `fuzzel` or `native` (default is `fuzzel`).\n`-i` or `--initial-query \u003cQUERY\u003e` pre-fills the search field on launch (native mode only).\n`-t` or `--theme \u003cTHEME\u003e` selects `dark` or `light` theme (default is `dark`, native mode only).\n`--default-script-shell \u003cSHELL\u003e` sets the default interpreter for scripts.\n\n## Window Manager Integration\n\n### Sway\n\n```config\nset $menu raffi -p\nset $super Mod4\nbindsym $super+Space exec $menu | xargs swaymsg exec --\n```\n\n### Hyprland\n\n```conf\n$super = SUPER\nbind = $super, R, exec, (val=$(raffi -pI); echo $val | grep -q . \u0026\u0026 hyprctl dispatch exec \"$val\")\n```\n\n## User Interfaces\n\nRaffi supports two interface modes.\n\nFuzzel mode uses the external Fuzzel launcher and integrates naturally with Wayland environments.\n\nNative mode uses an internal iced‑based graphical interface with fuzzy search, keyboard navigation, and theme support (dark by default, light available via `-t light` or config). It is suitable if you prefer a self‑contained graphical window.\n\n### Native Interface Extras\n\n#### Calculator\n\nThe native interface includes a built‑in calculator which evaluates expressions as you type. Standard mathematical operators are supported, along with functions such as `sqrt`, `sin`, `cos`, `tan`, `log`, `ln`, `exp`, `abs`, `floor`, and `ceil`. Results can be copied to the clipboard using Enter, provided `wl-copy` is available.\n\n#### Currency Converter\n\nThe native interface also includes a currency converter.\nEnter an amount prefixed with the configured trigger (default `$`) followed by a target currency. Exchange rates are fetched from the Frankfurter API and cached for one hour.\n\nExample inputs:\n\n```\n$10 to eur\n$50 gbp to usd\n$100eur to jpy\n€10 to usd    (with trigger set to €)\n```\n\n#### Dynamic Script Filters\n\nThe native interface supports script filters, which allow external commands to provide\ndynamic results in the launcher. This feature uses a subset of the\n[Alfred Script Filter JSON format](https://www.alfredapp.com/help/workflows/inputs/script-filter/json/).\n\nWhen the configured keyword is typed, the script is executed with the remaining input\npassed as the final argument. The script must print JSON to stdout. On selection, the\nitem's `arg` value (or `title` if `arg` is absent) is copied to the clipboard using\n`wl-copy`. Alternatively, a custom `action` can be configured to run any command with\nthe selected value substituted via `{value}` placeholder. A `secondary_action` can\nalso be defined, which is triggered with Alt+Enter instead of Enter.\n\n The `title` and `subtitle` fields support ANSI color codes in JSON output,\n which the launcher renders as colored text. For example, the [pr.py script\n from alfred-pr-workflow](https://gitlab.com/chmouel/alfred-pr-workflow) uses\n colors to display pull request states.\n\n[See below for how to configure this](#script-filters-configuration)\n\n#### Web Searches\n\nThe native interface supports quick web searches via URL templates. Type a configured keyword followed by your query, and the launcher will open your default browser with the search results.\n\nExample: typing `g rust traits` opens Google search for \"rust traits\" in your browser.\n\nCommon search engines are pre-configured in the example config (Google, DuckDuckGo, GitHub, Wikipedia, etc.), and you can add any search engine by providing a URL template with a `{query}` placeholder.\n\n[See below for how to configure this](#web-search-configuration)\n\n#### Text Snippets\n\nThe native interface supports text snippets, which let you define reusable text values that can be searched and copied to the clipboard. Snippets can come from three sources: inline in the config, an external YAML file, or a command's output (using the same Alfred JSON format as script filters).\n\nType a configured keyword to display the snippets from that source, then continue typing to fuzzy-filter by name. Selecting a snippet copies its value to the clipboard via `wl-copy`.\n\n[See below for how to configure this](#text-snippets-configuration)\n\n#### File Browser\n\nThe native interface includes a built-in file browser. Typing `/` browses the root filesystem and `~` browses the home directory. Selecting a directory navigates into it, while selecting a file opens it with `xdg-open`. Alt+Enter copies the file path to the clipboard instead. Tab autocompletes the selected entry into the search bar. Ctrl+H toggles hidden file visibility. Text after the last `/` fuzzy-filters the current directory listing (e.g., `/home/us` filters `/home/` by \"us\"). Directories are listed first in accent colour.\n\nThe file browser is enabled by default and can be disabled or configured under `addons.file_browser` ([see below](#addon-configuration)).\n\n## Configuration\n\n### Fuzzel Configuration\n\nFuzzel appearance can be configured through `~/.config/fuzzel/fuzzel.ini`. Refer to the [Fuzzel manual](https://man.archlinux.org/man/fuzzel.ini.5.en) for full details.\n\nExample:\n\n```ini\ndpi-aware=yes\nfont=RobotoMonoNerdFont-Thin:size=16\nterminal=kitty\nwidth=50\nlayer=overlay\nexit-on-keyboard-focus-loss=no\ninner-pad=15\nfields=filename,name\n\n[colors]\nbackground=282a36ff\ntext=f8f8f2ff\nmatch=8be9fdff\nselection-match=8be9fdff\nselection=44475add\nselection-text=f8f8f2ff\nborder=bd93f9ff\n```\n\n### Raffi Configuration\n\nConfiguration is stored in:\n\n```\n$HOME/.config/raffi/raffi.yaml\n```\n\nBasic example:\n\n```yaml\nfirefox:\n  binary: firefox\n  args: [--marionette]\n  icon: firefox\n  description: Firefox browser with marionette enabled\n```\n\nThe `binary` field defines the executable. If the binary is not present in PATH, the entry is ignored.\nThe `description` field defines the label shown in the launcher.\nThe `args` field defines optional command‑line arguments.\nThe `icon` field defines an icon name or absolute path. Icons are cached and can be refreshed with `-r`.\nThe `script` field defines inline script content.\nThe `disabled` field hides the entry when set to true.\n\n### General Settings\n\nPersistent defaults can be set under a `general` key. These are equivalent to command‑line flags and are overridden by them.\n\n```yaml\ngeneral:\n  ui_type: native\n  theme: light\n  no_icons: true\n  default_script_shell: /bin/zsh\n  theme_colors:\n    accent: \"#cba6f7\"\n```\n\nThe `ui_type` field selects the interface (`fuzzel` or `native`).\nThe `theme` field selects the colour theme for the native interface. `dark` (default) uses a Dracula‑inspired palette; `light` uses Rose Pine Dawn.\nThe `no_icons` field disables icon loading when set to true.\nThe `default_script_shell` field sets the default interpreter for inline scripts.\n\nIndividual theme colours can be customised under `theme_colors`. Each field\naccepts a hex colour string (`#RGB`, `#RRGGBB`, or `#RRGGBBAA`). Only the\ncolours you specify are overridden; the rest come from the base theme.\n\nAvailable colour keys: `bg_base`, `bg_input`, `accent`, `accent_hover`,\n`text_main`, `text_muted`, `selection_bg`, `border`.\n\nExample (Catppuccin Mocha on top of the dark base theme):\n\n```yaml\ngeneral:\n  theme: dark\n  theme_colors:\n    bg_base: \"#1e1e2e\"\n    bg_input: \"#313244\"\n    accent: \"#cba6f7\"\n    accent_hover: \"#89b4fa\"\n    text_main: \"#cdd6f4\"\n    text_muted: \"#6c7086\"\n    selection_bg: \"#45475a\"\n    border: \"#585b70\"\n```\n\n### Scripts\n\nEntries can run inline scripts instead of binaries. Scripts use `bash` by default, or another interpreter if configured via `--default-script-shell` or by explicitly setting `binary`.\n\nExample:\n\n```yaml\nhello_script:\n  script: |\n    echo \"hello world and show me your env\"\n    env\n  description: \"Hello Script\"\n  icon: \"script\"\n```\n\nPython example:\n\n```yaml\nhello_script:\n  binary: python3\n  script: |\n    import os\n    print(\"hello world and show me your env\")\n    print(os.environ)\n  description: \"Hello Python script\"\n  icon: \"script\"\n```\n\n### Conditional Display\n\nEntries can be shown or hidden based on simple conditions. Only one condition is supported per entry.\n\nConditions include checking whether a binary exists, whether an environment variable is set, not set, or equal to a specific value.\n\nExample:\n\n```yaml\nifenveq: [DESKTOP_SESSION, GNOME]\nifenvset: WAYLAND_DISPLAY\nifexist: firefox\n```\n\n### Path Expansion\n\nConfig values for most fields except the script field support path expansion:\n\n- `~/` is expanded to the user's home directory\n- `${VAR}` is replaced with the environment variable value (unset variables\nexpand to empty string)\n\nExample:\n\n```yaml\nmyapp:\n  binary: ${HOME}/bin/myapp\n  args: [\"${XDG_DATA_HOME}/files\", \"~/Documents\"]\n  icon: ~/icons/myapp.png\n  ifexist: ~/bin/myapp\n```\n\n### Addon Configuration\n\nThe native interface includes optional addons for calculations, currency conversion, file browsing, script filters, text snippets, and web searches.\n\n```yaml\naddons:\n  currency:\n    enabled: true\n    trigger: \"€\"\n    default_currency: EUR\n    currencies: [\"EUR\", \"USD\", \"GBP\"]\n  calculator:\n    enabled: true\n  file_browser:\n    enabled: true\n    show_hidden: false\n```\n\nThe `enabled` field controls whether the addon is active.\nThe `show_hidden` field for the file browser sets the initial hidden-file visibility (default `false`; toggled at runtime with Ctrl+H).\nThe `trigger` field sets the character that activates currency conversion. Defaults to `$` if omitted. Can be set to `€`, `£`, or any other symbol.\nThe `default_currency` field sets the source currency used when none is specified (e.g., `€10 to GBP` converts from EUR). Defaults to USD if omitted.\nThe `currencies` field for the currency addon defines which currencies are available for conversion.\nYou don't need to add a prefix for the calculator; simply typing a valid expression will show the result.\n\nAll three addons are enabled by default.\n\n#### Script Filters Configuration\n\nScript filters are configured under `addons.script_filters`. Here is an example using the [batz](https://github.com/chmouel/batzconverter) time converter (shown in the screenshot above):\n\n```yaml\naddons:\n  script_filters:\n    - name: \"Timezones\"\n      keyword: \"tz\"\n      command: \"batz\"\n      args: [\"-j\"]\n      icon: \"clock\"\n```\n\nThis will parse the output of `batz -j` and display it in the launcher when the\nuser types `tz` followed by a query. The script must output JSON in the format\ndescribed below.\n\nAn example with both a primary and secondary action:\n\n```yaml\naddons:\n  script_filters:\n    - name: \"Bookmarks\"\n      keyword: \"bm\"\n      command: \"my-bookmark-script\"\n      args: [\"-j\"]\n      action: \"echo -n {value}|wl-copy\"\n      secondary_action: \"xdg-open {value}\"\n```\n\nHere, pressing Enter copies the selected bookmark URL to the clipboard, while\nAlt+Enter opens it in the default browser.\n\nHere is the meaning of each field in the script filter configuration:\n\n| Field     | Required | Description                                                          |\n|-----------|----------|----------------------------------------------------------------------|\n| `name`    | yes      | Display name shown during loading                                    |\n| `keyword` | yes      | Text that activates the script filter                                |\n| `command` | yes      | Executable to run                                                    |\n| `args`    | no       | Arguments passed before the query                                    |\n| `icon`    | no       | Fallback icon name for results without their own                     |\n| `action`  | no       | Command template run on Enter; `{value}` is replaced with the selected value. Executed via `sh -c`. If omitted, the value is copied to the clipboard with `wl-copy`. |\n| `secondary_action` | no | Command template run on Alt+Enter; same `{value}` substitution and `sh -c` execution as `action`. If omitted, Alt+Enter behaves the same as Enter. |\n\nThe script must output JSON matching this structure (a subset of Alfred's format):\n\n```json\n{\n  \"items\": [\n    {\n      \"title\": \"New York\",\n      \"subtitle\": \"EST (UTC-5) — 14:30\",\n      \"arg\": \"America/New_York\",\n      \"icon\": { \"path\": \"/usr/share/icons/clock.png\" }\n    }\n  ]\n}\n```\n\n| Field          | Required | Description                                     |\n|----------------|----------|-------------------------------------------------|\n| `title`        | yes      | Main text displayed for the item                |\n| `subtitle`     | no       | Secondary text shown below the title            |\n| `arg`          | no       | Value copied to clipboard (falls back to title) |\n| `icon.path`    | no       | Absolute path to a PNG or SVG icon              |\n\n### Web Search Configuration\n\nWeb searches are configured under `addons.web_searches`. Each entry defines a keyword and URL template:\n\n```yaml\naddons:\n  web_searches:\n    - name: \"Google\"\n      keyword: \"g\"\n      url: \"https://google.com/search?q={query}\"\n      icon: \"google\"\n```\n\nWhen you type the keyword followed by a space and query (e.g., `g rust async`), the launcher displays a search row. Pressing Enter opens your browser with the URL template, replacing `{query}` with your search terms (properly percent-encoded).\n\nField descriptions:\n\n| Field     | Required | Description                                                          |\n|-----------|----------|----------------------------------------------------------------------|\n| `name`    | yes      | Display name shown in the search row (e.g., \"Search Google for...\")  |\n| `keyword` | yes      | Text that activates the web search (e.g., \"g\", \"ddg\")                |\n| `url`     | yes      | URL template with `{query}` placeholder for the search terms         |\n| `icon`    | no       | Icon name from your icon cache to display next to the search row     |\n\nThe URL template's `{query}` placeholder is replaced with your search terms, automatically percent-encoded for safe URL use. For example, `g hello world` becomes `https://google.com/search?q=hello%20world`.\n\n### Text Snippets Configuration\n\nText snippets are configured under `addons.text_snippets`. Each entry defines a keyword and a source for the snippets (inline, file, or command).\n\nInline snippets:\n\n```yaml\naddons:\n  text_snippets:\n    - name: \"Emails\"\n      keyword: \"em\"\n      icon: \"mail\"\n      snippets:\n        - name: \"Personal Email\"\n          value: \"user@example.com\"\n        - name: \"Work Email\"\n          value: \"user@company.com\"\n```\n\nFile source (YAML file containing a list of `name`/`value` pairs):\n\n```yaml\naddons:\n  text_snippets:\n    - name: \"Templates\"\n      keyword: \"tpl\"\n      icon: \"document\"\n      file: \"~/.config/raffi/snippets.yaml\"\n```\n\nThe snippet file uses the same format:\n\n```yaml\n- name: \"Greeting\"\n  value: \"Hello, world!\"\n- name: \"Signature\"\n  value: \"Best regards, User\"\n```\n\nCommand source (outputs Alfred Script Filter JSON):\n\n```yaml\naddons:\n  text_snippets:\n    - name: \"Dynamic\"\n      keyword: \"dyn\"\n      icon: \"terminal\"\n      command: \"my-snippet-gen\"\n      args: [\"-j\"]\n```\n\nThe command must output JSON in the same format used by [script filters](#script-filters-configuration). The `title` field maps to the snippet name and `arg` to the snippet value.\n\nDirectory source (a directory of `.snippet` files):\n\n```yaml\naddons:\n  text_snippets:\n    - name: \"Snippets\"\n      keyword: \"sn\"\n      icon: \"snippets\"\n      directory: \"~/.local/share/desktop-config/snippets\"\n```\n\nEach `.snippet` file has the format:\n\n```\nDescription (first line)\n---\nActual snippet content (everything after the separator)\n```\n\nThe first line becomes the snippet name, everything after `---` becomes the value. Files are sorted alphabetically by name and cached per session.\n\nField descriptions:\n\n| Field       | Required | Description                                                            |\n|-------------|----------|------------------------------------------------------------------------|\n| `name`      | yes      | Display name shown during loading (command source)                     |\n| `keyword`   | yes      | Text that activates the snippet source                                 |\n| `icon`      | no       | Icon name from your icon cache to display next to each snippet         |\n| `snippets`  | no       | Inline list of snippets (each with `name` and `value`)                 |\n| `file`      | no       | Path to a YAML file containing snippets (cached per session)           |\n| `command`   | no       | Executable that outputs Alfred Script Filter JSON                      |\n| `directory` | no       | Path to a directory of `.snippet` files (cached per session)           |\n| `args`      | no       | Arguments passed to the command                                        |\n\nExactly one of `snippets`, `file`, `command`, or `directory` should be specified per entry. On selection, the snippet's value is copied to the clipboard using `wl-copy`.\n\n## Development\n\nContributions are welcome. Issues, feature requests, and pull requests can be submitted via GitHub.\n\nTo enable pre‑commit hooks that run `cargo clippy` before pushing:\n\n```sh\npip install pre-commit\npre-commit install\n```\n\n## Screenshots\n\n### File Browser (`/`)\n\u003cimg width=\"321\" height=\"224\" alt=\"optimized-file-browse\" src=\"https://github.com/user-attachments/assets/bbfbe937-c590-43c9-8853-9aaf786a3dc6\" /\u003e\n\n### Currency Converter (`$`)\n\u003cimg width=\"522\" height=\"150\" alt=\"image\" src=\"https://github.com/user-attachments/assets/aaf35e3f-1cef-4604-b87a-ecfa626300c1\" /\u003e\n\n## Calculator\n\u003cimg width=\"522\" height=\"150\" alt=\"image\" src=\"https://github.com/user-attachments/assets/eb7069c9-21f7-413d-b455-c2db186591d5\" /\u003e\n\n### Script Filter with github PR browser\n\u003cimg width=\"441\" height=\"559\" alt=\"optimized-pull-requests-dashboard\" src=\"https://github.com/user-attachments/assets/48da3b90-b8dd-4f4d-8465-3ae27fe267c3\" /\u003e\n\n### Script Filter with timezone converter\n\u003cimg width=\"522\" height=\"400\" alt=\"image\" src=\"https://github.com/user-attachments/assets/f65acf34-b499-477d-9952-48590723d5bb\" /\u003e\n\n### Light Theme\n\u003cimg width=\"403\" height=\"473\" alt=\"suspend-to-sleep-then-hibernate\" src=\"https://github.com/user-attachments/assets/9c6549dc-be51-422d-9b82-5dbbb89779b6\" /\u003e\n\n## Licence\n\nThis project is released under the MIT Licence.\n\n## Author\n\nChmouel Boudjnah\n\n- GitHub: [https://github.com/chmouel](https://github.com/chmouel)\n- Fediverse: [https://fosstodon.org/@chmouel](https://fosstodon.org/@chmouel)\n- Twitter: [https://twitter.com/chmouel](https://twitter.com/chmouel)\n- Blog: [https://blog.chmouel.com](https://blog.chmouel.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchmouel%2Fraffi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchmouel%2Fraffi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchmouel%2Fraffi/lists"}