Take control of your web.

Weaver is a qt6-webengine browser focused on displaying web pages and offering customizable and scriptable user control mechanisms. There is no gui (or "user chrome") other than the windows that display web content and a few qt6 dialog windows. All behavior is controlled by commands via the comand line and users scripts (example scripts include extensive key bindings, hinting, and styling).


Below is a reference list of all currently available commands. Arguments in brackets are optional. Below the table are notes on a few of the commands that may require further explanation.

Command Arguments Description
action action name Run the specified WebAction in the target window
close N/A Close the currently targetted window
devtools N/A Alias for inspect
exit N/A Alias for quit
help N/A Open this README on the project webpage
incognito N/A Alias for profile with no argument (i.e., ram-only profile)
info [format] Provide information about the focused window following format
inspect N/A Launch a devtools / inspector page for the target window
javascript [script content] Alias for js
js [script content] W/ args, send script to target to run; w/o, check for results
list [format] List every open window with it's index and info
ls [format] Alias for list
open url / search Open the provided url, or send provided text to the search page
profile name Create a new profile named name in the targetted window
quit N/A Close all windows and exit
target index Target the window by index or create a new window if 0
ua user-agent-string Sets a new user-agent-string for the targetted window
useragent user-agent-string Alias for ua


The list of available actions and their names can be found here. For example //action/Back would navigate back one step in the history. Action names are case-sensitive.

//info/, //list/

Either of these commands can be used without arguments and will provide a useful default. But a format string can be provided to customize the output. Format specifiers for this string are in the table below. The default for //info is "%1\t%2" while //list just prepends a window number (this window number can be used for //target).

Placeholder Description
%1 Window title
%2 Full url
%3 All selected text on the page


All javascript calls are run asyncronously. If you do not need the result of the script you provide, then you can use just one call to this command. For example, to popup an alert in the currently targetted window you'd use //js/alert('Hello World');. This would need to be quoted appropriately to be used on the command line to prevent shell interpretation of the parentheses:

weaver "//js/alert('Hello World');"

If you want to get the result of the script (i.e., the value of the last line of the script), you need to make a second call to the //js command but with no parameters. The //js command will either return a message that no data is available (which means the script is still running) or it will return the result (which may be an empty string).

For trivial js calls like //js/location.href you could pass both commands at once and likely have success:

weaver //js/location.href //js

However for any substantial script, there is potential that the results might not be available yet for the second command. It's recommended to either wait a moment between entering the two, or use a sleep command:

weaver "//js/longFunction()"
sleep 0.5
weaver //js

The above assumes longFunction() was already defined on the page, perhaps by a userscript.


The profile command should be provided with a name as a parameter. This name will identify the alternative profile to be used in the target window. It will also define the on-disk name of the profile. If this is an empty string, it will result in a RAM-only profile in which no content is stored to disk. This is often called private mode or incognito mode (thus the //icognito alias for this purpose).

Note, however, that this change in profile applies only to the targetted window. Any subsequently created windows will revert to using the default profile.


Target must be passed an integer parameter and this must either match the index provided in //list output to identify a target window, or it must be 0 to specify that a new window should be created and targetted for subsequent commands.

Note that window indices are dynamic. Internally a list of open windows is maintained. The order of this list can be changed explicitly by //target/ commands, but it will also change every time a window is focused or brought to the front. In these cases, the focused / targetted window is popped from it's previous position in the list and prepended to be at the first position. So if you check a window's index from the //list command, then cycle through windows, that index may no longer point to the same window.

If no target is explicitly specified, most commands will act on the first window in the list (generally the most-recently focused weaver window). Some commands (those that will change window content like close, open, action, etc) will only act on either the currently focused or explicilty targetted windows.


Please see the well commented config.conf in the examples directory. Copy this file (or create your own) under $XDG_CONFIG_HOME/weaver/

User Scripts

User scripts are javascript. Again, userscripts are javascript. Not a subset, not a dialect. Anything you can do in javascript can be done in userscripts. Userscripts can include a greasemonkey style header to define matches / excludes to define which pages the script should be loaded on.

Examples of some of what can be done with userscripts are provided in the *.js files in the examples directory. These include key bindings, hinting, image viewing, and some custom CSS. User submissions of other interesting scripts are most welcome on the ticketting system.


Google services' sign in page actively blocks connections from browsers with QtWebEngine in their user agent string. You can quite easily use google services (calendar, gmail, etc) in weaver, but you need to do the following steps just once to get started.

  1. Set the user agent to a non-webengine string
  2. Log in to a google service
  3. Reset the user agent or just close the ua-spoofing window
  4. From then on you will be able to access google services with out any spoofing

The following command will do step 1 and allow you to do step 2:

weaver //target/0 "//ua/Mozilla/5.0 (Linux x86_64; rv:90.0) Gecko/20100101 Firefox/90.0" calendar.google.com


There most definitely are some, and there will be more. If you see them before I do, feel free to submit detailed descriptions via the ticketting system.

Current issues under investigation

Shift+Insert pastes clipboard rather than primary selection in Qt. This is far from ideal. Options under consideration:

  1. Override event handler to catch this key and ... still not sure how to paste primary
  2. Javascript in keys.js to paste ... but I don't think js can get primary selection
  3. 1+2 runJavascript to paste from event handler?

  4. 2+helper: add weaver://selection type command that returns primary selection content. Then in keys.js handle S+insert ...

Note: middle-click still pastes the primary selection. Perhaps a workaround for shift-insert is not worth the effort.