diff --git a/config/agents/AGENTS.md b/config/agents/AGENTS.md
index e69de29..e20b6be 100644
--- a/config/agents/AGENTS.md
+++ b/config/agents/AGENTS.md
@@ -0,0 +1,2 @@
+- When reporting information to me, be extremely concise and sacrifice grammar for the sake of concision.
+- My obsidian vault is located a /home/sjb/Documents/sjb-brain
diff --git a/config/agents/prompts/.empty b/config/agents/prompts/.empty
new file mode 100644
index 0000000..e69de29
diff --git a/config/fabric/config.yaml b/config/fabric/config.yaml
new file mode 100644
index 0000000..425c5c6
--- /dev/null
+++ b/config/fabric/config.yaml
@@ -0,0 +1,32 @@
+#this is an example yaml config file for fabric
+
+# use fabric pattern names
+# pattern: ai
+
+# or use a filename
+# pattern: ~/testpattern.md
+
+# model: openai/gpt-5.2
+
+# for models that support context length
+modelContextLength: 6000
+
+#frequencypenalty: 0.5
+#presencepenalty: 0.5
+#topp: 0.67
+#topp: 0.0
+#seed: 42
+#temperature: 0.88
+#temperature: 1.0
+
+stream: true
+raw: true
+
+# suppress vendor thinking output
+suppressThink: false
+thinkStartTag: ""
+thinkEndTag: ""
+
+# OpenAI Responses API settings
+# (use this for llama-server or other OpenAI-compatible local servers)
+disableResponsesAPI: true
diff --git a/config/fish/config.fish b/config/fish/config.fish
index 9875c9b..b837c4d 100644
--- a/config/fish/config.fish
+++ b/config/fish/config.fish
@@ -32,6 +32,7 @@ if status is-interactive
if command -q fzf
/usr/bin/fzf --fish | source
end
+
command -q nmcli && alias nmlist "nmcli device wifi list"
if command -q tree
@@ -50,13 +51,10 @@ if status is-interactive
if command -q nvim
set -gx EDITOR nvim
- end
-
- if command -q v
alias oo="cd ~/Documents/nca-notes/"
- alias on="v +Obsidian new"
- alias os="v +Obsidian search"
- end
+ alias on="nvim +Obsidian new"
+ alias os="nvim +Obsidian search"
+ end
command -q jj && alias rev "jj log -G -T 'commit_id.short(8)'"
@@ -80,13 +78,8 @@ if status is-interactive
alias ls="eza -al --color=always --group-directories-first"
end
- if command -q bat
- alias cat="bat"
- end
-
- if command -q git
- alias g=git
- end
+ command -q bat && alias cat="bat"
+ command -q git && alias g=git
set -gx VISUAL $EDITOR
diff --git a/config/foot/foot.ini b/config/foot/foot.ini
index 3bd1f40..3b4ea93 100644
--- a/config/foot/foot.ini
+++ b/config/foot/foot.ini
@@ -4,7 +4,7 @@ term=xterm-256color
pad=6x6
initial-window-mode=windowed
workers=0
-include=~/.local/share/themes/current/theme/foot.ini
+include=~/.config/omarchy/current/theme/foot.ini
[scrollback]
lines=10000
diff --git a/config/gnupg/common.conf b/config/gnupg/common.conf
new file mode 100644
index 0000000..5add401
--- /dev/null
+++ b/config/gnupg/common.conf
@@ -0,0 +1 @@
+use-keyboxd
diff --git a/config/gnupg/gpg-agent.conf b/config/gnupg/gpg-agent.conf
new file mode 100644
index 0000000..774efd5
--- /dev/null
+++ b/config/gnupg/gpg-agent.conf
@@ -0,0 +1,3 @@
+enable-ssh-support
+default-cache-ttl 60
+max-cache-ttl 120
diff --git a/config/gnupg/gpg.conf b/config/gnupg/gpg.conf
new file mode 100644
index 0000000..221abf7
--- /dev/null
+++ b/config/gnupg/gpg.conf
@@ -0,0 +1,2 @@
+utf8-strings
+use-agent
diff --git a/config/goose/config.yaml b/config/goose/config.yaml
new file mode 100644
index 0000000..d2fb342
--- /dev/null
+++ b/config/goose/config.yaml
@@ -0,0 +1,189 @@
+extensions:
+ extensionmanager:
+ enabled: true
+ type: platform
+ name: Extension Manager
+ description: Enable extension management tools for discovering, enabling, and disabling extensions
+ display_name: Extension Manager
+ bundled: true
+ available_tools: []
+ chatrecall:
+ enabled: false
+ type: platform
+ name: chatrecall
+ description: Search past conversations and load session summaries for contextual memory
+ display_name: Chat Recall
+ bundled: true
+ available_tools: []
+ skills:
+ enabled: true
+ type: platform
+ name: skills
+ description: Discover and provide skill instructions from filesystem and builtins
+ display_name: Skills
+ bundled: true
+ available_tools: []
+ todo:
+ enabled: true
+ type: platform
+ name: todo
+ description: Enable a todo list for goose so it can keep track of what it is doing
+ display_name: Todo
+ bundled: true
+ available_tools: []
+ code_execution:
+ enabled: true
+ type: platform
+ name: code_execution
+ description: Goose will make extension calls through code execution, saving tokens
+ display_name: Code Mode
+ bundled: true
+ available_tools: []
+ memory:
+ enabled: true
+ type: builtin
+ name: memory
+ description: Tools to save and retrieve durable memories
+ display_name: Memory
+ timeout: 300
+ bundled: true
+ available_tools: []
+ computercontroller:
+ enabled: true
+ type: builtin
+ name: computercontroller
+ description: controls for webscraping, file caching, and automations
+ display_name: Computer Controller
+ timeout: 300
+ bundled: true
+ available_tools: []
+ developer:
+ enabled: true
+ type: platform
+ name: developer
+ description: Write and edit files, and execute shell commands
+ display_name: Developer
+ bundled: true
+ available_tools: []
+ apps:
+ enabled: true
+ type: platform
+ name: apps
+ description: Create and manage custom Goose apps through chat. Apps are HTML/CSS/JavaScript and run in sandboxed windows.
+ display_name: Apps
+ bundled: true
+ available_tools: []
+ tom:
+ enabled: true
+ type: platform
+ name: tom
+ description: Inject custom context into every turn via GOOSE_MOIM_MESSAGE_TEXT and GOOSE_MOIM_MESSAGE_FILE environment variables
+ display_name: Top Of Mind
+ bundled: true
+ available_tools: []
+ summon:
+ enabled: true
+ type: platform
+ name: summon
+ description: Load knowledge and delegate tasks to subagents
+ display_name: Summon
+ bundled: true
+ available_tools: []
+ analyze:
+ enabled: true
+ type: platform
+ name: analyze
+ description: 'Analyze code structure with tree-sitter: directory overviews, file details, symbol call graphs'
+ display_name: Analyze
+ bundled: true
+ available_tools: []
+ summarize:
+ enabled: false
+ type: platform
+ name: summarize
+ description: Load files/directories and get an LLM summary in a single call
+ display_name: Summarize
+ bundled: true
+ available_tools: []
+ orchestrator:
+ enabled: false
+ type: platform
+ name: orchestrator
+ description: 'Manage agent sessions: list, view, start, send messages, interrupt, and stop agents'
+ display_name: Orchestrator
+ bundled: true
+ available_tools: []
+ autovisualiser:
+ enabled: false
+ type: builtin
+ name: autovisualiser
+ description: Data visualization and UI generation tools
+ display_name: Auto Visualiser
+ timeout: 300
+ bundled: true
+ available_tools: []
+ tutorial:
+ enabled: false
+ type: builtin
+ name: tutorial
+ description: Access interactive tutorials and guides
+ display_name: Tutorial
+ timeout: 300
+ bundled: true
+ available_tools: []
+GOOSE_TELEMETRY_ENABLED: false
+OLLAMA_HOST: 192.168.33.74:11434
+CHATGPT_CODEX_REASONING_EFFORT: medium
+providers:
+ chatgpt_codex:
+ enabled: true
+ model: gpt-5.5
+ configured: true
+ github_copilot:
+ enabled: true
+ model: gpt-5-mini
+ configured: true
+ custom_opencode_zen:
+ enabled: true
+ model: north-mini-code-free
+ configured: true
+ ollama:
+ enabled: true
+ model: qwen3.6:35b
+ configured: true
+ custom_sagacity:
+ enabled: true
+ model: gemma4:31b
+ configured: true
+ custom_opencode_go:
+ enabled: true
+ model: mimo-v2.5-pro
+ configured: true
+ opencode_go:
+ enabled: true
+ model: deepseek-v4-flash
+ configured: true
+ custom_allears:
+ enabled: true
+ model: qwen3.6:35b
+ configured: true
+ custom_obelix:
+ enabled: true
+ model: north-mini-code-1.0
+ configured: true
+ custom_dupont:
+ enabled: true
+ model: north-mini-code-1.0
+ configured: true
+active_provider: opencode_go
+GOOSE_THINKING_EFFORT: off
+voice_dictation_provider: openai
+GOOSE_MODE: auto
+OLLAMA_TIMEOUT: '600'
+SECURITY_PROMPT_ENABLED: false
+SECURITY_PROMPT_CLASSIFIER_ENABLED: false
+SECURITY_PROMPT_CLASSIFIER_MODEL: ''
+OPENAI_BASE_URL: https://opencode.ai/zen/go/
+OPENAI_HOST: https://api.openai.com
+OPENAI_BASE_PATH: v1/chat/completions
+OPENAI_TIMEOUT: '600'
diff --git a/config/herdr/config.toml b/config/herdr/config.toml
new file mode 100644
index 0000000..02b77fd
--- /dev/null
+++ b/config/herdr/config.toml
@@ -0,0 +1,15 @@
+onboarding = false
+[ui]
+show_agent_labels_on_pane_borders = true
+pane_gaps = false
+pane_borders = true
+
+[experimental]
+pane_history = true
+
+[theme]
+name = "gruvbox"
+auto_switch = false
+
+[keys]
+prefix = "ctrl+space"
diff --git a/config/mise/config.toml b/config/mise/config.toml
index b500ce8..b0c3b35 100644
--- a/config/mise/config.toml
+++ b/config/mise/config.toml
@@ -10,6 +10,7 @@ copilot-cli = "latest"
"github:danielmiessler/fabric" = "latest"
"github:mrusme/reader" = "latest"
"github:ulyssa/iamb" = "latest"
+"github:zed-industries/codex-acp" = "latest"
herdr = "latest"
"npm:@earendil-works/pi-coding-agent" = "latest"
"npm:mermaid-cli" = "latest"
@@ -25,10 +26,16 @@ run = [
'pi install npm:@tintinweb/pi-subagents',
'pi install npm:context-mode',
'pi install npm:@gotgenes/pi-permission-system',
- 'test -x /usr/bin/pass && /usr/bin/pass show agent/pi/auth.json > ~/.pi/agent/auth.json'
+ 'test -x /usr/bin/pass && /usr/bin/pass show config/pi/auth.json > ~/.pi/agent/auth.json'
]
[tasks.setup_nvim]
run = [
'uv tool install vectorcode'
]
+
+[tasks.skills]
+run = [
+ 'npx skills add SjB/skills',
+ 'npx skills add mattpocock/skills'
+]
diff --git a/config/ostt/ostt.toml b/config/ostt/ostt.toml
new file mode 100644
index 0000000..f4f4f7a
--- /dev/null
+++ b/config/ostt/ostt.toml
@@ -0,0 +1,21 @@
+config_version = "0.0.25"
+
+[transcription]
+provider = "whisper"
+model = "small"
+
+[audio]
+device = "default"
+output_format = "mp3 -ab 16k -ar 12000"
+peak_volume_threshold = 90
+reference_level_db = -20
+visualization = "spectrum"
+
+[popup]
+#terminal = "foot"
+borderless = true
+font_size = 25
+height = 15
+width = 90
+x = 630
+y = 790
diff --git a/config/pi/agent/extensions/pi-permission-system/config.json b/config/pi/agent/extensions/pi-permission-system/config.json
new file mode 100644
index 0000000..81bfaa0
--- /dev/null
+++ b/config/pi/agent/extensions/pi-permission-system/config.json
@@ -0,0 +1,24 @@
+{
+ "permission": {
+ "*": "ask",
+ "path": {
+ "./*": "allow",
+ "./.*": "allow",
+ "~/.ssh/*": "deny",
+ "*.env": "deny",
+ "*.env.*": "deny",
+ "*.env.example": "allow"
+ },
+ "bash": {
+ "*": "ask",
+ "rm -rf *": "deny",
+ "sudo *": "ask"
+ },
+ "external_directory": {
+ "*": "deny"
+ }
+ },
+ "debugLog": false,
+ "permissionReviewLog": true,
+ "yoloMode": true
+}
diff --git a/config/pi/agent/models.json b/config/pi/agent/models.json
index c1f95d8..a39587a 100644
--- a/config/pi/agent/models.json
+++ b/config/pi/agent/models.json
@@ -1,61 +1,108 @@
{
- "providers": {
- "dupont": {
- "baseUrl": "http://172.25.11.30/v1",
- "api": "openai-completions",
- "models": [
- {
- "id": "north-mini-code",
- "name": "north-mini-code",
- "reasoning": true,
- "input": ["text"],
- "contextWindow": 128000,
- "maxTokens": 128000,
- "cost": { "input": 1, "output": 1, "cacheRead": 1, "cacheWrite": 1 }
+ "providers": {
+ "dupont": {
+ "baseUrl": "http://172.25.11.30/v1",
+ "api": "openai-completions",
+ "models": [
+ {
+ "id": "glm-4.7-flash",
+ "name": "glm-4.7-flash",
+ "reasoning": true,
+ "input": [
+ "text"
+ ],
+ "contextWindow": 131072,
+ "maxTokens": 131072,
+ "cost": {
+ "input": 1,
+ "output": 1,
+ "cacheRead": 1,
+ "cacheWrite": 1
+ }
+ }
+ ],
+ "compat": {
+ "supportsDeveloperRole": true,
+ "supportsReasoningEffort": true
+ }
+ },
+ "obelix": {
+ "baseUrl": "http://172.25.11.32/v1",
+ "api": "openai-completions",
+ "models": [
+ {
+ "id": "ornith-1.0-35B",
+ "name": "ornith-1.0-35B",
+ "reasoning": true,
+ "input": [
+ "text"
+ ],
+ "contextWindow": 131072,
+ "maxTokens": 131072,
+ "cost": {
+ "input": 1,
+ "output": 1,
+ "cacheRead": 1,
+ "cacheWrite": 1
+ }
+ }
+ ],
+ "compat": {
+ "supportsDeveloperRole": true,
+ "supportsReasoningEffort": true
+ }
+ },
+ "bianca": {
+ "baseUrl": "http://172.25.11.33/v1",
+ "api": "openai-completions",
+ "models": [
+ {
+ "id": "gemma-4-12B-coder",
+ "name": "gemma-4-12B-coder",
+ "reasoning": true,
+ "input": [
+ "text"
+ ],
+ "contextWindow": 128000,
+ "maxTokens": 65536,
+ "cost": {
+ "input": 1,
+ "output": 1,
+ "cacheRead": 1,
+ "cacheWrite": 1
+ }
+ }
+ ],
+ "compat": {
+ "supportsDeveloperRole": true,
+ "supportsReasoningEffort": true
+ }
+ },
+ "cloudflare": {
+ "baseUrl": "https://api.cloudflare.com/client/v4/accounts/e54fa0b493ef3bef55746b1de8d33693/ai/v1",
+ "api": "openai-completions",
+ "models": [
+ {
+ "id": "@cf/zai-org/glm-5.2",
+ "name": "@cf/zai-org/glm-5.2",
+ "reasoning": true,
+ "input": [
+ "text"
+ ],
+ "contextWindow": 256000,
+ "maxTokens": 256000,
+ "cost": {
+ "input": 1,
+ "output": 1,
+ "cacheRead": 1,
+ "cacheWrite": 1
+ }
+ }
+ ],
+ "compat": {
+ "supportsDeveloperRole": true,
+ "supportsReasoningEffort": true
+ }
}
- ],
- "compat": {
- "supportsDeveloperRole": true,
- "supportsReasoningEffort": true
- }
- },
- "bianca": {
- "baseUrl": "http://172.25.11.33/v1",
- "api": "openai-completions",
- "models": [
- {
- "id": "gemma-4-12B-coder",
- "name": "gemma-4-12B-coder",
- "reasoning": true,
- "input": ["text"],
- "contextWindow": 128000,
- "maxTokens": 65536,
- "cost": { "input": 1, "output": 1, "cacheRead": 1, "cacheWrite": 1 }
- }
- ],
- "compat": {
- "supportsDeveloperRole": true,
- "supportsReasoningEffort": true
- }
- },
- "cloudflare": {
- "baseUrl": "https://api.cloudflare.com/client/v4/accounts/e54fa0b493ef3bef55746b1de8d33693/ai/v1",
- "api": "openai-completions",
- "models": [
- {
- "id": "@cf/zai-org/glm-5.2",
- "name": "@cf/zai-org/glm-5.2",
- "reasoning": true,
- "input": ["text"],
- "contextWindow": 256000,
- "maxTokens": 256000,
- "cost": { "input": 1, "output": 1, "cacheRead": 1, "cacheWrite": 1 }
- }
- ],
- "compat": {
- "supportsDeveloperRole": true,
- "supportsReasoningEffort": true
- }
}
- }
}
diff --git a/config/pi/agent/search-config.json b/config/pi/agent/search-config.json
new file mode 100644
index 0000000..ad731b7
--- /dev/null
+++ b/config/pi/agent/search-config.json
@@ -0,0 +1,13 @@
+{
+ "enabled": true,
+ "searchEnabled": true,
+ "fetchEnabled": true,
+ "providerOverrides": {
+ "claude-bridge": {
+ "searchEnabled": false
+ },
+ "opencode": {
+ "searchEnabled": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/config/pi/agent/settings.json b/config/pi/agent/settings.json
index e9348c2..1ba271e 100644
--- a/config/pi/agent/settings.json
+++ b/config/pi/agent/settings.json
@@ -1,19 +1,62 @@
{
- "lastChangelogVersion": "0.80.10",
+ "lastChangelogVersion": "0.80.7",
"theme": "light/dark",
- "defaultProvider": "opencode-go",
- "defaultModel": "deepseek-v4-flash",
- "defaultThinkingLevel": "high",
+ "defaultProvider": "github-copilot",
+ "defaultModel": "gpt-5-mini",
+ "defaultThinkingLevel": "minimal",
"hideThinkingBlock": true,
"compaction": {
"enabled": true
},
+ "thinkingLevelMap": {
+ "minimal": null,
+ "low": "low",
+ "medium": "medium",
+ "high": "high",
+ "xhigh": null,
+ "max": "max"
+ },
"enableInstallTelemetry": false,
+ "enabledModels": [
+ "opencode-go/qwen3.7-plus",
+ "opencode-go/deepseek-v4-pro",
+ "opencode-go/deepseek-v4-flash",
+ "opencode-go/kimi-k2.7-code",
+ "openai-codex/gpt-5.4",
+ "openai-codex/gpt-5.4-mini",
+ "openai-codex/gpt-5.3-codex-spark",
+ "obelix/ornith-1.0-35B",
+ "dupont/glm-4.7-flash",
+ "github-copilot/gpt-5-mini",
+ "github-copilot/mai-code-1-flash-picker"
+ ],
"packages": [
"npm:pi-lens",
+ "npm:@gotgenes/pi-permission-system",
"npm:pi-native-search",
- "npm:@tintinweb/pi-subagents",
"npm:context-mode",
- "npm:@gotgenes/pi-permission-system"
- ]
+ "npm:@tintinweb/pi-subagents"
+ ],
+ "subagents": {
+ "agentOverrides": {
+ "reviewer": {
+ "model": "opencode-go/mimo-v2.5-pro",
+ "fallbackModels": [
+ "openai/gpt-5-mini"
+ ]
+ },
+ "planner": {
+ "model": "opencode-go/qwen3.7-plus"
+ },
+ "worker": {
+ "model": "opencode-go/kimi-k2.7-code"
+ },
+ "oracle": {
+ "model": "opencode-go/qwen3.7-max",
+ "thinking": "high"
+ }
+ }
+ },
+ "quietStartup": true,
+ "steeringMode": "all"
}
\ No newline at end of file
diff --git a/config/ssh/config.d/default b/config/ssh/config.d/default
index 64727bd..befea6d 100644
--- a/config/ssh/config.d/default
+++ b/config/ssh/config.d/default
@@ -1,3 +1 @@
SetEnv TERM=xterm-256color
-
-
diff --git a/config/worktrunk/config.toml b/config/worktrunk/config.toml
index e0674e2..5503fdb 100644
--- a/config/worktrunk/config.toml
+++ b/config/worktrunk/config.toml
@@ -2,7 +2,7 @@ worktree-path = "{{ repo_path }}/../wt-{{ branch | sanitize }}"
[commit.generation]
-command = "opencode run -m github-copilot/gpt-5-mini --variant fast"
+command = "pi --model github-copilot/gpt-5-mini -p"
[post-create]
misetrust = "mise trust"
diff --git a/config/zero/config.json b/config/zero/config.json
new file mode 100644
index 0000000..f621539
--- /dev/null
+++ b/config/zero/config.json
@@ -0,0 +1,20 @@
+{
+ "activeProvider": "chatgpt",
+ "providers": [
+ {
+ "name": "chatgpt",
+ "provider_kind": "openai-compatible",
+ "catalogID": "chatgpt",
+ "baseURL": "https://chatgpt.com/backend-api/codex",
+ "apiFormat": "chat-completions",
+ "model": "gpt-5.5"
+ }
+ ],
+ "mcp": {},
+ "sandbox": {},
+ "notify": {},
+ "tools": {},
+ "swarm": {},
+ "preferences": {},
+ "keybindings": {}
+}
diff --git a/desktop/RampClient.desktop b/desktop/RampClient.desktop
new file mode 100644
index 0000000..9377ed3
--- /dev/null
+++ b/desktop/RampClient.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Version=1.0
+Name=RampClient PRD
+GenericName=Java Web Start Application
+Comment=RampClient PRD
+Categories=Network;Desktop;Java;Javaws;
+Type=Application
+Icon=/home/sjb/.config/icedtea-web/icons/b1bfbd7f-6c3e-40cf-8023-752cc6c45b66
+X-Vendor=UWO
+Exec="/opt/OpenWebStart/javaws" "https://wts.uwo.ca/ramp/prd/rampclient-prd.jnlp"
diff --git a/desktop/terminal.desktop b/desktop/terminal.desktop
new file mode 100644
index 0000000..cd9268b
--- /dev/null
+++ b/desktop/terminal.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Type=Application
+Exec=foot
+Icon=foot
+Terminal=false
+Categories=System;TerminalEmulator;
+Keywords=shell;prompt;command;commandline;
+
+Name=Terminal
+GenericName=Terminal
+Comment=A wayland native terminal emulator
diff --git a/desktop/tmux.desktop b/desktop/tmux.desktop
new file mode 100644
index 0000000..d721324
--- /dev/null
+++ b/desktop/tmux.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Version=1.0
+Name=Tmux Terminal
+Comment=Tmux Terminal
+Exec=foot tmux new -A -s main
+Terminal=false
+Type=Application
+Icon=tmux
+StartupNotify=true
diff --git a/mise.toml b/mise.toml
index 5dab48f..ac937dd 100644
--- a/mise.toml
+++ b/mise.toml
@@ -16,6 +16,7 @@ dotfiles.default_mode = "symlink-each"
"~/.config/btop/themes/current.theme" = { source = "~/.config/omarchy/current/theme/btop.theme", mode = "symlink" }
"~/.config/emacs" = "config/emacs"
"~/.config/environment.d" = "config/environment.d"
+"~/.gnupg" = "config/gnupg"
"~/.config/environment.d/dotfiles.conf" = { source = "templates/dofiles.conf.tmpl", template = "tera", mode = "template" }
"~/.config/fish" = "config/fish" # check if we really need the fisher plugins
"~/.config/gdb" = "config/gdb"
@@ -23,6 +24,10 @@ dotfiles.default_mode = "symlink-each"
"~/.config/ghostty/theme" = { source = "~/.config/omarchy/current/theme/ghostty.conf", mode = "symlink" }
"~/.config/git" = "config/git"
"~/.config/git/local" = { source = "templates/git-local.tmpl", mode = "template", template = "tera" }
+"~/.config/goose" = "config/goose"
+"~/.config/herdr" = "config/herdr"
+"~/.config/ostt" = "config/ostt"
+"~/.config/fabric" = "config/fabric"
"~/.config/fontconfig" = { source = "config/fontconfig", mode = "copy" }
"~/.config/foot" = "config/foot"
"~/.config/hypr" = "config/hypr"
@@ -48,15 +53,24 @@ dotfiles.default_mode = "symlink-each"
"~/.config/worktrunck" = "config/worktrunk"
"~/.config/chromium-flags.conf" = { source = "config/chromium-flags.conf", mode = "symlink" }
"~/.profile" = { source = "config/profile", mode = "symlink" }
+"~/.config/zero" = "config/zero"
"~/.local/share/fonts/" = { source = "fonts", mode = "copy" }
+# Desktop files
+"~/.local/share/applications/RampClient.desktop" = { source = "desktop/RampClient.desktop", mode = "symlink" }
+"~/.local/share/applications/terminal.desktop" = { source = "desktop/terminal.desktop", mode = "symlink" }
+"~/.local/share/applications/tmux.desktop" = { source = "desktop/tmux.desktop", mode = "symlink" }
+
# scripts.
"~/.local/bin/hyprland-activeworkspace" = { source = "script/hyprland-activeworkspace", mode = "symlink" }
"~/.local/bin/hyprland-keybindings" = { source = "script/hyprland-keybindings", mode = "symlink" }
"~/.local/bin/hyprland-fetch-client" = { source = "script/hyprland-fetch-client", mode = "symlink" }
"~/.local/bin/hyprland-focus-client" = { source = "script/hyprland-focus-client", mode = "symlink" }
+"~/.local/bin/battery" = { source = "script/battery", mode = "symlink" }
+# "~/.config/bin/ec" = { source = "script/ec", mode = "symlink" }
+"~/.local/bin/tmux-open" = { source = "script/tmux-open", mode = "symlink" }
"~/.local/bin/active-workspace" = { source = "script/active-workspace", mode = "symlink" }
"~/.local/bin/avr-flash" = { source = "script/avr-flash", mode = "symlink" }
"~/.local/bin/dfu-flash" = { source = "script/dfu-flash", mode = "symlink" }
diff --git a/script/battery.sh b/script/battery
similarity index 100%
rename from script/battery.sh
rename to script/battery
diff --git a/script/tmux-open b/script/tmux-open
new file mode 100755
index 0000000..6b50930
--- /dev/null
+++ b/script/tmux-open
@@ -0,0 +1,115 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# tmux-open — open a new tmux window (or session) and run a command
+# Usage: tmux-open [-k|--keep] [-h|--help] [args...]
+
+usage() {
+ cat <<'EOF'
+Usage: tmux-open [-k|--keep] [-h|--help] [args...]
+
+Open a new tmux window in the current session and run a command.
+If not inside tmux, create a new session named after the window and attach.
+
+Positional arguments:
+ window-name Name for the new tmux window (and session, if creating one)
+ start-dir Working directory for the new window
+ cmd [args...] Command to run (variadic)
+
+Options:
+ -k, --keep After the command exits, keep the pane visible (remain-on-exit)
+ so you can inspect output. Default: pane closes when command exits.
+ -h, --help Show this help message
+
+If `mise` is on PATH, the command runs under `mise x`.
+
+Errors:
+ - tmux not installed
+ - fewer than 3 positional args
+ - start-dir does not exist
+ - a window with the same name already exists in the current session
+EOF
+}
+
+# --- Flag parsing ---
+keep_shell=0
+while (( $# > 0 )); do
+ case "$1" in
+ -k|--keep) keep_shell=1; shift ;;
+ -h|--help) usage; exit 0 ;;
+ --) shift; break ;;
+ -*) echo "error: unknown option: $1" >&2; usage >&2; exit 1 ;;
+ *) break ;;
+ esac
+done
+
+# --- Positional arg validation ---
+if (( $# < 3 )); then
+ echo "error: expected at least 3 positional arguments (window-name, start-dir, cmd)" >&2
+ usage >&2
+ exit 1
+fi
+
+window_name="$1"; shift
+start_dir="$1"; shift
+cmd_args=("$@")
+
+# --- Pre-flight checks ---
+if ! command -v tmux >/dev/null 2>&1; then
+ echo "error: tmux is not installed or not on PATH" >&2
+ exit 1
+fi
+
+if [[ ! -d "$start_dir" ]]; then
+ echo "error: directory does not exist: $start_dir" >&2
+ exit 1
+fi
+
+if (( ${#cmd_args[@]} == 0 )); then
+ echo "error: no command specified" >&2
+ exit 1
+fi
+
+# Duplicate window name check (only relevant inside tmux)
+if [[ -n "${TMUX:-}" ]]; then
+ if tmux list-windows -F '#{window_name}' | grep -Fxq "$window_name"; then
+ echo "error: a window named '$window_name' already exists in the current session" >&2
+ exit 1
+ fi
+fi
+
+# --- Detect mise ---
+has_mise=0
+if command -v mise >/dev/null 2>&1; then
+ has_mise=1
+fi
+
+# --- Build the command for the new window ---
+# We need to construct a single shell command string for tmux.
+# The command runs; pane closes on exit (or stays visible with --keep via remain-on-exit).
+
+# Build the inner command based on mode and mise availability
+# For argv mode, quote each argument
+quoted_args=()
+for arg in "${cmd_args[@]}"; do
+ quoted_args+=("$(printf '%q' "$arg")")
+done
+if (( has_mise )); then
+ inner_cmd="mise x -- ${quoted_args[*]}"
+else
+ inner_cmd="${quoted_args[*]}"
+fi
+
+# --- Create window or session ---
+if [[ -n "${TMUX:-}" ]]; then
+ tmux new-window -n "$window_name" -c "$start_dir" "$inner_cmd"
+ if (( keep_shell )); then
+ tmux set-option remain-on-exit on
+ fi
+else
+ tmux new-session -d -n "$window_name" -s "$window_name" -c "$start_dir" "$inner_cmd"
+ if (( keep_shell )); then
+ tmux set-option -t "$window_name" remain-on-exit on
+ fi
+ tmux attach-session -t "$window_name"
+fi