{"id":20649092,"url":"https://github.com/soulim/q","last_synced_at":"2025-04-17T00:57:39.582Z","repository":{"id":56392033,"uuid":"487561138","full_name":"soulim/q","owner":"soulim","description":"Q is a browser extension that allows you to process web pages with external commands.","archived":false,"fork":false,"pushed_at":"2025-03-18T20:00:01.000Z","size":1128,"stargazers_count":6,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-29T05:51:12.681Z","etag":null,"topics":["browser-extension","nativemessaging","scriptrunner"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/soulim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","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":"2022-05-01T14:39:53.000Z","updated_at":"2025-03-05T06:01:02.000Z","dependencies_parsed_at":"2024-06-21T15:38:50.023Z","dependency_job_id":"2656e7c5-0d8d-41df-812f-7f977857820e","html_url":"https://github.com/soulim/q","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soulim%2Fq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soulim%2Fq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soulim%2Fq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soulim%2Fq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soulim","download_url":"https://codeload.github.com/soulim/q/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249295855,"owners_count":21246203,"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":["browser-extension","nativemessaging","scriptrunner"],"created_at":"2024-11-16T17:12:30.180Z","updated_at":"2025-04-17T00:57:39.562Z","avatar_url":"https://github.com/soulim.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Q\n\n![Screenshot][q-screenshot]\n\nQ is a browser extension that allows to run external commands and process open\npages. It's better explained on examples in the background section below.\n\n## Background\n\nQ started from an idea of keeping browser bookmarks as notes in Obsidian. I\nkeep my personal notes in plain text files (formatted with Markdown) and use\n[Obsidian](https://obsidian.md/) to work with them. So having notes pages as\n`bookmark` sounded as a great idea. To achieve that it was necessary to simply\nsave a URL of a browser tab in a plain text file. Easy? Nope!\n\nAs I learned, browsers are very isolated environments. That makes total sense\nbecause no one wants some JavaScript code loaded on a random page doing some\ncrazy things on a local disk. Therefore, it isn't easy to simply save a URL in a\nplain text file.\n\nDuring my research I discovered \"hackable\" browsers like\n[qutebrowser](https://qutebrowser.org/), [luakit](https://luakit.github.io/),\n[Nyxt](https://nyxt.atlas.engineer/). They allow not only have keyboard\nnavigation, but also process pages with external scripts. That was exactly what\nwas necessary because at that point I wanted not only save bookmark notes, but\nbe able to do anything I want with pages using my scripts.\n\nUnfortunately none of \"hackable\" browsers worked well for me (some have\nannoying bugs, some don't work all platforms I use, and so on). They all great,\nbut not for me. Therefore, I kept doing research and discovered [the\nWebExtensions\nAPI][webextensions-api].\nIt allows to create add-ons that work for all major browsers and it's a\nstandard. That was a starting point for Q.\n\n### Why it's called \"Q\"?\n\n\u003e Q is a fictional character, as well as the name of a race, in Star Trek. ...\n\u003e He is an extra-dimensional being of unknown origin who possesses immeasurable\n\u003e power over time, space, the laws of physics, and reality itself, being\n\u003e capable of altering it to his whim.\n\u003e\n\u003e [Wikipedia](\u003chttps://en.wikipedia.org/wiki/Q_(Star_Trek)\u003e)\n\nQ gives you immeasurable power over pages loaded in the browser. Use it\nresponsibly :wink:\n\n### How it works\n\nQ isn't just a browser extension. It's tiny eco-system consisting of the\nfollowing components:\n\n  1. The browser extension (add-on).\n  2. The host application.\n  3. A configuration file.\n  4. Scripts, or better to say executables, *you* write to do anything *you* like\n   with URLs and pages received from the browser.\n\nThe extension does nothing more than provides a human-friendly interface to\ntalk to the host application.\n\nThe host application is there to serve a list of possible commands to execute,\nand to run a selected command at *your* order. At runtime each command has\naccess to following environment variables provided by the host:\n\n  - `Q_PAGE_URL`, a URL of the page\n  - `Q_PAGE_HTML`, a path to temporary file containing source code of the page\n\nYou define all available commands in a configuration file. See the\nconfiguration section below for all details.\n\nIf you script or executable sends something to the standard output stream\n(STDOUT), Q displays that using notifications. That could be useful for example\nin cases of long running scripts when you would like to be notified about\nfinished operation. However it's totally up to you to decide whether it makes\nsense to display any notification or not. Q isn't going to be \"smart\" to decide\non that for you. It's designed to assist, but never stay on your way.\n\n**NOTE:** by design Q *cannot* execute any random code or run any arbitrary\napp or script available on your machine. It operates only on what *you* define\nas possible in its configuration.\n\n## Install\n\n1. From [the latest release](https://github.com/soulim/q/releases/latest):\n\n    - Download, extract, and place somewhere (for example `$HOME/.local/bin`) the host binary\n    - Install the extension by opening its file with Firefox\n\n2. Using the following template create a manifest file for the native messaging host and place in:\n\n    - Linux: `$(HOME)/.mozilla/native-messaging-hosts`\n    - macOS: `$(HOME)/Library/Application\\ Support/Mozilla/NativeMessagingHosts`\n\n    ```json\n    {\n      \"name\": \"dev.sulim.q\",\n      \"description\": \"Q is a browser extension that allows you to process web pages with external commands.\",\n      \"path\": \"\u003cABSOLUTE_PATH_TO_Q_HOST_BINARY\u003e\",\n      \"type\": \"stdio\",\n      \"allowed_extensions\": [ \"q@sulim.dev\" ]\n    }\n    ```\n\n3. Create a configuration file with commands you would like to execute using Q. See the configuration section below.\n\n## Usage\n\nTODO: Add usage instructions\n\n### Configuration\n\nConfiguration should be defined in `$HOME/.config/q/config.toml`. This file\ncontains a table of available commands.\n\nExample:\n\n```toml\n[commands.bookmark]\nlabel = \"Save as a bookmark note\"\ncommand = \"/home/soulim/.local/share/q/bin/add-bookmark-note\"\n\n[commands.demo-script]\nlabel = \"Run a demo script \"\ncommand = \"/home/soulim/.local/share/q/bin/demo\"\n```\n\nNOTE: `command` keys must use absolute paths to executables as their values.\n\n## Architecture\n\nThe architecture of Q is based and highly influenced by the [WebExtensions\nAPIs][webextensions-api]. There are two main components:\n\n1. the browser extension (or add-on),\n2. the host application.\n\nThe user interacts with the extension in the browser. The extension doesn't\nhave direct access to the host application, but communicates with it via the\n[native messaging][native-messaging] interface provided by the browser. The\nhost application runs external commands or scripts, but only those defined by\nthe user (see configuration below).\n\n![System context diagram][diagram-system-context]\n\n### Command execution flow\n\n![Command execution flow][diagram-command-execution]\n\n### Security\n\n  - The extension never communicates directly with the host. The communication is controlled by the browser.\n  - The extension cannot send any arbitrary command to the host to execute. In other words, it cannot request to execute `rm -rf /`.\n  - The extension does not have access to the list of configured commands. It \"knows\" all commands only by their IDs.\n\n## Contributing\n\nQ is open to code contributions for bug fixes only. As features might carry a\nlong-term maintenance burden, they will not be accepted at this time. Please\n[submit an issue](https://github.com/soulim/q/issues) if you have a feature you\nwould like to request.\n\n## License\n\nCopyright (c) 2022 Alexander Sulim\n\nQ is free software: you can redistribute it and/or modify it under the terms of\nthe GNU General Public License as published by the Free Software Foundation,\neither version 3 of the License, or (at your option) any later version.\n\nSee [COPYING](COPYING) for license text.\n\n[webextensions-api]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs\n[native-messaging]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging\n[diagram-system-context]: docs/context.puml.png\n[diagram-command-execution]: docs/command-execution.puml.png\n[q-screenshot]: docs/q-screenshot.png\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoulim%2Fq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoulim%2Fq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoulim%2Fq/lists"}