12 Commits

Author SHA1 Message Date
David Tomaschik
2e0c11c044 Support LC paths 2026-06-09 08:59:05 -07:00
David Tomaschik
68daa27893 Remove starship custom for gemini-cli 2026-06-04 14:41:59 -07:00
David Tomaschik
398d55b8e4 Add newnote 2026-06-02 15:40:34 -07:00
David Tomaschik
c9918cf213 Update install.sh 2026-05-27 16:53:38 -07:00
David Tomaschik
d1e3c8e43e Update gitignore 2026-05-27 15:58:25 -07:00
David Tomaschik
f4bb5108ab Add SCRIPT_DIR 2026-05-26 14:32:06 -07:00
David Tomaschik
5eac8826da Cleanup 2026-05-26 14:21:13 -07:00
David Tomaschik
b1d625d3c5 Merge branch 'main' of https://github.com/Matir/skel 2026-05-26 14:12:43 -07:00
David Tomaschik
5a7d9cf060 Update skel, common functions. 2026-05-26 14:12:32 -07:00
David Tomaschik
9770514d6a Finish brew updates 2026-05-25 15:11:06 -07:00
David Tomaschik
e1724c77f3 Update Brewfile 2026-05-22 18:23:18 -07:00
David Tomaschik
ecbc25e5ac Improve skelify 2026-05-20 14:35:14 -07:00
10 changed files with 434 additions and 79 deletions

View File

@@ -21,9 +21,11 @@ brew "dfu-util"
brew "difftastic" brew "difftastic"
brew "direnv" brew "direnv"
brew "duck" brew "duck"
brew "dust"
brew "earthly" brew "earthly"
brew "esptool" brew "esptool"
brew "fish" brew "fish"
brew "fq"
brew "gh" brew "gh"
brew "ghidra", link: false brew "ghidra", link: false
brew "git" brew "git"
@@ -58,6 +60,7 @@ brew "pkgconf"
brew "protobuf" brew "protobuf"
brew "pwgen" brew "pwgen"
brew "pwntools" brew "pwntools"
brew "python@3.13"
brew "qemu" brew "qemu"
brew "restic" brew "restic"
brew "ripgrep" brew "ripgrep"
@@ -115,6 +118,7 @@ end
if !is_corp? if !is_corp?
brew "bazelisk" brew "bazelisk"
brew "openssh" brew "openssh"
brew "virt-manager"
cask "claude-code" cask "claude-code"
cask "cryptomator" cask "cryptomator"
@@ -123,4 +127,5 @@ if !is_corp?
cask "google-cloud-sdk" cask "google-cloud-sdk"
cask "keybase" cask "keybase"
cask "orbstack" cask "orbstack"
cask "jordanbaird-ice"
end end

212
bin/newnote Executable file
View File

@@ -0,0 +1,212 @@
#!/usr/bin/env bash
# Exit on error, undefined variables, and pipe failures
set -euo pipefail
show_help() {
cat << EOF
Usage: $(basename "$0") [options] <note_name_or_path>
Create a new note in your Obsidian vault.
Options:
-v, --vault <dir> Specify the Obsidian vault directory.
--overwrite Overwrite the file if it already exists.
-h, --help Show this help message.
EOF
}
VAULT_DIR=""
OVERWRITE="false"
NOTE_PATH=""
# Parse arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-v|--vault)
if [[ -z "${2:-}" ]]; then
echo "Error: --vault requires a directory path." >&2
exit 1
fi
VAULT_DIR="$2"
shift 2
;;
--overwrite)
OVERWRITE="true"
shift
;;
-h|--help)
show_help
exit 0
;;
-*)
echo "Error: Unknown option: $1" >&2
show_help
exit 1
;;
*)
if [[ -n "$NOTE_PATH" ]]; then
echo "Error: Multiple note paths provided: $NOTE_PATH and $1" >&2
exit 1
fi
NOTE_PATH="$1"
shift
;;
esac
done
if [[ -z "$NOTE_PATH" ]]; then
echo "Error: Missing note path/name." >&2
show_help
exit 1
fi
# 1. Find the Obsidian vault.
if [[ -n "$VAULT_DIR" ]]; then
# -v/--vault was passed. Check that the directory exists and contains a .obsidian directory.
if [[ ! -d "$VAULT_DIR" ]]; then
echo "Error: Specified vault directory does not exist: $VAULT_DIR" >&2
exit 1
fi
if [[ ! -d "$VAULT_DIR/.obsidian" ]]; then
echo "Error: Specified directory is not an Obsidian vault (missing .obsidian): $VAULT_DIR" >&2
exit 1
fi
VAULT_DIR="$(cd "$VAULT_DIR" && pwd)"
else
# Search directories upward for a parent (or current) directory containing a .obsidian subdirectory.
# Stop at the user's home directory or a filesystem boundary.
CURRENT_DIR="$PWD"
FOUND_VAULT=""
get_device_id() {
local dir="$1"
if [[ "$(uname)" == "Darwin" ]]; then
stat -f '%d' "$dir" 2>/dev/null || echo ""
else
stat -c '%d' "$dir" 2>/dev/null || echo ""
fi
}
CURRENT_DEV="$(get_device_id "$CURRENT_DIR")"
while [[ "$CURRENT_DIR" != "/" && "$CURRENT_DIR" != "$HOME" ]]; do
if [[ -d "$CURRENT_DIR/.obsidian" ]]; then
FOUND_VAULT="$CURRENT_DIR"
break
fi
PARENT_DIR="$(dirname "$CURRENT_DIR")"
if [[ "$PARENT_DIR" == "$CURRENT_DIR" ]]; then
break
fi
# Check filesystem boundary
PARENT_DEV="$(get_device_id "$PARENT_DIR")"
if [[ -n "$CURRENT_DEV" && -n "$PARENT_DEV" && "$CURRENT_DEV" != "$PARENT_DEV" ]]; then
break
fi
CURRENT_DIR="$PARENT_DIR"
CURRENT_DEV="$PARENT_DEV"
done
# Check the last checked directory (could be HOME or /)
if [[ -z "$FOUND_VAULT" && -d "$CURRENT_DIR/.obsidian" ]]; then
FOUND_VAULT="$CURRENT_DIR"
fi
if [[ -n "$FOUND_VAULT" ]]; then
VAULT_DIR="$FOUND_VAULT"
else
# Fallback paths in order: ~/Notes, ~/Obsidian/Notes, ~/Personal/Notes, ~/Projects/Notes.
FALLBACKS=(
"$HOME/Notes"
"$HOME/notes"
"$HOME/Obsidian/Notes"
"$HOME/Obsidian/notes"
"$HOME/Personal/Notes"
"$HOME/Personal/notes"
"$HOME/Projects/Notes"
"$HOME/Projects/notes"
)
for path in "${FALLBACKS[@]}"; do
if [[ -d "$path" && -d "$path/.obsidian" ]]; then
VAULT_DIR="$(cd "$path" && pwd)"
break
fi
done
fi
fi
if [[ -z "$VAULT_DIR" ]]; then
echo "Error: Could not find an Obsidian vault. Please specify one with -v/--vault." >&2
exit 1
fi
# Strip leading slash from NOTE_PATH to handle relative paths properly
NOTE_PATH="${NOTE_PATH#/}"
# 2. Determine if current working directory is within the vault.
# Resolve physical paths to handle symlinks cleanly.
RESOLVED_PWD="$(pwd -P)"
RESOLVED_VAULT="$(cd "$VAULT_DIR" && pwd -P)"
if [[ "$RESOLVED_PWD" == "$RESOLVED_VAULT" || "$RESOLVED_PWD" == "$RESOLVED_VAULT"/* ]]; then
# Within the vault, treat relative to CWD
TARGET_FILE="$PWD/$NOTE_PATH"
else
# Not within the vault, treat relative to vault root
TARGET_FILE="$VAULT_DIR/$NOTE_PATH"
fi
TARGET_DIR="$(dirname "$TARGET_FILE")"
TARGET_BASE="$(basename "$TARGET_FILE")"
# If there's no file extension on the argument, add .md.
if [[ "$TARGET_BASE" != *.* ]]; then
TARGET_BASE="$TARGET_BASE.md"
fi
TARGET_FILE="$TARGET_DIR/$TARGET_BASE"
# If the necessary directory components don't exist, create them.
if [[ ! -d "$TARGET_DIR" ]]; then
mkdir -p "$TARGET_DIR"
fi
# 3. If the file exists and there's no --overwrite argument, throw an error.
if [[ -f "$TARGET_FILE" && "$OVERWRITE" != "true" ]]; then
echo "Error: File already exists: $TARGET_FILE (use --overwrite to replace it)" >&2
exit 1
fi
# 4. If the path ends in .md (case-insensitive), generate appropriate YAML front matter and write it to the new file.
if [[ "${TARGET_BASE,,}" == *.md ]]; then
NOTE_TITLE="${TARGET_BASE%.*}"
CURRENT_DATE="$(date +"%Y-%m-%d %H:%M")"
cat << EOF > "$TARGET_FILE"
---
title: "$NOTE_TITLE"
date: $CURRENT_DATE
tags: []
---
EOF
else
# Just touch the file to ensure it exists
touch "$TARGET_FILE"
fi
# 5. Open the user's $EDITOR (falling back to vim/vi if unset) pointing to the new file.
EDITOR="${EDITOR:-}"
if [[ -z "$EDITOR" ]]; then
if command -v vim >/dev/null 2>&1; then
EDITOR="vim"
else
EDITOR="vi"
fi
fi
exec "$EDITOR" "$TARGET_FILE"

63
dotfiles/commonrc.sh Normal file
View File

@@ -0,0 +1,63 @@
#!/bin/sh
# shellcheck disable=SC1090
# common functions for use in shell scripts
find_first() {
while [ "$#" -gt 0 ]; do
if test -e "${1}" ; then
echo "${1}"
return 0
fi
shift
done
return 1
}
have_command() {
command -v "$1" >/dev/null 2>&1
}
# Helper function: Returns 0 if the directory is in PATH, 1 otherwise
path_contains() {
case ":${PATH}:" in
*:"$1":*) return 0 ;;
*) return 1 ;;
esac
}
# Prepend a directory to PATH if it's not already there
path_prepend() {
if [ -d "$1" ] && ! path_contains "$1"; then
PATH="$1:${PATH}"
fi
}
# Append a directory to PATH if it's not already there
path_append() {
if [ -d "$1" ] && ! path_contains "$1"; then
PATH="${PATH}:$1"
fi
}
source_first_existing() {
_sfe_script="$(find_first "$@")"
_sfe_status=$?
if [ "$_sfe_status" -eq 0 ]; then
. "$_sfe_script"
# Clean up our temporary variables before returning success
unset -v _sfe_script _sfe_status
return 0
fi
# Clean up our temporary variables before returning failure
unset -v _sfe_script _sfe_status
return 1
}
source_if_existing() {
if [ -f "$1" ]; then
. "$1"
fi
}

View File

@@ -39,16 +39,3 @@ disabled = true
[kubernetes] [kubernetes]
disabled = false disabled = false
detect_folders = ["k8s"] detect_folders = ["k8s"]
[custom.gemini_context]
description = "Displays the current Gemini CLI context"
when = "test -n \"$GEMINI_CLI_HOME\""
command = """
context_dir=\"${XDG_CONFIG_HOME:-$HOME/.config}/gemini\"
if [[ \"$GEMINI_CLI_HOME\" == $context_dir/* ]]; then
basename \"$GEMINI_CLI_HOME\"
fi
"""
style = "bold blue"
format = "♊[$output](blue) "
shell = ["/bin/sh", "-c"]

View File

@@ -38,3 +38,4 @@ mise.local.toml
.copilot/ .copilot/
.cursor/ .cursor/
.gemini/ .gemini/
.jetskicli/

View File

@@ -59,6 +59,8 @@ DIRSTACKSIZE=16
export OS="$(uname 2>/dev/null || echo "Unknown")" export OS="$(uname 2>/dev/null || echo "Unknown")"
source ~/.commonrc.sh
# Set terminal title # Set terminal title
case $TERM in case $TERM in
# Only set the title for terminals that are likely to support it # Only set the title for terminals that are likely to support it
@@ -163,31 +165,9 @@ bindkey '^r' history-incremental-search-backward
# delete really deletes # delete really deletes
bindkey "^[[3~" delete-char bindkey "^[[3~" delete-char
source_if_existing() {
[[ -f "${1}" ]] && source "${1}"
}
source_first_existing() { path_prepend "${HOME}/.npm-packages/bin"
while (($#)); do path_prepend "${HOME}/.local/bin"
if test -e "${1}" ; then
source "${1}"
return
fi
shift
done
return 1
}
have_command() {
command -v "${1}" &>/dev/null
}
if test -d ${HOME}/.local/bin ; then
export PATH="${HOME}/.local/bin:${PATH}"
fi
if test -d ${HOME}/.npm-packages/bin ; then
export PATH="${HOME}/.npm-packages/bin:${PATH}"
fi
# Source extras and aliases if interactive # Source extras and aliases if interactive
if [[ $- == *i* ]] ; then if [[ $- == *i* ]] ; then
@@ -273,8 +253,7 @@ if [[ $- == *i* ]] ; then
if command -v direnv >/dev/null 2>&1 ; then if command -v direnv >/dev/null 2>&1 ; then
eval "$(direnv hook zsh)" eval "$(direnv hook zsh)"
fi fi
test -e "${HOME}/.iterm2_shell_integration.zsh" && \ source_if_existing "${HOME}/.iterm2_shell_integration.zsh"
source "${HOME}/.iterm2_shell_integration.zsh" || true
# mise, if installed # mise, if installed
command -v mise >/dev/null 2>&1 && eval "$(mise activate zsh)" command -v mise >/dev/null 2>&1 && eval "$(mise activate zsh)"
@@ -289,11 +268,11 @@ if [ -x /usr/bin/ack-grep ] ; then
fi fi
# I want these first always # I want these first always
PATH="${HOME}/bin:${PATH}" path_prepend "${HOME}/bin"
if [[ "$(uname)" == "Darwin" ]]; then if [[ "$(uname)" == "Darwin" ]]; then
PATH="${HOME}/bin/macos:${PATH}" path_prepend "${HOME}/bin/macos"
elif [[ "$(uname)" == "Linux" ]]; then elif [[ "$(uname)" == "Linux" ]]; then
PATH="${HOME}/bin/linux:${PATH}" path_prepend "${HOME}/bin/linux"
fi fi
# Load any local settings # Load any local settings

View File

@@ -8,25 +8,12 @@ function dumpenv {
fi fi
} }
if test -x "/sbin/starship" ; then _STARSHIP_PATH="$(find_first "$(command -v starship)" /sbin/starship "${HOME}/tools/starship/starship" "${HOME}/.local/bin/starship" /usr/local/bin/starship)"
_STARSHIP_PATH="/sbin/starship" if test -n "$_STARSHIP_PATH" ; then
function starship_prompt { function starship_prompt {
eval "$(/sbin/starship init zsh)" eval "$($_STARSHIP_PATH init zsh)"
}
elif test -x "${HOME}/tools/starship/starship" ; then
_STARSHIP_PATH="${HOME}/tools/starship/starship"
function starship_prompt {
eval "$($HOME/tools/starship/starship init zsh)"
} }
fi fi
if test -f ${HOME}/.zprompt ; then
if test "$(cat ${HOME}/.zprompt)" = "starship" ; then
if test -n "${_STARSHIP_PATH:-}" ; then
eval "$(${_STARSHIP_PATH} init zsh)"
fi
fi
fi
unset _STARSHIP_PATH
function hashall { function hashall {
tee >(md5sum) | tee >(sha1sum) | sha256sum tee >(md5sum) | tee >(sha1sum) | sha256sum

View File

@@ -3,6 +3,17 @@
# Skelify -- move a file to my .skel and setup symlinks # Skelify -- move a file to my .skel and setup symlinks
function skelify { function skelify {
local -A opts
zparseopts -D -A opts -overlay:
local overlay_name="${opts[--overlay]}"
local base_skel_dir="${HOME}/.skel/dotfiles"
local extra_args=()
if [[ -n "${overlay_name}" ]]; then
base_skel_dir="${HOME}/.skel/dotfile_overlays/${overlay_name}"
extra_args=(--overlay "${overlay_name}")
fi
local target local target
local whichdir local whichdir
local relhome local relhome
@@ -10,16 +21,19 @@ function skelify {
local fulltarget local fulltarget
for target in $~@; do for target in $~@; do
if test -d ${target} ; then if test -d ${target} ; then
skelify ${target}/* || return 1 skelify "${extra_args[@]}" ${target}/* || return 1
elif test -f ${target} ; then elif test -f ${target} ; then
if ! whichdir=$(cd $(dirname $target) && pwd); then if ! whichdir=$(cd $(dirname $target) && pwd); then
echo Could not find directory for $target >/dev/stderr echo Could not find directory for $target >/dev/stderr
return 1 return 1
fi fi
fname=$(basename ${target}) fname=$(basename ${target})
relhome=${whichdir#${HOME}/}
fulltarget="${whichdir}/${fname}" fulltarget="${whichdir}/${fname}"
if [[ ${relhome} == ${whichdir} ]] ; then if [[ ${whichdir} == ${HOME} ]] ; then
relhome=""
elif [[ ${whichdir} == ${HOME}/* ]] ; then
relhome=${whichdir#${HOME}/}
else
echo ${whichdir} is not in home >/dev/stderr echo ${whichdir} is not in home >/dev/stderr
return 1 return 1
fi fi
@@ -32,7 +46,7 @@ function skelify {
return 1 return 1
fi fi
echo ${target} echo ${target}
local skeldir="${HOME}/.skel/dotfiles/${relhome}" local skeldir="${base_skel_dir}/${relhome}"
mkdir -p "${skeldir}" mkdir -p "${skeldir}"
mv ${target} "${skeldir}/${fname}" mv ${target} "${skeldir}/${fname}"
ln -s "${skeldir}/${fname}" "${fulltarget}" ln -s "${skeldir}/${fname}" "${fulltarget}"

View File

@@ -7,14 +7,65 @@ set -o errexit
set -o shwordsplit 2>/dev/null || true # Make zsh behave like bash set -o shwordsplit 2>/dev/null || true # Make zsh behave like bash
HOME=${HOME:-$(cd ~ && pwd)} HOME=${HOME:-$(cd ~ && pwd)}
LOCAL_BIN="${HOME}/.local/bin"
STARSHIP_INSTALL_HASH="52c64f14a558034ebeb1907ea9364e802b32474576fd3e68265f73bc33cc8fbb"
# 1. Get the raw script path (handles Bash vs Zsh)
TARGET="${BASH_SOURCE[0]}"
# 2. Loop to resolve symlinks completely
while [ -L "$TARGET" ]; do
DIR=$(cd -P "$(dirname -- "$TARGET")" &>/dev/null && pwd)
TARGET=$(readlink "$TARGET")
# If $TARGET is a relative symlink, resolve it relative to the symlink's directory
[[ $TARGET != /* ]] && TARGET="$DIR/$TARGET"
done
# 3. Get the final absolute directory
SCRIPT_DIR="$(cd -P "$(dirname -- "$TARGET")" &>/dev/null && pwd)"
have_command() { have_command() {
command -v "${1}" >/dev/null 2>&1 command -v "${1}" >/dev/null 2>&1
} }
raw_sha256sum() {
local file="${1}"
if [[ -z "${file}" ]]; then
echo "Error: No file specified" >&2
return 1
fi
if [[ ! -f "${file}" ]]; then
echo "Error: File not found: ${file}" >&2
return 1
fi
if have_command sha256sum ; then
sha256sum "${file}" | awk '{print $1}'
elif have_command shasum ; then
shasum -a 256 "${file}" | awk '{print $1}'
else
echo "Error: Neither sha256sum nor shasum is available" >&2
return 1
fi
}
sudo_group() {
if [[ "$(id -u)" -eq 0 ]] ; then
return 0
fi
have_command sudo && ( id -Gn | grep -q '\bsudo\b' )
}
maybe_sudo() {
if [[ "$(id -u)" -eq 0 ]] ; then
"$@"
return
fi
if ! have_command sudo ; then
return 1
fi
sudo "$@"
}
link_directory_contents() { link_directory_contents() {
local SRCDIR="${1}" local SRCDIR="${1}"
@@ -43,7 +94,7 @@ ssh_key_already_installed() {
fi fi
# Extract the key data (field 2) from the key file, ignoring comments # Extract the key data (field 2) from the key file, ignoring comments
local key_data local key_data
key_data=$(awk '/^ssh-/ {print $2}' "$1") key_data=$(awk '/^(ssh|ecdsa|sk)-/ {print $2}' "$1")
if [[ -z "${key_data}" ]]; then if [[ -z "${key_data}" ]]; then
# Not a valid key file # Not a valid key file
return 1 return 1
@@ -90,7 +141,7 @@ install_known_hosts() {
verbose 'Installing known hosts...' >&2 verbose 'Installing known hosts...' >&2
local skel_hosts="${BASEDIR}/keys/known_hosts" local skel_hosts="${BASEDIR}/keys/known_hosts"
local user_hosts="${HOME}/.ssh/known_hosts" local user_hosts="${HOME}/.ssh/known_hosts"
local merge_script="${BASEDIR}/skeltools/merge_authorized_keys" local merge_script="${BASEDIR}/skeltools/merge_known_hosts"
if [[ ! -f "${skel_hosts}" ]]; then if [[ ! -f "${skel_hosts}" ]]; then
return 0 return 0
@@ -176,6 +227,60 @@ install_dotfiles() {
fi fi
} }
install_starship() {
if have_command starship ; then return 0 ; fi
if have_command brew ; then
verbose "Attempting to install Starship via Homebrew..."
if brew install starship ; then
return 0
fi
echo "brew install starship failed, trying other methods..." >&2
fi
if have_command apt-get && sudo_group ; then
if maybe_sudo apt-get install -qy starship ; then
return 0
fi
echo "apt-get install starship failed, installing locally" >&2
fi
local tmpd
tmpd="$(mktemp -d tmp.starship.XXXXXX)" || return 1
trap '[[ -n "${tmpd}" && -d "${tmpd}" ]] && rm -rf "${tmpd}"' EXIT
local install_path="${tmpd}/install.sh"
if have_command curl ; then
curl -sSL --show-error -o "${install_path}" https://starship.rs/install.sh
elif have_command wget ; then
wget -q -O "${install_path}" --https-only https://starship.rs/install.sh
else
echo "No curl or wget available!!" >&2
rm -rf "${tmpd}"
trap - EXIT
return 1
fi
local dl_hash
dl_hash="$(raw_sha256sum "${install_path}")"
if [[ "$dl_hash" != "${STARSHIP_INSTALL_HASH}" ]] ; then
echo "Hash check failed!!" >&2
echo "Expected: ${STARSHIP_INSTALL_HASH}, got ${dl_hash} on ${install_path}" >&2
rm -rf "${tmpd}"
trap - EXIT
return 1
fi
if sudo_group ; then
if maybe_sudo sh "${install_path}" ; then
rm -rf "${tmpd}"
trap - EXIT
return 0
fi
echo "root installation failed, falling back to user-local" >&2
fi
sh "${install_path}" -b "${LOCAL_BIN}"
rm -rf "${tmpd}"
trap - EXIT
}
install_main() { install_main() {
if [[ -d "${BASEDIR}/.git" ]] && have_command git ; then if [[ -d "${BASEDIR}/.git" ]] && have_command git ; then
if [[ -z "$(git -C "${BASEDIR}" status --porcelain)" ]]; then if [[ -z "$(git -C "${BASEDIR}" status --porcelain)" ]]; then
@@ -185,6 +290,8 @@ install_main() {
fi fi
fi fi
[[ "$MINIMAL" = 1 ]] || { [[ "$MINIMAL" = 1 ]] || {
mkdir -p "${LOCAL_BIN}"
install_starship
# Install vim-plug if not already present # Install vim-plug if not already present
local VIM_PLUG_URL="https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim" local VIM_PLUG_URL="https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim"
@@ -243,7 +350,7 @@ read_saved_prefs
# Defaults if not passed in or saved. # Defaults if not passed in or saved.
# TODO: use flags instead of environment variables. # TODO: use flags instead of environment variables.
: ${BASEDIR:=$HOME/.skel} : ${BASEDIR:=${SCRIPT_DIR}}
: ${MINIMAL:=0} : ${MINIMAL:=0}
: ${INSTALL_KEYS:=1} : ${INSTALL_KEYS:=1}
: ${TRUST_ALL_KEYS:=0} : ${TRUST_ALL_KEYS:=0}