{"id":13735075,"url":"https://github.com/cerebroapp/create-cerebro-plugin","last_synced_at":"2025-10-10T10:32:32.775Z","repository":{"id":41331378,"uuid":"92755383","full_name":"cerebroapp/create-cerebro-plugin","owner":"cerebroapp","description":"Create Cerebro plugins with no configuration","archived":false,"fork":false,"pushed_at":"2022-12-11T15:36:01.000Z","size":179,"stargazers_count":28,"open_issues_count":0,"forks_count":10,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-08-31T19:43:48.158Z","etag":null,"topics":["cerebro","cerebro-plugin","development"],"latest_commit_sha":null,"homepage":"https://cerebroapp.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cerebroapp.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-29T16:09:39.000Z","updated_at":"2025-06-19T20:27:28.000Z","dependencies_parsed_at":"2023-01-27T02:15:32.985Z","dependency_job_id":null,"html_url":"https://github.com/cerebroapp/create-cerebro-plugin","commit_stats":null,"previous_names":["kelion/create-cerebro-plugin"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/cerebroapp/create-cerebro-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cerebroapp%2Fcreate-cerebro-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cerebroapp%2Fcreate-cerebro-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cerebroapp%2Fcreate-cerebro-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cerebroapp%2Fcreate-cerebro-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cerebroapp","download_url":"https://codeload.github.com/cerebroapp/create-cerebro-plugin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cerebroapp%2Fcreate-cerebro-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277595068,"owners_count":25844742,"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","status":"online","status_checked_at":"2025-09-29T02:00:09.175Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["cerebro","cerebro-plugin","development"],"created_at":"2024-08-03T03:01:02.746Z","updated_at":"2025-10-10T10:32:32.740Z","avatar_url":"https://github.com/cerebroapp.png","language":"JavaScript","funding_links":[],"categories":["Development"],"sub_categories":["Operational System Exclusives"],"readme":"# Create Cerebro Plugin\n\nFastest way to create Cerebro plugins.\n\n\n## Quick Overview\nBefore start make sure you have installed yarn package manager. Follow [installation instructions](https://yarnpkg.com/lang/en/docs/install/) if you don't.\n\n\n```\nyarn create cerebro-plugin my-plugin\ncd ./my-plugin\nyarn start\n```\n\n# Plugins\n\nA Cerebro plugin is just a javascript module. All you need is to write a function, that takes one object and call a function from arguments with your results.\n\nYou can create your plugin using [create-cerebro-plugin](https://github.com/cerebroapp/create-cerebro-plugin) so you can focus on code of your plugin, not on tools and configuration around it.\n### Prerequisites\n\n* [Node.js](https://nodejs.org/en/) (\u003e= 16)\n* [yarn](https://classic.yarnpkg.com/en/)\n\n### Install and manage custom plugins\n\nSometimes you need to manually install a plugin (maybe you have published it to npm but you dind't added the keywords to the package.json so it is not available in Cerebro).\nIf you want to test this plugin, you can install it manually:\n\n1. Open a terminal in the [configuration directory](/docs/cerebro-developers.md#config-file-path) of Cerebro\n2. Go to the plugins directory\n\n    ```bash\n    cd ./plugins\n    ```\n\n3. Install the plugin\n\n    ```bash\n    npm install --save name-of-plugin\n    ```\n\n4. Restart Cerebro\n\n\n# Plugin structure\n\nThis is a minimum source code of your plugin:\n\n```js\nexport const fn = (scope) =\u003e console.log(scope.term)\n```\n\n\u003e You can open the developer tools by pressing `ctrl+shift+i`(for the main window) and `ctrl+shift+b`(for the background). Developer mode should be enabled from the settings\n\nThis plugin will write to console all changes in your search field of Cerebro app. So, `fn` key is a heart of your plugin: this function receives `scope` object and you can send results back to Cerebro. Scope object is:\n\n* `term` – `String`, entered by Cerebro user;\n* `display` – `Function(result: Object | Array\u003cobject\u003e)`, display your result\n* `update` – `Function(id: String, result: Object)`, update your previously displayed result. This action updates only passed fields, so if you displayed result `{id: 1, title: 'Result'}` and call `update(1, {subtitle: 'Subtitle'})`, you will have merged result: `{id: 1, title: 'Result', subtitle: 'Subtitle'}`;\n* `hide` – `Function(id: String)`, hide result from results list by id. You can use it to remove temporar results, like \"loading...\" placeholder;\n* `actions` – object with main actions, provided for cerebro plugins:\n  * `open` – `Function(path: String)`, open external URL in browser or open local file;\n  * `reveal` – `Function(path: String)`, reveal file in finder;\n  * `copyToClipboard` – `Function(text: String)`, copy text to clipboard;\n  * `replaceTerm` – `Function(text: String)`, replace text in main Cerebro input;\n  * `hideWindow` – `Function()`, hide main Cerebro window.\n* `settings` - `Object`, contains user provided values of all specified settings keys;\n\nLet's show something in results list:\n\n```js\nexport const fn = (scope) =\u003e {\n  scope.display({\n    title: 'It works!',\n    subtitle: `You entered ${scope.term}`\n  })\n}\n```\n\n`scope.display` accepts one result object or array of result objects. Result object is:\n\n## Basic fields\n\n### `title`\n\nType: `String`\n\nTitle of your result;\n\n### `subtitle`\n\nType: `String`\n\nSubtitle of your result;\n\n### `icon`\n\nType: `String`\n\nIcon, that is shown near your result. It can be absolute URL to external image, absolute path to local image or base64-encoded [data-uri](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs).\n\nFor local icons you can use path to some `.app` file, i.e. `/Applications/Calculator.app` will render default icon for Calculator application.\n\n## Advanced fields\n\n### `id`\n\nType: `String`\nUse this field when you need to update your result dynamically. Check `id` [example](./examples.md#using-id)\n\n### `term`\n\nType: `String`\n\nAutocomplete for your result. So, user can update search term using \u003ckbd\u003etab\u003c/kbd\u003e button;\n\n### `clipboard`\n\nType: `String`\n\nText, that will be copied to clipboard using \u003ckbd\u003ecmd+c\u003c/kbd\u003e, when your result is focused;\n\n### `getPreview`\n\nType: `Function`\n\nArguments: no\n\nFunction that returns preview for your result. Preview can be an html string or React component;\n\n### `onSelect`\n\nType: `Function`.\nArguments: `event: Event`\n\nAction, that should be executed when user selects your result. I.e, to open provided url in default browser:\n\n```js\nonSelect: (event) =\u003e actions.open(`http://www.cerebroapp.com`),\n```\n\nIf you don't want to close main window after your action, you should call `event.preventDefault()` in your action.\n\n### `onKeyDown`\n\nType: `Function`\n\nArguments: `event: Event`\n\nHandle keyboard events when your result is focused, so you can do custom actions, i.e. reveal file in finder by \u003ckbd\u003ecmd+r\u003c/kbd\u003e (or \u003ckbd\u003ectrl+r\u003c/kbd\u003e on windows and linux):\n\n```js\nonKeyDown: (event) =\u003e {\n  if ((event.metaKey || event.ctrlKey) \u0026\u0026 event.keyCode === 82) {\n    actions.reveal(path);\n    event.preventDefault();\n  }\n}\n```\n\nYou can also prevent default action by `event.preventDefault()`.\n\n## Advanced plugin fields\n\nAlong with `fn`, your module could have more keys:\n\n### `keyword`\n\nType: `String`\n\nThis field is used for autocomplete. You can prefix your plugin usage by this keyword. Checkout emoji [example](./examples.md#using-keyword-and-name)\n\n### `name`\n\nType: `String`\n\nThis field is also used for autocomplete and shown as title in results list. Checkout emoji [example](./examples.md#using-keyword-and-name)\n\n### `initialize`\n\nType: `Function`\nArguments: no\n\nUse this function, when you need to prepare some data for your plugin on start. If you need to do some long-running processes, check `initializeAsync`\n\nCheck `initialize` [example](./examples.md#using-initialize)\n\n### `initializeAsync`\n\nType: `Function`\n\nArguments: `callback: Function(message: Object)` – callback to send data back to main process.\n\nUse this function when you need to execute some long-running initializer process. I.e. in contacts plugin we are fetching all contacts using osx-specific libraries using `nodobjc` module.\n\nThis function will be executed in another process and you can receive results using `onMessage` function.\n\nCheck `initializeAsync` and `onMessage` [example](./examples.md#using-initializeasync-and-onmessage)\n\n### `onMessage`\n\nType: `Function`\nArguments: `message: Object` – object that you sent from `initializeAsync`\n\nUse this function to receive data back from your `initializeAsync` function.\n\nCheck `initializeAsync` and `onMessage` [example](./examples.md#using-initializeasync-and-onmessage)\n\n### `settings`\n\nType: `Object`\n\nThis object is used to specify settings that a plugin user can change. Each setting should include a `description` and a `type`. Other keys include:\n\n* `label` - `String`, object key for the setting. also used to access it;\n* `description` -  `String`, description of the setting;\n* `type` - `String`, used to decide element for rendering a setting:\n  * `string`\n  * `number`\n  * `bool`\n  * `option`\n* `defaultValue` - `Any`, default value for the setting;\n* `options` - `Array`, all possible options that can be selected by the user. applicable only for `option`;\n* `multi` - `Bool`, allows user to select more than one option for `option` settings. applicable only for `option`;\n* `createable` - `Bool`, allows user created options. applicable only for `option`;\n\nCheck `settings` [example](./examples.md#using-settings)\n\nTake a look at [React Select](https://github.com/JedWatson/react-select) for more details on how the `option` type works.\n\n## Available `env` variables\n\nThe following variables are available in the `process.env` object:\n\n* `CEREBRO_VERSION` – Version of Cerebro\n* `CEREBRO_DATA_PATH` – Path to Cerebro data directory\n\n\n## Styles for your plugin preview\n\nCurrently if you want to reuse main app styles, you can use CSS variables from main themes (light, dark)\n\n\u003e It is better to reuse css variables so custom themes can affect not only main app styles, but your plugin too.\n\nExample (reuse main border styles):\n\n```css\n.item {\n  border-bottom: var(--main-border);\n}\n```\n\n### Reusable components\n\n- [@cerebroapp/cerebro-ui](https://github.com/cerebroapp/cerebro-ui)\n\n\n## Share\n\nWhen your plugin is ready, you can share it with all Cerebro users so they can find and install it using `plugins` command in Cerebro.\n\nAll you need is to publish your module to npm. Just run from your plugin folder:\n\n```bash\nnpm publish ./\n```\n\nIf you have any problems check out [publishing packages](https://docs.npmjs.com/getting-started/publishing-npm-packages) in npm documentation\n\n### Checklist\n\n1. Update your repository `Readme.md`, add screenshot or gif;\n1. Push your plugin to open github repository – this repository is used by cerebro, at least to show `Readme.md` of your plugin;\n1. Make sure that you have changed package.json metadata: module name, description, author and link to github repository;\n1. Add `cerebro-plugin` keyword to package.json keywords section. Otherwise your plugin won't be shown in Cerebro;\n\n# Examples\n\nYou always can check out source code of existing plugins, like:\n\n* [cerebro-math](https://github.com/cerebroapp/cerebro-math)\n* [cerebro-google](https://github.com/cerebroapp/cerebro-google)\n* [cerebro-emoj](https://github.com/cerebroapp/cerebro-emoj)\n* [cerebro-gif](https://github.com/cerebroapp/cerebro-gif)\n* [cerebro-kill](https://github.com/cerebroapp/cerebro-kill)\n* [cerebro-ip](https://github.com/cerebroapp/cerebro-ip)\n\n## Using `id`\n\n```js\nexport const fn = ({display}) =\u003e {\n  display({\n    id: 'my-id',\n    title: 'Loading'\n  })\n  fetchResult().then((result) =\u003e {\n    display({\n      id: 'my-id',\n      title: `Fetched result: ${result}`\n    })\n  });\n}\n```\n\n## Using `icon`\n\n```js\nimport icon from '[path-to-icon]/icon.png';\n\nconst plugin = ({display}) =\u003e {\n  display({\n    icon,\n    title: 'Title',\n    subtitle: 'Subtitle'\n  });\n}\n\nexport default {\n  fn: plugin,\n}\n```\n\n## Using `keyword` and `name`\n\n```js\nconst plugin = (scope) =\u003e {\n  const match = scope.term.match(/^emoj\\s(.+)/);\n  if (match) {\n    searchEmojis(match[1]).then(results =\u003e {\n      scope.display(results)\n    })\n  };\n}\n\nexport default {\n  name: 'Search emojis...',\n  fn: plugin,\n  keyword: 'emoj'\n}\n\n```\n\n## Using `initialize`\n\n```js\n// Some data needed for your plugin\nlet data;\n\n// Fetch some data only on app initialization\nconst initialize = () =\u003e {\n  fetchYourData().then(result =\u003e {\n    data = result\n  });\n}\n\nconst plugin = (scope) =\u003e {\n  const results = search(data, scope.term);\n  scope.display(results);\n}\n\nexport default {\n  initialize: initialize,\n  fn: plugin\n}\n```\n\n## Using `initializeAsync` and `onMessage`\n\n```js\nlet data;\n\n// Run some long-running initialization process in background\nconst initialize = (cb) =\u003e {\n  fetchYourData().then(cb);\n  // and re-fetch this information once in 1h\n  setInterval(() =\u003e {\n    initialize(cb);\n  }, 60 * 3600);\n}\n\nconst onMessage = (results) =\u003e {\n  data = results;\n}\n\nconst plugin = (scope) =\u003e {\n  const results = search(data, scope.term);\n  scope.display(results);\n}\n\nexport default {\n  initializeAsync: initialize,\n  onMessage: onMessage,\n  fn: plugin\n}\n```\n\n## Using `cerebro-tools`\n\n```js\nimport { memoize, search } from 'cerebro-tools';\nimport preprocessJson from './preprocessJson';\n\n// Memoize your fetched data from external API\nconst fetchData = memoize(() =\u003e {\n  return fetch('http://api/url')\n    .then(response =\u003e response.json())\n    .then(preprocessJson)\n});\n\nconst plugin = ({term, display}) =\u003e {\n  fetchData().then(data =\u003e {\n    const results = search(data, term, (el) =\u003e el.name);\n    display(term);\n  })\n}\n\nexport default {\n  fn: plugin\n};\n```\n\n## using `settings`\n\n```js\nconst plugin = ({ display, settings }) =\u003e {\n  const icon = require('[path-to-icon]/icon.png');\n\n  display({\n    icon: settings.icon ? icon : '',\n    title: `${settings.username}, you have been around for ${settings.age}`,\n    subtitle: `Favorite languages: ${settings.languages.join(',')}`,\n  })\n}\n\nexport default {\n  fn: plugin,\n  settings: {\n    username: { type: 'string' },\n    age: { type: 'number', defaultValue: 42 },\n    icon: { type: 'bool' },\n    languages: {\n      type: 'option',\n      description: 'Your favorite programming languages'\n      options: [\n        { label: 'JavaScript', value: 'js' },\n        { label: 'Haskell', value: 'hsk' },\n        { label: 'Rust', value: 'rs' }\n      ],\n      multi: true,\n      createable: true,\n    }\n  }\n}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcerebroapp%2Fcreate-cerebro-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcerebroapp%2Fcreate-cerebro-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcerebroapp%2Fcreate-cerebro-plugin/lists"}