{"data":{"slug":"sindresorhus-alfy","name":"alfy","tagline":"Create Alfred workflows with ease","github_url":"https://github.com/sindresorhus/alfy","owner":"sindresorhus","repo":"alfy","owner_avatar_url":"https://avatars.githubusercontent.com/u/170270?v=4","primary_language":"JavaScript","stars":2654,"forks":105,"topics":["alfred","alfred-workflow","alfred3-workflow","alfy","framework","javascript","macos","nodejs","workflow"],"archived":false,"github_pushed_at":"2026-02-02T06:00:15+00:00","maintenance_label":"Slowing","url":"https://www.graphcanon.com/tools/sindresorhus-alfy","markdown_url":"https://www.graphcanon.com/tools/sindresorhus-alfy.md","api_url":"https://www.graphcanon.com/api/graphcanon/tools/sindresorhus-alfy","graph_url":"https://www.graphcanon.com/api/graphcanon/graph?tool=sindresorhus-alfy","description":"Create Alfred workflows with ease","homepage_url":null,"license":"MIT","open_issues":0,"watchers":22,"ai_summary":null,"readme_excerpt":"# \n\n> Create [Alfred workflows](https://www.alfredapp.com/workflows/) with ease\n\n## Highlights\n\n- Easy input↔output.\n- Config and [cache](#caching) handling built-in.\n- Fetching remote files with optional caching.\n- Publish your workflow to npm.\n- Automatic [update notifications](#update-notifications).\n- Easily [testable workflows](#testing).\n- [Finds the `node` binary.](run-node.sh)\n- Support for top-level `await`.\n- Presents uncaught exceptions and unhandled Promise rejections to the user.\\\n  *No need to manually `.catch()` top-level promises.*\n\n## Prerequisites\n\nYou need [Node.js 18+](https://nodejs.org) and [Alfred 4 or later](https://www.alfredapp.com) with the paid [Powerpack](https://www.alfredapp.com/powerpack/) upgrade.\n\n## Install\n\n```sh\nnpm install alfy\n```\n\n## Usage\n\n**IMPORTANT:** Your script will be run as [ESM](https://nodejs.org/api/esm.html).\n\n1. Create a new blank Alfred workflow.\n\n2. Add a `Script Filter` (right-click the canvas → `Inputs` → `Script Filter`), set `Language` to `/bin/bash`, and add the following script:\n\n```\n./node_modules/.bin/run-node index.js \"$1\"\n```\n\n*We can't call `node` directly as GUI apps on macOS doesn't inherit the $PATH.*\n\n> Tip: You can use [generator-alfred](https://github.com/SamVerschueren/generator-alfred) to scaffold out an `alfy` based workflow. If so, you can skip the rest of the steps, go straight to the `index.js` and do your thing.\n\n3. Set the `Keyword` by which you want to invoke your workflow.\n\n4. Go to your new workflow directory (right-click on the workflow in the sidebar → `Open in Finder`).\n\n5. Initialize a repo with `npm init`.\n\n6. Add `\"type\": \"module\"` to package.json.\n\n7. Install Alfy with `npm install alfy`.\n\n8. In the workflow directory, create a `index.js` file, import `alfy`, and do your thing.\n\n## Example\n\nHere we fetch some JSON from a placeholder API and present matching items to the user:\n\n```js\nimport alfy from 'alfy';\n\nconst data = await alfy.fetch('https://jsonplaceholder.typicode.com/posts');\n\nconst items = alfy\n\t.inputMatches(data, 'title')\n\t.map(element => ({\n\t\ttitle: element.title,\n\t\tsubtitle: element.body,\n\t\targ: element.id\n\t}));\n\nalfy.output(items);\n```\n\n<img src=\"media/screenshot.png\" width=\"694\">\n\n###### More\n\nSome example usage in the wild: [`alfred-npms`](https://github.com/sindresorhus/alfred-npms), [`alfred-emoj`](https://github.com/sindresorhus/alfred-emoj), [`alfred-ng`](https://github.com/SamVerschueren/alfred-ng).\n\n## Update notifications\n\nAlfy uses [alfred-notifier](https://github.com/SamVerschueren/alfred-notifier) in the background to show a notification when an update for your workflow is available.\n\n<img src=\"media/screenshot-update.png\" width=\"694\">\n\n## Caching\n\nAlfy offers the possibility of caching data, either with the [fetch](#fetchurl-options) or directly through the [cache](#cache) object.\n\nAn important thing to note is that the cached data gets invalidated automatically when you update your workflow. This offers the flexibility for developers to change the structure of the cached data between workflows without having to worry about invalid older data.\n\n## Publish to npm\n\nBy adding `alfy-init` as `postinstall` and `alfy-cleanup` as `preuninstall` script, you can publish your package to [npm](https://npmjs.org) instead of to [Packal](http://www.packal.org). This way, your packages are only one simple `npm install` command away.\n\n```json\n{\n\t\"name\": \"alfred-unicorn\",\n\t\"version\": \"1.0.0\",\n\t\"description\": \"My awesome unicorn workflow\",\n\t\"author\": {\n\t\t\"name\": \"Sindre Sorhus\",\n\t\t\"email\": \"sindresorhus@gmail.com\",\n\t\t\"url\": \"https://sindresorhus.com\"\n\t},\n\t\"scripts\": {\n\t\t\"postinstall\": \"alfy-init\",\n\t\t\"preuninstall\": \"alfy-cleanup\"\n\t},\n\t\"dependencies\": {\n\t\t\"alfy\": \"*\"\n\t}\n}\n```\n\n> Tip: Prefix your workflow with `alfred-` to make them easy searchable through npm.\n\nYou can remove [these](https://github.com/samverschueren/alfred-link#infoplist) properties from your `info.plist` file as they are being added automatically at install time","github_created_at":"2016-07-08T12:58:58+00:00","created_at":"2026-07-15T10:48:29.064999+00:00","updated_at":"2026-07-15T10:48:31.721963+00:00","categories":[{"slug":"developer-tools","name":"Developer Tools","url":"https://www.graphcanon.com/categories/developer-tools","markdown_url":"https://www.graphcanon.com/categories/developer-tools.md","api_url":"https://www.graphcanon.com/api/graphcanon/categories/developer-tools"}],"tags":[{"slug":"alfred","name":"alfred"},{"slug":"alfred-workflow","name":"alfred-workflow"},{"slug":"alfred3-workflow","name":"alfred3-workflow"},{"slug":"alfy","name":"alfy"},{"slug":"framework","name":"framework"},{"slug":"javascript","name":"javascript"},{"slug":"macos","name":"macos"},{"slug":"nodejs","name":"nodejs"}],"trust":{"provenance":{"is_fork":false,"github_id":62888800,"owner_type":"User","methodology":"github_public_v1","parent_repo":null,"near_duplicate_slugs":[]},"computed_at":"2026-07-15T10:48:30.033Z","maintenance":{"label":"Slowing","score":36,"methodology":"github_public_v1","releases_90d":0,"days_since_push":163,"last_release_at":"2026-02-02T06:00:21Z"},"security_summary":{"status":"no_lockfile","scanner":null,"low_count":0,"high_count":0,"last_scan_at":"2026-07-15T10:48:30.491Z","medium_count":0,"scan_profile":"none","critical_count":0}},"capability_facts":{"mcp":{"source":"repo_scan","observed_at":"2026-07-15T10:48:29.801Z","server_manifest":false},"scan":{"source":"repo_scan","observed_at":"2026-07-15T10:48:29.801Z"},"has_cli":{"value":true,"source":"package.json:bin|scripts","observed_at":"2026-07-15T10:48:29.801Z"},"languages":{"value":["javascript"],"source":"github.language+package.json","observed_at":"2026-07-15T10:48:29.801Z"},"license_spdx":{"value":"MIT","source":"github.license","observed_at":"2026-07-15T10:48:29.801Z"}}}}