diff --git a/notfiles.toml b/notfiles.toml deleted file mode 100644 index 194fdc1..0000000 --- a/notfiles.toml +++ /dev/null @@ -1,7 +0,0 @@ -[defaults] -target = "~" -ignore = [".git", ".DS_Store", "README.md", "LICENSE*", "notfiles.toml", ".notfiles-state.toml", ".nothooks-state.toml", "Cargo.toml", "Cargo.lock", "crates", "docs", "tests", "target", "scripts", "mise.toml", "deny.toml", "rustqual.toml", ".github", ".gitea", ".envrc", ".sccignore", ".codex", ".superpowers", ".remember", ".worktrees", ".ctx", "HANDOFF.md", "AGENTS.md", "preflight.md"] - -include = ["nushell"] - -[packages.nushell] diff --git a/nushell/.DS_Store b/nushell/.DS_Store deleted file mode 100644 index 8a9b3a7..0000000 Binary files a/nushell/.DS_Store and /dev/null differ diff --git a/nushell/.config/.DS_Store b/nushell/.config/.DS_Store deleted file mode 100644 index b65668a..0000000 Binary files a/nushell/.config/.DS_Store and /dev/null differ diff --git a/nushell/.config/nushell/.DS_Store b/nushell/.config/nushell/.DS_Store deleted file mode 100644 index 80e66bc..0000000 Binary files a/nushell/.config/nushell/.DS_Store and /dev/null differ diff --git a/nushell/.config/nushell/autoload/aliases.nu b/nushell/.config/nushell/autoload/aliases.nu deleted file mode 100644 index 779d08e..0000000 --- a/nushell/.config/nushell/autoload/aliases.nu +++ /dev/null @@ -1,108 +0,0 @@ -# Aliases - -# ── Shell ───────────────────────────────────────────────────────────────────── -alias rr = exec nu # reload nushell (re-reads config.nu and env.nu) - -# ── Files ──────────────────────────────────────────────────────────────────── -alias ll = ls -l -alias la = ls -la - -# ── Editor ─────────────────────────────────────────────────────────────────── -alias ide = zed . -alias ocm = opencode -m ollama/gpt-mbx - -# ── mise ───────────────────────────────────────────────────────────────────── -alias m = mise -alias mr = mise run -alias mi = mise install -alias mt = mise tasks ls - -# ── Rust / cargo ───────────────────────────────────────────────────────────── -alias x = cargo xtask - -# ── Git (gitoxide) ─────────────────────────────────────────────────────────── -# gix-supported: status, branch, log, fetch, clone, diff(objects), blame, worktree -# not yet in gix: add, commit, checkout/switch/restore, push, stash, rebase, merge -def --wrapped g [...args] { gix ...$args } -def gs [] { gix status } -def --wrapped gb [...args] { gix branch list ...$args } -def --wrapped ga [...args] { git add ...$args } -def --wrapped gc [...args] { git commit ...$args } -def --wrapped gco [...args] { git checkout ...$args } -def --wrapped gd [...args] { git diff ...$args } # gix diff = object-level only -def gl [] { git pull --ff-only } -def --wrapped gp [...args] { git push ...$args } -def --wrapped gpf [...args] { git push --force-with-lease ...$args } -def gitgood [] { git stash; git pull --rebase; git stash pop; git push } - -# ── GitHub CLI ─────────────────────────────────────────────────────────────── -alias ghst = gh auth status -alias ghrepo = gh repo view --web -alias ghpr = gh pr create -alias ghprv = gh pr view -alias ghprw = gh pr view --web -alias ghiss = gh issue list -alias ghrun = gh run list - -# ── BAML ───────────────────────────────────────────────────────────────────── -alias baml = uvx --from baml-py baml-cli - -# ── Python / uv ────────────────────────────────────────────────────────────── -alias pip = uv pip -alias pip3 = uv pip -alias py = uv run python - -# ── JS / Bun ───────────────────────────────────────────────────────────────── -alias npm = bun -alias npx = bunx -alias pnpm = bun -alias yarn = bun - -# ── Zerobrew ───────────────────────────────────────────────────────────────── -alias zbi = zb install -alias zbl = zb list -alias zbu = zb update - -# ── notfiles ───────────────────────────────────────────────────────────────── -def --wrapped nf [...args] { notfiles --dir /Users/joe/dev/notfiles ...$args } - -# ── Dotfiles ───────────────────────────────────────────────────────────────── -alias dotfiles = cd ~/dotfiles -def --env dotgs [] { cd ~/dotfiles; git status -sb } -def --env dotpull [] { cd ~/dotfiles; git pull --ff-only } -def --env dotpush [] { cd ~/dotfiles; git push } -def --env dotopen [] { cd ~/dotfiles; gh repo view --web } - -# ── Docker / Colima ────────────────────────────────────────────────────────── -alias dps = docker ps -alias dpsa = docker ps -a -alias di = docker images -alias dstop = docker stop -alias drm = docker rm -alias drmi = docker rmi -alias drmif = docker rmi -f -alias colima-start = colima start --profile dev --cpu 4 --memory 6 --disk 60 --runtime docker -alias colima-stop = colima stop --profile dev -alias colima-status = colima status --profile dev - -# ── Kubernetes ─────────────────────────────────────────────────────────────── -alias kctx = kubectl config current-context -alias kpods = kubectl get pods -A -alias kmpods = kubectl --context=gke_toptal-maestro_us-east1_main-0 -n team-maestro get pods -alias kmlogs = kubectl --context=gke_toptal-maestro_us-east1_main-0 -n team-maestro logs -alias kmexec = kubectl --context=gke_toptal-maestro_us-east1_main-0 -n team-maestro exec -it - -# ── Maestro ────────────────────────────────────────────────────────────────── -alias ms = maestro start -alias mst = maestro stop -alias ml = maestro list -alias mlogs = maestro logs -alias mwork = maestro work -alias mcfg = maestro config show -alias mpurge = maestro purge -alias mauth = maestro auth login - -alias maestro-attach = docker exec -it -u vscode (docker ps --filter name=maestro-maestro-dev --format "{{.ID}}" | head -1) tmux -S /tmp/tmux-shared/maestro.sock -u attach-session - -# ── Secrets / obfsck ───────────────────────────────────────────────────────── -alias obfs = pj secret redact diff --git a/nushell/.config/nushell/autoload/audit.nu b/nushell/.config/nushell/autoload/audit.nu deleted file mode 100644 index 7f772a4..0000000 --- a/nushell/.config/nushell/autoload/audit.nu +++ /dev/null @@ -1,131 +0,0 @@ -# Redaction audit helpers — wraps scripts/redact-audit.sh and .logs/redact-audit.jsonl - -# ── Internal ───────────────────────────────────────────────────────────────── - -def _dotfiles [] { $env.HOME | path join "dotfiles" } -def _audit_log [] { $env.HOME | path join "dotfiles/.logs/redact-audit.jsonl" } - -def _read_audit_log [] { - let log = _audit_log - if not ($log | path exists) { return [] } - open $log - | lines - | where { |l| ($l | str trim) != "" } - | each { |l| $l | from json } - | update ts { |r| $r.ts | into datetime } -} - -# ── audit-log ──────────────────────────────────────────────────────────────── - -# Read the redaction audit log as a table. -# Filter by --tier, --file, --hook, or --since (e.g. "1day", "2hr", "30min") -def audit-log [ - --tier: string # Filter to a specific tier (critical, high, medium, low) - --file: string # Filter by file path substring - --hook: string # Filter by hook name (pre-commit, manual, ...) - --since: string # Only show entries newer than this duration (e.g. 1day, 2hr) -] { - mut rows = _read_audit_log - - if ($tier | is-not-empty) { - $rows = ($rows | where tier == $tier) - } - if ($file | is-not-empty) { - $rows = ($rows | where { |r| $r.file | str contains $file }) - } - if ($hook | is-not-empty) { - $rows = ($rows | where hook == $hook) - } - if ($since | is-not-empty) { - let cutoff = (date now) - ($since | into duration) - $rows = ($rows | where ts > $cutoff) - } - - $rows | select ts hook commit file tier group label match_count -} - -# ── audit-summary ───────────────────────────────────────────────────────────── - -# Summarise audit log hits grouped by tier and group. -# Pass --since to limit to a recent window (e.g. "7day"). -def audit-summary [ - --since: string # Limit to entries newer than this duration (e.g. 7day) -] { - mut rows = _read_audit_log - - if ($since | is-not-empty) { - let cutoff = (date now) - ($since | into duration) - $rows = ($rows | where ts > $cutoff) - } - - if ($rows | is-empty) { - print "No audit entries found." - return - } - - $rows - | group-by tier - | transpose tier entries - | each { |t| - let total = ($t.entries | get match_count | math sum) - let by_group = ( - $t.entries - | group-by group - | transpose group rows - | each { |g| { group: $g.group, hits: ($g.rows | get match_count | math sum) } } - | sort-by hits -r - ) - { tier: $t.tier, total_hits: $total, breakdown: $by_group } - } - | sort-by total_hits -r -} - -# ── audit-scan ─────────────────────────────────────────────────────────────── - -# Scan files through the redaction auditor and log findings. -# With no args, scans staged git files (same as pre-commit hook). -# Pass file paths to scan specific files. -def audit-scan [ - ...files: string # Files to scan (default: staged git files) - --verbose (-v) # Print findings to terminal as well as logging -] { - let script = (_dotfiles | path join "scripts/redact-audit.sh") - - if not ($script | path exists) { - error make { msg: $"audit script not found: ($script)" } - } - - mut args = ["--hook", "manual"] - - if $verbose { $args = ($args | append "--verbose") } - - if ($files | is-empty) { - $args = ($args | append "--staged") - } else { - $args = ($args | append $files) - } - - ^bash $script ...$args -} - -# ── audit-top ───────────────────────────────────────────────────────────────── - -# Show the most frequently hit files in the audit log. -def audit-top [ - --n: int = 10 # Number of results to show - --since: string # Limit to entries newer than this duration (e.g. 7day) -] { - mut rows = _read_audit_log - - if ($since | is-not-empty) { - let cutoff = (date now) - ($since | into duration) - $rows = ($rows | where ts > $cutoff) - } - - $rows - | group-by file - | transpose file entries - | each { |f| { file: $f.file, hits: ($f.entries | get match_count | math sum), scans: ($f.entries | length) } } - | sort-by hits -r - | first $n -} diff --git a/nushell/.config/nushell/autoload/did-you-mean.nu b/nushell/.config/nushell/autoload/did-you-mean.nu deleted file mode 100644 index 251ed33..0000000 --- a/nushell/.config/nushell/autoload/did-you-mean.nu +++ /dev/null @@ -1,55 +0,0 @@ -# did-you-mean.nu — command_not_found hook -# Source: nushell/nu_scripts (nu-hooks/command_not_found) -# Suggests 3 closest commands from PATH when a command is not found. - -export def hook [] { - {|cmd| - let commands_in_path = ( - if ($nu.os-info.name == windows) { - $env.Path | each {|directory| - if ($directory | path exists) { - let cmd_exts = ( - $env.PATHEXT | str downcase | split row ';' | str trim --char . - ) - ls $directory - | get name - | path parse - | where {|it| - $cmd_exts | any {|ext| $ext == ($it.extension | str downcase)} - } - | get stem - } - } - } else { - $env.PATH | each {|directory| - if ($directory | path exists) { - ls $directory - | get name - | path parse - | update parent "" - | path join - } - } - } - | flatten - | wrap cmd - ) - - let closest_commands = ( - $commands_in_path - | insert distance {|it| $it.cmd | str distance $cmd} - | uniq - | sort-by distance - | get cmd - | first 3 - ) - - let pretty_commands = ( - $closest_commands | each {|cmd| - $" (ansi {fg: "default" attr: "di"})($cmd)(ansi reset)" - } - ) - - $"\ndid you mean?\n($pretty_commands | str join "\n")" - } -} diff --git a/nushell/.config/nushell/autoload/functions.nu b/nushell/.config/nushell/autoload/functions.nu deleted file mode 100644 index 202afee..0000000 --- a/nushell/.config/nushell/autoload/functions.nu +++ /dev/null @@ -1,168 +0,0 @@ -# Custom functions - -# ── nu_libs ────────────────────────────────────────────────────────────────── - -# Show all commands loaded from nu_libs, grouped by domain -def libs [ - --filter(-f): string = "" # filter by name substring -] { - let nu_libs_dir = "/Users/joe/dev/nu_libs/lib" - - # Build name→domain map by scanning export defs in each domain's files - let domain_map = ( - ls $nu_libs_dir - | where type == "dir" - | get name - | each {|dir| - let domain = $dir | path basename - let names = ( - glob $"($dir)/**/*.nu" - | each {|f| - open $f | lines - | where {|l| ($l | str starts-with "export def") or ($l | str starts-with "export alias")} - | each {|l| - # extract the command name: third or fourth word depending on flags - let parts = $l | split row " " | where {|p| ($p | str length) > 0} - # skip "export", "def"/"alias", and any --flags - $parts | skip 2 | where {|p| not ($p | str starts-with "-")} | first - } - | compact - } - | flatten - | compact - | each {|n| $n | str replace --all '"' "" | str replace --all "`" "" | str trim} - ) - $names | each {|n| {name: $n, domain: $domain}} - } - | flatten - | uniq-by name - | reduce -f {} {|x, acc| $acc | upsert $x.name $x.domain} - ) - - let nu_libs_names = $domain_map | columns - - help commands - | where command_type == "custom" - | where {|cmd| $cmd.name in $nu_libs_names} - | if ($filter | is-not-empty) { where name =~ $filter } else { $in } - | select name description - | each {|cmd| - $cmd | insert domain ($domain_map | get $cmd.name) - } - | sort-by domain name - | group-by domain - | transpose domain cmds - | each {|g| - print $"(ansi cyan_bold)── ($g.domain) ──(ansi reset)" - $g.cmds | select name description | print - } - null -} - -# ── Files ──────────────────────────────────────────────────────────────────── - -# Quick directory listing sorted by size -def dirsize [] { - ls | select name size type | sort-by size -r -} - -# Make a directory and cd into it -def --env mkcd [dir: string] { - mkdir $dir - cd $dir -} - -# ── Dotfiles ───────────────────────────────────────────────────────────────── - -# Run a mise task from the dotfiles repo -def dfr [...args: string] { - let root = ($env.HOME | path join "dotfiles") - ^mise --cd $root run ...$args -} - -# Run a just recipe from the dotfiles repo -def dfj [...args: string] { - let root = ($env.HOME | path join "dotfiles") - ^just --justfile $"($root)/Justfile" ...$args -} - -# ── Kubernetes ─────────────────────────────────────────────────────────────── - -# Tail logs across all namespaces (uses stern) -def klogs [pattern: string = "."] { - ^stern $pattern -A -} - -# ── Secrets / redaction ────────────────────────────────────────────────────── - -# Run a command and pipe its output through obfsck redact -def obfsrun [...args: string] { - let config = ($nu.home-path | path join "dotfiles/config/obfsck-secrets.yaml") - if (which obfsck | is-not-empty) { - ^$args.0 ...($args | skip 1) | ^obfsck --config $config - } else { - ^$args.0 ...($args | skip 1) - } -} - -# ── Docker / Colima ────────────────────────────────────────────────────────── - -def _colima_ensure_running [] { - if (which colima | is-empty) { return } - let profile = if ("COLIMA_PROFILE" in $env) { $env.COLIMA_PROFILE } else { "dev" } - let running = (^colima status --profile $profile | complete | get exit_code) == 0 - if not $running { - print $"[colima] Starting profile '($profile)' \(4 CPU, 6GB RAM, 60GB disk\)..." - ^colima start --profile $profile --cpu 4 --memory 6 --disk 60 --runtime docker - } -} - -def _colima_set_socket [] { - let dev_sock = ($env.HOME | path join ".colima/dev/docker.sock") - let default_sock = ($env.HOME | path join ".config/colima/default/docker.sock") - if ($dev_sock | path exists) { - $env.DOCKER_HOST = $"unix://($dev_sock)" - } else if ($default_sock | path exists) { - $env.DOCKER_HOST = $"unix://($default_sock)" - } -} - -def --wrapped docker [...args: string] { - _colima_ensure_running - _colima_set_socket - ^docker ...$args -} - -def --wrapped docker-compose [...args: string] { - _colima_ensure_running - _colima_set_socket - ^docker-compose ...$args -} - -def colima-restart [] { - colima-stop - colima-start -} - -# ── JS ─────────────────────────────────────────────────────────────────────── - -# Real npm bypass (bun alias doesn't cover maestro-ui which needs real npm) -def mnpm [...args: string] { - ^npm ...$args -} - -# ── Secrets helpers ────────────────────────────────────────────────────────── - -# Run a command with secrets injected from ~/.secrets via op run. -# Works around $HOME not being expanded by op CLI. -def oprun [...args: string] { - let secrets = ($env.HOME | path join ".secrets") - ^op run --account=my.1password.com $"--env-file=($secrets)" -- ...$args -} - -# ── Git helpers ────────────────────────────────────────────────────────────── - -# Push via gh credential helper -def _git_gh [...args: string] { - ^git -c credential.helper= -c "credential.helper=!/opt/homebrew/bin/gh auth git-credential" ...$args -} diff --git a/nushell/.config/nushell/autoload/nu_libs.nu b/nushell/.config/nushell/autoload/nu_libs.nu deleted file mode 100644 index 426a8eb..0000000 --- a/nushell/.config/nushell/autoload/nu_libs.nu +++ /dev/null @@ -1,10 +0,0 @@ -# nu_libs — load all lib/* modules on shell startup -# Managed by notfiles (nushell package). Link with: notfiles link nushell -# lib/ai is excluded from lib/mod.nu (requires runtime deps) — loaded separately below. -# lib/extensions is excluded (requires external project repos) — load manually as needed. - -const NU_LIBS = "/Users/joe/dev/nu_libs/lib/mod.nu" -const NU_LIBS_AI = "/Users/joe/dev/nu_libs/lib/ai/mod.nu" - -use $NU_LIBS * -use $NU_LIBS_AI * diff --git a/nushell/.config/nushell/autoload/nuenv.nu b/nushell/.config/nushell/autoload/nuenv.nu deleted file mode 100644 index 3a9005f..0000000 --- a/nushell/.config/nushell/autoload/nuenv.nu +++ /dev/null @@ -1,84 +0,0 @@ -# nuenv.nu — secure .env.nu loader (replaces direnv for Nu-native projects) -# Source: nushell/nu_scripts (nu-hooks/nuenv), adapted for local conventions. -# -# Usage: -# source autoload/nuenv.nu -# # In config.nu hooks section: -# $env.config.hooks.env_change.PWD = (... | append (nuenv-hook)) -# # Then in any project dir: -# nuenv allow # approve .env.nu (sha256 allowlist) -# nuenv disallow # revoke - -const NUENV_FILE = ($nu.cache-dir | path join 'nuenv' 'allowed.txt') - -def get-allowed []: [ nothing -> list ] { - if ($NUENV_FILE | path exists) { - open $NUENV_FILE | lines - } else { - [] - } -} - -# Returns the PWD-change hook record for use in env_change.PWD -export def nuenv-hook []: [ nothing -> record ] { - { - condition: {|_, after| $after | path join '.env.nu' | path exists } - code: $" - let allowed = if \('($NUENV_FILE)' | path exists\) { - open ($NUENV_FILE) | lines - } else { - [] - } - - if \(open .env.nu | hash sha256\) not-in $allowed { - error make --unspanned { - msg: $'\(ansi purple\)\('.env.nu' | path expand\)\(ansi reset\) is not allowed', - help: $'please run \(ansi default_dimmed\)nuenv allow\(ansi reset\) first', - } - } - - print $'[\(ansi yellow_bold\)nuenv\(ansi reset\)] loading \(ansi purple\)\('.env.nu' | path expand\)\(ansi reset\)' - source .env.nu - " - } -} - -def _log [msg: string, color: string] { - print $'[(ansi $color)nuenv(ansi reset)] (ansi purple)(".env.nu" | path expand)(ansi reset) ($msg)' -} - -def check-env-file [] { - if not (".env.nu" | path exists) { - error make --unspanned { - msg: $"(ansi red_bold)env file not found(ansi reset)", - help: $"no (ansi yellow).env.nu(ansi reset) in (ansi purple)(pwd)(ansi reset)", - } - } -} - -# Adds ./.env.nu to the allowlist -export def "nuenv allow" [] { - check-env-file - let allowed = get-allowed - let hash = open .env.nu | hash sha256 - if $hash in $allowed { - _log "is already allowed" "yellow_bold" - return - } - mkdir ($nu.cache-dir | path join "nuenv") - $hash | $in + "\n" out>> $NUENV_FILE - _log "has been allowed" "green_bold" -} - -# Removes ./.env.nu from the allowlist -export def "nuenv disallow" [] { - check-env-file - let allowed = get-allowed - let hash = open .env.nu | hash sha256 - if $hash not-in $allowed { - _log "is already disallowed" "yellow_bold" - return - } - $allowed | find --invert $hash | to text | save --force $NUENV_FILE - _log "has been disallowed" "green_bold" -} diff --git a/nushell/.config/nushell/autoload/session-guard.nu b/nushell/.config/nushell/autoload/session-guard.nu deleted file mode 100644 index 5e65bcc..0000000 --- a/nushell/.config/nushell/autoload/session-guard.nu +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env nu - -# Session Guard: Validates config/env file hashes and expected env keys at shell startup -# Runs at every nushell startup to detect configuration drift. - -def validate_session [] { - let baseline_path = $"($env.HOME)/.config/nushell/.session-baseline.json" - let files_to_check = [ - $"($env.HOME)/.config/nushell/env.nu" - $"($env.HOME)/.config/nushell/config.nu" - $"($env.HOME)/dev/.envrc" - $"($env.HOME)/dev/.env" - $"($env.HOME)/.mise.toml" - ] - let required_env_keys = [ - "ANTHROPIC_API_KEY" - "OPENAI_API_KEY" - "GITHUB_TOKEN" - ] - - # Check if baseline exists - if not ($baseline_path | path exists) { - print "[session-guard] No baseline found. Run session-baseline.nu to initialize." - return - } - - # Load baseline - let baseline = (open --raw $baseline_path | from json) - - # Check file hashes - for file_path in $files_to_check { - if ($file_path | path exists) { - let current_hash = (open --raw $file_path | hash sha256) - let file_name = ($file_path | path basename) - - if ($baseline.files | get -i $file_name) != $current_hash { - print $"[session-guard] DRIFT: ($file_name) hash changed" - } - } - } - - # Check required env vars - for key in $required_env_keys { - if ($env | get -i $key) == null { - print $"[session-guard] MISSING ENV: ($key)" - } - } -} - -# Run validation (silent if all OK) -validate_session diff --git a/nushell/.config/nushell/autoload/settings.nu b/nushell/.config/nushell/autoload/settings.nu deleted file mode 100644 index 36b29fb..0000000 --- a/nushell/.config/nushell/autoload/settings.nu +++ /dev/null @@ -1,70 +0,0 @@ -# Shell settings - -$env.config.show_banner = false -$env.config.history.file_format = "sqlite" -$env.config.history.max_size = 100_000 -$env.config.completions.external.enable = true -$env.config.edit_mode = "emacs" # or "vi" - -# ── Colors ─────────────────────────────────────────────────────────────────── -$env.config.color_config = { - separator: default - leading_trailing_space_bg: { attr: n } - header: green_bold - empty: blue - bool: light_cyan - int: default - filesize: cyan - duration: default - datetime: purple - range: default - float: default - string: default - nothing: default - binary: default - cell-path: default - row_index: green_bold - record: default - list: default - closure: green_bold - glob: cyan_bold - block: default - hints: dark_gray - search_result: { bg: red fg: default } - shape_binary: purple_bold - shape_block: blue_bold - shape_bool: light_cyan - shape_closure: green_bold - shape_custom: green - shape_datetime: cyan_bold - shape_directory: cyan - shape_external: cyan - shape_externalarg: green_bold - shape_external_resolved: light_yellow_bold - shape_filepath: cyan - shape_flag: blue_bold - shape_float: purple_bold - shape_glob_interpolation: cyan_bold - shape_globpattern: cyan_bold - shape_int: purple_bold - shape_internalcall: cyan_bold - shape_keyword: cyan_bold - shape_list: cyan_bold - shape_literal: blue - shape_match_pattern: green - shape_matching_brackets: { attr: u } - shape_nothing: light_cyan - shape_operator: yellow - shape_pipe: purple_bold - shape_range: yellow_bold - shape_record: cyan_bold - shape_redirection: purple_bold - shape_signature: green_bold - shape_string: green - shape_string_interpolation: cyan_bold - shape_table: blue_bold - shape_variable: purple - shape_vardecl: purple - shape_raw_string: light_purple - shape_garbage: { fg: default bg: red attr: b } -} diff --git a/nushell/.config/nushell/autoload/toolkit-hook.nu b/nushell/.config/nushell/autoload/toolkit-hook.nu deleted file mode 100644 index 8e241b9..0000000 --- a/nushell/.config/nushell/autoload/toolkit-hook.nu +++ /dev/null @@ -1,18 +0,0 @@ -# toolkit-hook.nu — auto-load toolkit.nu overlay on cd -# Source: nushell/nu_scripts (nu-hooks/toolkit) -# -# When you cd into a directory containing toolkit.nu, it loads as an overlay -# with the prefix "tk". Define project-local commands in toolkit.nu files. - -export def toolkit-hook [ - --name: string = "tk", - --color: string = "yellow_bold", -]: [ nothing -> record ] { - { - condition: {|_, after| $after | path join 'toolkit.nu' | path exists } - code: $" - print $'[\(ansi ($color)\)toolkit\(ansi reset\)] loading \(ansi purple\)toolkit.nu\(ansi reset\) as overlay' - overlay use --prefix toolkit.nu as ($name) - " - } -} diff --git a/nushell/.config/nushell/config.nu b/nushell/.config/nushell/config.nu deleted file mode 100644 index efb5ddb..0000000 --- a/nushell/.config/nushell/config.nu +++ /dev/null @@ -1,94 +0,0 @@ -# config.nu — main nushell configuration -# env.nu and autoload/ are sourced automatically by nushell before this file. - -# ── Vendor/autoload seeding ─────────────────────────────────────────────────── -# Generates tool init scripts into $nu.data-dir/vendor/autoload/ on every -# shell startup. Nushell auto-sources everything in that directory. - -let vendor = $nu.data-dir | path join "vendor/autoload" -mkdir $vendor - -# Ensure nix and mise are on PATH for vendor seeding — may already be set by env.nu -$env.PATH = ($env.PATH | prepend [ - ($env.HOME | path join ".nix-profile/bin") - ($env.HOME | path join ".local/share/mise/shims") -] | uniq) - -try { starship init nu | save -f ($vendor | path join "starship.nu") } -try { zoxide init nushell | save -f ($vendor | path join "zoxide.nu") } -try { ^mise activate nu | save -f ($vendor | path join "mise.nu") } -try { atuin init nu | save -f ($vendor | path join "atuin.nu") } -try { carapace _carapace nushell | save -f ($vendor | path join "carapace.nu") } - - -# ── User autoload ──────────────────────────────────────────────────────────── -# Sourced explicitly so they are available immediately (vendor/autoload is -# sourced before config.nu, so copying there only takes effect next session). -source autoload/settings.nu -source autoload/aliases.nu -source autoload/functions.nu -source autoload/audit.nu -source autoload/nuenv.nu -source autoload/did-you-mean.nu -source autoload/toolkit-hook.nu -source autoload/nu_libs.nu - -# ── Keybindings ─────────────────────────────────────────────────────────────── - -$env.config.keybindings = ($env.config.keybindings? | default [] | append [ - # Ctrl+F — fzf file picker, inserts selected path at cursor - { - name: fzf_file_picker - modifier: control - keycode: char_f - mode: [emacs, vi_insert] - event: { - send: executehostcommand - cmd: "commandline edit --insert (fd --type f | fzf | str trim)" - } - } -]) - -# ── Hooks ───────────────────────────────────────────────────────────────────── -# Prevent accumulation from repeated config.nu sourcing by tracking registration - -let pwd_hooks = [ - (nuenv-hook) - (toolkit-hook) - {|before, after| - let cache = ($env.HOME | path join ".cache/doob/status.json") - if not ($cache | path exists) { return } - let data = (open $cache | from json) - let overdue = ($data.overdue_total? | default 0) - if $overdue == 0 { return } - let repo = ($after | path basename) - let repo_count = ($data.overdue_by_repo? | default {} | get -o $repo | default 0) - if $repo_count > 0 { - print $"(ansi yellow)doob: ($repo_count) overdue in ($repo)(ansi reset)" - } else { - print $"(ansi dim)doob: ($overdue) overdue total(ansi reset)" - } - } -] - -# Guard against accumulation from repeated sourcing (e.g., user runs 'source config.nu') -if ($env.NUSHELL_CONFIG_SOURCED? == "true") { - # Already sourced in this session, skip hook registration -} else { - $env.config.hooks.env_change.PWD = $pwd_hooks - $env.NUSHELL_CONFIG_SOURCED = "true" -} - -# display_output: expand table columns on wide terminals -$env.config.hooks.display_output = {|| - if (term size).columns >= 100 { table -e } else { table } -} - -# command_not_found: fuzzy-match 3 closest commands from PATH -$env.config.hooks.command_not_found = (use autoload/did-you-mean.nu; hook) - -# go wrapper: install to $HOME/go/bin by default -def go [...args] { with-env { GOBIN: $"($env.HOME)/go/bin" } { ^go ...$args } } - -# naptrace: run from source checkout so prompts/ is found -def --wrapped naptrace [...args] { cd ~/dev/naptrace; ^naptrace ...$args } diff --git a/nushell/.config/nushell/env.nu b/nushell/.config/nushell/env.nu deleted file mode 100644 index a302d0b..0000000 --- a/nushell/.config/nushell/env.nu +++ /dev/null @@ -1,173 +0,0 @@ -# Environment variables - -# Guard: reset PWD to $HOME if inherited value is not an absolute path. -# if not ($env.PWD | str starts-with "/") { -# $env.PWD = $env.HOME -# } - -# ── PATH ──────────────────────────────────────────────────────────────────── -$env.PATH = ( - $env.PATH - | prepend ($env.HOME | path join ".local/bin") - | prepend ($env.HOME | path join ".local/share/mise/shims") - | prepend ($env.HOME | path join ".bun/bin") - | prepend "/opt/zerobrew/bin" - | prepend ($env.HOME | path join ".zerobrew/bin") - | prepend ($env.HOME | path join ".nix-profile/bin") - | prepend "/nix/var/nix/profiles/default/bin" - | prepend ($env.HOME | path join ".cargo/bin") - | prepend "/opt/homebrew/bin" - | prepend "/opt/homebrew/sbin" - | prepend "/opt/homebrew/opt/openjdk/bin" - | prepend "/opt/homebrew/share/google-cloud-sdk/bin" - | uniq -) - -# ── ENV_CONVERSIONS ────────────────────────────────────────────────────────── -# Teach nushell to handle colon-separated vars from external tools -$env.ENV_CONVERSIONS = { - PATH: { - from_string: { |s| $s | split row (char esep) | path expand -n } - to_string: { |v| $v | str join (char esep) } - } - XDG_DATA_DIRS: { - from_string: { |s| $s | split row (char esep) } - to_string: { |v| $v | str join (char esep) } - } -} - -# ── Core env ───────────────────────────────────────────────────────────────── -$env.SHLVL = 1 -$env.EDITOR = "vim" -$env.VISUAL = "zed --wait" -$env.BUN_INSTALL = ($env.HOME | path join ".bun") -$env.JAVA_HOME = "/opt/homebrew/opt/openjdk" -$env.RTK_HOOK_AUDIT = "1" - -# ── mise ───────────────────────────────────────────────────────────────────── -# Shims are on PATH above. Full activation (hooks, cd triggers) requires -# sourcing `mise activate nu` in config.nu — see settings.nu note. -$env.MISE_SHELL = "nu" - -# ── Secrets / SOPS ────────────────────────────────────────────────────────── -let age_key = ($env.HOME | path join ".config/sops/age/keys.txt") -# Populate keys.txt from 1Password if it's missing or contains only a placeholder -if (which op | is-not-empty) { - let needs_refresh = ( - not ($age_key | path exists) or - (open $age_key | str trim) == "AGE-SECRET-KEY-1TESTKEY" - ) - if $needs_refresh { - try { - op item get 6meypnchchq3tsb32mdnzxtlia --fields notesPlain - | str replace --all '"' '' - | lines - | where { |l| $l | str starts-with "AGE-SECRET-KEY" } - | str join "\n" - | save --force $age_key - } - } -} -if ($age_key | path exists) { - $env.SOPS_AGE_KEY_FILE = $age_key - $env.MISE_SOPS_AGE_KEY_FILE = $age_key -} - -# Bootstrap secrets (dotenv format, no op:// refs) -let bootstrap_secrets = ($env.HOME | path join ".config/dev-bootstrap/secrets.env") -if ($bootstrap_secrets | path exists) { - open $bootstrap_secrets - | lines - | where { |l| not ($l | str starts-with "#") and ($l | str trim | str length) > 0 } - | each { |l| $l | parse "{key}={value}" | first } - | each { |kv| load-env {($kv.key): $kv.value} } - | ignore -} - -# Cache dotenvx private key so nuenv .env.nu never re-prompts 1Password -if (which op | is-not-empty) and ($env.DOTENV_PRIVATE_KEY? | default "" | is-empty) { - try { - $env.DOTENV_PRIVATE_KEY = ( - op read "op://Personal/nihl7o2bojy53zy4aqtr7txyqi/password" - --account=my.1password.com - ) - } -} - -# ── Colima / Docker ────────────────────────────────────────────────────────── -let colima_dev_sock = ($env.HOME | path join ".colima/dev/docker.sock") -let colima_default_sock = ($env.HOME | path join ".config/colima/default/docker.sock") -if ($colima_dev_sock | path exists) { - $env.DOCKER_HOST = $"unix://($colima_dev_sock)" -} else if ($colima_default_sock | path exists) { - $env.DOCKER_HOST = $"unix://($colima_default_sock)" -} - -# ── Maestro ────────────────────────────────────────────────────────────────── -$env.MAESTRO_API_URL = "https://api.maestro-staging.toptal.net" -$env.MAESTRO_RESOURCE_PROFILE = "development" - - -# ── Homebrew ────────────────────────────────────────────────────────────────── -$env.HOMEBREW_PREFIX = "/opt/homebrew" -$env.HOMEBREW_CELLAR = "/opt/homebrew/Cellar" -$env.HOMEBREW_REPOSITORY = "/opt/homebrew" - -# ── Handon banner ──────────────────────────────────────────────────────────── -# Show top handoff items for current repo on shell start. -if (which handoff-detect | is-not-empty) { - let _result = (do { run-external "handoff-detect" $env.PWD } | complete) - if $_result.exit_code == 0 and ($_result.stdout | str trim | is-not-empty) { - print $"(ansi cyan)--- handoff ---" - print $_result.stdout - print (ansi reset) - } -} - -# ── SSH agent ──────────────────────────────────────────────────────────────── -# Prefer gpg-agent (YubiKey/OpenPGP), fall back to native macOS launchd agent. -$env.SSH_AUTH_SOCK = ( - [ - (^gpgconf --list-dirs agent-ssh-socket | str trim) - (glob "/var/run/com.apple.launchd.*/Listeners" | first | default "") - ] - | where { |it| $it | path exists } - | first - | default "" -) -$env.PATH = ($env.PATH | split row (char esep) | where { $in != "/Users/joe/Library/Application Support/carapace/bin" } | prepend "/Users/joe/Library/Application Support/carapace/bin") - -def --env get-env [name] { $env | get $name } -def --env set-env [name, value] { load-env { $name: $value } } -def --env unset-env [name] { hide-env $name } - -let carapace_completer = {|spans| - load-env { - CARAPACE_SHELL_BUILTINS: (help commands | where category != "" | get name | each { split row " " | first } | uniq | str join "\n") - CARAPACE_SHELL_FUNCTIONS: (help commands | where category == "" | get name | each { split row " " | first } | uniq | str join "\n") - } - - # if the current command is an alias, get it's expansion - let expanded_alias = (scope aliases | where name == $spans.0 | $in.0?.expansion?) - - # overwrite - let spans = (if $expanded_alias != null { - # put the first word of the expanded alias first in the span - $spans | skip 1 | prepend ($expanded_alias | split row " " | take 1) - } else { - $spans | skip 1 | prepend ($spans.0) - }) - - carapace $spans.0 nushell ...$spans - | from json -} - -mut current = (($env | default {} config).config | default {} completions) -$current.completions = ($current.completions | default {} external) -$current.completions.external = ($current.completions.external -| default true enable -# backwards compatible workaround for default, see nushell #15654 -| upsert completer { if $in == null { $carapace_completer } else { $in } }) - -$env.config = $current -