Skip to content

Instantly share code, notes, and snippets.

@knatsakis
Last active January 15, 2025 22:32
Show Gist options
  • Save knatsakis/8cf329853330893cd2d7fa3dbd5692b0 to your computer and use it in GitHub Desktop.
Save knatsakis/8cf329853330893cd2d7fa3dbd5692b0 to your computer and use it in GitHub Desktop.
qutebrowser in daemon mode + extras
c.aliases.update({
'recycle': 'quit --save _recycle',
'restart': 'quit --save _restart',
'shutdown': 'quit --save _shutdown',
})
#!/bin/bash -eu
set -o pipefail
DAEMON="${XDG_RUNTIME_DIR}"/qutebrowser
case "${1:-}" in
'--daemon')
shift
while true; do
if [ "${1:-}" == '--restore' ]; then
shift
else
mkdir "${DAEMON}"
fi
BASE="${DAEMON}" "${0}" --no-daemon --nowindow "${@:-}"
done
;;
'--no-daemon')
shift
BASE="${BASE:-$(mktemp -d -p '' qute-nodaemon-XXXXX)}"
SESSION="${BASE}"/data/sessions
while true; do
if ! [ -d "${BASE}"/config ]; then
cp -a "${HOME}/.config/qutebrowser-${USER}" "${BASE}/config"
fi
if ! [ -d "${BASE}"/data ]; then
cp -a "${HOME}/.local/share/qutebrowser-${USER}" "${BASE}/data"
fi
if [ "${SAVED:-}" ]; then
cat <&${SAVED} > "${SESSION}"/_autosave.yml
exec {SAVED}<&- && unset SAVED
fi
if ! python3 -m qutebrowser -B "${BASE}" "${@}"; then
case "${BASE}" in
*"${XDG_RUNTIME_DIR}"*)
mv "${BASE}" "$(mktemp --dry-run --tmpdir='' qute-crash-XXXXX)"
mkdir "${BASE}"
continue ;;
*)
exit 1 ;;
esac
fi
if [ -e "${SESSION}"/_recycle.yml ]; then
exec {SAVED}< "${SESSION}"/_recycle.yml
rm -rf "${SESSION}"/_recycle.yml
continue
fi
if [ -e "${SESSION}"/_restart.yml ]; then
exec {SAVED}< "${SESSION}"/_restart.yml
rm -rf "${BASE}"/*
continue
fi
if [ -e "${SESSION}"/_shutdown.yml ]; then
rm -rf "${BASE}"
exit 1
fi
rm -rf "${BASE}"
exit 0
done
;;
*)
until IPC=$(ls "${DAEMON}"/runtime/ipc-*); do
sleep 0.1 && [ -d "${DAEMON}" ]
done 2> /dev/null
ARGS=$(printf %s\\n "${@:-about:blank}")
jq -c . <<-EOT | socat - "${IPC}"
{
"args": $(jq -R . <<< "${ARGS}" | jq -s .),
"cwd": "${PWD}",
"protocol_version": 1,
"target_arg": "window"
}
EOT
;;
esac
@knatsakis
Copy link
Author

I updated the script to:

  • remove some stuff not needed for general use
  • changed "${@}" to "${@:-}" in line 20

The error you get is probably because MacOS's /bin/bash is pretty old and behaves differently.

I suggest that you either install a new/latest version of bash via homebrew,
or, try this script again, but it may still not work because it hasn't been tested or used with an old bash version.

For reference, my bash version is 5.1.16. I guess anything > 5.0.0 should work.

@knatsakis
Copy link
Author

I now mamaged to run qutebrowser als "kind of" daemon over systemd. But your script seems to be more advanced than simply restarting qutebrowser --nowindow everytime it quits.

One of the nice things this script does, in addition to the systemd solution you mention, is that it supports the restart/recycle/shutdown commands. See the aliases at the top.

  • shutdown is pretty much self-explanatory
  • restart, restarts without keeping any not-yet-persisted user data (cookies, etc. See below)
  • recycle, restarts but keeps non-yet-persisted user data

The other is that, it always starts qutebrowser from a clean state. No cookies, web page data or caches are persisted. I have some user scripts for persisting such data on-demand, on a page by page basis (I could share them if you are interested). This way, I can keep cookies etc., only for few, select, pages where I want to stay logged in. Cookies and other data from any other page gets deleted when the last qutebrowser window closes.

All this works nicely for me, but it is something you may not want or need.

@tbsmn
Copy link

tbsmn commented May 12, 2022

Thank your for the elaboration. I tried the updates put I still get some errors.
But as I read your explanations about the script I guess I am fine running the systemd solution.

Anyway thank you very much for your Help!

@askeladd123
Copy link

This script is really helpful! Is it hard to make all data persist?

I don't completely understand how you made the windows start this fast, but here's what I gathered:

  • the IPC and daemon creates new windows without spawning new processes
    • this prevents slow python libs from reloading?
  • config and data is loaded from memory rather than files
    • this also is quicker I guess

But if the last point is true; won't that make it hard to have all data persist? I don't know how you solved this in your scripts, but if session data, cookies and cache are stored in a temporary file system, they will not be saved I would imagine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment