Compare commits

..

21 Commits

Author SHA1 Message Date
KK
b712c714cf setup: remove section numberings 2026-06-20 11:05:19 +02:00
KK
bc287e40e0 setup: ffmpeg 2026-06-20 11:04:16 +02:00
KK
ab04d5ae63 setup: readme instead of script 2026-06-20 10:57:45 +02:00
KK
116b66db4b setup: add fonts + gdb 2026-06-20 10:11:55 +02:00
KK
7bfb9a2d7d sway: suspend without turning off screen 2026-06-20 10:11:39 +02:00
KK
6559d05e06 kakoune config update 2026-06-20 10:10:48 +02:00
KK
8d1fb991fa Add voice control 2026-06-18 15:13:57 +02:00
KK
89e9f63019 remove tmux from .profile 2026-06-18 15:12:40 +02:00
KK
a00ad450bf Add script for scratchpad to ask stuff 2026-06-18 15:12:10 +02:00
KK
5ea5794ce6 Update command list to search internet and use @ 2026-06-18 15:11:49 +02:00
KK
ebcff99d2d Remove pavucontrol 2026-06-18 11:20:55 +02:00
KK
c6bd25182a Screenshots, polish layout, filelog 2026-06-18 11:20:01 +02:00
KK
b9b2d652f7 Modify the gitconfig 2026-06-18 10:59:40 +02:00
KK
4b2b24e052 Add gitconfig 2026-06-18 10:53:00 +02:00
Karol Krzosa
5534eee012 Remove fonts, improvements to sway and tmux, open sway in tmux session 2026-06-18 10:40:27 +02:00
Karol Krzosa
0159412aa6 bash improvements 2026-06-18 10:39:57 +02:00
Karol Krzosa
5b5e28221e kakrc copy to system clipboard 2026-06-18 10:17:18 +02:00
Karol Krzosa
e4851ca9a8 Handle LibreWolf / Firefox in command-list 2026-06-18 09:07:45 +02:00
Karol Krzosa
c4a251ce09 Install kakoune, new bash_alias 2026-06-18 08:41:00 +02:00
Karol Krzosa
a67e7b0aa1 Start sway on startup, fix command-list launching apps 2026-06-17 22:33:39 +02:00
Karol Krzosa
bd9506a9be setup.sh and installing on new system 2026-06-17 22:13:50 +02:00
18 changed files with 667 additions and 96 deletions

11
.bashrc
View File

@@ -16,8 +16,8 @@ HISTCONTROL=ignoreboth
shopt -s histappend shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1) # for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000 HISTSIZE=100000
HISTFILESIZE=2000 HISTFILESIZE=200000
# check the window size after each command and, if necessary, # check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS. # update the values of LINES and COLUMNS.
@@ -25,7 +25,10 @@ shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will # If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories. # match all files and zero or more directories and subdirectories.
#shopt -s globstar shopt -s globstar
# Type directory names directly, without 'cd' and still move there
shopt -s autocd
# make less more friendly for non-text input files, see lesspipe(1) # make less more friendly for non-text input files, see lesspipe(1)
#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" #[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
@@ -111,3 +114,5 @@ if ! shopt -oq posix; then
. /etc/bash_completion . /etc/bash_completion
fi fi
fi fi
export PATH="$PATH:/home/kk/.local/share/pi-node/node-v22.22.3-linux-x64/bin"

View File

@@ -1,3 +1,4 @@
alias ls='ls -lahtr' alias ls='ls -lahtr'
alias vi='vim' alias vi='kak'
alias df='/usr/bin/git --git-dir=$HOME/.dotfilesrepo/ --work-tree=$HOME' alias df='/usr/bin/git --git-dir=$HOME/.dotfilesrepo/ --work-tree=$HOME'
alias unpack='dtrx'

32
.config/git/config Normal file
View File

@@ -0,0 +1,32 @@
[user]
name = KK
email = git.exclaim518@passmail.net
[core]
editor = kak
excludesFile = ~/.config/git/ignore
[commit]
verbose = true
[push]
autoSetupRemote = true
[diff]
colorMoved = default
algorithm = histogram
[merge]
conflictStyle = zdiff3
[color]
ui = auto
[branch]
sort = -committerdate
[tag]
sort = version:refname
[alias]
s = status --short --branch
st = status
co = checkout
br = branch
ci = commit
lg = log --graph --pretty=format:'%C(auto)%h%Creset %Cgreen%cr%Creset %C(bold blue)%an%Creset %s%C(auto)%d%Creset' --all
branches = for-each-ref --sort=-committerdate refs/heads/ --format='%(committerdate:relative) %(refname:short)'
filelog = log --follow --graph --decorate --date=relative --pretty=format:'%C(auto)%h%Creset %Cgreen%cr%Creset %C(bold blue)%an%Creset %s'

View File

@@ -1,53 +0,0 @@
# TODO:
# - [ ] Mount /krk-pc on startup
# - [ ] Add server SSH keys and PC ssh keys
# - [ ] Mount /proton on startup
# - [x] Hibernate if not using PC for 10 minutes
#
# - [ ] Combine apps + bin + bookmarks
# - [x] everything relevant wmenu browser (programs and scripts without arguments, bookmarks, files)
# - [x] plocate + wmenu > xdg-open
# - [x] applications + bin folder
# - [x] bookmarks
#
# - [x] fzf starship zoxide eza bat (only fzf seems descent)
#
# Solutions in search for problems:
# - [ ] tmux automation
#
# Setup sudo for user
su root
export PATH="$PATH:/usr/sbin"
apt install sudo
usermod -aG sudo kk
exit # exit root
exit # exit user to reload config
# Basic utilities
sudo apt install clang cmake build-essential make tcc vim ripgrep curl git man-db plocate tmux zip unzip fzf
sudo updatedb
# Standard enviroment setup
sudo apt install xdg-desktop-portal-wlr xdg-desktop-portal-gtk xdg-user-dirs
# DE setup
sudo apt install sway swayidle swaybg swaylock foot wmenu brightnessctl
# Clipboard and history
sudo apt install wl-clipboard cliphist
# Issue fix
# there were issues because user was not in render group (error messages on start of sway)
sudo usermod -aG render kk
# Setup audio
sudo apt install pipewire pipewire-pulse wireplumber pavucontrol
sudo apt install sshfs
# Setup internet
# sudo apt install w3m surfraw
sudo apt install chromium

20
.config/kak/kakrc Normal file
View File

@@ -0,0 +1,20 @@
colorscheme gruvbox-dark
# Use 4 spaces for indentation.
# indentwidth controls Kakoune's indentation commands; tabstop controls display width.
set-option global tabstop 4
set-option global indentwidth 4
set-option global makecmd 'bash build.sh'
map global user n :make-next-error<ret>
map global user p :make-previous-error<ret>
# Kakoune does not have a Vim-style 'expandtab' option. Make a literal Tab key
# insert four spaces instead of a tab character while in insert mode.
map global insert <tab> '<space><space><space><space>'
hook global RegisterModified '"' %{ nop %sh{
printf %s "$kak_main_reg_dquote" | wl-copy > /dev/null 2>&1 &
}}
add-highlighter global/ number-lines

View File

@@ -42,18 +42,8 @@ include /etc/sway/config-vars.d/*
# #
# You can get the names of your outputs by running: swaymsg -t get_outputs # You can get the names of your outputs by running: swaymsg -t get_outputs
### Idle configuration # Suspend the machine after 600 seconds
# exec swayidle -w timeout 600 'systemctl suspend'
# Example configuration:
#
exec swayidle -w \
timeout 300 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \
timeout 600 'systemctl hibernate' \
before-sleep 'swaylock -f -c 000000'
#
# This will lock your screen after 300 seconds of inactivity, then turn off
# your displays after another 300 seconds, and turn your screens back on when
# resumed. It will also lock your screen before your computer goes to sleep.
### Input configuration ### Input configuration
# #
@@ -70,6 +60,8 @@ exec swayidle -w \
# Read `man 5 sway-input` for more information about this section. # Read `man 5 sway-input` for more information about this section.
input * { input * {
xkb_layout pl
xkb_options caps:none
repeat_rate 80 repeat_rate 80
repeat_delay 300 repeat_delay 300
} }
@@ -86,14 +78,13 @@ input "1267:12734:ELAN06FA:00_04F3:31BE_Touchpad" {
scroll_factor 0.8 scroll_factor 0.8
} }
# Clipboard history
exec wl-paste --type text --watch cliphist store
exec wl-paste --type image --watch cliphist store
### Key bindings ### Key bindings
# #
# Basics: # Basics:
# #
# Start a terminal # Start a terminal
bindsym $mod+Return exec $term bindsym $mod+Return exec $term
@@ -203,6 +194,9 @@ exec wl-paste --type image --watch cliphist store
# Show the next scratchpad window or hide the focused scratchpad window. # Show the next scratchpad window or hide the focused scratchpad window.
# If there are multiple scratchpad windows, this command cycles through them. # If there are multiple scratchpad windows, this command cycles through them.
bindsym $mod+minus scratchpad show bindsym $mod+minus scratchpad show
# Dedicated scratchpad terminal for voice queries to pi.
for_window [app_id="pi-voice"] border pixel 2, move scratchpad
# #
# Resizing containers: # Resizing containers:
# #
@@ -217,7 +211,7 @@ mode "resize" {
bindsym $right resize grow width 10px bindsym $right resize grow width 10px
# Ditto, with arrow keys # Ditto, with arrow keys
bindsym Left kesize shrink width 10px bindsym Left resize shrink width 10px
bindsym Down resize grow height 10px bindsym Down resize grow height 10px
bindsym Up resize shrink height 10px bindsym Up resize shrink height 10px
bindsym Right resize grow width 10px bindsym Right resize grow width 10px
@@ -225,7 +219,9 @@ mode "resize" {
# Return to default mode # Return to default mode
bindsym Return mode "default" bindsym Return mode "default"
bindsym Escape mode "default" bindsym Escape mode "default"
bindsym $mod+r mode "default"
} }
bindsym $mod+r mode "resize" bindsym $mod+r mode "resize"
# #
# Utilities: # Utilities:
@@ -239,7 +235,19 @@ bindsym $mod+r mode "resize"
bindsym --locked XF86MonBrightnessDown exec brightnessctl set 5%-; pkill -USR1 -f "$HOME/.config/sway/status.sh" bindsym --locked XF86MonBrightnessDown exec brightnessctl set 5%-; pkill -USR1 -f "$HOME/.config/sway/status.sh"
bindsym --locked XF86MonBrightnessUp exec brightnessctl set 5%+; pkill -USR1 -f "$HOME/.config/sway/status.sh" bindsym --locked XF86MonBrightnessUp exec brightnessctl set 5%+; pkill -USR1 -f "$HOME/.config/sway/status.sh"
# Special key to take a screenshot with grim # Special key to take a screenshot with grim
bindsym Print exec grim bindsym Print exec sh -c 'mkdir -p ~/screenshots; f=~/screenshots/$(date +%F-%H%M%S).png; grim "$f"; wl-copy < "$f"'
bindsym Shift+Print exec sh -c 'mkdir -p ~/screenshots; f=~/screenshots/$(date +%F-%H%M%S).png; grim -g "$(slurp)" "$f"; wl-copy < "$f"'
# Push-to-talk: hold Caps Lock to record, release to transcribe.
# xkb_options caps:none above disables the normal Caps Lock toggle, so bind by keycode.
bindcode 66 exec sh -c 'voxtype record start; pkill -USR1 -f "$HOME/.config/sway/status.sh"'
bindcode --release 66 exec sh -c 'voxtype record stop; pkill -USR1 -f "$HOME/.config/sway/status.sh"'
# Voice query to pi in a dedicated tmux session/scratchpad terminal.
# Hold $mod+Shift+x, speak, release; transcription is submitted to pi.
bindsym $mod+Shift+x exec ~/bin/pi-voice-query start
bindsym --release $mod+Shift+x exec ~/bin/pi-voice-query stop
# Pick an entry from clipboard history and copy it back to the clipboard # Pick an entry from clipboard history and copy it back to the clipboard
bindsym $mod+c exec sh -c 'cliphist list | wmenu -l 10 | cliphist decode | wl-copy' bindsym $mod+c exec sh -c 'cliphist list | wmenu -l 10 | cliphist decode | wl-copy'

View File

@@ -7,14 +7,21 @@ print_status() {
brightness=$(brightnessctl -m 2>/dev/null | awk -F, '{print $4}') brightness=$(brightnessctl -m 2>/dev/null | awk -F, '{print $4}')
printf 'VOL %s | BRI %s | %s\n' "${volume:-n/a}" "${brightness:-n/a}" "$(date +'%Y-%m-%d %H:%M:%S')" voxtype_state=$(voxtype status 2>/dev/null)
case "$voxtype_state" in
recording) voxtype=' | VOX REC' ;;
transcribing) voxtype=' | VOX ...' ;;
*) voxtype='' ;;
esac
printf 'VOL %s | BRI %s%s | %s\n' "${volume:-n/a}" "${brightness:-n/a}" "$voxtype" "$(date +'%Y-%m-%d %H:%M:%S')"
} }
trap print_status USR1 trap print_status USR1
print_status print_status
while :; do while :; do
sleep 60 & sleep 1 &
wait $! wait $!
print_status print_status
done done

View File

@@ -4,6 +4,13 @@
set -g extended-keys on set -g extended-keys on
set -g extended-keys-format csi-u set -g extended-keys-format csi-u
# Index windows/tabs and panes from 1 instead of 0.
set -g base-index 1
setw -g pane-base-index 1
# Automatically close gaps in window/tab numbers after a window is closed.
set -g renumber-windows on
# Use 256-colour tmux terminfo and advertise truecolour support to apps. # Use 256-colour tmux terminfo and advertise truecolour support to apps.
set -g default-terminal "tmux-256color" set -g default-terminal "tmux-256color"
set -as terminal-features ",*:RGB" set -as terminal-features ",*:RGB"
@@ -20,12 +27,6 @@ bind-key j select-pane -D
bind-key k select-pane -U bind-key k select-pane -U
bind-key l select-pane -R bind-key l select-pane -R
# Optional no-prefix pane navigation with Alt+hjkl
bind-key -n M-h select-pane -L
bind-key -n M-j select-pane -D
bind-key -n M-k select-pane -U
bind-key -n M-l select-pane -R
# Mouse support: scroll with the wheel, resize/select panes, and make mouse # Mouse support: scroll with the wheel, resize/select panes, and make mouse
# selections pane-aware instead of selecting across the whole terminal window. # selections pane-aware instead of selecting across the whole terminal window.
set-option -g mouse on set-option -g mouse on

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.config/librewolf/
.config/pulse/
bin/pi

View File

@@ -30,3 +30,9 @@ fi
if [ -d "$HOME/.local/bin" ] ; then if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH" PATH="$HOME/.local/bin:$PATH"
fi fi
if [ -z "$WAYLAND_DISPLAY" ] && [ "$XDG_VTNR" = 1 ]; then
export WLR_NO_HARDWARE_CURSORS=1
exec sway --unsupported-gpu
fi

348
README.md Normal file
View File

@@ -0,0 +1,348 @@
# System install guide
Install guide with DIY spirit, key is to reproduce my system setup while making sure understanding is there and all.
- Commands are written for user `kk` unless stated otherwise.
## Current TODOs
### System / mounts
- [x] Add server SSH keys and PC SSH keys
- [ ] Mount the mobile phone
- Make sure nobody else can log in when I connect to random Wi-Fi.
- [ ] Mount `/proton` on startup
- [x] Mount `/lenovo-laptop`
- [x] Mount server at `/server-vps`
### Desktop / UX
- [x] Hibernate if not using the PC for 10 minutes
- [ ] Start Sway in a tmux session for debugging
- [ ] Kakoune setup
- [x] Firefox bookmarks
- [ ] Ideas for Chinese learning integration
### Launcher / search
- [x] Combine apps, scripts, bookmarks, and files
- [x] Use `.desktop` file name instead of the `Name` parameter
- [x] Everything relevant in `wmenu` browser
- [x] `plocate + wmenu > xdg-open`
- [x] Applications + `bin` folder
- [x] Bookmarks
### Ideas looking for problems
- [ ] tmux automation
---
## Bootstrap sudo and git
```sh
su root
export PATH="$PATH:/usr/sbin"
apt install sudo git
usermod -aG sudo kk
```
Then exit both root and the user session, and log in again so the `sudo` group change applies.
Verify:
```sh
groups # should see "sudo"
sudo whoami # you should see "root"
```
Expected output from `sudo whoami`:
```text
root
```
---
## Install basic utilities
**Automate later.**
```sh
sudo apt update
sudo apt install -y \
clang \
cmake \
build-essential \
make \
tcc \
vim \
ripgrep \
curl \
git \
man-db \
plocate \
tmux \
fzf \
dtrx \
gdb
sudo updatedb # plocate update the database so you can query files on PC nicely
```
- fzf - fuzzy search on command line, good for making command line tools
- ripgrep - better grep, nicer syntax and faster: rg "query"
- dtrx - nice archive unpacking wrapper that makes it less confusing, just dtrx thing.zip or whatever other tar and it should work nicely
Mostly development tools are downloaded here, stuff like tmux, vim and the compiler toolchain needed for development, compiling etc.
---
## Speed up GRUB boot
**Automate later.** Edit `/etc/default/grub`:
```sh
sudo vi /etc/default/grub
```
Set:
```ini
GRUB_TIMEOUT=0
GRUB_TIMEOUT_STYLE=hidden
```
Apply changes:
```sh
sudo update-grub
```
---
## Enable Debian non-free repositories
**Automate later.** Needed for NVIDIA and firmware packages.
Edit `/etc/apt/sources.list` and add:
```text
contrib non-free non-free-firmware
```
Then update apt:
```sh
sudo apt update
```
---
## Install drivers and firmware
**Machine-specific / automate carefully.**
```sh
sudo apt install -y \
nvidia-driver \
firmware-misc-nonfree \
linux-headers-amd64
```
TODO:
- Set NVIDIA modeset to `1`.
- Update initramfs.
- Reboot.
---
## Desktop environment: Sway
**Automate later.**
```sh
sudo apt install -y \
sway \
swayidle \
swaybg \
swaylock \
foot \
wmenu \
brightnessctl \
xwayland \
wl-clipboard \
xdg-desktop-portal-wlr \
xdg-desktop-portal-gtk \
xdg-user-dirs \
fonts-jetbrains-mono \
fonts-noto-cjk \
fonts-noto-cjk-extra \
pipewire \
pipewire-pulse \
pipewire-alsa \
wireplumber \
pavucontrol \
grim \
ffmpeg libavcodec-extra
```
Package notes:
- sway, terminal, menu, addons:
- `sway` - the Wayland window manager / desktop environment of choice. This is the main thing that replaces a traditional desktop like GNOME or KDE.
- `swayidle` - idle manager for Sway. Used for things like locking the screen, turning off the display, suspending, or hibernating after a timeout.
- `swaybg` - simple wallpaper/background setter for Sway.
- `swaylock` - screen locker for Sway/Wayland. Used when locking the session manually or from `swayidle`.
- `foot` - terminal emulator for Wayland. This is the main terminal.
- `wmenu` - small menu/launcher for Wayland. Useful for app launching and custom scripts like bookmarks/search/file opening.
- `grim` - screenshot tool for Wayland. Usually used together with selection/clipboard scripts later.
- `brightnessctl` - command line tool for changing screen brightness, usually bound to laptop brightness keys.
- `xwayland` - compatibility layer that allows older X11 applications to run inside the Wayland/Sway session.
- `wl-clipboard` - Wayland clipboard tools, mainly `wl-copy` and `wl-paste`. Needed by scripts and editor integrations.
- `fonts-jetbrains-mono` - nice monospace font for terminal/editor use.
- xdg, a standard required by some apps (shared enviroment variables and such):
- `xdg-desktop-portal-wlr` - desktop portal backend for wlroots compositors like Sway. Needed for screen sharing, screenshots, file pickers, and other app integrations.
- `xdg-desktop-portal-gtk` - GTK portal backend/fallback. Helps with file picker dialogs and desktop integration for some applications.
- `xdg-user-dirs` - creates standard user folders like `~/Downloads`, `~/Documents`, `~/Pictures`, etc.
- fix unicode characters (like Chinese) not showing up properly in firefox:
- `fonts-noto-cjk` - fonts needed for displaying Chinese, Japanese, Korean, etc. characters in Firefox, Chromium, terminal apps, and other programs.
- `fonts-noto-cjk-extra` - additional CJK font coverage/styles.
- audio:
- `pipewire` - the main modern Linux audio/media server. Handles audio routing and is also useful for screen sharing/media integration on Wayland.
- `pipewire-pulse` - PulseAudio compatibility layer for PipeWire. Makes applications that expect PulseAudio work through PipeWire instead.
- `pipewire-alsa` - ALSA compatibility layer for PipeWire. Helps applications that use ALSA directly play/record audio through PipeWire.
- `wireplumber` - PipeWire session/policy manager. It decides how audio devices and streams should be connected automatically.
- `pavucontrol` - graphical volume mixer. Useful for choosing input/output devices, changing app volumes, and debugging audio problems.
- codecs (to fix videos not playing in browser):
- ffmpeg libavcodec-extra
### Fix Sway permission issues
If Sway reports render/video permission errors, add the user to the relevant groups:
```sh
sudo usermod -aG video,render kk
```
Log out and back in afterwards.
---
## SSH keys
**Manual.** Generate a key if the machine does not already have one:
```sh
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
```
Now exchange the keys with relevant machines so as to make communication easier. This prepares the ground for mounting these machines as easy to access drives.
---
## SSHFS drives
**Partly manual.** Install SSHFS:
```sh
sudo apt install -y sshfs
```
Create mount points as needed:
```sh
sudo mkdir -p /server-vps /lenovo-laptop /proton
```
Example `/etc/fstab` entry for the VPS:
```fstab
root@157.90.144.237:/ /server-vps fuse.sshfs noauto,x-systemd.automount,_netdev,x-systemd.idle-timeout=2min,x-systemd.mount-timeout=10s,reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,IdentityFile=/home/kk/.ssh/id_ed25519,UserKnownHostsFile=/home/kk/.ssh/known_hosts,StrictHostKeyChecking=accept-new,allow_other,default_permissions 0 0
```
Test after editing `/etc/fstab`:
```sh
sudo systemctl daemon-reload
ls /server-vps
```
---
## Browser / internet tools
**Automate later.**
```sh
sudo apt install -y chromium
```
Optional text/web search tools:
```sh
sudo apt install -y w3m surfraw
```
---
## Extras
### Clipboard history
```sh
sudo apt install -y cliphist
```
---
## Voice typing: Voxtype
**Manual / automate carefully.**
Install Voxtype:
```sh
curl -LO https://github.com/peteonrails/voxtype/releases/download/v0.6.0/voxtype_0.6.0-1_amd64.deb
sudo dpkg -i voxtype_0.6.0-1_amd64.deb
rm voxtype_0.6.0-1_amd64.deb
```
Install runtime dependencies:
```sh
sudo apt install -y \
wtype \
wl-clipboard \
libnotify-bin \
playerctl
```
Allow input access:
```sh
sudo usermod -aG input "$USER"
```
Log out and back in afterwards.
### Optional GPU support
```sh
read -r -p "Enable GPU support? [y/N] " answer
case "$answer" in
[yY]|[yY][eE][sS])
sudo voxtype setup gpu --enable
;;
esac
```
### Voxtype setup
```sh
voxtype setup
voxtype setup systemd
voxtype setup model
```

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python3 #!/usr/bin/python3
import os, subprocess, json import os, subprocess, json, sqlite3, shutil, tempfile
from pathlib import Path
def readfile(path): def readfile(path):
fd = open(path, "r") fd = open(path, "r")
@@ -8,6 +8,9 @@ def readfile(path):
fd.close() fd.close()
return result return result
#
# GTK apps
#
vals = {} vals = {}
home = os.environ["HOME"] home = os.environ["HOME"]
appsdir=["/usr/share/applications", f"{home}/.local/share/applications"] appsdir=["/usr/share/applications", f"{home}/.local/share/applications"]
@@ -34,7 +37,7 @@ for appdir in appsdir:
_exec = line[5:] _exec = line[5:]
elif line.startswith("Type="): elif line.startswith("Type="):
_type = line[5:] _type = line[5:]
elif line.startswith("Name="): elif line.startswith("Name=") and _name is None:
_name = line[5:] _name = line[5:]
elif line.startswith("NoDisplay="): elif line.startswith("NoDisplay="):
_nodisplay = line[10:] _nodisplay = line[10:]
@@ -49,9 +52,11 @@ for appdir in appsdir:
if _nodisplay == "true" or _hidden == "true": if _nodisplay == "true" or _hidden == "true":
continue continue
vals[_name] = {"kind": "app", "exec": _exec, "path": path} vals[_name] = {"kind": "app", "exec": _exec, "path": path, "name": appfile[:-8]}
#
# Bin
#
bindir = f"{home}/bin" bindir = f"{home}/bin"
for file in os.listdir(bindir): for file in os.listdir(bindir):
path = f"{bindir}/{file}" path = f"{bindir}/{file}"
@@ -61,6 +66,9 @@ for file in os.listdir(bindir):
continue continue
vals[file] = {"kind": "bin", "path": path} vals[file] = {"kind": "bin", "path": path}
#
# Chromium bookmarks
#
def walk_bookmarks(node, folder=""): def walk_bookmarks(node, folder=""):
if isinstance(node, dict): if isinstance(node, dict):
if node.get("type") == "url" and node.get("url"): if node.get("type") == "url" and node.get("url"):
@@ -82,6 +90,74 @@ if os.path.isfile(bookmarkfile):
for root in roots.values(): for root in roots.values():
walk_bookmarks(root) walk_bookmarks(root)
#
# Firefox bookmarks
#
SEARCH_DIRS = [
Path.home() / ".config" / "librewolf",
]
def find_places_databases():
seen = set()
for base in SEARCH_DIRS:
if not base.exists():
continue
for db in base.glob("**/places.sqlite"):
resolved = db.resolve()
if resolved not in seen:
seen.add(resolved)
yield db
def read_firefox_bookmarks(db_path):
# Copy the DB first so this also works while Firefox/LibreWolf is running.
with tempfile.TemporaryDirectory() as tmp:
tmp_db = Path(tmp) / "places.sqlite"
shutil.copy2(db_path, tmp_db)
for suffix in ("-wal", "-shm"):
sidecar = Path(str(db_path) + suffix)
if sidecar.exists():
shutil.copy2(sidecar, Path(str(tmp_db) + suffix))
con = sqlite3.connect(f"file:{tmp_db}?mode=ro", uri=True)
cur = con.cursor()
query = """
WITH RECURSIVE folders(id, path) AS (
SELECT id, COALESCE(title, '')
FROM moz_bookmarks
WHERE parent = 0
UNION ALL
SELECT b.id,
CASE
WHEN folders.path = '' THEN COALESCE(b.title, '')
WHEN COALESCE(b.title, '') = '' THEN folders.path
ELSE folders.path || '/' || b.title
END
FROM moz_bookmarks b
JOIN folders ON b.parent = folders.id
WHERE b.type = 2
)
SELECT COALESCE(folders.path, ''), COALESCE(b.title, ''), p.url
FROM moz_bookmarks b
JOIN moz_places p ON b.fk = p.id
LEFT JOIN folders ON b.parent = folders.id
WHERE b.type = 1
AND p.url IS NOT NULL
ORDER BY b.dateAdded
"""
for folder, title, url in cur.execute(query):
name = title or url
label = f"{folder}/{name}" if folder else name
vals[label] = {"kind": "url", "url": url}
con.close()
for it in find_places_databases():
read_firefox_bookmarks(it)
entries = [] entries = []
for it in vals.items(): for it in vals.items():
entries.append(it[0]) entries.append(it[0])
@@ -92,12 +168,15 @@ if result.returncode != 0:
exit(result.returncode) exit(result.returncode)
choice = result.stdout.strip() choice = result.stdout.strip()
val = vals[choice] if choice[0] == '@':
choice = choice[1:]
val = vals.get(choice)
if val["kind"] == "bin": if val is not None:
subprocess.run([val["path"]]) if val["kind"] == "bin":
elif val["kind"] == "app": subprocess.run([val["path"]])
subprocess.run(["gtk-launch", choice]) elif val["kind"] == "app":
elif val["kind"] == "url": subprocess.run(["gtk-launch", val["name"]])
subprocess.run(["xdg-open", val["url"]]) elif val["kind"] == "url":
subprocess.run(["xdg-open", val["url"]])
else:
subprocess.run(["xdg-open", "https://www.google.com/search?q=" + choice])

95
bin/pi-voice-query Executable file
View File

@@ -0,0 +1,95 @@
#!/bin/sh
set -eu
SESSION="pi-voice"
APP_ID="pi-voice"
TITLE="Pi Voice"
OUT="${XDG_RUNTIME_DIR:-/tmp}/pi-voice-query.txt"
STATUS_SCRIPT="$HOME/.config/sway/status.sh"
refresh_bar() {
pkill -USR1 -f "$STATUS_SCRIPT" 2>/dev/null || true
}
position_pi_window() {
# Size scratchpad window to 60% of the focused output using absolute pixels.
# Doing this here is more reliable than a for_window percentage resize.
set -- $(swaymsg -t get_outputs 2>/dev/null | python3 -c '
import json, sys
outs = json.load(sys.stdin)
out = next((o for o in outs if o.get("focused")), None) or next((o for o in outs if o.get("active")), None)
rect = (out or {}).get("rect", {})
w = int(rect.get("width", 1200) * 0.6)
h = int(rect.get("height", 800) * 0.6)
print(w, h)
')
w=${1:-1200}
h=${2:-800}
swaymsg '[app_id="'"$APP_ID"'"] border pixel 2, resize set width '"$w"' px height '"$h"' px, move position center' >/dev/null 2>&1 || true
}
ensure_pi_terminal() {
if ! tmux has-session -t "$SESSION" 2>/dev/null; then
tmux new-session -d -s "$SESSION" 'pi'
fi
if command -v swaymsg >/dev/null 2>&1; then
if ! swaymsg -t get_tree 2>/dev/null | grep -q '"app_id": "'"$APP_ID"'"'; then
foot --app-id="$APP_ID" --title="$TITLE" \
--override=main.resize-by-cells=no \
--override=colors.alpha=1.0 \
--override=main.pad=0x0 \
tmux attach-session -t "$SESSION" >/dev/null 2>&1 &
# Give the window a moment to appear before trying to show/focus it.
sleep 0.5
fi
swaymsg '[app_id="'"$APP_ID"'"] scratchpad show, focus' >/dev/null 2>&1 || true
position_pi_window
fi
}
send_to_pi() {
text=$1
[ -n "$text" ] || exit 0
ensure_pi_terminal
# Paste literally, then press Enter to submit to pi.
printf '%s' "$text" | tmux load-buffer -
tmux paste-buffer -t "$SESSION"
tmux send-keys -t "$SESSION" Enter
}
case "${1:-}" in
start)
ensure_pi_terminal
: > "$OUT"
voxtype record start --file="$OUT"
refresh_bar
;;
stop)
voxtype record stop
refresh_bar
# Wait for transcription to land in OUT. Stop early once voxtype is idle
# and the file has text, otherwise allow slower large-model runs.
i=0
while [ "$i" -lt 180 ]; do
if [ -s "$OUT" ]; then
break
fi
state=$(voxtype status 2>/dev/null || true)
[ "$state" = idle ] && [ "$i" -gt 2 ] && break
sleep 0.5
i=$((i + 1))
done
refresh_bar
text=$(cat "$OUT" 2>/dev/null || true)
send_to_pi "$text"
;;
*)
echo "usage: $0 start|stop" >&2
exit 2
;;
esac

19
setup.sh Normal file
View File

@@ -0,0 +1,19 @@
SRC=$HOME/.dotfilesrepo
rm $HOME/.bashrc
rm $HOME/.profile
ln -sf $SRC/.bashrc $HOME/.bashrc
ln -sf $SRC/.vimrc $HOME/.vimrc
ln -sf $SRC/.profile $HOME/.profile
ln -sf $SRC/.config $HOME/.config
ln -sf $SRC/bin $HOME/bin
# Install kakoune
wget https://github.com/mawww/kakoune/releases/download/v2026.05.21/kakoune-v2026.05.21-linux.tar.bz2
unpack kakoune-v2026.05.21-linux.tar.bz2
cd kakoune-v2026.05.21-linux
sudo cp -r bin/* /usr/local/bin/
sudo cp -r libexec/* /usr/local/libexec/
sudo cp -r share/* /usr/local/share/
cd ..
rm kakoune-v2026.05.21-linux -rf
rm kakoune-v2026.05.21-linux.tar.bz2