diff --git a/README.md b/README.md
index 9bf1296..b699d54 100644
--- a/README.md
+++ b/README.md
@@ -116,3 +116,8 @@ what?- Consider entr in dwm-start for watching files
 - unicode character insertion
 change prompt icon to nerd icon
 - finish dwm patching, select window with wmctrl, then setup vpn, then maybe dmenu patches
+
+## Searching the web
+The prompt's rawurlencode function makes it easy to create new search functions for any website or service. Append the output of a call to rawurlencode to the site's search prefix, then pass the resulting string to an application like lynx or brave-browser. No need for installing packages or directories of config files.
+Example:
+```firefox "html.duckduckgo.com/html?q=$(rawurlencode "$1")"```
diff --git a/conveniently b/conveniently
new file mode 100755
index 0000000..8e25f53
--- /dev/null
+++ b/conveniently
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+project="$HOME/projects/$2"
+
+watch() {
+	npx browser-sync start --proxy "$2.test" -w --files $project/resources/views $project/resources/scss &
+	pid=$!
+	sass --load-path=sass --watch --error-css $project/resources/scss/main.scss $project/public/main.css &
+	pid="$pid $!"
+	trap "kill -TERM $pid" 0 1 2 15
+	wait
+}
+
+once() {
+	sass --load-path=sass $project/resources/scss/main.scss $project/public/main.css
+}
+
+deploy() {
+	rsync -av --delete onyeka assets view files onyeka@onyeka.ca:~/site/
+}
+
+case $1 in
+	'watch') watch "$2" ;;
+	'transpile') transpile "$2" ;;
+	'deploy') deploy ;;
+	'build') deploy ;; #Should be a function that automatically git pull and builds important applications like stuff in projects/macros, dwm, plugins etc
+esac
diff --git a/create b/create
new file mode 100755
index 0000000..6bd185b
--- /dev/null
+++ b/create
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+password() {
+	tr -d '\n' < /dev/urandom | fold -w30 | head -n1
+}
+
+password_easy() {
+	tr -cd '[:alnum:]' < /dev/urandom | fold -w20 | head -n1
+}
+
+case $1 in
+	password) password;;
+	*) printf "Invalid argument";;
+esac
diff --git a/dwm-start b/dwm-start
index bee0b20..9ee7363 100755
--- a/dwm-start
+++ b/dwm-start
@@ -4,6 +4,7 @@ source ~/.profile
 picom -b
 ~/.fehbg
 xbindkeys -f $HOME/backups/configs/xbindkeysrc
+protonmail-bridge --no-window --noninteractive &
 ( mru update; mru updatedirs ) &
 
 # relaunch DWM if the binary changes, otherwise bail
diff --git a/prompt b/prompt
index 6f99a39..de9d360 100755
--- a/prompt
+++ b/prompt
@@ -11,11 +11,12 @@ launch() {
 	Open
 	Pick
 	Choose
+	Tasks
 	Terminal
 	Multiplexer
-	LBRY
 	Chat
 	Music
+	Bookmarks
 	Equalizer
 	Browser
 	Hidden browser
@@ -27,8 +28,9 @@ launch() {
 	Games
 	Play clipboard
 	Play downloads
-	Processes" | tr -d '\t' |
-		dmenu -i -p "Launcher")
+	Processes
+	Mixer" | tr -d '\t' |
+		dmenu -i -c -l 20 -p "Launcher")
 
 	case $app in 
 		Notes) st -t "Notes" -e vim "+cd ~/notes/text" "+CtrlP";;
@@ -38,22 +40,24 @@ launch() {
 		Open) opener;; 
 		Pick) pick;;
 		Choose) choose;;
+		Bookmarks) st -t "Bookmarks" -e sh -lc buku;;
 		Terminal) st -t "Terminal";;
+		Tasks) st -t "Tasks" -e sh -lc taskwarrior-tui;;
 		Page) pages pager "$(printf "1\n2\n3\n" | dmenu -p 'page')";;
 		Games) games;;
 		Multiplexer) st -t "Multiplexer" -e tmux attach-session -t 0 || st -t "Multiplexer" -e tmux new-session -s 0;;
-		LBRY) lbry;;
 		'Go page') num=$(go_page); pages pager $num;;
 		Chat) element-desktop;;
 		Music) st -t "Music" -e ncmpcpp;;
 		Browser) $browser_cmd;;
 		'Hidden browser') $browser_cmd --incognito;;
-		Email) st -t 'Email' -e neomutt;;
+		Email) st -t 'Email' -e sh -lc neomutt;;
 		Images) view_images;;
 	'Play clipboard') mpv "$(xclip -o -selection clipboard)";;
 	'Play downloads') mpv "$HOME/downloads/tmp/$(ls ~/downloads/tmp/ | dmenu -i -l 10 -p 'play')";;
+	'Mixer') st -t "Mixer" -e pulsemixer;;
 	'Equalizer') qpaeq;;
-		Processes) st -t "Processes" -e htop;;
+		Processes) st -t "Processes" -e top;;
 	esac
 }
 
@@ -62,6 +66,7 @@ action() {
 	Pause Music
 	Play Music
 	Single on
+	Bookmarks
 	Command
 	Command to clipboard
 	Select VPN
@@ -80,7 +85,7 @@ action() {
 	Update cache
 	Enable Bar
 	Exit" | tr -d '\t' |
-		dmenu -i -p "Actions")
+		dmenu -i -c -l 20 -p "Actions")
 
 	case $action in
 		'Play Music') mpc play ;;
@@ -90,6 +95,7 @@ action() {
 		'Rebind Keys') setup-xbindkeys;;
 		'Disable Bar') tmux set -g status off;;
 		'Enable Bar') tmux set -g status on;;
+		'Bookmarks') bookmarks;;
 		'Command') cmd;;
 		'Command to clipboard') cmd_clip;;
 		'Username') username;;
@@ -111,7 +117,7 @@ login() {
 	Password
 	Alternate
 	Show
-	Edit" | tr -d '\t' | dmenu -i -p "login")
+	Edit" | tr -d '\t' | dmenu -i -c -p "login")
 
 	case $choice in
 		Username) username;;
@@ -128,10 +134,10 @@ do_search() {
 		Godocs
 		Mojeek
 		Package
-		Github" | tr -d '\t' | dmenu -i -p "Search")
+		Github" | tr -d '\t' | dmenu -i -c -p "Search")
 	
 	case "$type" in
-		Manual) p=$(man -k '' | dmenu -l 20 -p 'Manual' | cut -d' ' -f1); if [ -z $p ]; then exit; fi; st -t "Manual - $p" -e man "$p";;
+		Manual) p=$(man -k '' | dmenu -i -c -l 20 -p 'Manual' | cut -d' ' -f1); if [ -z $p ]; then exit; fi; st -t "Manual - $p" -e man "$p";;
 		Github) github;;
 		Godocs) godoc;;
 		DDG) ddg;;
@@ -141,42 +147,48 @@ do_search() {
 }
 
 download() {
-youtube-dl --add-metadata --no-progress -o "$HOME/downloads/%(title)s.%(ext)s" "$(xclip -selection clipboard -o)"
-notify-send -u low -t 3000 "Download complete"
+	youtube-dl --add-metadata --no-progress -o "$HOME/downloads/%(title)s.%(ext)s" "$(xclip -selection clipboard -o)"
+	notify-send -u low -t 3000 "Download complete"
 }
+
 download_music() {
 	youtube-dl -x --add-metadata --no-progress --audio-format mp3 -o \
-		"$HOME/music/%(track)s - %(artist)s.%(ext)s" "$(xclip -selection clipboard -o)"
+		"$HOME/music/new/%(track)s - %(artist)s.%(ext)s" "$(xclip -selection clipboard -o)"
 	if [ ! $? ]; then
-		youtube-dl -x --no-progress --audio-format mp3 -o \
-			"$HOME/music/%(title)s - %(artist)s.%(ext)s" "$(xclip -selection clipboard -o)"
+		youtube-dl -x --add-metadata --no-progress --audio-format mp3 -o \
+			"$HOME/music/new/%(title)s - %(artist)s.%(ext)s" "$(xclip -selection clipboard -o)"
+	fi
+	if [ -e "$HOME/music/new/NA - NA"* ]; then
+		rm "$HOME/music/new/NA - NA"*
+		youtube-dl -x --add-metadata --no-progress --audio-format mp3 -o \
+			"$HOME/music/new/%(title)s - %(artist)s.%(ext)s" "$(xclip -selection clipboard -o)"
 	fi
 	notify-send -u low -t 3000 "Download complete"
 
 }
 
 view_images() {
-	d=$(mru listdirs | dmenu -l 20 -i -p 'where?')
+	d=$(mru listdirs | dmenu -c -l 20 -i -p 'where?')
 	if [ -z "$d" ]; then exit; fi
 	sxiv -r "$d"
 }
 
 package() {
-	type=$(printf "search\ninfo" | dmenu -p 'package')
+	type=$(printf "search\ninfo" | dmenu -c -p 'package')
 	if [ -z "$type" ]; then
 		exit
 	elif [ "$type" = "info" ]; then
-		s=$(dmenu_path | dmenu -i -p 'package info')
+		s=$(dmenu_path | dmenu -i -c -p 'package info')
 		st -e sh -lc "apt-cache show $s"
 	else
-		s=$(dmenu -i -p 'package search')
+		s=$(dmenu -i -c -p 'package search')
 		st -e sh -lc "apt search \"$s\""
 	fi
 }
 
 editor() {
 	#handle spacing in filenames bug
-	file=$(mru list | dmenu -i -l 10 -p 'edit file')
+	file=$(mru list | dmenu -i -c -l 20 -p 'edit file')
 	if [ -z "$file" ]; then exit; fi
 	first=$(printf "$file" | head -n1 -)
 	d=$(dirname "$first")
@@ -186,7 +198,7 @@ editor() {
 }
 
 opener() {
-	mru list | dmenu -i -l 20 -p 'open' | while read f; do xdg-open "$f"; done
+	mru list | dmenu -i -c -l 20 -p 'open' | while read f; do xdg-open "$f"; done
 }
 
 screenshot() {
@@ -214,11 +226,11 @@ both" |
 }
 
 search_type() {
-	search_string="$(printf "New window\nBookmarks\nHistory" | dmenu -p "$1")"
+	search_string="$(printf "New window\nBookmarks\nHistory" | dmenu -c -p "$1")"
 	search_mode='tab'
 
 	case "$search_string" in
-		'New window') search_mode='window'; search_string=$(printf '' | dmenu -p "new $1");;
+		'New window') search_mode='window'; search_string=$(printf '' | dmenu -c -p "new $1");;
 		'Bookmarks');;
 		'History') ;;
 		# *) printf "Invalid argument";;
@@ -316,7 +328,7 @@ sel_account() {
 	account=$(
 	find ~/.password-store/[!\.]* -type f |
 		sed -e "s:$HOME/.password-store/::" -e "s:\.gpg::" |
-		dmenu -p 'account'
+		dmenu -c -i -l 20 -p 'account'
 	)
 	if [ -z "$account" ]; then exit; fi
 	printf "$account"
@@ -326,7 +338,7 @@ username() {
 	account=$(sel_account)
 	if [ -z "$account" ]; then exit; fi
 	name=$(pass show "$account" | sed -n -e "s/^username: //p" |
-		dmenu -p 'which username' | xclip -f -selection clipboard)
+		dmenu -c -i -l 20 -p 'which username' | xclip -f -selection clipboard)
 	if [ -z "$name" ]; then exit; fi
 	notify-send -u low -t 2000 "username copied" "$account: $name"
 }
@@ -336,7 +348,7 @@ password() {
 	touch /tmp/prompt-login-$$
 	account=$(find ~/.password-store/[!\.]* -type f |
 		sed -e "s:$HOME/.password-store/::" -e "s:\.gpg::" |
-		dmenu -p 'which service')
+		dmenu -i -c -l 20 -p 'which service')
 	pass -c $account
 	notify-send -u low -t 1000 'password copied' "Copied $account"
 
@@ -348,7 +360,7 @@ password() {
 other_password() {
 	account=$(sel_account)
 	name=$(pass show "$account" | sed -n -e "s/^username: //p" |
-		dmenu -i -p 'which user password')
+		dmenu -i -c -l 20 -p 'which user password')
 	if [ -z "$name" ]; then exit; fi
 	copy=$(pass show $account | grep -B 1 "^username: $name" | head -n1 | tr -d '\n')
 	printf "$copy" | xclip -selection clipboard
@@ -375,15 +387,15 @@ edit_password() {
 
 # Execute a command with the specified file or directory as it's argument
 choose() {
-	d=$(mru listdirs | dmenu -i -l 20 -p 'from')
+	d=$(mru listdirs | dmenu -i -c -l 20 -p 'from')
 	if [ -z "$d" ]; then exit; fi
 	f=$(
 	(printf "$d\n"; find "$d" -type f -not \( -path '*/.*/*' -o -path '*node_modules/*' -o -ipath '*backups/my-plugins*' -o -ipath '*/.uuid' -ipath '*.swp*' \)) |
-		dmenu -i -l 20 -p 'choose file'
+		dmenu -i -c -l 20 -p 'choose file'
 	)
 	if [ -z "$f" ]; then exit; fi
 
-	c=$(dmenu_path | dmenu -i -p 'operation')
+	c=$(dmenu_path | dmenu -i -c -p 'operation')
 	if [ -z $c ]; then exit; fi
 	$c "$f"
 }
@@ -395,11 +407,11 @@ vpn() {
 # It finds all the current files in a known directory without needing to update the mru list of files
 # If the directory is chosen instead of the file within it, it opens the directory with nnn
 pick() {
-	d=$(mru listdirs | dmenu -i -l 20 -p 'from')
+	d=$(mru listdirs | dmenu -i -c -l 20 -p 'from')
 	if [ -z "$d" ]; then exit; fi
 	f=$(
 	(printf "$d\n"; find "$d" -type f -not \( -path '*/.*/*' -o -path '*node_modules/*' -o -ipath '*backups/my-plugins*' -o -ipath '*/.uuid' -ipath '*.swp*' \)) |
-		dmenu -i -l 20 -p 'pick file'
+		dmenu -i -c -l 20 -p 'pick file'
 	)
 	if [ -z "$f" ]; then exit; fi
 	if [ "$d" = "$f" ]; then st -t 'Files' -e sh -lc "nnn '$f'"; exit; fi
@@ -408,7 +420,7 @@ pick() {
 
 do_exit() {
 	choice=$(printf "Shutdown
-	Reboot"| dmenu -i -p 'Exit')
+	Reboot"| dmenu -i -c -p 'Exit')
 
 	case $choice in
 		Shutdown) ls;;
@@ -417,7 +429,7 @@ do_exit() {
 }
 
 select_song() {
-	song=$(mpc playlist | dmenu -i -l 20 -p 'song')
+	song=$(mpc playlist | dmenu -i -c -l 20 -p 'song')
 	num=$(mpc playlist | sed -n "/$song/=")
 	mpc play $num
 }
@@ -428,7 +440,7 @@ games() {
 	Divinity
 	Rise to Ruins
 	Witcher 3
-	POE" | dmenu -i -p 'Games')
+	POE" | dmenu -i -c -p 'Games')
 
 	case "$sel" in
 		Albion);;
@@ -439,6 +451,21 @@ games() {
 	esac
 }
 
+bookmarks() {
+	sel=$(printf "Open
+	Select by tag
+	Modify
+	Delete
+	Edit" | tr -d "\t" | dmenu -i -c -p 'Bookmarks')
+
+	case "$sel" in
+		'Open') m=$(buku --nc -p | dmenu -i -c -l 30 -p "open bookmark");;
+		'Select by tag');;
+		'Modify');;
+		'Delete');;
+	esac
+}
+
 case $1 in
 	launch ) launch;;
 	action) action;;
diff --git a/splitchapters b/splitchapters
new file mode 100755
index 0000000..91b3e4f
--- /dev/null
+++ b/splitchapters
@@ -0,0 +1,70 @@
+#!/bin/bash
+# Copied from Eloise Speight's Stack Exchange answer
+# script to convert m4b (audiobook) files with embedded chapted (for eg. converted from Audbile) into individual chapter files
+
+# required: ffmpeg; jg (json interpreter) & AtomicParsley (to embed pictures and add additional metadata to m4a/m4b AAC files)
+
+# discover the file type (extension) of the input file
+ext=${1##*.}
+echo "extension: $ext"
+# all files / folders are named based on the "shortname" of the input file
+shortname=$(basename "$1" ".$ext")
+picture=$shortname.jpg
+chapterdata=$shortname.dat
+metadata=$shortname.tmp
+echo "shortname: $shortname"
+
+# if an output type has been given on the command line, set parameters (used in ffmpeg command later)
+if [[ $2 = "mp3"  ]]; then
+  outputtype="mp3"
+    codec="libmp3lame"
+	elif [[ $2 = "m4a"  ]]; then
+	  outputtype="m4a"
+	    codec="copy"
+		else
+		  outputtype="m4b"
+		    codec="copy"
+			fi
+			echo "outputtype: |$outputtype|"
+
+			# if it doesn't already exist, create a json file containing the chapter breaks (you can edit this file if you want chapters to be named rather than simply "Chapter 1", etc that Audible use)
+			[ ! -e "$chapterdata"  ] && ffprobe -loglevel error \
+			            -i "$1" -print_format json -show_chapters -loglevel error -sexagesimal \
+						            >"$chapterdata"
+									read -p "Now edit the file $chapterdata if required. Press ENTER to continue."
+									# comment out above if you don't want the script to pause!
+
+									# read the chapters into arrays for later processing
+									readarray -t id <<< $(jq -r '.chapters[].id' "$chapterdata")
+									readarray -t start <<< $(jq -r '.chapters[].start_time' "$chapterdata")
+									readarray -t end <<< $(jq -r '.chapters[].end_time' "$chapterdata")
+									readarray -t title <<< $(jq -r '.chapters[].tags.title' "$chapterdata")
+
+									# create a ffmpeg metadata file to extract addition metadata lost in splitting files - deleted afterwards
+									ffmpeg -loglevel error -i "$1" -f ffmetadata "$metadata"
+									artist_sort=$(sed 's/.*=\(.*\)/\1/' <<<$(cat "$metadata" |grep -m 1 ^sort_artist))
+									album_sort=$(sed 's/.*=\(.*\)/\1/' <<<$(cat "$metadata" |grep -m 1 ^sort_album))
+									rm "$metadata"
+
+									# create directory for the output
+									mkdir -p "$shortname"
+									echo -e "\fID\tStart Time\tEnd Time\tTitle\t\tFilename"
+									for i in ${!id[@]}; do
+									  let trackno=$i+1
+									    # set the name for output - currently in format <bookname>/<tranck number>
+										  outname="$shortname/$(printf "%02d" $trackno). $shortname - ${title[$i]}.$outputtype"
+										    #outname=$(sed -e 's/[^A-Za-z0-9._- ]/_/g' <<< $outname)
+											  outname=$(sed 's/:/_/g' <<< $outname)
+											    echo -e "${id[$i]}\t${start[$i]}\t${end[$i]}\t${title[$i]}\n\t\t$(basename "$outname")"
+												  ffmpeg -loglevel error -i "$1" -vn -c $codec \
+												              -ss ${start[$i]} -to ${end[$i]} \
+															              -metadata title="${title[$i]}" \
+																		              -metadata track=$trackno \
+																					              -map_metadata 0 -id3v2_version 3 \
+																								              "$outname"
+																											    [[ $outputtype == m4*  ]] && AtomicParsley "$outname" \
+																												            --artwork "$picture" --overWrite \
+																															            --sortOrder artist "$artist_sort" \
+																																		            --sortOrder album "$album_sort" \
+																																					            > /dev/null
+																																								done