diff --git a/.chezmoiignore b/.chezmoiignore index f37c3c0..511fe30 100644 --- a/.chezmoiignore +++ b/.chezmoiignore @@ -23,3 +23,8 @@ Documents # pycache __pycache__/ *.pyc + +# k9s Victoria TUI build artifacts +.config/k9s/plugins/victoria-tui-bin +.config/k9s/plugins/victoria-tui-bin.* +.config/k9s/plugins/victoria-tui/victoria-tui diff --git a/dot_config/global_gitignore b/dot_config/global_gitignore index 28a816f..7a1f409 100644 --- a/dot_config/global_gitignore +++ b/dot_config/global_gitignore @@ -5,3 +5,5 @@ .playwright-mcp .sisyphus + +.envrc diff --git a/dot_config/private_fish/config.fish b/dot_config/private_fish/config.fish index af92543..3e4334e 100644 --- a/dot_config/private_fish/config.fish +++ b/dot_config/private_fish/config.fish @@ -11,6 +11,7 @@ end abbr -a .. 'cd ..' abbr -a cc "claude" abbr -a oc "jai -j opencode opencode" +abbr -a oca "jai -j opencode opencode --auto" abbr -a co "codex" abbr -a v "nvim" abbr -a z "zellij" diff --git a/dot_config/private_k9s/plugins/executable_loki-logcli b/dot_config/private_k9s/plugins/executable_loki-logcli deleted file mode 100755 index df0e362..0000000 --- a/dot_config/private_k9s/plugins/executable_loki-logcli +++ /dev/null @@ -1,335 +0,0 @@ -#!/bin/sh -set -eu - -usage() { - echo "usage: loki-logcli [selector args...] [helper flags...] [logcli args...]" >&2 - exit 2 -} - -context="${1:-}" -selector="${2:-}" -[ -n "$selector" ] || usage -shift 2 - -addr="http://localhost:3100" -format=false -pager=false -table=false -table_scope="query" - -case "$selector" in - --pod) - namespace="${1:-}" - pod="${2:-}" - [ -n "$namespace" ] && [ -n "$pod" ] || usage - shift 2 - query="{namespace=\"$namespace\",pod=\"$pod\"}" - table_scope="pod" - ;; - --app) - namespace="${1:-}" - app="${2:-}" - [ -n "$namespace" ] && [ -n "$app" ] || usage - shift 2 - query="{namespace=\"$namespace\",service_name=\"$app\"}" - table_scope="app" - ;; - *) - query="$selector" - ;; -esac - -while [ "$#" -gt 0 ]; do - case "$1" in - --k9s-format) format=true; shift ;; - --pager) pager=true; shift ;; - --table) table=true; shift ;; - *) break ;; - esac -done - -if [ "$table_scope" = "query" ]; then - case "$query" in - *'container="'*) table_scope="container" ;; - *'pod="'*) table_scope="pod" ;; - *'namespace="'*) table_scope="namespace" ;; - *'node_name="'*) table_scope="node" ;; - esac -fi - -if [ -n "${XDG_RUNTIME_DIR:-}" ] && [ -d "$XDG_RUNTIME_DIR" ]; then - runtime_dir="$XDG_RUNTIME_DIR" -elif [ -d /dev/shm ]; then - runtime_dir=/dev/shm -else - runtime_dir=/tmp -fi - -state_dir="$runtime_dir/k9s-loki-port-forward" -session_dir="$state_dir/sessions" -pid_file="$state_dir/pid" -janitor_pid_file="$state_dir/janitor.pid" -port_forward_log="$state_dir/kubectl.log" -tail_log="$state_dir/logcli-tail.log" -session_file="$session_dir/$$" - -mkdir -p "$session_dir" - -is_alive() { - [ -n "${1:-}" ] && kill -0 "$1" 2>/dev/null -} - -kill_tree() { - pid="${1:-}" - [ -n "$pid" ] || return 0 - - for child in $(pgrep -P "$pid" 2>/dev/null || true); do - kill_tree "$child" - done - - kill "$pid" 2>/dev/null || true -} - -is_loki_up() { - nc -z localhost 3100 >/dev/null 2>&1 -} - -k9s_running() { - pgrep -x k9s >/dev/null 2>&1 -} - -register_session() { - : >"$session_file" -} - -release_session() { - rm -f "$session_file" -} - -start_janitor() { - k9s_running || return 0 - - if [ -f "$janitor_pid_file" ]; then - janitor_pid="$(cat "$janitor_pid_file" 2>/dev/null || true)" - is_alive "$janitor_pid" && return 0 - fi - - ( - while :; do - if ! pgrep -x k9s >/dev/null 2>&1; then - if [ -f "$pid_file" ]; then - pid="$(cat "$pid_file" 2>/dev/null || true)" - is_alive "$pid" && kill "$pid" 2>/dev/null || true - rm -f "$pid_file" - fi - rm -f "$janitor_pid_file" - exit 0 - fi - sleep 5 - done - ) >/dev/null 2>&1 & - printf '%s\n' "$!" >"$janitor_pid_file" -} - -start_port_forward() { - if [ -f "$pid_file" ]; then - pid="$(cat "$pid_file" 2>/dev/null || true)" - if is_alive "$pid" && is_loki_up; then - return 0 - fi - fi - - is_loki_up && return 0 - - : >"$port_forward_log" - if [ -n "$context" ]; then - kubectl --context "$context" port-forward -n loki svc/loki 3100:3100 --address localhost >>"$port_forward_log" 2>&1 & - else - kubectl port-forward -n loki svc/loki 3100:3100 --address localhost >>"$port_forward_log" 2>&1 & - fi - - pf_pid="$!" - printf '%s\n' "$pf_pid" >"$pid_file" - - i=0 - while [ "$i" -lt 50 ]; do - is_loki_up && return 0 - if ! is_alive "$pf_pid"; then - cat "$port_forward_log" >&2 - exit 1 - fi - i=$((i + 1)) - sleep 0.1 - done - - cat "$port_forward_log" >&2 - exit 1 -} - -logcli_json() { - logcli query "$query" --addr "$addr" -o jsonl --include-common-labels "$@" -} - -format_logs() { - jq --unbuffered -r --arg color "${1:-true}" ' - def c($level): - if $color != "true" then "" - elif ["error", "fatal", "panic"] | index($level) then "\u001b[31m" - elif ["warn", "warning"] | index($level) then "\u001b[33m" - elif $level == "info" then "\u001b[36m" - elif ["debug", "trace"] | index($level) then "\u001b[90m" - else "\u001b[35m" - end; - def reset: if $color == "true" then "\u001b[0m" else "" end; - def app: (.line | fromjson?); - def message($app; $line): - if $app.message then - [ - $app.message, - $app.method, - $app.path, - (if $app.status != null then ($app.status | tostring) else empty end), - (if $app.duration_ms then (($app.duration_ms | tostring) + "ms") else empty end) - ] | map(select(. != null and . != "")) | join(" ") - else - $line - end; - . as $entry - | (app // {}) as $app - | (($app.level // .labels.level // .labels.detected_level // "unknown") | ascii_downcase) as $level - | (.timestamp[11:19] // "--:--:--") as $time - | (.labels.namespace // "-") as $namespace - | (.labels.pod // "-") as $pod - | (.labels.container // .labels.service_name // "-") as $container - | message($app; $entry.line) as $message - | "\($time) \(c($level))\($level | ascii_upcase)\(reset) \($namespace)/\($pod) \($container) \($message)" - ' -} - -format_table() { - jq --unbuffered -r --arg scope "$table_scope" ' - def app: (.line | fromjson?); - def clean: tostring | gsub("[|\t\r\n]"; " "); - def message($app; $line): - if $app.message then - [ - $app.message, - $app.method, - $app.path, - (if $app.status != null then ($app.status | tostring) else empty end), - (if $app.duration_ms then (($app.duration_ms | tostring) + "ms") else empty end) - ] | map(select(. != null and . != "")) | join(" ") - else - $line - end; - . as $entry - | (app // {}) as $app - | (($app.level // .labels.level // .labels.detected_level // "unknown") | ascii_upcase) as $level - | (.timestamp[11:19] // "--:--:--") as $time - | (.labels.namespace // "-") as $namespace - | (.labels.pod // "-") as $pod - | (.labels.container // .labels.service_name // "-") as $container - | message($app; $entry.line) as $message - | if $scope == "container" then - [$time, $level, $message] - elif $scope == "pod" then - [$time, $level, $container, $message] - elif $scope == "app" or $scope == "namespace" then - [$time, $level, $pod, $container, $message] - else - [$time, $level, $namespace, $pod, $container, $message] - end - | map(clean) - | join(" | ") - ' -} - -table_header() { - case "$table_scope" in - container) printf 'time | level | message\n' ;; - pod) printf 'time | level | container | message\n' ;; - app|namespace) printf 'time | level | pod | container | message\n' ;; - *) printf 'time | level | namespace | pod | container | message\n' ;; - esac -} - -preload_file() { - file="$1" - if [ "$table" = true ]; then - table_header >"$file" - logcli_json --quiet --limit 500 --since=24h | format_table >>"$file" - else - logcli_json --quiet --limit 500 --since=24h | format_logs false >"$file" - fi -} - -start_live_writer() { - file="$1" - shift - : >"$tail_log" - - if [ "$table" = true ]; then - (sleep 0.2; logcli_json "$@" 2>>"$tail_log" | format_table >>"$file") 2>>"$tail_log" & - else - (sleep 0.2; logcli_json "$@" 2>>"$tail_log" | format_logs false >>"$file") 2>>"$tail_log" & - fi - producer_pid="$!" -} - -run_ov() { - file="$1" - - if [ "$table" = true ]; then - ov --follow-mode --align --column-mode --column-rainbow --column-delimiter '|' --header 1 --multi-color 'ERROR,FATAL,PANIC,WARN,WARNING,INFO,DEBUG,TRACE,UNKNOWN' "$file" - else - ov --follow-mode --multi-color 'ERROR,FATAL,PANIC,WARN,WARNING,INFO,DEBUG,TRACE,UNKNOWN' "$file" - fi -} - -run_pager() { - if command -v ov >/dev/null 2>&1; then - tmp_file="$state_dir/logs.$$" - producer_pid="" - - cleanup_pager() { - if [ -n "${producer_pid:-}" ]; then - kill_tree "$producer_pid" - wait "$producer_pid" 2>/dev/null || true - fi - rm -f "$tmp_file" - } - - rm -f "$tmp_file" - trap 'cleanup_pager; release_session' EXIT INT TERM - preload_file "$tmp_file" - start_live_writer "$tmp_file" "$@" - run_ov "$tmp_file" - cleanup_pager - elif command -v less >/dev/null 2>&1; then - logcli_json "$@" | format_logs true | less -R +F - else - logcli_json "$@" | format_logs false | more - fi -} - -run_formatted() { - if [ "$pager" = true ]; then - run_pager "$@" - elif [ "$table" = true ]; then - table_header - logcli_json "$@" | format_table - else - logcli_json "$@" | format_logs true - fi -} - -register_session -trap release_session EXIT INT TERM -start_port_forward -start_janitor - -if [ "$format" = true ]; then - run_formatted "$@" -else - exec logcli query "$query" --addr "$addr" "$@" -fi diff --git a/dot_config/private_k9s/plugins/log-loki.yaml b/dot_config/private_k9s/plugins/log-loki.yaml deleted file mode 100644 index bad2f1e..0000000 --- a/dot_config/private_k9s/plugins/log-loki.yaml +++ /dev/null @@ -1,304 +0,0 @@ -plugins: - # Starts a local Loki port-forward on first use, then queries it with logcli. - loki-container: - shortCut: Shift-L - description: "loki fmt" - scopes: - - containers - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - '{namespace="$NAMESPACE",pod="$POD",container="$NAME"}' - - --k9s-format - - --pager - - --quiet - - --limit - - "500" - - -f - loki-container-raw: - shortCut: Ctrl-E - description: "loki raw" - scopes: - - containers - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - '{namespace="$NAMESPACE",pod="$POD",container="$NAME"}' - - --quiet - - --limit - - "500" - - -f - - -o - - raw - loki-container-table: - shortCut: k - description: "loki table" - scopes: - - containers - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - '{namespace="$NAMESPACE",pod="$POD",container="$NAME"}' - - --k9s-format - - --pager - - --table - - --quiet - - --limit - - "500" - - -f - loki-pods: - shortCut: Shift-L - description: "loki fmt" - scopes: - - po - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - --pod - - $NAMESPACE - - $NAME - - --k9s-format - - --pager - - --quiet - - --limit - - "500" - - -f - loki-pods-raw: - shortCut: Ctrl-L - description: "loki raw" - scopes: - - po - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - --pod - - $NAMESPACE - - $NAME - - --quiet - - --limit - - "500" - - -f - - -o - - raw - loki-pods-table: - shortCut: k - description: "loki table" - scopes: - - po - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - --pod - - $NAMESPACE - - $NAME - - --k9s-format - - --pager - - --table - - --quiet - - --limit - - "500" - - -f - loki-deployments: - shortCut: Shift-L - description: "loki fmt" - scopes: - - deployments - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - --app - - $NAMESPACE - - $NAME - - --k9s-format - - --pager - - --quiet - - --limit - - "500" - - -f - loki-deployments-raw: - shortCut: Ctrl-L - description: "loki raw" - scopes: - - deployments - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - --app - - $NAMESPACE - - $NAME - - --quiet - - --limit - - "500" - - -f - - -o - - raw - loki-deployments-table: - shortCut: k - description: "loki table" - scopes: - - deployments - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - --app - - $NAMESPACE - - $NAME - - --k9s-format - - --pager - - --table - - --quiet - - --limit - - "500" - - -f - loki-node: - shortCut: Shift-L - description: "loki fmt" - scopes: - - node - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - '{node_name="$NAME"}' - - --k9s-format - - --pager - - --quiet - - --limit - - "500" - - -f - loki-node-raw: - shortCut: Ctrl-L - description: "loki raw" - scopes: - - node - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - '{node_name="$NAME"}' - - --quiet - - --limit - - "500" - - -f - - -o - - raw - loki-node-table: - shortCut: k - description: "loki table" - scopes: - - node - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - '{node_name="$NAME"}' - - --k9s-format - - --pager - - --table - - --quiet - - --limit - - "500" - - -f - loki-ns: - shortCut: Shift-L - description: "loki fmt" - scopes: - - namespace - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - '{namespace="$NAME"}' - - --k9s-format - - --pager - - --quiet - - --limit - - "500" - - -f - loki-ns-raw: - shortCut: Ctrl-L - description: "loki raw" - scopes: - - namespace - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - '{namespace="$NAME"}' - - --quiet - - --limit - - "500" - - -f - - -o - - raw - loki-ns-table: - shortCut: k - description: "loki table" - scopes: - - namespace - command: sh - background: false - args: - - -c - - exec "${XDG_CONFIG_HOME:-$HOME/.config}/k9s/plugins/loki-logcli" "$@" - - -- - - $CONTEXT - - '{namespace="$NAME"}' - - --k9s-format - - --pager - - --table - - --quiet - - --limit - - "500" - - -f