19 Commits

Author SHA1 Message Date
Claude
7444f5b97b Remove pointless exports from ssh/rc, add process-model comment
ssh/rc runs as a sshd child process so exports never reach the user's
shell. SSH_REMOTE_AUTH_SOCK was set and exported but never used (a
leftover from a prior failed fix attempt). SSH_AUTH_SOCK was reassigned
to the symlink path and exported, also to no effect. Remove both.

https://claude.ai/code/session_01RhXaFzxJA5D2BcGcz18ipA
2026-04-19 02:19:05 +00:00
Claude
c5e1157f47 Fix shenv clobbering forwarded SSH socket with local agent in tmux
ssh/rc env changes (including SSH_REMOTE_AUTH_SOCK) are lost because
ssh/rc runs as a sshd child process, not the user's shell. The shell
always receives SSH_AUTH_SOCK set to the raw forwarded socket path.

Fresh SSH login worked fine (step 1 catches the raw socket). The bug
was in tmux new windows: SSH_AUTH_SOCK there is our stable symlink, so
step 1 fails, then steps 2/3 look up the system agent and overwrite the
symlink that ssh/rc just set to the forwarded socket.

Fix: only run the system agent lookup when the stable symlink is already
broken. A valid symlink means ssh/rc (or a previous shenv run) already
set it correctly; don't clobber it.

https://claude.ai/code/session_01RhXaFzxJA5D2BcGcz18ipA
2026-04-19 01:47:36 +00:00
Claude
6b50be84a9 Fix SSH agent forwarding clobbered by local agent in shenv
ssh/rc saves the raw forwarded socket in SSH_REMOTE_AUTH_SOCK before
rewriting SSH_AUTH_SOCK to the stable symlink. shenv was ignoring that
variable, so it saw SSH_AUTH_SOCK as "our link" and fell through to the
systemd lookup, which could overwrite the symlink with a local agent
socket and silently drop the forwarded one.

Now shenv checks SSH_REMOTE_AUTH_SOCK first, giving forwarded sockets
priority over any local agent.

https://claude.ai/code/session_01RhXaFzxJA5D2BcGcz18ipA
2026-04-19 01:43:12 +00:00
David Tomaschik
1804357162 Update skel 2026-04-14 10:27:17 -07:00
David Tomaschik
202d871a59 Merge branch 'main' of github.com:Matir/skel 2026-04-09 21:18:29 -07:00
David Tomaschik
467d916f33 Update zshrc 2026-04-09 21:18:24 -07:00
David Tomaschik
6d2bfdbcea Update custom starship shell 2026-04-09 18:03:14 -07:00
David Tomaschik
1d0a09c442 Bump Brewfile 2026-04-07 16:32:02 -07:00
David Tomaschik
37c765ae29 Update for bundles 2026-04-07 16:02:49 -07:00
David Tomaschik
41f8a49381 Remove missing brew entry 2026-04-07 14:53:41 -07:00
David Tomaschik
3f9c41d266 Merge branch 'main' of https://github.com/Matir/skel 2026-04-06 18:34:17 -07:00
David Tomaschik
69e4b83652 Fix brew manager 2026-04-06 18:34:06 -07:00
David Tomaschik
74c2472dd2 Fix zsh completion 2026-04-06 15:30:14 -07:00
David Tomaschik
ecc39344ca Improve gemini context 2026-04-02 16:37:51 -07:00
David Tomaschik
49a314e388 Merge branch 'main' of github.com:Matir/skel 2026-04-01 23:02:57 -07:00
David Tomaschik
41293eb788 Add more vscode extensions 2026-04-01 23:02:55 -07:00
David Tomaschik
05798dcb67 Update AGENTS.md 2026-04-01 18:24:15 -07:00
David Tomaschik
4e1b263170 Remove weechat 2026-04-01 14:23:54 -07:00
David Tomaschik
46c00c61be Update dotfiles 2026-04-01 14:02:33 -07:00
29 changed files with 460 additions and 1410 deletions

View File

@@ -9,8 +9,9 @@ fi
UPDATE_SCRIPT="bin/macos/update_brewfile"
if [[ -x "$UPDATE_SCRIPT" ]]; then
# Run in dry-run mode and see if there's output
DIFF_OUTPUT=$("$UPDATE_SCRIPT" --dry-run 2>/dev/null)
echo "🔍 Checking Brewfile synchronization..."
# Run in dry-run mode with --add-only and see if there's output
DIFF_OUTPUT=$("$UPDATE_SCRIPT" --dry-run --add-only 2>/dev/null)
if [[ "$DIFF_OUTPUT" == *"Changes detected"* ]]; then
echo "⚠️ Brewfile is out of sync with your installed packages."
echo " Run '$UPDATE_SCRIPT' to synchronize it."

View File

@@ -10,7 +10,8 @@ locations, but also installs dependencies in various ways.
I primarily target Debian Linux-based (Debian, Ubuntu, and Kali Linux) systems
as well as MacOS. Other platforms are lower priorities. Shell scripts ending
in `.sh` should use only POSIX features unless there is a shebang line at the
beginning suggesting a different shell will be used.
beginning suggesting a different shell will be used. In particular, those
in directories with names like bash might use those shells.
`zsh` and `fish` are the key interactive shells to be configured, but `bash`
may also be used at times.

View File

@@ -1,5 +1,6 @@
tap "dart-lang/dart"
tap "sass/sass"
brew "ack"
brew "acme.sh"
brew "age"
@@ -7,14 +8,16 @@ brew "autoconf"
brew "automake"
brew "b2-tools"
brew "bat"
brew "bazelisk"
brew "binwalk"
brew "cask"
brew "ccache"
brew "certbot"
brew "cmake"
brew "colima"
brew "devcontainer"
brew "difftastic"
brew "dfu-util"
brew "difftastic"
brew "direnv"
brew "duck"
brew "earthly"
@@ -27,6 +30,7 @@ brew "git-lfs"
brew "gnupg"
brew "go"
brew "gradle"
brew "hf"
brew "htop"
brew "httpie"
brew "huggingface-cli"
@@ -40,11 +44,12 @@ brew "mosh"
brew "neovim"
brew "ninja"
brew "nmap"
brew "protobuf"
brew "ollama"
brew "p7zip"
brew "pipenv"
brew "pipx"
brew "pkgconf"
brew "protobuf"
brew "pwgen"
brew "pwntools"
brew "qemu"
@@ -53,7 +58,8 @@ brew "ripgrep"
brew "ruby"
brew "ruby@3.3"
brew "rustup"
brew "scroll-reverser"
brew "sass/sass/migrator"
brew "sass/sass/sass"
brew "shellcheck"
brew "smartmontools"
brew "starship"
@@ -64,8 +70,7 @@ brew "wget"
brew "yt-dlp"
brew "zlib"
brew "zsh-syntax-highlighting"
brew "sass/sass/migrator"
brew "sass/sass/sass"
cask "codeql"
cask "cyberduck"
cask "font-fira-code-nerd-font"
@@ -82,6 +87,7 @@ cask "iterm2"
cask "macfuse"
cask "meld"
cask "mitmproxy"
cask "processmonitor"
cask "raycast"
cask "rectangle"
cask "scroll-reverser"

View File

@@ -7,16 +7,69 @@ import sys
import argparse
import difflib
import tempfile
# Regex to match brew/cask/tap/mas lines
PKG_RE = re.compile(r'^\s*(brew|cask|tap|mas)\s+["\']([^"\']+)["\'](.*)$')
def colorize_diff(lines):
for line in lines:
if line.startswith('+') and not line.startswith('+++'):
yield f"\033[32m{line}\033[0m"
elif line.startswith('-') and not line.startswith('---'):
yield f"\033[31m{line}\033[0m"
elif line.startswith('^'):
yield f"\033[36m{line}\033[0m"
else:
yield line
class Entry:
def sort_key(self): raise NotImplementedError()
def to_lines(self): raise NotImplementedError()
class PackageEntry(Entry):
def __init__(self, pkg_type, name, options, comments=None):
self.pkg_type = pkg_type
self.name = name
self.options = options.strip()
self.comments = comments or []
def sort_key(self):
order = {'tap': 0, 'brew': 1, 'cask': 2, 'mas': 3}
return (order.get(self.pkg_type, 4), self.name)
def to_lines(self):
res = list(self.comments)
pkg_line = f'{self.pkg_type} "{self.name}"'
if self.options:
if not self.options.startswith(','):
pkg_line += ' '
pkg_line += self.options
res.append(pkg_line)
return res
class TextEntry(Entry):
def __init__(self, lines, is_header=True):
self.lines = lines
self.is_header = is_header
def sort_key(self):
# Header is -1, Trailing is 5 (after all package types 0-4)
return (-1 if self.is_header else 5, "")
def to_lines(self):
return self.lines
def get_repo_root():
script_dir = os.path.dirname(os.path.realpath(__file__))
try:
root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'],
root = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'],
cwd=script_dir,
stderr=subprocess.STDOUT).decode().strip()
return root
except subprocess.CalledProcessError:
return os.getcwd()
# If not in a git repo, go up 2 levels from script_dir (bin/macos/)
return os.path.abspath(os.path.join(script_dir, '..', '..'))
def get_ignore_list(repo_root):
ignore = set()
@@ -34,11 +87,19 @@ def get_ignore_list(repo_root):
ignore.add(line)
return ignore
def get_current_packages():
def get_current_packages(args):
"""Runs brew bundle dump and returns lines."""
env = os.environ.copy()
env["HOMEBREW_NO_AUTO_UPDATE"] = "1"
env["HOMEBREW_NO_INSTALL_CLEANUP"] = "1"
env["HOMEBREW_NO_ENV_HINTS"] = "1"
cmd = ['brew', 'bundle', 'dump', '--file=-']
if args.no_mas: cmd.append('--no-mas')
if args.no_vscode: cmd.append('--no-vscode')
try:
output = subprocess.check_output(['brew', 'bundle', 'dump', '--file=-'],
stderr=subprocess.DEVNULL).decode()
output = subprocess.check_output(cmd, env=env, stderr=subprocess.DEVNULL).decode()
return output.splitlines()
except subprocess.CalledProcessError:
print("Error: 'brew bundle dump' failed. Is homebrew installed?", file=sys.stderr)
@@ -48,19 +109,20 @@ def parse_brewfile(content):
"""
Parses Brewfile content.
Returns:
- entries: list of Entry objects
- conditional_pkgs: set of (type, name)
- preserved_footer: string (everything from first conditional onwards)
- footer: string (everything from first conditional onwards)
"""
lines = content.splitlines()
conditional_pkgs = set()
# Find the start of the first conditional block
first_conditional_idx = -1
in_conditional = 0
for i, line in enumerate(lines):
stripped = line.strip()
if stripped.startswith(('if ', 'unless ', 'case ')) and not stripped.endswith('; end'):
if stripped.startswith(('if ', 'unless ', 'case ', 'def ', 'begin ')) and not stripped.endswith('; end'):
if first_conditional_idx == -1:
# Look back for comments that might belong to this block
j = i - 1
@@ -68,65 +130,132 @@ def parse_brewfile(content):
j -= 1
first_conditional_idx = j + 1
in_conditional += 1
if in_conditional > 0:
match = PKG_RE.match(line)
if match:
conditional_pkgs.add((match.group(1), match.group(2)))
if stripped == 'end' or stripped.endswith('; end'):
in_conditional -= 1
if first_conditional_idx == -1:
return set(), ""
footer = "\n".join(lines[first_conditional_idx:])
return conditional_pkgs, footer
unconditional_lines = lines[:first_conditional_idx] if first_conditional_idx != -1 else lines
footer = "\n".join(lines[first_conditional_idx:]) if first_conditional_idx != -1 else ""
entries = []
comment_buffer = []
first_pkg_seen = False
for line in unconditional_lines:
match = PKG_RE.match(line)
if match:
if not first_pkg_seen:
if comment_buffer:
entries.append(TextEntry(comment_buffer, is_header=True))
comment_buffer = []
first_pkg_seen = True
entries.append(PackageEntry(match.group(1), match.group(2), match.group(3), comment_buffer))
comment_buffer = []
else:
comment_buffer.append(line)
if comment_buffer:
entries.append(TextEntry(comment_buffer, is_header=False))
return entries, conditional_pkgs, footer
def main(args):
if sys.platform != "darwin":
print(f"Warning: Running on {sys.platform}. Brewfile is primarily for macOS.", file=sys.stderr)
repo_root = get_repo_root()
brewfile_path = os.path.join(repo_root, 'Brewfile')
if not os.path.exists(brewfile_path):
print(f"Error: Brewfile not found at {brewfile_path}", file=sys.stderr)
sys.exit(1)
with open(brewfile_path) as f:
old_content = f.read()
conditional_pkgs, footer = parse_brewfile(old_content)
old_entries, conditional_pkgs, footer = parse_brewfile(old_content)
ignore_list = get_ignore_list(repo_root)
dumped_lines = get_current_packages()
new_unconditional_lines = []
old_pkg_map = {}
for e in old_entries:
if isinstance(e, PackageEntry):
key = (e.pkg_type, e.name)
if key not in old_pkg_map:
old_pkg_map[key] = e
dumped_lines = get_current_packages(args)
dumped_pkgs = []
for line in dumped_lines:
match = PKG_RE.match(line)
if match:
pkg_type, pkg_name = match.group(1), match.group(2)
if pkg_name in ignore_list:
pkg_type, pkg_name, pkg_options = match.group(1), match.group(2), match.group(3)
if pkg_name in ignore_list or (pkg_type, pkg_name) in conditional_pkgs:
continue
if (pkg_type, pkg_name) in conditional_pkgs:
continue
# If it's not a package line (e.g. comment from dump), we can skip or keep
if line.strip():
new_unconditional_lines.append(line)
dumped_pkgs.append(PackageEntry(pkg_type, pkg_name, pkg_options))
# Sort lines by type (tap, brew, cask, mas) then name
def sort_key(line):
match = PKG_RE.match(line)
if not match: return (4, line)
order = {'tap': 0, 'brew': 1, 'cask': 2, 'mas': 3}
return (order.get(match.group(1), 4), match.group(2))
new_entries = []
for e in old_entries:
if isinstance(e, TextEntry) and e.is_header:
new_entries.append(e)
new_unconditional_lines.sort(key=sort_key)
# Build new content
new_content = "\n".join(new_unconditional_lines)
seen_in_new = set()
added_count = 0
removed_count = 0
merged_count = 0
if args.add_only:
for e in old_entries:
if isinstance(e, PackageEntry):
new_entries.append(e)
seen_in_new.add((e.pkg_type, e.name))
for d in dumped_pkgs:
if (d.pkg_type, d.name) not in seen_in_new:
new_entries.append(d)
seen_in_new.add((d.pkg_type, d.name))
added_count += 1
else:
for d in dumped_pkgs:
key = (d.pkg_type, d.name)
if key in seen_in_new: continue
if key in old_pkg_map:
merged = old_pkg_map[key]
if not merged.options:
merged.options = d.options
new_entries.append(merged)
merged_count += 1
else:
new_entries.append(d)
added_count += 1
seen_in_new.add(key)
# Check for removals
for key in old_pkg_map:
if key not in seen_in_new:
removed_count += 1
for e in old_entries:
if isinstance(e, TextEntry) and not e.is_header:
new_entries.append(e)
new_entries.sort(key=lambda x: x.sort_key())
output_lines = []
last_type = None
for e in new_entries:
if isinstance(e, PackageEntry):
if last_type and e.pkg_type != last_type:
output_lines.append("")
last_type = e.pkg_type
output_lines.extend(e.to_lines())
new_content = "\n".join(output_lines)
if footer:
if new_unconditional_lines:
if output_lines and output_lines[-1].strip():
new_content += "\n\n"
new_content += footer.strip() + "\n"
else:
@@ -137,20 +266,33 @@ def main(args):
else:
if args.dry_run:
print("Changes detected (dry run):")
diff = difflib.unified_diff(
diff = list(difflib.unified_diff(
old_content.splitlines(keepends=True),
new_content.splitlines(keepends=True),
fromfile='Brewfile (original)',
tofile='Brewfile (new)'
)
sys.stdout.writelines(diff)
))
if sys.stdout.isatty():
sys.stdout.writelines(colorize_diff(diff))
else:
sys.stdout.writelines(diff)
else:
with open(brewfile_path, 'w') as f:
f.write(new_content)
dir_name = os.path.dirname(brewfile_path)
with tempfile.NamedTemporaryFile('w', dir=dir_name, delete=False) as tf:
tf.write(new_content)
tempname = tf.name
os.replace(tempname, brewfile_path)
print("Brewfile updated.")
if args.verbose:
print(f"Summary: {added_count} added, {removed_count} removed, {merged_count} kept/merged.")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Update Brewfile while preserving conditionals.")
parser.add_argument("--dry-run", action="store_true", help="Show changes without applying them.")
parser.add_argument("--add-only", action="store_true", help="Only add missing entries, do not remove existing ones.")
parser.add_argument("--verbose", "-v", action="store_true", help="Print summary of changes.")
parser.add_argument("--no-mas", action="store_true", help="Do not include Mac App Store apps.")
parser.add_argument("--no-vscode", action="store_true", help="Do not include VSCode extensions.")
args = parser.parse_args()
main(args)

View File

@@ -0,0 +1,95 @@
# Bridge to Gemini CLI Context Management (Zsh-backed)
# This allows using the Zsh implementation from Fish to avoid dual maintenance.
# Ensure the base context directory exists
if set -q XDG_CONFIG_HOME
set -gx GEMINI_CONTEXT_DIR $XDG_CONFIG_HOME/gemini
else
set -gx GEMINI_CONTEXT_DIR $HOME/.config/gemini
end
mkdir -p "$GEMINI_CONTEXT_DIR"
# Path to the source of truth
set -l gemini_zsh_script "$HOME/.skel/dotfiles/zshrc.d/gemini.zsh"
function _gemini_context_bridge
# Check if Zsh script exists
if not test -f "$gemini_zsh_script"
echo "Error: Gemini Zsh script not found at $gemini_zsh_script"
return 1
end
# We use a temporary file to reliably pass the environment variable back
set -l env_file (mktemp -t gemini_context.XXXXXX)
# Run zsh with -e (exit on error):
# 1. Source the context manager
# 2. Run the requested command with arguments
# 3. Write the resulting GEMINI_CLI_HOME to the temp file
command zsh -ec "
source '$gemini_zsh_script'
$argv
echo \"\$GEMINI_CLI_HOME\" > '$env_file'
"
set -l zsh_status $status
# Only sync environment and clean up on success
if test $zsh_status -eq 0
set -l new_home (cat $env_file | string trim)
if test -n "$new_home"
set -gx GEMINI_CLI_HOME "$new_home"
else
set -e GEMINI_CLI_HOME
end
end
rm -f $env_file
return $zsh_status
end
# Wrapper functions
function gemini-context-use
_gemini_context_bridge "gemini-context-use $argv"
end
function gemini-context-create
_gemini_context_bridge "gemini-context-create $argv"
end
function gemini-context-list
_gemini_context_bridge "gemini-context-list $argv"
end
function gemini-context-delete
_gemini_context_bridge "gemini-context-delete $argv"
end
function gemini-context-rename
_gemini_context_bridge "gemini-context-rename $argv"
end
function gemini-context-edit
_gemini_context_bridge "gemini-context-edit $argv"
end
function gemini-context-current
_gemini_context_bridge "gemini-context-current $argv"
end
function gemini-context-unset
_gemini_context_bridge "gemini-context-unset $argv"
end
# Aliases
alias gemctx='gemini-context-use'
# Completion
function _gemini_context_list
zsh -c "source '$gemini_zsh_script'; _gemini_context_list_internal"
end
complete -c gemini-context-use -f -a "(_gemini_context_list)"
complete -c gemctx -f -a "(_gemini_context_list)"
complete -c gemini-context-edit -f -a "(_gemini_context_list)"
complete -c gemini-context-delete -f -a "(_gemini_context_list)"
complete -c gemini-context-rename -f -a "(_gemini_context_list)"

View File

@@ -30,5 +30,8 @@ if status --is-interactive
install_fisher
end
# Want this at the bottom to put this path first
# Want these at the bottom to put them first in PATH
fish_add_path --move --path {$HOME}/bin
if test (uname) = "Darwin"
fish_add_path --move --path {$HOME}/bin/macos
end

View File

@@ -9,6 +9,7 @@ uv_venv_auto = true
[tools]
age = "latest"
age-plugin-yubikey = "latest"
usage = "latest"
uv = "latest"

View File

@@ -51,3 +51,4 @@ fi
"""
style = "bold blue"
format = "♊[$output](blue) "
shell = ["/bin/sh", "-c"]

View File

@@ -0,0 +1,9 @@
[alias]
commit-assumed = "!f() { \
file=\"$1\"; \
shift; \
git update-index --no-assume-unchanged \"$file\" && \
git add \"$file\" && \
git commit \"$@\" && \
git update-index --assume-unchanged \"$file\"; \
}; f"

View File

@@ -113,13 +113,17 @@ _is_link_path() {
_CANDIDATE=""
# 1. If current environment has a valid socket that is NOT our link, it's a prime candidate (e.g. SSH forwarding).
# 1. If current environment has a valid socket that is NOT our link, it's a prime candidate
# (e.g. fresh SSH login: sshd sets SSH_AUTH_SOCK to the raw forwarded socket before ssh/rc
# rewrites it to the stable symlink; the shell inherits the original raw path).
if [ -S "${SSH_AUTH_SOCK:-}" ] && ! _is_link_path "${SSH_AUTH_SOCK}"; then
_CANDIDATE="${SSH_AUTH_SOCK}"
fi
# 2. If no candidate yet, or we're currently using the link, try to find the "real" system agent.
if [ -z "${_CANDIDATE}" ] || _is_link_path "${SSH_AUTH_SOCK:-}"; then
# 2. Only look for a system agent if the stable link is already broken. If the link is
# valid (e.g. a tmux pane where SSH_AUTH_SOCK points to our symlink which ssh/rc just
# updated to the forwarded socket), leave it alone — don't clobber it with a local agent.
if [ -z "${_CANDIDATE}" ] && [ ! -S "${_SSH_AUTH_LINK}" ]; then
_FOUND=""
if [ "$(uname)" = "Darwin" ]; then
_FOUND=$(launchctl getenv SSH_AUTH_SOCK 2>/dev/null)
@@ -143,8 +147,8 @@ if [ -z "${_CANDIDATE}" ] || _is_link_path "${SSH_AUTH_SOCK:-}"; then
fi
fi
# 3. Last resort: search common paths if we still don't have a valid candidate.
if [ ! -S "${_CANDIDATE}" ]; then
# 3. Last resort: search common paths if we still don't have a candidate and the link is broken.
if [ ! -S "${_CANDIDATE}" ] && [ ! -S "${_SSH_AUTH_LINK}" ]; then
_U=$(id -u)
for _p in "/run/user/${_U}/keyring/ssh" "/run/user/${_U}/ssh-agent.socket" "/run/user/${_U}/openssh_agent" "/run/user/${_U}/gnupg/S.gpg-agent.ssh"; do
if [ -S "${_p}" ] && ! _is_link_path "${_p}"; then
@@ -189,6 +193,7 @@ if [ "$(uname)" = "Darwin" ] ; then
# Using id -u for better POSIX compatibility than $UID
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-$TMPDIR/runtime-$(id -u)}"
export XDG_STATE_HOME="${XDG_STATE_HOME:-$HOME/.local/state}"
export PATH="${HOME}/bin/macos:${PATH}"
fi
if test -e "$HOME/.localenv"; then

View File

@@ -2,19 +2,19 @@
# Roughly based on this article:
# https://werat.github.io/2017/02/04/tmux-ssh-agent-forwarding.html
#
# NOTE: this file is executed by sshd as a child process, NOT sourced by the
# user's shell. Any variable assignments or exports here have no effect on the
# shell environment the user will land in.
REMOTE_LINK="${HOME}/.ssh/ssh_auth_sock"
if [ -S "${SSH_AUTH_SOCK}" ] ; then
SSH_REMOTE_AUTH_SOCK="${SSH_AUTH_SOCK}"
export SSH_REMOTE_AUTH_SOCK
# Always update the symlink to the latest session's socket.
# This ensures that tmux (which uses the static path) always points to a
# This ensures that tmux (which uses the static path) always points to a
# current agent.
mkdir -p "$(dirname "${REMOTE_LINK}")"
ln -sf "${SSH_AUTH_SOCK}" "${REMOTE_LINK}"
SSH_AUTH_SOCK="${REMOTE_LINK}"
export SSH_AUTH_SOCK
fi
# if stdin is a tty, don't do the cookie step

View File

@@ -1,41 +0,0 @@
#
# weechat -- alias.conf
#
[cmd]
AAWAY = "allserv /away"
AME = "allchan /me"
AMSG = "allchan /msg *"
ANICK = "allserv /nick"
BEEP = "print -beep"
BYE = "quit"
C = "buffer clear"
CHAT = "dcc chat"
CL = "buffer clear"
CLOSE = "buffer close"
EXIT = "quit"
IG = "ignore"
J = "join"
K = "kick"
KB = "kickban"
LEAVE = "part"
M = "msg"
MSGBUF = "command -buffer $1 * /input send $2-"
MUB = "unban *"
N = "names"
Q = "query"
REDRAW = "window refresh"
SAY = "msg *"
SIGNOFF = "quit"
T = "topic"
UB = "unban"
UMODE = "mode $nick"
V = "command core version"
W = "who"
WC = "window merge"
WI = "whois"
WII = "whois $1 $1"
WW = "whowas"
[completion]
MSGBUF = "%(buffers_plugins_names)"

View File

@@ -1,20 +0,0 @@
#
# weechat -- aspell.conf
#
[color]
misspelled = lightred
suggestions = default
[check]
commands = "ame,amsg,away,command,cycle,kick,kickban,me,msg,notice,part,query,quit,topic"
default_dict = ""
during_search = off
enabled = off
real_time = off
suggestions = -1
word_min_length = 2
[dict]
[option]

View File

@@ -1,11 +0,0 @@
#
# weechat -- charset.conf
#
[default]
decode = "iso-8859-1"
encode = ""
[decode]
[encode]

View File

@@ -1,11 +0,0 @@
#
# weechat -- exec.conf
#
[command]
default_options = ""
purge_delay = 0
[color]
flag_finished = lightred
flag_running = lightgreen

View File

@@ -1,377 +0,0 @@
#
# weechat -- irc.conf
#
[look]
buffer_open_before_autojoin = on
buffer_open_before_join = off
buffer_switch_autojoin = on
buffer_switch_join = on
color_nicks_in_names = off
color_nicks_in_nicklist = off
color_nicks_in_server_messages = on
color_pv_nick_like_channel = on
ctcp_time_format = "%a, %d %b %Y %T %z"
display_away = local
display_ctcp_blocked = on
display_ctcp_reply = on
display_ctcp_unknown = on
display_host_join = on
display_host_join_local = on
display_host_quit = on
display_join_message = "329,332,333,366"
display_old_topic = on
display_pv_away_once = on
display_pv_back = on
highlight_channel = "$nick"
highlight_pv = "$nick"
highlight_server = "$nick"
highlight_tags_restrict = "irc_privmsg,irc_notice"
item_channel_modes_hide_args = "k"
item_display_server = buffer_plugin
item_nick_modes = on
item_nick_prefix = on
join_auto_add_chantype = off
msgbuffer_fallback = current
new_channel_position = none
new_pv_position = none
nick_completion_smart = speakers
nick_mode = prefix
nick_mode_empty = off
nicks_hide_password = "nickserv"
notice_as_pv = auto
notice_welcome_redirect = on
notice_welcome_tags = ""
notify_tags_ison = "notify_message"
notify_tags_whois = "notify_message"
part_closes_buffer = on
pv_buffer = independent
pv_tags = "notify_private"
raw_messages = 256
server_buffer = merge_with_core
smart_filter = on
smart_filter_delay = 5
smart_filter_join = on
smart_filter_join_unmask = 30
smart_filter_mode = "+"
smart_filter_nick = on
smart_filter_quit = on
temporary_servers = off
topic_strip_colors = off
[color]
input_nick = lightcyan
item_channel_modes = default
item_lag_counting = default
item_lag_finished = yellow
item_nick_modes = default
message_join = green
message_quit = red
mirc_remap = "1,-1:darkgray"
nick_prefixes = "q:lightred;a:lightcyan;o:lightgreen;h:lightmagenta;v:yellow;*:lightblue"
notice = green
reason_quit = default
topic_current = default
topic_new = white
topic_old = default
[network]
autoreconnect_delay_growing = 2
autoreconnect_delay_max = 600
ban_mask_default = "*!$ident@$host"
channel_encode = off
colors_receive = on
colors_send = on
lag_check = 60
lag_max = 1800
lag_min_show = 500
lag_reconnect = 0
lag_refresh_interval = 1
notify_check_ison = 1
notify_check_whois = 5
sasl_fail_unavailable = on
send_unknown_commands = off
whois_double_nick = off
[msgbuffer]
[ctcp]
[ignore]
[server_default]
addresses = ""
anti_flood_prio_high = 2
anti_flood_prio_low = 2
autoconnect = off
autojoin = ""
autoreconnect = on
autoreconnect_delay = 10
autorejoin = off
autorejoin_delay = 30
away_check = 0
away_check_max_nicks = 25
capabilities = ""
command = ""
command_delay = 0
connection_timeout = 60
ipv6 = on
local_hostname = ""
msg_kick = ""
msg_part = "WeeChat ${info:version}"
msg_quit = "WeeChat ${info:version}"
nicks = "Matir,Matir~,Matir[]"
nicks_alternate = on
notify = ""
password = ""
proxy = ""
realname = ""
sasl_fail = continue
sasl_key = ""
sasl_mechanism = plain
sasl_password = ""
sasl_timeout = 15
sasl_username = ""
ssl = off
ssl_cert = ""
ssl_dhkey_size = 2048
ssl_fingerprint = ""
ssl_priorities = "NORMAL"
ssl_verify = on
username = "matir"
[server]
freenode.addresses = "chat.freenode.net/7000"
freenode.proxy
freenode.ipv6
freenode.ssl = on
freenode.ssl_cert = "%h/certs/freenode-matir.pem"
freenode.ssl_priorities
freenode.ssl_dhkey_size
freenode.ssl_fingerprint
freenode.ssl_verify = on
freenode.password
freenode.capabilities
freenode.sasl_mechanism
freenode.sasl_username
freenode.sasl_password
freenode.sasl_key
freenode.sasl_timeout
freenode.sasl_fail
freenode.autoconnect = on
freenode.autoreconnect
freenode.autoreconnect_delay
freenode.nicks = "Matir,Matir~"
freenode.nicks_alternate
freenode.username
freenode.realname
freenode.local_hostname
freenode.command
freenode.command_delay
freenode.autojoin = "#kali-linux,#openvpn,#radare,#vulnhub,#offsec,#offtopicsec,##ctfcompetition,#dc404,#droidsec"
freenode.autorejoin
freenode.autorejoin_delay
freenode.connection_timeout
freenode.anti_flood_prio_high
freenode.anti_flood_prio_low
freenode.away_check
freenode.away_check_max_nicks
freenode.msg_kick
freenode.msg_part
freenode.msg_quit
freenode.notify
hak5.addresses = "irc.hak5.org/6697"
hak5.proxy
hak5.ipv6
hak5.ssl = on
hak5.ssl_cert = "%h/certs/freenode-matir.pem"
hak5.ssl_priorities
hak5.ssl_dhkey_size
hak5.ssl_fingerprint
hak5.ssl_verify = off
hak5.password
hak5.capabilities
hak5.sasl_mechanism
hak5.sasl_username
hak5.sasl_password
hak5.sasl_key
hak5.sasl_timeout
hak5.sasl_fail
hak5.autoconnect = on
hak5.autoreconnect
hak5.autoreconnect_delay
hak5.nicks
hak5.nicks_alternate
hak5.username
hak5.realname
hak5.local_hostname
hak5.command
hak5.command_delay
hak5.autojoin = "#hak5,#pineapple,#ducky,#SDR,#lanturtle,#bashbunny"
hak5.autorejoin
hak5.autorejoin_delay
hak5.connection_timeout
hak5.anti_flood_prio_high
hak5.anti_flood_prio_low
hak5.away_check
hak5.away_check_max_nicks
hak5.msg_kick
hak5.msg_part
hak5.msg_quit
hak5.notify
rpisec.addresses = "irc.rpis.ec/6697"
rpisec.proxy
rpisec.ipv6
rpisec.ssl = on
rpisec.ssl_cert
rpisec.ssl_priorities
rpisec.ssl_dhkey_size
rpisec.ssl_fingerprint
rpisec.ssl_verify = on
rpisec.password
rpisec.capabilities
rpisec.sasl_mechanism
rpisec.sasl_username
rpisec.sasl_password
rpisec.sasl_key
rpisec.sasl_timeout
rpisec.sasl_fail
rpisec.autoconnect = on
rpisec.autoreconnect
rpisec.autoreconnect_delay
rpisec.nicks
rpisec.nicks_alternate
rpisec.username
rpisec.realname
rpisec.local_hostname
rpisec.command
rpisec.command_delay
rpisec.autojoin = "#rpisec"
rpisec.autorejoin
rpisec.autorejoin_delay
rpisec.connection_timeout
rpisec.anti_flood_prio_high
rpisec.anti_flood_prio_low
rpisec.away_check
rpisec.away_check_max_nicks
rpisec.msg_kick
rpisec.msg_part
rpisec.msg_quit
rpisec.notify
overthewire.addresses = "ircs.overthewire.org/6697"
overthewire.proxy
overthewire.ipv6
overthewire.ssl = on
overthewire.ssl_cert = "%h/certs/freenode-matir.pem"
overthewire.ssl_priorities
overthewire.ssl_dhkey_size
overthewire.ssl_fingerprint
overthewire.ssl_verify = on
overthewire.password
overthewire.capabilities
overthewire.sasl_mechanism
overthewire.sasl_username
overthewire.sasl_password
overthewire.sasl_key
overthewire.sasl_timeout
overthewire.sasl_fail
overthewire.autoconnect = on
overthewire.autoreconnect
overthewire.autoreconnect_delay
overthewire.nicks
overthewire.nicks_alternate
overthewire.username
overthewire.realname
overthewire.local_hostname
overthewire.command
overthewire.command_delay
overthewire.autojoin = "#wargames,#social,#amateria,#io"
overthewire.autorejoin
overthewire.autorejoin_delay
overthewire.connection_timeout
overthewire.anti_flood_prio_high
overthewire.anti_flood_prio_low
overthewire.away_check
overthewire.away_check_max_nicks
overthewire.msg_kick
overthewire.msg_part
overthewire.msg_quit
overthewire.notify
hackint.addresses = "irc.hackint.org/9999"
hackint.proxy
hackint.ipv6
hackint.ssl = on
hackint.ssl_cert
hackint.ssl_priorities
hackint.ssl_dhkey_size
hackint.ssl_fingerprint
hackint.ssl_verify = on
hackint.password
hackint.capabilities
hackint.sasl_mechanism
hackint.sasl_username
hackint.sasl_password
hackint.sasl_key
hackint.sasl_timeout
hackint.sasl_fail
hackint.autoconnect = on
hackint.autoreconnect
hackint.autoreconnect_delay
hackint.nicks
hackint.nicks_alternate
hackint.username
hackint.realname
hackint.local_hostname
hackint.command
hackint.command_delay
hackint.autojoin
hackint.autorejoin
hackint.autorejoin_delay
hackint.connection_timeout
hackint.anti_flood_prio_high
hackint.anti_flood_prio_low
hackint.away_check
hackint.away_check_max_nicks
hackint.msg_kick
hackint.msg_part
hackint.msg_quit
hackint.notify
afternet.addresses = "irc.afternet.org/6697"
afternet.proxy
afternet.ipv6
afternet.ssl = on
afternet.ssl_cert
afternet.ssl_priorities
afternet.ssl_dhkey_size
afternet.ssl_fingerprint
afternet.ssl_verify = on
afternet.password
afternet.capabilities
afternet.sasl_mechanism
afternet.sasl_username
afternet.sasl_password
afternet.sasl_key
afternet.sasl_timeout
afternet.sasl_fail
afternet.autoconnect = on
afternet.autoreconnect
afternet.autoreconnect_delay
afternet.nicks
afternet.nicks_alternate
afternet.username
afternet.realname
afternet.local_hostname
afternet.command
afternet.command_delay
afternet.autojoin = "#eevblog"
afternet.autorejoin
afternet.autorejoin_delay
afternet.connection_timeout
afternet.anti_flood_prio_high
afternet.anti_flood_prio_low
afternet.away_check
afternet.away_check_max_nicks
afternet.msg_kick
afternet.msg_part
afternet.msg_quit
afternet.notify

View File

@@ -1,14 +0,0 @@
#!/bin/bash
# Update the weechat SSL key. Should be called from cron via sudo.
eval WEEDIR="$(printf "~%q/.weechat/" "${SUDO_USER}")"
LIVEKEY="${WEEDIR}/ssl/relay.pem"
certbot renew -q
cat /etc/letsencrypt/live/$(hostname -f)/{privkey,fullchain}.pem > \
${LIVEKEY}
chown ${SUDO_USER}:$(id -gn ${SUDO_USER}) ${LIVEKEY}
for fifo in ${WEEDIR}/weechat_fifo* ; do
echo '*/relay sslcertkey' > ${fifo}
done

View File

@@ -1,26 +0,0 @@
#
# weechat -- logger.conf
#
[look]
backlog = 20
[color]
backlog_end = default
backlog_line = default
[file]
auto_log = on
flush_delay = 120
info_lines = off
mask = "$plugin.$name.weechatlog"
name_lower_case = on
nick_prefix = ""
nick_suffix = ""
path = "%h/logs/"
replacement_char = "_"
time_format = "%Y-%m-%d %H:%M:%S"
[level]
[mask]

View File

@@ -1,15 +0,0 @@
#
# weechat -- plugins.conf
#
[var]
fifo.fifo = "on"
guile.check_license = "off"
javascript.check_license = "off"
lua.check_license = "off"
perl.check_license = "off"
python.check_license = "off"
ruby.check_license = "off"
tcl.check_license = "off"
[desc]

View File

@@ -1,42 +0,0 @@
#
# weechat -- relay.conf
#
[look]
auto_open_buffer = on
raw_messages = 256
[color]
client = cyan
status_active = lightblue
status_auth_failed = lightred
status_connecting = yellow
status_disconnected = lightred
status_waiting_auth = brown
text = default
text_bg = default
text_selected = white
[network]
allow_empty_password = off
allowed_ips = ""
bind_address = ""
clients_purge_delay = 0
compression_level = 6
ipv6 = on
max_clients = 5
password = "${sec.data.relay_password}"
ssl_cert_key = "%h/ssl/relay.pem"
ssl_priorities = "NORMAL:-VERS-SSL3.0"
websocket_allowed_origins = ""
[irc]
backlog_max_minutes = 1440
backlog_max_number = 256
backlog_since_last_disconnect = on
backlog_since_last_message = off
backlog_tags = "irc_privmsg"
backlog_time_format = "[%H:%M] "
[port]
ssl.weechat = 9001

View File

@@ -1,50 +0,0 @@
#
# weechat -- script.conf
#
[look]
columns = "%s %n %V %v %u | %d | %t"
diff_color = on
diff_command = "auto"
display_source = on
quiet_actions = on
sort = "p,n"
translate_description = on
use_keys = on
[color]
status_autoloaded = cyan
status_held = white
status_installed = lightcyan
status_obsolete = lightmagenta
status_popular = yellow
status_running = lightgreen
status_unknown = lightred
text = default
text_bg = default
text_bg_selected = red
text_date = default
text_date_selected = white
text_delimiters = default
text_description = default
text_description_selected = white
text_extension = default
text_extension_selected = white
text_name = cyan
text_name_selected = lightcyan
text_selected = white
text_tags = brown
text_tags_selected = yellow
text_version = magenta
text_version_loaded = default
text_version_loaded_selected = white
text_version_selected = lightmagenta
[scripts]
autoload = on
cache_expire = 1440
download_timeout = 30
hold = ""
path = "%h/script"
url = "http://weechat.org/files/plugins.xml.gz"
url_force_https = on

View File

@@ -1,13 +0,0 @@
#
# weechat -- sec.conf
#
[crypt]
cipher = aes256
hash_algo = sha256
passphrase_file = "~/.weechat-passphrase"
salt = on
[data]
__passphrase__ = on
relay_password = "D1FD30C08951B1A5BCBBB7EE6AAFB6AF9B86017B353182A1CA8826D5A98EB88E7E723591C544FC41A6913EA67E8764E50BDD8A5AD3D0A0"

View File

@@ -1,52 +0,0 @@
#
# weechat -- trigger.conf
#
[look]
enabled = on
monitor_strip_colors = off
[color]
flag_command = lightgreen
flag_conditions = yellow
flag_post_action = lightblue
flag_regex = lightcyan
flag_return_code = lightmagenta
regex = white
replace = cyan
trigger = green
trigger_disabled = red
[trigger]
beep.arguments = ""
beep.command = "/print -beep"
beep.conditions = "${tg_highlight} || ${tg_msg_pv}"
beep.enabled = on
beep.hook = print
beep.post_action = none
beep.regex = ""
beep.return_code = ok
cmd_pass.arguments = "5000|input_text_display;5000|history_add;5000|irc_command_auth"
cmd_pass.command = ""
cmd_pass.conditions = ""
cmd_pass.enabled = on
cmd_pass.hook = modifier
cmd_pass.post_action = none
cmd_pass.regex = "==^((/(msg|quote) +nickserv +(id|identify|register|ghost +[^ ]+|release +[^ ]+|regain +[^ ]+) +)|/oper +[^ ]+ +|/quote +pass +|/set +[^ ]*password[^ ]* +|/secure +(passphrase|decrypt|set +[^ ]+) +)(.*)==$1$.*+"
cmd_pass.return_code = ok
msg_auth.arguments = "5000|irc_message_auth"
msg_auth.command = ""
msg_auth.conditions = ""
msg_auth.enabled = on
msg_auth.hook = modifier
msg_auth.post_action = none
msg_auth.regex = "==^(.*(id|identify|register|ghost +[^ ]+|release +[^ ]+) +)(.*)==$1$.*+"
msg_auth.return_code = ok
server_pass.arguments = "5000|input_text_display;5000|history_add"
server_pass.command = ""
server_pass.conditions = ""
server_pass.enabled = on
server_pass.hook = modifier
server_pass.post_action = none
server_pass.regex = "==^(/(server|connect) .*-(sasl_)?password=)([^ ]+)(.*)==$1$.*4$5"
server_pass.return_code = ok

View File

@@ -1,595 +0,0 @@
#
# weechat -- weechat.conf
#
[debug]
[startup]
command_after_plugins = ""
command_before_plugins = ""
display_logo = on
display_version = on
sys_rlimit = ""
[look]
align_end_of_lines = message
bar_more_down = "++"
bar_more_left = "<<"
bar_more_right = ">>"
bar_more_up = "--"
bare_display_exit_on_input = on
bare_display_time_format = "%H:%M"
buffer_auto_renumber = on
buffer_notify_default = all
buffer_position = end
buffer_search_case_sensitive = off
buffer_search_force_default = off
buffer_search_regex = off
buffer_search_where = prefix_message
buffer_time_format = "%H:%M:%S"
color_basic_force_bold = off
color_inactive_buffer = on
color_inactive_message = on
color_inactive_prefix = on
color_inactive_prefix_buffer = on
color_inactive_time = off
color_inactive_window = on
color_nick_offline = off
color_pairs_auto_reset = 5
color_real_white = off
command_chars = ""
command_incomplete = off
confirm_quit = off
confirm_upgrade = off
day_change = on
day_change_message_1date = "-- %a, %d %b %Y --"
day_change_message_2dates = "-- %%a, %%d %%b %%Y (%a, %d %b %Y) --"
eat_newline_glitch = off
emphasized_attributes = ""
highlight = ""
highlight_regex = ""
highlight_tags = ""
hotlist_add_conditions = "${buffer.num_displayed} == 0 && ${priority} >= 1"
hotlist_buffer_separator = ", "
hotlist_count_max = 0
hotlist_count_min_msg = 2
hotlist_names_count = 10000
hotlist_names_length = 0
hotlist_names_level = 14
hotlist_names_merged_buffers = off
hotlist_prefix = "Act: "
hotlist_remove = merged
hotlist_short_names = on
hotlist_sort = group_time_asc
hotlist_suffix = ""
hotlist_unique_numbers = on
input_cursor_scroll = 20
input_share = none
input_share_overwrite = off
input_undo_max = 32
item_away_message = on
item_buffer_filter = "*"
item_buffer_zoom = "!"
item_mouse_status = "M"
item_time_format = "%H:%M"
jump_current_to_previous_buffer = on
jump_previous_buffer_when_closing = on
jump_smart_back_to_buffer = on
key_bind_safe = on
key_grab_delay = 800
mouse = off
mouse_timer_delay = 100
nick_color_force = ""
nick_color_hash = djb2
nick_color_stop_chars = "_|["
nick_prefix = ""
nick_suffix = ""
paste_auto_add_newline = on
paste_bracketed = on
paste_bracketed_timer_delay = 10
paste_max_lines = 1
prefix_action = " *"
prefix_align = right
prefix_align_max = 15
prefix_align_min = 0
prefix_align_more = "+"
prefix_align_more_after = on
prefix_buffer_align = right
prefix_buffer_align_max = 0
prefix_buffer_align_more = "+"
prefix_buffer_align_more_after = on
prefix_error = "=!="
prefix_join = "-->"
prefix_network = "--"
prefix_quit = "<--"
prefix_same_nick = ""
prefix_suffix = "|"
quote_nick_prefix = "<"
quote_nick_suffix = ">"
quote_time_format = "%H:%M:%S"
read_marker = line
read_marker_always_show = off
read_marker_string = "- "
save_config_on_exit = on
save_layout_on_exit = none
scroll_amount = 3
scroll_bottom_after_switch = off
scroll_page_percent = 100
search_text_not_found_alert = on
separator_horizontal = "-"
separator_vertical = ""
tab_width = 1
time_format = "%a, %d %b %Y %T"
window_auto_zoom = off
window_separator_horizontal = on
window_separator_vertical = on
window_title = "irc"
word_chars_highlight = "!\u00A0,-,_,|,alnum"
word_chars_input = "!\u00A0,-,_,|,alnum"
[palette]
[color]
bar_more = lightmagenta
chat = default
chat_bg = default
chat_buffer = white
chat_channel = white
chat_day_change = cyan
chat_delimiters = green
chat_highlight = yellow
chat_highlight_bg = magenta
chat_host = cyan
chat_inactive_buffer = default
chat_inactive_window = default
chat_nick = lightcyan
chat_nick_colors = "cyan,magenta,green,brown,lightblue,default,lightcyan,lightmagenta,lightgreen,blue"
chat_nick_offline = default
chat_nick_offline_highlight = default
chat_nick_offline_highlight_bg = blue
chat_nick_other = cyan
chat_nick_prefix = green
chat_nick_self = white
chat_nick_suffix = green
chat_prefix_action = white
chat_prefix_buffer = brown
chat_prefix_buffer_inactive_buffer = default
chat_prefix_error = yellow
chat_prefix_join = lightgreen
chat_prefix_more = lightmagenta
chat_prefix_network = magenta
chat_prefix_quit = lightred
chat_prefix_suffix = green
chat_read_marker = magenta
chat_read_marker_bg = default
chat_server = brown
chat_tags = red
chat_text_found = yellow
chat_text_found_bg = lightmagenta
chat_time = default
chat_time_delimiters = brown
chat_value = cyan
chat_value_null = blue
emphasized = yellow
emphasized_bg = magenta
input_actions = lightgreen
input_text_not_found = red
item_away = yellow
nicklist_away = cyan
nicklist_group = green
separator = blue
status_count_highlight = magenta
status_count_msg = brown
status_count_other = default
status_count_private = green
status_data_highlight = lightmagenta
status_data_msg = yellow
status_data_other = default
status_data_private = lightgreen
status_filter = green
status_more = yellow
status_mouse = green
status_name = white
status_name_ssl = lightgreen
status_nicklist_count = default
status_number = yellow
status_time = default
[completion]
base_word_until_cursor = on
command_inline = on
default_template = "%(nicks)|%(irc_channels)"
nick_add_space = on
nick_completer = ":"
nick_first_only = off
nick_ignore_chars = "[]`_-^"
partial_completion_alert = on
partial_completion_command = off
partial_completion_command_arg = off
partial_completion_count = on
partial_completion_other = off
[history]
display_default = 5
max_buffer_lines_minutes = 0
max_buffer_lines_number = 4096
max_commands = 100
max_visited_buffers = 50
[proxy]
[network]
connection_timeout = 60
gnutls_ca_file = "~/.weechat/certs/ca-certificates.crt"
gnutls_handshake_timeout = 30
proxy_curl = ""
[plugin]
autoload = "*"
debug = off
extension = ".so,.dll"
path = "%h/plugins"
save_config_on_unload = on
[bar]
input.color_bg = default
input.color_delim = cyan
input.color_fg = default
input.conditions = ""
input.filling_left_right = vertical
input.filling_top_bottom = horizontal
input.hidden = off
input.items = "[input_prompt]+(away),[input_search],[input_paste],input_text"
input.position = bottom
input.priority = 1000
input.separator = off
input.size = 1
input.size_max = 0
input.type = window
nicklist.color_bg = default
nicklist.color_delim = cyan
nicklist.color_fg = default
nicklist.conditions = "${nicklist}"
nicklist.filling_left_right = vertical
nicklist.filling_top_bottom = columns_vertical
nicklist.hidden = on
nicklist.items = "buffer_nicklist"
nicklist.position = right
nicklist.priority = 200
nicklist.separator = on
nicklist.size = 0
nicklist.size_max = 0
nicklist.type = window
status.color_bg = 0
status.color_delim = cyan
status.color_fg = default
status.conditions = ""
status.filling_left_right = vertical
status.filling_top_bottom = horizontal
status.hidden = off
status.items = "[time],[buffer_plugin],buffer_number+:+buffer_name+(buffer_modes)+{buffer_nicklist_count}+buffer_zoom+buffer_filter,[lag],[hotlist],completion,scroll"
status.position = bottom
status.priority = 500
status.separator = off
status.size = 2
status.size_max = 0
status.type = window
title.color_bg = 0
title.color_delim = cyan
title.color_fg = default
title.conditions = ""
title.filling_left_right = vertical
title.filling_top_bottom = horizontal
title.hidden = off
title.items = "buffer_title"
title.position = top
title.priority = 500
title.separator = off
title.size = 1
title.size_max = 0
title.type = window
[layout]
[notify]
[filter]
irc_smart = on;*;irc_smart_filter;*
[key]
ctrl-? = "/input delete_previous_char"
ctrl-A = "/input move_beginning_of_line"
ctrl-B = "/input move_previous_char"
ctrl-C_ = "/input insert \x1F"
ctrl-Cb = "/input insert \x02"
ctrl-Cc = "/input insert \x03"
ctrl-Ci = "/input insert \x1D"
ctrl-Co = "/input insert \x0F"
ctrl-Cv = "/input insert \x16"
ctrl-D = "/input delete_next_char"
ctrl-E = "/input move_end_of_line"
ctrl-F = "/input move_next_char"
ctrl-H = "/input delete_previous_char"
ctrl-I = "/input complete_next"
ctrl-J = "/input return"
ctrl-K = "/input delete_end_of_line"
ctrl-L = "/window refresh"
ctrl-M = "/input return"
ctrl-N = "/buffer +1"
ctrl-P = "/buffer -1"
ctrl-R = "/input search_text"
ctrl-Sctrl-U = "/input set_unread"
ctrl-T = "/input transpose_chars"
ctrl-U = "/input delete_beginning_of_line"
ctrl-W = "/input delete_previous_word"
ctrl-X = "/input switch_active_buffer"
ctrl-Y = "/input clipboard_paste"
meta-meta2-1~ = "/window scroll_top"
meta-meta2-23~ = "/bar scroll nicklist * b"
meta-meta2-24~ = "/bar scroll nicklist * e"
meta-meta2-4~ = "/window scroll_bottom"
meta-meta2-5~ = "/window scroll_up"
meta-meta2-6~ = "/window scroll_down"
meta-meta2-7~ = "/window scroll_top"
meta-meta2-8~ = "/window scroll_bottom"
meta-meta2-A = "/buffer -1"
meta-meta2-B = "/buffer +1"
meta-meta2-C = "/buffer +1"
meta-meta2-D = "/buffer -1"
meta-- = "/filter toggle @"
meta-/ = "/input jump_last_buffer_displayed"
meta-0 = "/buffer *10"
meta-1 = "/buffer *1"
meta-2 = "/buffer *2"
meta-3 = "/buffer *3"
meta-4 = "/buffer *4"
meta-5 = "/buffer *5"
meta-6 = "/buffer *6"
meta-7 = "/buffer *7"
meta-8 = "/buffer *8"
meta-9 = "/buffer *9"
meta-< = "/input jump_previously_visited_buffer"
meta-= = "/filter toggle"
meta-> = "/input jump_next_visited_buffer"
meta-OA = "/input history_global_previous"
meta-OB = "/input history_global_next"
meta-OC = "/input move_next_word"
meta-OD = "/input move_previous_word"
meta-OF = "/input move_end_of_line"
meta-OH = "/input move_beginning_of_line"
meta-Oa = "/input history_global_previous"
meta-Ob = "/input history_global_next"
meta-Oc = "/input move_next_word"
meta-Od = "/input move_previous_word"
meta2-15~ = "/buffer -1"
meta2-17~ = "/buffer +1"
meta2-18~ = "/window -1"
meta2-19~ = "/window +1"
meta2-1;3A = "/buffer -1"
meta2-1;3B = "/buffer +1"
meta2-1;3C = "/buffer +1"
meta2-1;3D = "/buffer -1"
meta2-1;3F = "/window scroll_bottom"
meta2-1;3H = "/window scroll_top"
meta2-1;5A = "/input history_global_previous"
meta2-1;5B = "/input history_global_next"
meta2-1;5C = "/input move_next_word"
meta2-1;5D = "/input move_previous_word"
meta2-1~ = "/input move_beginning_of_line"
meta2-200~ = "/input paste_start"
meta2-201~ = "/input paste_stop"
meta2-20~ = "/bar scroll title * -30%"
meta2-21~ = "/bar scroll title * +30%"
meta2-23;3~ = "/bar scroll nicklist * b"
meta2-23~ = "/bar scroll nicklist * -100%"
meta2-24;3~ = "/bar scroll nicklist * e"
meta2-24~ = "/bar scroll nicklist * +100%"
meta2-3~ = "/input delete_next_char"
meta2-4~ = "/input move_end_of_line"
meta2-5;3~ = "/window scroll_up"
meta2-5~ = "/window page_up"
meta2-6;3~ = "/window scroll_down"
meta2-6~ = "/window page_down"
meta2-7~ = "/input move_beginning_of_line"
meta2-8~ = "/input move_end_of_line"
meta2-A = "/input history_previous"
meta2-B = "/input history_next"
meta2-C = "/input move_next_char"
meta2-D = "/input move_previous_char"
meta2-F = "/input move_end_of_line"
meta2-G = "/window page_down"
meta2-H = "/input move_beginning_of_line"
meta2-I = "/window page_up"
meta2-Z = "/input complete_previous"
meta2-[E = "/buffer -1"
meta-_ = "/input redo"
meta-a = "/input jump_smart"
meta-b = "/input move_previous_word"
meta-d = "/input delete_next_word"
meta-f = "/input move_next_word"
meta-h = "/input hotlist_clear"
meta-jmeta-f = "/buffer -"
meta-jmeta-l = "/buffer +"
meta-jmeta-r = "/server raw"
meta-jmeta-s = "/server jump"
meta-j01 = "/buffer 1"
meta-j02 = "/buffer 2"
meta-j03 = "/buffer 3"
meta-j04 = "/buffer 4"
meta-j05 = "/buffer 5"
meta-j06 = "/buffer 6"
meta-j07 = "/buffer 7"
meta-j08 = "/buffer 8"
meta-j09 = "/buffer 9"
meta-j10 = "/buffer 10"
meta-j11 = "/buffer 11"
meta-j12 = "/buffer 12"
meta-j13 = "/buffer 13"
meta-j14 = "/buffer 14"
meta-j15 = "/buffer 15"
meta-j16 = "/buffer 16"
meta-j17 = "/buffer 17"
meta-j18 = "/buffer 18"
meta-j19 = "/buffer 19"
meta-j20 = "/buffer 20"
meta-j21 = "/buffer 21"
meta-j22 = "/buffer 22"
meta-j23 = "/buffer 23"
meta-j24 = "/buffer 24"
meta-j25 = "/buffer 25"
meta-j26 = "/buffer 26"
meta-j27 = "/buffer 27"
meta-j28 = "/buffer 28"
meta-j29 = "/buffer 29"
meta-j30 = "/buffer 30"
meta-j31 = "/buffer 31"
meta-j32 = "/buffer 32"
meta-j33 = "/buffer 33"
meta-j34 = "/buffer 34"
meta-j35 = "/buffer 35"
meta-j36 = "/buffer 36"
meta-j37 = "/buffer 37"
meta-j38 = "/buffer 38"
meta-j39 = "/buffer 39"
meta-j40 = "/buffer 40"
meta-j41 = "/buffer 41"
meta-j42 = "/buffer 42"
meta-j43 = "/buffer 43"
meta-j44 = "/buffer 44"
meta-j45 = "/buffer 45"
meta-j46 = "/buffer 46"
meta-j47 = "/buffer 47"
meta-j48 = "/buffer 48"
meta-j49 = "/buffer 49"
meta-j50 = "/buffer 50"
meta-j51 = "/buffer 51"
meta-j52 = "/buffer 52"
meta-j53 = "/buffer 53"
meta-j54 = "/buffer 54"
meta-j55 = "/buffer 55"
meta-j56 = "/buffer 56"
meta-j57 = "/buffer 57"
meta-j58 = "/buffer 58"
meta-j59 = "/buffer 59"
meta-j60 = "/buffer 60"
meta-j61 = "/buffer 61"
meta-j62 = "/buffer 62"
meta-j63 = "/buffer 63"
meta-j64 = "/buffer 64"
meta-j65 = "/buffer 65"
meta-j66 = "/buffer 66"
meta-j67 = "/buffer 67"
meta-j68 = "/buffer 68"
meta-j69 = "/buffer 69"
meta-j70 = "/buffer 70"
meta-j71 = "/buffer 71"
meta-j72 = "/buffer 72"
meta-j73 = "/buffer 73"
meta-j74 = "/buffer 74"
meta-j75 = "/buffer 75"
meta-j76 = "/buffer 76"
meta-j77 = "/buffer 77"
meta-j78 = "/buffer 78"
meta-j79 = "/buffer 79"
meta-j80 = "/buffer 80"
meta-j81 = "/buffer 81"
meta-j82 = "/buffer 82"
meta-j83 = "/buffer 83"
meta-j84 = "/buffer 84"
meta-j85 = "/buffer 85"
meta-j86 = "/buffer 86"
meta-j87 = "/buffer 87"
meta-j88 = "/buffer 88"
meta-j89 = "/buffer 89"
meta-j90 = "/buffer 90"
meta-j91 = "/buffer 91"
meta-j92 = "/buffer 92"
meta-j93 = "/buffer 93"
meta-j94 = "/buffer 94"
meta-j95 = "/buffer 95"
meta-j96 = "/buffer 96"
meta-j97 = "/buffer 97"
meta-j98 = "/buffer 98"
meta-j99 = "/buffer 99"
meta-k = "/input grab_key_command"
meta-l = "/window bare"
meta-m = "/mute mouse toggle"
meta-n = "/window scroll_next_highlight"
meta-p = "/window scroll_previous_highlight"
meta-r = "/input delete_line"
meta-s = "/mute aspell toggle"
meta-u = "/window scroll_unread"
meta-wmeta-meta2-A = "/window up"
meta-wmeta-meta2-B = "/window down"
meta-wmeta-meta2-C = "/window right"
meta-wmeta-meta2-D = "/window left"
meta-wmeta2-1;3A = "/window up"
meta-wmeta2-1;3B = "/window down"
meta-wmeta2-1;3C = "/window right"
meta-wmeta2-1;3D = "/window left"
meta-wmeta-b = "/window balance"
meta-wmeta-s = "/window swap"
meta-x = "/input zoom_merged_buffer"
meta-z = "/window zoom"
ctrl-_ = "/input undo"
[key_search]
ctrl-I = "/input search_switch_where"
ctrl-J = "/input search_stop"
ctrl-M = "/input search_stop"
ctrl-R = "/input search_switch_regex"
meta2-A = "/input search_previous"
meta2-B = "/input search_next"
meta-c = "/input search_switch_case"
[key_cursor]
ctrl-J = "/cursor stop"
ctrl-M = "/cursor stop"
meta-meta2-A = "/cursor move area_up"
meta-meta2-B = "/cursor move area_down"
meta-meta2-C = "/cursor move area_right"
meta-meta2-D = "/cursor move area_left"
meta2-1;3A = "/cursor move area_up"
meta2-1;3B = "/cursor move area_down"
meta2-1;3C = "/cursor move area_right"
meta2-1;3D = "/cursor move area_left"
meta2-A = "/cursor move up"
meta2-B = "/cursor move down"
meta2-C = "/cursor move right"
meta2-D = "/cursor move left"
@item(buffer_nicklist):K = "/window ${_window_number};/kickban ${nick}"
@item(buffer_nicklist):b = "/window ${_window_number};/ban ${nick}"
@item(buffer_nicklist):k = "/window ${_window_number};/kick ${nick}"
@item(buffer_nicklist):q = "/window ${_window_number};/query ${nick};/cursor stop"
@item(buffer_nicklist):w = "/window ${_window_number};/whois ${nick}"
@chat:Q = "hsignal:chat_quote_time_prefix_message;/cursor stop"
@chat:m = "hsignal:chat_quote_message;/cursor stop"
@chat:q = "hsignal:chat_quote_prefix_message;/cursor stop"
[key_mouse]
@bar(input):button2 = "/input grab_mouse_area"
@bar(nicklist):button1-gesture-down = "/bar scroll nicklist ${_window_number} +100%"
@bar(nicklist):button1-gesture-down-long = "/bar scroll nicklist ${_window_number} e"
@bar(nicklist):button1-gesture-up = "/bar scroll nicklist ${_window_number} -100%"
@bar(nicklist):button1-gesture-up-long = "/bar scroll nicklist ${_window_number} b"
@chat(script.scripts):button1 = "/window ${_window_number};/script go ${_chat_line_y}"
@chat(script.scripts):button2 = "/window ${_window_number};/script go ${_chat_line_y};/script installremove -q ${script_name_with_extension}"
@chat(script.scripts):wheeldown = "/script down 5"
@chat(script.scripts):wheelup = "/script up 5"
@item(buffer_nicklist):button1 = "/window ${_window_number};/query ${nick}"
@item(buffer_nicklist):button1-gesture-left = "/window ${_window_number};/kick ${nick}"
@item(buffer_nicklist):button1-gesture-left-long = "/window ${_window_number};/kickban ${nick}"
@item(buffer_nicklist):button2 = "/window ${_window_number};/whois ${nick}"
@item(buffer_nicklist):button2-gesture-left = "/window ${_window_number};/ban ${nick}"
@bar:wheeldown = "/bar scroll ${_bar_name} ${_window_number} +20%"
@bar:wheelup = "/bar scroll ${_bar_name} ${_window_number} -20%"
@chat:button1 = "/window ${_window_number}"
@chat:button1-gesture-left = "/window ${_window_number};/buffer -1"
@chat:button1-gesture-left-long = "/window ${_window_number};/buffer 1"
@chat:button1-gesture-right = "/window ${_window_number};/buffer +1"
@chat:button1-gesture-right-long = "/window ${_window_number};/input jump_last_buffer"
@chat:ctrl-wheeldown = "/window scroll_horiz -window ${_window_number} +10%"
@chat:ctrl-wheelup = "/window scroll_horiz -window ${_window_number} -10%"
@chat:wheeldown = "/window scroll_down -window ${_window_number}"
@chat:wheelup = "/window scroll_up -window ${_window_number}"
@*:button3 = "/cursor go ${_x},${_y}"

View File

@@ -1,39 +0,0 @@
#
# weechat -- xfer.conf
#
[look]
auto_open_buffer = on
progress_bar_size = 20
pv_tags = "notify_private"
[color]
status_aborted = lightred
status_active = lightblue
status_connecting = yellow
status_done = lightgreen
status_failed = lightred
status_waiting = lightcyan
text = default
text_bg = default
text_selected = white
[network]
blocksize = 65536
fast_send = on
own_ip = ""
port_range = ""
speed_limit = 0
timeout = 300
[file]
auto_accept_chats = off
auto_accept_files = off
auto_accept_nicks = ""
auto_check_crc32 = off
auto_rename = on
auto_resume = on
convert_spaces = on
download_path = "%h/xfer"
upload_path = "~"
use_nick_in_filename = on

View File

@@ -10,7 +10,7 @@ if test -d ${HOME}/.local/bin ; then
fi
if [[ ! -o interactive || ! -t 0 ]]; then
if command -v mise >/dev/null 2>&1 ; then
if [[ "$PWD" != /google* ]] && command -v mise >/dev/null 2>&1 ; then
eval "$(mise activate zsh --shims)"
fi
fi

View File

@@ -1,6 +1,7 @@
# For interactive shells
[[ -n "$ZSH_PROFILE" ]] && {
zshrc_start_time=$(date +%s.%N)
zmodload zsh/datetime
zshrc_start_time=$EPOCHREALTIME
zmodload zsh/zprof
}
HISTFILE=~/.zhistory
@@ -191,6 +192,15 @@ if [[ $- == *i* ]] ; then
source_if_existing $HOME/.aliases.local
# zsh-only-ism to avoid error if glob doesn't expand
# specifically sets NULLGLOB for this one glob
typeset -gA _deferred_comps
compdef() {
# Store the arguments: first arg is the function, the rest are the commands
local func=$1
shift
for cmd in "$@"; do
_deferred_comps[$cmd]=$func
done
}
for file in $HOME/.zshrc.d/[a-zA-Z0-9]*.zsh(N) ; do
source "$file"
done
@@ -205,19 +215,27 @@ if [[ $- == *i* ]] ; then
zstyle ':completion:*' users root ${USER}
# Modules after fpath
autoload -Uz compinit
for cmd func in "${(@kv)_deferred_comps}"; do
compdef "$func" "$cmd"
done
unset _deferred_comps
# Regenerate zcompdump if it's older than any file in fpath
DUMPFILE="${ZDOTDIR:-$HOME}/.zcompdump"
updated_files=(${^fpath}(N.om[1]))
# Find the newest file across all fpath directories to detect edits/additions
# (N.om[1]) = Null-glob, plain files only, sort by mtime, pick the first (newest)
local newest_comp=(${^fpath}/*(N.om[1]))
if [[ ! -f "$DUMPFILE" || ( ${#updated_files} -gt 0 && "$updated_files[1]" -nt "$DUMPFILE" ) ]]; then
compinit -i -D "$DUMPFILE"
# Asynchronously compile the dump file
{ zcompile "$DUMPFILE" } &!
# If any completion file was modified, or dump doesn't exist, we might need to update.
if [[ ! -f "$DUMPFILE" || ( -n "$newest_comp" && "$newest_comp" -nt "$DUMPFILE" ) ]]; then
compinit -i -d "$DUMPFILE"
# Asynchronously compile the dump file with an atomic rename
{ zcompile "$DUMPFILE.zwc.tmp" "$DUMPFILE" && mv -f "$DUMPFILE.zwc.tmp" "$DUMPFILE.zwc" } &!
else
compinit -C -i -D "$DUMPFILE"
compinit -C -i -d "$DUMPFILE"
fi
unset DUMPFILE updated_files
unset DUMPFILE newest_comp
autoload -Uz promptinit && promptinit
# Virtualenvwrapper
source_first_existing \
@@ -267,8 +285,11 @@ if [ -x /usr/bin/ack-grep ] ; then
alias ack='/usr/bin/ack-grep'
fi
# I want this first always
# I want these first always
PATH="${HOME}/bin:${PATH}"
if [[ "$(uname)" == "Darwin" ]]; then
PATH="${HOME}/bin/macos:${PATH}"
fi
# Load any local settings
source_if_existing $HOME/.zshrc.local
@@ -292,9 +313,9 @@ fi
typeset -U PATH
if [[ -n "$ZSH_PROFILE" ]]; then
zshrc_end_time=$(date +%s.%N)
elapsed_seconds=$(echo "$zshrc_end_time - $zshrc_start_time" | bc -l)
elapsed_ms=$(printf "%.0f" "$(echo "$elapsed_seconds * 1000" | bc -l)")
echo "zshrc done: ${elapsed_ms}ms"
zshrc_end_time=$EPOCHREALTIME
# Calculation in ms using zsh floating point math
elapsed_ms=$(( (zshrc_end_time - zshrc_start_time) * 1000 ))
printf "zshrc done: %.0fms\n" "$elapsed_ms"
zprof
fi

View File

@@ -7,7 +7,7 @@ export GEMINI_CONTEXT_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/gemini"
mkdir -p "$GEMINI_CONTEXT_DIR"
# Template settings file
GEMINI_TEMPLATE_SETTINGS="${HOME}/.skel/dotfiles/config/gemini/settings.json"
GEMINI_TEMPLATE_SETTINGS="${GEMINI_CONTEXT_DIR}/settings.json"
# Create a new Gemini context
gemini-context-create() {
@@ -19,8 +19,13 @@ gemini-context-create() {
local context_name="$1"
local context_path="$GEMINI_CONTEXT_DIR/$context_name"
if [[ "$context_name" =~ [/] ]]; then
echo "Error: Context name cannot contain slashes."
if [[ "$context_name" =~ [^a-zA-Z0-9_-] ]]; then
echo "Error: Context name should only contain alphanumeric characters, underscores, or dashes."
return 1
fi
if [[ "$context_name" == .* ]]; then
echo "Error: Context name cannot start with a dot."
return 1
fi
@@ -42,25 +47,90 @@ gemini-context-create() {
echo "Context '$context_name' created."
}
# List available Gemini contexts
# List available Gemini contexts (directories only, containing .gemini)
_gemini_context_list_internal() {
command ls "$GEMINI_CONTEXT_DIR" 2>/dev/null
local contexts
# Use Zsh globbing: find directories containing a .gemini subdir
contexts=($GEMINI_CONTEXT_DIR/*/.gemini(N/:h:t))
[[ ${#contexts} -gt 0 ]] && print -l "${contexts[@]}"
}
gemini-context-list() {
echo "Available Gemini contexts:"
local contexts=$(_gemini_context_list_internal)
if [ -z "$contexts" ]; then
local contexts=($(_gemini_context_list_internal))
if [ ${#contexts} -eq 0 ]; then
echo " (No contexts found)"
return
fi
for context in $contexts; do
if [ -d "$GEMINI_CONTEXT_DIR/$context" ]; then
echo " $context"
for context in "${contexts[@]}"; do
if [ "$GEMINI_CLI_HOME" = "$GEMINI_CONTEXT_DIR/$context" ]; then
echo " * $context (active)"
else
echo " $context"
fi
done
}
# Delete a Gemini context
gemini-context-delete() {
local context_name
if [ -z "$1" ]; then
if command -v fzf >/dev/null; then
context_name=$(_gemini_context_list_internal | fzf --prompt="Select Gemini Context to DELETE: ")
[[ -z "$context_name" ]] && return 1
else
echo "Usage: gemini-context-delete <name>"
return 1
fi
else
context_name="$1"
fi
local context_path="$GEMINI_CONTEXT_DIR/$context_name"
if [ ! -d "$context_path" ]; then
echo "Error: Context '$context_name' not found."
return 1
fi
if read -q "confirm?Are you sure you want to delete context '$context_name'? [y/N] "; then
echo
rm -rf "$context_path"
echo "Context '$context_name' deleted."
if [ "$GEMINI_CLI_HOME" = "$context_path" ]; then
gemini-context-unset
fi
else
echo "\nDeletion cancelled."
fi
}
# Rename a Gemini context
gemini-context-rename() {
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: gemini-context-rename <old_name> <new_name>"
return 1
fi
local old_path="$GEMINI_CONTEXT_DIR/$1"
local new_path="$GEMINI_CONTEXT_DIR/$2"
if [ ! -d "$old_path" ]; then
echo "Error: Source context '$1' not found."
return 1
fi
if [ -d "$new_path" ]; then
echo "Error: Destination context '$2' already exists."
return 1
fi
mv "$old_path" "$new_path"
echo "Context '$1' renamed to '$2'."
if [ "$GEMINI_CLI_HOME" = "$old_path" ]; then
gemini-context-use -q "$2"
fi
}
# Use a specific Gemini context
gemini-context-use() {
local context_name
@@ -89,14 +159,13 @@ gemini-context-use() {
local context_path="$GEMINI_CONTEXT_DIR/$context_name"
if [ ! -d "$context_path" ]; then
[[ "$quiet" -eq 0 ]] && echo "Error: Context '$context_name' not found at $context_path"
[[ "$quiet" -eq 0 ]] && gemini-context-list
if [ ! -d "$context_path/.gemini" ]; then
[[ "$quiet" -eq 0 ]] && echo "Error: '$context_name' is not a valid Gemini context (missing .gemini directory)."
return 1
fi
export GEMINI_CLI_HOME="$context_path"
[[ "$quiet" -eq 0 ]] && echo "Switched to Gemini context '$context_name' (GEMINI_CLI_HOME=$GEMINI_CLI_HOME)"
[[ "$quiet" -eq 0 ]] && echo "Switched to Gemini context '$context_name'"
}
# Edit a context's settings
@@ -136,13 +205,12 @@ gemini-context-edit() {
# Show the current Gemini context
gemini-context-current() {
if [ -n "$GEMINI_CLI_HOME" ]; then
local current_context=$(basename "$GEMINI_CLI_HOME")
local current_context=${GEMINI_CLI_HOME:t}
if [ "$GEMINI_CONTEXT_DIR/$current_context" = "$GEMINI_CLI_HOME" ]; then
echo "Current Gemini context: $current_context"
else
echo "Current Gemini context: Custom"
echo "Current Gemini context: Custom ($GEMINI_CLI_HOME)"
fi
echo "GEMINI_CLI_HOME=$GEMINI_CLI_HOME"
else
echo "No Gemini context set, using default."
fi
@@ -157,12 +225,12 @@ gemini-context-unset() {
# Alias for gemini-context-use
alias gemctx='gemini-context-use'
# Zsh Completion for gemini-context-use and gemctx
# Zsh Completion
_gemini_contexts() {
local contexts
local -a contexts
contexts=($(_gemini_context_list_internal))
_describe 'gemini contexts' contexts
}
compdef _gemini_contexts gemini-context-use
compdef _gemini_contexts gemctx
compdef _gemini_contexts gemini-context-edit
compdef _gemini_contexts gemini-context-use gemctx gemini-context-edit gemini-context-delete gemini-context-rename

View File

@@ -1,9 +1,12 @@
anthropic.claude-code
bazelbuild.vscode-bazel
dnut.rewrap-revived
docker.docker
formulahendry.code-runner
github.vscode-codeql
golang.go
hverlin.mise-vscode
kilocode.Kilo-Code
ms-azuretools.vscode-containers
ms-azuretools.vscode-docker
ms-python.black-formatter