{"id":21736386,"url":"https://github.com/kyza/scrype","last_synced_at":"2026-05-18T01:31:33.730Z","repository":{"id":160533622,"uuid":"612881287","full_name":"Kyza/scrype","owner":"Kyza","description":"Script your typing.","archived":false,"fork":false,"pushed_at":"2023-03-29T17:41:50.000Z","size":222,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"trunk","last_synced_at":"2025-03-19T23:41:37.256Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/Kyza.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}},"created_at":"2023-03-12T09:03:52.000Z","updated_at":"2023-06-23T16:19:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"cf99ee3b-ed9b-415b-8e8c-a8b220d1e53e","html_url":"https://github.com/Kyza/scrype","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/Kyza%2Fscrype","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Fscrype/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Fscrype/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kyza%2Fscrype/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kyza","download_url":"https://codeload.github.com/Kyza/scrype/tar.gz/refs/heads/trunk","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244715168,"owners_count":20497979,"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-11-26T05:18:32.917Z","updated_at":"2026-05-18T01:31:33.694Z","avatar_url":"https://github.com/Kyza.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Scrype\n\nScript your typing.\n\n## What is this?\n\nScrype is a cross-platform program that watches what you type and runs scripts when it detects certain strings have been typed.\n\nThose scripts are run in [Deno](https://github.com/denoland/deno), and can then perform actions and return text to type out in response.\n\nFor example you could type `shrug`, Scrype would erase that, and the script would type out `¯\\_(ツ)_/¯`.\n\n### Macros\n\nMacros are defined as folders in the Scrype config directory.\n\nMacros have configs that match text, and JavaScript scripts that run when those matches are met in the text you type.\n\n### Prefixes \u0026 Suffixes\n\nYou can provide global prefixes and suffixes to matches. If you defined `;;` as your suffix, and had a script matching `shrug`, you would need to type out `shrug;;` to trigger it.\n\nThis feature exists because in alternatives such as [Espanso](https://github.com/espanso/espanso)--the inspiration for this project--, macros have to define prefixes and suffixes themselves, and often use different ones. Different people also prefer different setups. That problem frequently causes confusion when trying to memorize how to use macros you download.\n\n## Features\n\n✅ Implemented | 🌱 In Progress | ⏲️ Planned | ❔ Considering\n\n| Feature | Status | How To Implement | Progress |\n| :-: | :-: | :-: | :-: |\n| [Deno](https://github.com/denoland/deno) Code Runner | ✅ |  |  |\n| Native Code Runner | ❔ | Run compiled libraries in FFI. |  |\n| Global Prefix \u0026 Suffix | ✅ |  |  |\n| Macro Permissions With Deno | ⏲️ | Set Deno args in main config. |  |\n| Text Pasting | ✅ |  |  |\n| Direct Text Injection | 🌱 | Write native bindings for each platform. | Working on Windows. |\n| Text Matching | ✅ |  |  |\n| RegEx Matching | ⏲️ | Match using RegEx in Rust, then pass the matched groups to the script. |  |\n| [Pomsky](https://github.com/pomsky-lang/pomsky) Matching | ⏲️ | The same as RegEx, but use the Pomsky core to match instead. |  |\n| Custom Deno Path | ⏲️ | Set path in main config. |  |\n| Backspace To Undo | ⏲️ | Track how many characters are sent and the history match of the last macro. |  |\n| Android | ❔ | Use accessibility API. |  |\n\n## Ideas\n\n### Setting Storage\n\nYou can use [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage#examples) to save settings for specific scripts that persist between runs.\n\n### GUI\n\nYou can use [Gluon](https://github.com/gluon-framework/gluon) or [WebView](https://github.com/webview/webview_deno) to show temporary GUIs to take more complex input.\n\nNote that while these windows are open, all macros are paused and no more typing gets tracked.\n\n#### Eval Example\n\nHere's an example script that opens a window using WebView, takes input from it when the user presses enter, evaluates it using JavaScript, and pastes the result.\n\n`index.ts`\n```ts\nimport { SizeHint, Webview } from \"https://deno.land/x/webview@0.7.5/mod.ts\";\n\nconst html = new TextDecoder(\"utf-8\").decode(\n\tDeno.readFileSync(\"./index.html\")\n);\n\nconst webview = new Webview(true, {\n\twidth: 400,\n\theight: 50,\n\thint: SizeHint.FIXED,\n});\nwebview.title = \"Eval\";\n\nwebview.navigate(`data:text/html,${encodeURIComponent(html)}`);\nwebview.bind(\"resolve\", (text) =\u003e {\n\twebview.destroy();\n\tconsole.log(`[SCRYPE]:${JSON.stringify({ type: \"PASTE\", data: { text } })}`);\n});\nwebview.bind(\"exit\", () =\u003e {\n\twebview.destroy();\n});\nwebview.run();\n```\n`index.html`\n```html\n\u003chtml\u003e\n\t\u003cbody style=\"margin: 0\"\u003e\n\t\t\u003cinput\n\t\t\tstyle=\"\n\t\t\t\twidth: 100vw;\n\t\t\t\theight: 100vh;\n\t\t\t\tpadding: 0;\n\t\t\t\tmargin: 0;\n\t\t\t\toutline: none;\n\t\t\t\tborder: none;\n\t\t\t\tresize: none;\n\t\t\t\"\n\t\t\ttype=\"text\"\n\t\t\tonkeydown=\"keys(event)\"\n\t\t\tautofocus\n\t\t/\u003e\n\t\t\u003cscript\u003e\n\t\t\tfunction keys(event) {\n\t\t\t\tswitch (event.key) {\n\t\t\t\t\tcase \"Enter\":\n\t\t\t\t\t\tconst evalFunction = new Function(`return (${event.target.value})`);\n\t\t\t\t\t\tlet result = evalFunction();\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresult = JSON.stringify(result);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tresult = result.toString();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresolve(result);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"Escape\":\n\t\t\t\t\t\texit();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\u003c/script\u003e\n\t\u003c/body\u003e\n\u003c/html\u003e\n```\n\nThis is a very basic UI. You can make it as complex as you want.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkyza%2Fscrype","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkyza%2Fscrype","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkyza%2Fscrype/lists"}