From ff0decc1e47e34b6ce77402adca27b1a13b6710f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Wed, 12 Aug 2026 09:37:23 +0200 Subject: [PATCH 01/16] feat(codex): manage complete user config - sync all non-project settings through managed block - update model, tui, plugin, hook trust, and migration state - remove unsupported rtk pre-tool hook and stale guidance --- ai-stuff/codex/README.md | 13 ++++---- ai-stuff/codex/RTK.md | 5 ---- ai-stuff/codex/config.managed.toml | 43 +++++++++++++++++++++++---- ai-stuff/codex/hooks.json | 12 -------- ai-stuff/codex/scripts/sync-config.sh | 15 +++++----- 5 files changed, 50 insertions(+), 38 deletions(-) diff --git a/ai-stuff/codex/README.md b/ai-stuff/codex/README.md index 218cf3aa..54831c25 100644 --- a/ai-stuff/codex/README.md +++ b/ai-stuff/codex/README.md @@ -14,16 +14,16 @@ skills arrive via ai.mk's `agents` pseudo-tool (`~/.agents/skills`), which ## config.toml -`~/.codex/config.toml` is mostly machine state (project trust levels, -`hooks.state` trusted hashes, caches) and cannot be symlinked wholesale. -Instead, [`config.managed.toml`](config.managed.toml) holds the versionable -prefs (model, reasoning effort) and +`~/.codex/config.toml` contains machine-local project trust levels and cannot +be symlinked wholesale. Instead, +[`config.managed.toml`](config.managed.toml) holds all non-project settings and +state, and [`scripts/sync-config.sh`](scripts/sync-config.sh) idempotently rewrites a marker-delimited block at the top of the file (`make codex` runs it). -Everything outside the markers is machine-local and untouched. +Project tables outside the markers are machine-local and untouched. Hooks are enabled by default in current Codex; disable with -`[features] hooks = false` (documented in the managed block). +`[features] hooks = false`. ## Hooks @@ -38,7 +38,6 @@ Converted from the Claude Code setup: | --- | --- | --- | | SessionStart | caveman-mode context echo | migrated from hand-made `~/.codex/hooks.json` | | SessionStart | git worktree context echo | same command as Claude's | -| PreToolUse | `rtk hook claude` | rtk has no `codex` processor yet; its `claude` processor rewrites commands without granting permission. ⚠ Unverified whether Codex applies `updatedInput` mutations like Claude does — check `rtk gain` after a few Codex sessions; flat counters mean the rewrite silently no-ops | | PostToolUse (`apply_patch\|Edit\|Write`) | nvim `checktime` | refresh open buffers | | Stop | `notify-stop.sh` | terminal-notifier + click-to-focus iTerm | diff --git a/ai-stuff/codex/RTK.md b/ai-stuff/codex/RTK.md index 973e5e0d..7ae285e1 100644 --- a/ai-stuff/codex/RTK.md +++ b/ai-stuff/codex/RTK.md @@ -15,11 +15,6 @@ rtk npm run build rtk pytest -q ``` -A PreToolUse hook (`rtk hook claude` in `~/.codex/hooks.json`) also attempts -to rewrite unprefixed commands, but whether Codex applies `updatedInput` -mutations is unverified — the manual prefix rule above is the reliable path -(this matches `rtk init -g --codex`'s own instructions-only approach). - ## Meta Commands ```bash diff --git a/ai-stuff/codex/config.managed.toml b/ai-stuff/codex/config.managed.toml index 95429ceb..183ce5cb 100644 --- a/ai-stuff/codex/config.managed.toml +++ b/ai-stuff/codex/config.managed.toml @@ -1,7 +1,38 @@ -model = "gpt-5.4-mini" -model_reasoning_effort = "low" +model = "gpt-5.6-sol" +model_reasoning_effort = "high" +service_tier = "default" -# Hooks (~/.codex/hooks.json) are enabled by default in current Codex. -# To disable, uncomment: -# [features] -# hooks = false +[tui] +vim_mode_default = true +status_line = ["model-with-reasoning", "current-dir", "git-branch", "context-remaining", "context-used", "five-hour-limit", "weekly-limit"] +status_line_use_colors = true +pet = "fireball" + +[mcp_servers] + +[plugins."atlassian-rovo@openai-curated"] +enabled = true + +[tui.model_availability_nux] +"gpt-5.5" = 4 + +[hooks.state] + +[hooks.state."/Users/denizgokcin/.codex/hooks.json:session_start:0:0"] +trusted_hash = "sha256:0ed786805542f7114c30eda6945e72a2f1285c06fd6d4320de621a9549c095ed" + +[hooks.state."/Users/denizgokcin/.codex/hooks.json:permission_request:0:0"] +trusted_hash = "sha256:3edef66d977c01b02c741ef44307a0b3e66fee85aa11e802deab1bb871ba6041" + +[hooks.state."/Users/denizgokcin/.codex/hooks.json:post_tool_use:0:0"] +trusted_hash = "sha256:c56424322e17fd654a4c1e93b61f6529c420ecd40f3ee9cc0ae3fd3b7b9c6353" + +[hooks.state."/Users/denizgokcin/.codex/hooks.json:session_start:0:1"] +trusted_hash = "sha256:167ff2b32ddd73315d8846a7b8c09462b039251374f878321d72fca941bb3587" + +[hooks.state."/Users/denizgokcin/.codex/hooks.json:stop:0:0"] +trusted_hash = "sha256:0a3971c2697e522540874c3dd1a79802fe7482405e8960f960a83b8bc866dbf9" + +[notice.model_migrations] +"gpt-5.4-mini" = "gpt-5.6-luna" +"gpt-5.4" = "gpt-5.6-terra" diff --git a/ai-stuff/codex/hooks.json b/ai-stuff/codex/hooks.json index 33d3d304..1a9ae033 100644 --- a/ai-stuff/codex/hooks.json +++ b/ai-stuff/codex/hooks.json @@ -19,18 +19,6 @@ ] } ], - "PreToolUse": [ - { - "hooks": [ - { - "type": "command", - "command": "rtk hook claude", - "timeout": 10, - "statusMessage": "rtk token-optimizer rewrite" - } - ] - } - ], "PostToolUse": [ { "matcher": "apply_patch|Edit|Write", diff --git a/ai-stuff/codex/scripts/sync-config.sh b/ai-stuff/codex/scripts/sync-config.sh index adfe9d41..a7936707 100755 --- a/ai-stuff/codex/scripts/sync-config.sh +++ b/ai-stuff/codex/scripts/sync-config.sh @@ -1,8 +1,7 @@ #!/usr/bin/env bash # Sync the dotfiles-managed block of ~/.codex/config.toml from # config.managed.toml. Only the block between the markers is owned by -# dotfiles; everything else (project trust levels, hooks.state trusted -# hashes, caches) is machine state and left untouched. +# dotfiles; project trust levels stay machine-local and are left untouched. # # The block is prepended because TOML requires top-level keys to appear # before the first table header. @@ -20,12 +19,12 @@ tmp=$(mktemp) # Drop the previous managed block. awk -v b="$BEGIN" -v e="$END" '$0==b{skip=1} !skip; $0==e{skip=0}' "$DST" > "$tmp" -# Drop bare duplicates (outside any table) of top-level keys the block owns, -# so the merged file has no duplicate TOML keys. -managed_keys=$(grep -oE '^[a-zA-Z_]+' "$SRC" | sort -u) -for k in $managed_keys; do - awk -v key="$k" '/^\[/{intable=1} !(intable!=1 && $0 ~ "^"key" *=")' "$tmp" > "$tmp.2" && mv "$tmp.2" "$tmp" -done +# Keep only machine-local project tables outside the managed block. This also +# removes stale generated state for hooks that no longer exist. +awk ' + /^\[/ { keep = ($0 ~ /^\[projects\./) } + keep { print } +' "$tmp" > "$tmp.2" && mv "$tmp.2" "$tmp" { echo "$BEGIN"; cat "$SRC"; echo "$END"; echo; cat "$tmp"; } > "$DST" rm -f "$tmp" From e7a2ed393e2f89ed456a7b7225590b635e068398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Wed, 12 Aug 2026 12:29:55 +0200 Subject: [PATCH 02/16] chore(settings): enable sendmessage and switch to fable model - add sendmessage to global permission allowlist - update model from sonnet to claude-fable-5 --- ai-stuff/claude/settings.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ai-stuff/claude/settings.json b/ai-stuff/claude/settings.json index c100b398..03b7ba36 100644 --- a/ai-stuff/claude/settings.json +++ b/ai-stuff/claude/settings.json @@ -53,14 +53,15 @@ "Bash(rtk head:*)", "Bash(rtk ls:*)", "Bash(rtk grep:*)", - "Bash(rtk read:*)" + "Bash(rtk read:*)", + "SendMessage" ], "ask": [ "Edit(~/vault/personal/nl/house search/buying a house/**)" ], "defaultMode": "auto" }, - "model": "sonnet", + "model": "claude-fable-5[1m]", "enableAllProjectMcpServers": false, "skillOverrides": { "commit": "off", From 83371715257c5fe7abda3d3a481b93f63f7b62a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Mon, 24 Aug 2026 22:06:31 +0200 Subject: [PATCH 03/16] docs(.gitignore): update traefik migration notes - traefik-dev, traefik-recon, and traefik skill moved to k8s-gitops-platform-apps on 2026-08-12 - only personal obsidian layer (traefik-epic.md, traefik-vault.md) remains in dotfiles --- .gitignore | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 40684826..fc6a4471 100644 --- a/.gitignore +++ b/.gitignore @@ -25,9 +25,7 @@ ai-stuff/_shared/config/.clusters.json ai-stuff/claude/skills/add-recipe/*.original* ai-stuff/claude/skills/**/SKILL.original.md -# Private work-specific traefik migration agents/skills/config +# Private work-specific traefik migration config. The skill, traefik-dev and traefik-recon moved into +# k8s-gitops-platform-apps on 2026-08-12; only the personal Obsidian layer stays here. ai-stuff/_shared/config/traefik-epic.md -ai-stuff/agents/traefik-dev.md -ai-stuff/agents/traefik-recon.md ai-stuff/agents/traefik-vault.md -ai-stuff/skills/traefik/ From 1b983b77406820a30e27faa94274d2da7c8845e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Mon, 24 Aug 2026 22:06:35 +0200 Subject: [PATCH 04/16] feat(codex): add codex-backed models support to statusline - detect routed models via clodex endpoint or config.json alias lookup - query chatgpt backend rate limits instead of anthropic quota - cache limit data for 60s to match codex cli polling cadence - compute api-equivalent cost from transcript at openai pricing rates - derive window labels (5h/weekly/etc) from limit window minutes --- ai-stuff/claude/scripts/statusline.sh | 266 +++++++++++++++++++++++++- 1 file changed, 263 insertions(+), 3 deletions(-) diff --git a/ai-stuff/claude/scripts/statusline.sh b/ai-stuff/claude/scripts/statusline.sh index 30e7e77f..998b1d77 100755 --- a/ai-stuff/claude/scripts/statusline.sh +++ b/ai-stuff/claude/scripts/statusline.sh @@ -159,6 +159,213 @@ if [ -n "$five_hour_pct_raw" ]; then seven_day_reset=$(format_reset_time_epoch "$seven_day_reset_epoch" "datetime") fi +# Codex-backed models — Claude Code as the interface, the ChatGPT/Codex backend +# behind it via the clodex proxy. The limits Claude Code puts on stdin describe +# the Anthropic account, i.e. the wrong quota, so for these models query the +# ChatGPT backend's own usage endpoint (the same one the codex CLI polls). +# +# Detection is registry-driven, not name-driven: a routed model arrives either +# as clodex:: (endpoint mode) or as a bare alias like "sol" +# (patched binary — the alias IS the model id). Resolve the alias through +# ~/.clodex/config.json, then only treat it as ChatGPT-quota if the provider is +# an OAuth provider pointed at OpenAI. New models/aliases need no script edits. +model_id=$(echo "$input" | jq -r '.model.id // empty') +clodex_home="${CLODEX_HOME:-$HOME/.clodex}" +is_codex_model=0 +clodex_provider="" +case "$model_id" in +clodex:*:*) + clodex_provider=$(printf '%s' "$model_id" | cut -d: -f2) + ;; +?*) + if [ -f "$clodex_home/config.json" ]; then + clodex_provider=$(jq -r --arg a "$model_id" \ + '[.modelAliases[]? | select(.name == $a) | .providerId] | first // empty' \ + "$clodex_home/config.json" 2>/dev/null) + fi + ;; +esac +if [ -n "$clodex_provider" ] && [ -f "$clodex_home/providers.json" ]; then + if jq -e --arg p "$clodex_provider" \ + '[.providers[]? | select(.id == $p and .authType == "oauth") + | (.api.url // "") | test("openai")] | first == true' \ + "$clodex_home/providers.json" >/dev/null 2>&1; then + is_codex_model=1 + fi +fi + +file_mtime() { + stat -f %m "$1" 2>/dev/null || stat -c %Y "$1" 2>/dev/null +} + +# Codex reports each limit as a rolling window in minutes; name the two we know +# to match the labels used for Anthropic limits, derive the rest. +codex_window_label() { + local mins=$1 + case "$mins" in + 10080) echo "weekly" ;; + 300) echo "5h" ;; + '' | *[!0-9]*) echo "limit" ;; + *) + if [ "$mins" -ge 1440 ] && [ $((mins % 1440)) -eq 0 ]; then + echo "$((mins / 1440))d" + elif [ "$mins" -ge 60 ]; then + echo "$((mins / 60))h" + else + echo "${mins}m" + fi + ;; + esac +} + +format_age() { + local secs=$1 + [ "$secs" -lt 0 ] 2>/dev/null && secs=0 + if [ "$secs" -lt 60 ]; then + echo "${secs}s ago" + elif [ "$secs" -lt 3600 ]; then + echo "$((secs / 60))m ago" + elif [ "$secs" -lt 86400 ]; then + echo "$((secs / 3600))h ago" + else + echo "$((secs / 86400))d ago" + fi +} + +codex_pct_primary="" +codex_label_primary="" +codex_reset_primary="" +codex_pct_secondary="" +codex_label_secondary="" +codex_reset_secondary="" +codex_as_of="" + +# "$1=used_percent $2=window_minutes $3=resets_at" -> "pctlabelreset". +# Absent fields arrive as "-" (see the @tsv projection below). +codex_window_fields() { + local pct=$1 win=$2 reset=$3 style="time" reset_fmt="" + [ "$pct" = "-" ] && return 1 + pct=$(printf '%s' "$pct" | awk '{printf "%d", int($1 + 0.5)}') + [ "$win" = "-" ] && win="" + # Windows of a day or more reset far enough out that the date matters. + if [ -n "$win" ] && [ "$win" -ge 1440 ] 2>/dev/null; then style="datetime"; fi + [ "$reset" != "-" ] && reset_fmt=$(format_reset_time_epoch "$reset" "$style") + printf '%s\t%s\t%s' "$pct" "$(codex_window_label "$win")" "$reset_fmt" +} + +if [ "$is_codex_model" = 1 ]; then + codex_auth="${CODEX_HOME:-$HOME/.codex}/auth.json" + codex_cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/claude-statusline" + codex_cache="$codex_cache_dir/codex-rate-limits" + + # Live quota from the ChatGPT backend, reusing the codex CLI's token. The + # codex CLI itself polls this endpoint once a minute, so mirror that cadence: + # memoise for 60s. Cache holds two lines: the fetch epoch, then the tsv + # projection. On fetch failure the last good reading survives and the "as of" + # stamp below surfaces its age. + codex_cache_age=99999 + if [ -f "$codex_cache" ]; then + codex_cache_mtime=$(file_mtime "$codex_cache") + [ -n "$codex_cache_mtime" ] && codex_cache_age=$(($(date +%s) - codex_cache_mtime)) + fi + + if [ "$codex_cache_age" -gt 60 ] && [ -f "$codex_auth" ]; then + codex_token=$(jq -r '.tokens.access_token // empty' "$codex_auth" 2>/dev/null) + codex_acct=$(jq -r '.tokens.account_id // empty' "$codex_auth" 2>/dev/null) + codex_payload="" + if [ -n "$codex_token" ] && [ -n "$codex_acct" ]; then + # Windows come back in seconds; project to minutes so codex_window_label + # and the cache format stay unchanged. secondary_window may be null + # (team plans expose only the weekly window). + codex_payload=$(curl -s --max-time 2 \ + -H "Authorization: Bearer $codex_token" \ + -H "chatgpt-account-id: $codex_acct" \ + "https://chatgpt.com/backend-api/wham/usage" 2>/dev/null | jq -r ' + .rate_limit + | select(.primary_window.used_percent != null) + | [.primary_window, .secondary_window] + | map(.used_percent, + (.limit_window_seconds | if . == null then null else . / 60 | floor end), + .reset_at) + | map(if . == null then "-" else tostring end) | @tsv' 2>/dev/null) + fi + if [ -n "$codex_payload" ] && mkdir -p "$codex_cache_dir" 2>/dev/null; then + printf '%s\n%s\n' "$(date +%s)" "$codex_payload" >"$codex_cache" 2>/dev/null + fi + fi + + if [ -f "$codex_cache" ]; then + codex_as_of=$(sed -n 1p "$codex_cache" 2>/dev/null) + # Live polling keeps readings ≤60s old; only stamp the age once fetches + # have been failing long enough to matter (stale token, offline). + if [ -n "$codex_as_of" ]; then + codex_data_age=$(($(date +%s) - codex_as_of)) + [ "$codex_data_age" -lt 300 ] 2>/dev/null && codex_as_of="" + fi + IFS=$'\t' read -r cx_p_pct cx_p_win cx_p_reset cx_s_pct cx_s_win cx_s_reset \ + < <(sed -n 2p "$codex_cache" 2>/dev/null) + + if codex_fields=$(codex_window_fields "${cx_p_pct:--}" "${cx_p_win:--}" "${cx_p_reset:--}"); then + IFS=$'\t' read -r codex_pct_primary codex_label_primary codex_reset_primary <<<"$codex_fields" + fi + if codex_fields=$(codex_window_fields "${cx_s_pct:--}" "${cx_s_win:--}" "${cx_s_reset:--}"); then + IFS=$'\t' read -r codex_pct_secondary codex_label_secondary codex_reset_secondary <<<"$codex_fields" + fi + fi + + # API-equivalent cost. Claude Code's total_cost_usd prices routed models off + # its own Anthropic table — fiction for a ChatGPT-plan backend. Recompute + # from the transcript's real per-message token counts at OpenAI's published + # API rates (clodex's models.dev pricing cache). The plan itself is + # flat-rate, so this is "what the session would cost via API key". + transcript_path=$(echo "$input" | jq -r '.transcript_path // empty') + session_id=$(echo "$input" | jq -r '.session_id // "nosession"') + codex_cost="" + codex_cost_cache="$codex_cache_dir/codex-cost-$session_id" + codex_cost_age=99999 + if [ -f "$codex_cost_cache" ]; then + codex_cost_mtime=$(file_mtime "$codex_cost_cache") + [ -n "$codex_cost_mtime" ] && codex_cost_age=$(($(date +%s) - codex_cost_mtime)) + fi + if [ "$codex_cost_age" -gt 15 ] && [ -f "$transcript_path" ]; then + # Resolve the routed alias to the upstream model id the pricing data knows. + case "$model_id" in + clodex:*:*) codex_upstream=${model_id#clodex:*:} ;; + *) codex_upstream=$(jq -r --arg a "$model_id" \ + '[.modelAliases[]? | select(.name == $a) | .modelId] | first // empty' \ + "$clodex_home/config.json" 2>/dev/null) ;; + esac + codex_prices="" + if [ -n "$codex_upstream" ] && [ -f "$clodex_home/pricing-cache.json" ]; then + codex_prices=$(jq -r --arg m "$codex_upstream" ' + [.models[] | select(.model_id == $m)] | first + | [.pricing[]? | select(.platform == "openai" and .tier == "standard" + and ((.notes // "") | test("long") | not))] | first + | select(.input_per_1m_tokens != null) + | [.input_per_1m_tokens, .cached_input_per_1m_tokens // 0, .output_per_1m_tokens // 0] + | @tsv' "$clodex_home/pricing-cache.json" 2>/dev/null) + fi + if [ -n "$codex_prices" ]; then + IFS=$'\t' read -r cx_price_in cx_price_cached cx_price_out <<<"$codex_prices" + # fromjson? tolerates the half-written last line of a live transcript. + # Cache writes are billed at the plain input rate (OpenAI has no + # separate write price); cache reads at the cached-input rate. + codex_cost_val=$(jq -R -n --arg m "$model_id" \ + --arg pin "$cx_price_in" --arg pcached "$cx_price_cached" --arg pout "$cx_price_out" ' + [inputs | fromjson? | .message? | select(.model == $m) | .usage // empty] as $u + | ( (($u | map(.input_tokens // 0) | add // 0) + + ($u | map(.cache_creation_input_tokens // 0) | add // 0)) * ($pin | tonumber) + + ($u | map(.cache_read_input_tokens // 0) | add // 0) * ($pcached | tonumber) + + ($u | map(.output_tokens // 0) | add // 0) * ($pout | tonumber) ) / 1e6' \ + <"$transcript_path" 2>/dev/null) + if [ -n "$codex_cost_val" ] && mkdir -p "$codex_cache_dir" 2>/dev/null; then + printf '%s\n' "$codex_cost_val" >"$codex_cost_cache" 2>/dev/null + fi + fi + fi + [ -f "$codex_cost_cache" ] && codex_cost=$(head -1 "$codex_cost_cache" 2>/dev/null) +fi + # Format cost as $X.XXXX (4 decimal places), dropping trailing zeros after 2 format_cost() { local raw=$1 @@ -172,6 +379,17 @@ format_cost() { cost_fmt=$(format_cost "$cost_usd") +# For codex-backed models replace Claude Code's Anthropic-priced figure with +# the API-equivalent estimate; if that couldn't be computed, show nothing +# rather than a made-up number. +if [ "$is_codex_model" = 1 ]; then + if [ -n "$codex_cost" ]; then + cost_fmt="~$(format_cost "$codex_cost") api" + else + cost_fmt="" + fi +fi + SEP=" ${C_DIM}|${C_RESET} " # ===== OUTPUT ===== @@ -288,8 +506,51 @@ fi printf "%b" "$SEP" printf "effort: %b%s%b" "$effort_color" "$effort_disp" "$C_RESET" -# Line 2: Current (5h) bar | Weekly (7d) bar -if [ -n "$five_hour_pct_raw" ]; then +# Line 2: usage bars | Line 3: reset times. +# Codex-backed models poll the ChatGPT usage endpoint (see above); everything +# else uses the rate limits Claude Code puts on stdin. +if [ "$is_codex_model" = 1 ]; then + if [ -n "$codex_pct_primary" ] || [ -n "$codex_pct_secondary" ]; then + printf "\n" + printf "%bcodex%b" "$C_ORANGE" "$C_RESET" + if [ -n "$codex_pct_primary" ]; then + printf " %b%s:%b " "$C_WHITE" "$codex_label_primary" "$C_RESET" + build_bar "$codex_pct_primary" 10 + printf " %b%s%%%b" "$C_CYAN" "$codex_pct_primary" "$C_RESET" + fi + if [ -n "$codex_pct_secondary" ]; then + printf "%b" "$SEP" + printf "%b%s:%b " "$C_WHITE" "$codex_label_secondary" "$C_RESET" + build_bar "$codex_pct_secondary" 10 + printf " %b%s%%%b" "$C_CYAN" "$codex_pct_secondary" "$C_RESET" + fi + + if [ -n "$codex_reset_primary" ] || [ -n "$codex_reset_secondary" ] || [ -n "$codex_as_of" ]; then + printf "\n" + printf "%bresets:%b" "$C_WHITE" "$C_RESET" + reset_sep=" " + if [ -n "$codex_reset_primary" ]; then + printf " %s @ %s" "$codex_label_primary" "$codex_reset_primary" + reset_sep="$SEP" + fi + if [ -n "$codex_reset_secondary" ]; then + printf "%b%s @ %s" "$reset_sep" "$codex_label_secondary" "$codex_reset_secondary" + fi + if [ -n "$codex_as_of" ]; then + # Only set when fetches have been failing >5m (stale token, offline). + codex_age=$(($(date +%s) - codex_as_of)) + age_color="$C_DIM" + [ "$codex_age" -ge 7200 ] && age_color="$C_YELLOW" + printf "%b" "$SEP" + printf "%bas of %s%b" "$age_color" "$(format_age "$codex_age")" "$C_RESET" + fi + fi + else + printf "\n" + printf "%bcodex:%b %bno limit data — check %s%b" \ + "$C_ORANGE" "$C_RESET" "$C_DIM" "${CODEX_HOME:-~/.codex}/auth.json" "$C_RESET" + fi +elif [ -n "$five_hour_pct_raw" ]; then printf "\n" printf "%bcurrent:%b " "$C_WHITE" "$C_RESET" build_bar "$five_hour_pct" 10 @@ -299,7 +560,6 @@ if [ -n "$five_hour_pct_raw" ]; then build_bar "$seven_day_pct" 10 printf " %b%s%%%b" "$C_CYAN" "$seven_day_pct" "$C_RESET" - # Line 3: Reset times printf "\n" printf "%bresets:%b 5h @ %s" "$C_WHITE" "$C_RESET" "$five_hour_reset" printf "%b" "$SEP" From 88f17740ffd889da125c9fb96ba549440e1acd6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Mon, 24 Aug 2026 22:06:39 +0200 Subject: [PATCH 05/16] chore(models): switch to sol model (gpt-5.6) - claude code: set model to 'sol' (chatgpt-backed via codex) - codex config: update model from gpt-5.4 to gpt-5.6-sol - sol model receives medium effort level per modelSettings --- ai-stuff/claude/settings.json | 21 +++++++++++++++------ ai-stuff/codex/config.managed.toml | 3 +++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ai-stuff/claude/settings.json b/ai-stuff/claude/settings.json index 03b7ba36..06d334b9 100644 --- a/ai-stuff/claude/settings.json +++ b/ai-stuff/claude/settings.json @@ -61,7 +61,7 @@ ], "defaultMode": "auto" }, - "model": "claude-fable-5[1m]", + "model": "sol", "enableAllProjectMcpServers": false, "skillOverrides": { "commit": "off", @@ -187,6 +187,8 @@ "worktree": { "baseRef": "fresh" }, + "enableArtifact": false, + "enableWorkflows": false, "statusLine": { "type": "command", "command": "~/.claude/scripts/statusline.sh" @@ -198,11 +200,11 @@ "context7@claude-plugins-official": false, "ralph-loop@claude-plugins-official": false, "feature-dev@claude-plugins-official": false, - "skill-creator@claude-plugins-official": true, + "skill-creator@claude-plugins-official": false, "caveman@caveman": false, - "plugin-dev@claude-plugins-official": true, + "plugin-dev@claude-plugins-official": false, "gitops@treatwell": true, - "session-handover@treatwell": true, + "session-handover@treatwell": false, "i-have-adhd@i-have-adhd": false, "ponytail@ponytail": false, "datadog@treatwell": true, @@ -249,8 +251,13 @@ } } }, - "outputStyle": "Terse", + "outputStyle": "Coincise", "effortLevel": "high", + "modelSettings": { + "sol": { + "effortLevel": "medium" + } + }, "promptSuggestionEnabled": false, "pluginConfigs": { "gitops@treatwell": { @@ -272,7 +279,9 @@ "skipWorkflowUsageWarning": true, "theme": "dark", "verbose": false, - "teammateMode": "auto", + "teammateMode": "iterm2", + "remoteControlAtStartup": false, + "agentPushNotifEnabled": true, "skipAutoPermissionPrompt": true, "voiceEnabled": true } diff --git a/ai-stuff/codex/config.managed.toml b/ai-stuff/codex/config.managed.toml index 183ce5cb..1a7ea0a6 100644 --- a/ai-stuff/codex/config.managed.toml +++ b/ai-stuff/codex/config.managed.toml @@ -1,6 +1,9 @@ model = "gpt-5.6-sol" +model_context_window = 1000000 +model_auto_compact_token_limit = 900000 model_reasoning_effort = "high" service_tier = "default" +approvals_reviewer = "auto_review" [tui] vim_mode_default = true From 24f3f9433904e65a79d5e36eb20007307627cf2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Mon, 24 Aug 2026 22:06:43 +0200 Subject: [PATCH 06/16] feat(nvim): enable claude-code plugin and add keybindings - set enabled = true for claudecode.nvim - terminal split right at 45% width - vertical diff layout, keep terminal focus - leader shortcuts: ac=toggle, af=focus, ar=resume, aK=continue, ab=add-buffer, as=send/add-file, aa=accept, ad=deny --- nvim/lua/plugins/claude-code.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nvim/lua/plugins/claude-code.lua b/nvim/lua/plugins/claude-code.lua index 206a7896..c038d7cb 100644 --- a/nvim/lua/plugins/claude-code.lua +++ b/nvim/lua/plugins/claude-code.lua @@ -18,7 +18,7 @@ return { { "ac", "ClaudeCode", desc = "Toggle Claude" }, { "af", "ClaudeCodeFocus", desc = "Focus Claude" }, { "ar", "ClaudeCode --resume", desc = "Resume Claude" }, - { "aC", "ClaudeCode --continue", desc = "Continue Claude" }, + { "aK", "ClaudeCode --continue", desc = "Continue Claude" }, { "ab", "ClaudeCodeAdd %", desc = "Add current buffer" }, { "as", "ClaudeCodeSend", mode = "v", desc = "Send to Claude" }, { From efe448f5b355e30b01c0093b964668a9228f0069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Mon, 24 Aug 2026 22:06:48 +0200 Subject: [PATCH 07/16] feat(skills): add slackify skill - rewrite content in deniz's slack voice - all lowercase (code/commands/acronyms verbatim) - direct, no preamble/fluff, fragments ok - lead with answer, root cause before fix - no em-dashes, inline links --- ai-stuff/skills/slackify/SKILL.md | 55 +++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 ai-stuff/skills/slackify/SKILL.md diff --git a/ai-stuff/skills/slackify/SKILL.md b/ai-stuff/skills/slackify/SKILL.md new file mode 100644 index 00000000..838239d9 --- /dev/null +++ b/ai-stuff/skills/slackify/SKILL.md @@ -0,0 +1,55 @@ +--- +name: slackify +description: This skill should be used when the user asks to "slackify" something, "write a slack message", "post this to slack", "turn this into a slack update", or wants any text rewritten in Deniz's Slack voice. Rewrites content as Deniz writes in public channels, all lowercase, direct, zero AI fluff, tl;dr first on long updates, root cause before fix. +--- + +Rewrite the given content (or draft a new message) in Deniz's Slack voice. Output the message as plain prose in the response body: no code fence around it, no hand-written mrkdwn (`*bold*`, `_italic_`). Paste from the terminal carries formatting on its own. If the surrounding response would blur into the message, put a one-line heading before it, never a fence. + +## lowercase + +Everything lowercase: sentence starts, "i", proper nouns, headings. Keep verbatim only: + +- code, commands, file paths, env vars, error strings, api names (`MasqueradeRequestHandler`, `X-Forwarded-Host`) +- acronyms where lowercasing hurts scanning: MR, CI, PR, AWS, EKS, SOPS + +## voice + +Competent engineer typing fast in slack. Direct, warm underneath, never performative. + +- no preamble ("great question", "quick update:"), no closing pleasantries ("hope this helps", "let me know if") +- no AI fluff: certainly, absolutely, it's worth noting, importantly +- drop filler: just, really, basically, actually, simply +- fragments fine. one thought per line beats a paragraph +- honest uncertainty is cheap and human: "i think", "most likely", "(i think)" as a parenthetical, "i may be missing something" +- own mistakes plainly, one line, then move on: "this is most likely me. working on a fix." no groveling, no drama +- short status style for updates: "working on a fix", "applied and merged", "need to look into it" +- never drop not/never/no/only/except. numbers, units, versions, timestamps exact + +## shape + +- lead with the answer or the verdict. context after, if at all +- long technical update: "tl;dr of what happened:" first, then detail for whoever wants it +- root cause before fix, fix before speculation. name the exact file/line/commit when known ("shared-gh-actions@c4f386e added packages: read") +- procedures: numbered steps, one bounded action per step. call out ordering constraints explicitly ("order is important:") +- links inline where they belong, not collected at the bottom +- announcements (a la the karpenter post): lead with the headline and the number that matters, then "what is X" for the unfamiliar, then the interesting part, then methodology last +- emoji sparingly, as the literal character (🎉 👋), not `:shortcode:` +- @-mentions where a specific person needs to act, written as plain @name placeholders for the user to resolve + +## punctuation + +Never use em-dashes (—) or en-dashes (–). Use a comma, a period, parentheses, or a colon. Hyphens in compound words are fine. + +## reference samples + +Real messages, match this register: + +> made an investigation with claude and this is what it came up with. it's a behavioral difference between nginx and traefik. do you think the proposed changes/diagnosis makes sense @james? + +> sorry for the inconvenience. in the meantime, could you please ask a twbox user if they are having the same issues + +> tl;dr of what happened: Root cause: shared-gh-actions@c4f386e (DEVX-1427, merged to main Aug 4 14:57 GMT+2) added packages: read to ci-build-and-deploy.yml's build job [...] every prod/staging run since fails at parse time, hence "Startup failure" with 0s duration. + +> i merged the shared actions. please merge the uala-backend one whenever you want as it will trigger a new deploy(i think) + +> happy that it worked, last couple of days was a little bit surgical because of traefik sorry for any inconvenience From 8488fe26c723315641ed6d865e169822f87f5f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:32:30 +0200 Subject: [PATCH 08/16] chore: minor clean-up with some plugins --- .zshrc | 3 + ai-stuff/claude/README.md | 3 +- ai-stuff/claude/scripts/statusline.sh | 9 +- .../claude/scripts/subagent-statusline.sh | 23 ++ ai-stuff/claude/settings.json | 37 ++- ai-stuff/skills/daily-recap/SKILL.md | 25 +- makefiles/claude.mk | 1 + nvim/lua/config/misc.lua | 2 +- nvim/lua/plugins/agentic.lua | 62 ---- nvim/lua/plugins/cc.lua | 76 +++++ nvim/lua/plugins/claude-code.lua | 2 +- nvim/lua/plugins/copilot-chat.lua | 309 ------------------ nvim/lua/plugins/copilot.lua | 25 -- nvim/lua/plugins/snacks.lua | 68 +++- 14 files changed, 213 insertions(+), 432 deletions(-) create mode 100755 ai-stuff/claude/scripts/subagent-statusline.sh delete mode 100644 nvim/lua/plugins/agentic.lua create mode 100644 nvim/lua/plugins/cc.lua delete mode 100644 nvim/lua/plugins/copilot-chat.lua delete mode 100644 nvim/lua/plugins/copilot.lua diff --git a/.zshrc b/.zshrc index 23ed90cc..f70ce8df 100644 --- a/.zshrc +++ b/.zshrc @@ -224,3 +224,6 @@ export BASH_MAX_OUTPUT_LENGTH=15000 # Added by Antigravity CLI installer export PATH="/Users/denizgokcin/.local/bin:$PATH" + +# opencode +export PATH=/Users/denizgokcin/.opencode/bin:$PATH diff --git a/ai-stuff/claude/README.md b/ai-stuff/claude/README.md index b68fb962..c63b719c 100644 --- a/ai-stuff/claude/README.md +++ b/ai-stuff/claude/README.md @@ -12,7 +12,8 @@ cross-tool architecture. ai-stuff/claude/ ├── scripts/ # Claude-only hook + integration scripts (→ ~/.claude/scripts) │ ├── file-suggestion.sh # Custom file suggestion using rg + fzf -│ ├── statusline.sh # Statusline with git, context, vim mode +│ ├── statusline.sh # Main-session statusline with git, context, vim mode +│ ├── subagent-statusline.sh # Subagent rows with each task's resolved model │ ├── session-start.sh # Auto-name worktree sessions │ ├── notify.sh # Notification-event alert (claude-only event) │ └── worktree-*.sh # EnterWorktree/ExitWorktree hook scripts (claude hook protocol) diff --git a/ai-stuff/claude/scripts/statusline.sh b/ai-stuff/claude/scripts/statusline.sh index 998b1d77..f9546499 100755 --- a/ai-stuff/claude/scripts/statusline.sh +++ b/ai-stuff/claude/scripts/statusline.sh @@ -269,7 +269,7 @@ if [ "$is_codex_model" = 1 ]; then [ -n "$codex_cache_mtime" ] && codex_cache_age=$(($(date +%s) - codex_cache_mtime)) fi - if [ "$codex_cache_age" -gt 60 ] && [ -f "$codex_auth" ]; then + if [ "$codex_cache_age" -ge 60 ] && [ -f "$codex_auth" ]; then codex_token=$(jq -r '.tokens.access_token // empty' "$codex_auth" 2>/dev/null) codex_acct=$(jq -r '.tokens.account_id // empty' "$codex_auth" 2>/dev/null) codex_payload="" @@ -348,11 +348,16 @@ if [ "$is_codex_model" = 1 ]; then if [ -n "$codex_prices" ]; then IFS=$'\t' read -r cx_price_in cx_price_cached cx_price_out <<<"$codex_prices" # fromjson? tolerates the half-written last line of a live transcript. + # Claude Code writes one line per content block, so a single response + # (text + tool call) repeats its usage on several lines sharing one + # message.id — count each id once or the total nearly doubles. # Cache writes are billed at the plain input rate (OpenAI has no # separate write price); cache reads at the cached-input rate. codex_cost_val=$(jq -R -n --arg m "$model_id" \ --arg pin "$cx_price_in" --arg pcached "$cx_price_cached" --arg pout "$cx_price_out" ' - [inputs | fromjson? | .message? | select(.model == $m) | .usage // empty] as $u + [inputs | fromjson? | .message? | select(.model == $m and .usage != null)] as $all + | ((($all | map(select(.id != null)) | unique_by(.id)) + + ($all | map(select(.id == null)))) | map(.usage)) as $u | ( (($u | map(.input_tokens // 0) | add // 0) + ($u | map(.cache_creation_input_tokens // 0) | add // 0)) * ($pin | tonumber) + ($u | map(.cache_read_input_tokens // 0) | add // 0) * ($pcached | tonumber) diff --git a/ai-stuff/claude/scripts/subagent-statusline.sh b/ai-stuff/claude/scripts/subagent-statusline.sh new file mode 100755 index 00000000..751be081 --- /dev/null +++ b/ai-stuff/claude/scripts/subagent-statusline.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Custom row content for Claude Code's subagent panel. +# Reads all visible tasks from stdin and emits one JSON line per task. + +input=$(cat) + +printf '%s' "$input" | jq -c ' + (.columns // 120) as $columns + | .tasks[]? + | (.name // .label // .id) as $name + | (.model // "resolving model…") as $model + | ([$name, "model: \($model)", (.description // "")] + | map(select(length > 0)) + | join(" · ")) as $content + | ([($columns - 1), 1] | max) as $limit + | { + id, + content: (if ($content | length) > $columns + then $content[0:$limit] + "…" + else $content + end) + } +' diff --git a/ai-stuff/claude/settings.json b/ai-stuff/claude/settings.json index 06d334b9..65ece48b 100644 --- a/ai-stuff/claude/settings.json +++ b/ai-stuff/claude/settings.json @@ -61,7 +61,7 @@ ], "defaultMode": "auto" }, - "model": "sol", + "model": "astra", "enableAllProjectMcpServers": false, "skillOverrides": { "commit": "off", @@ -191,7 +191,12 @@ "enableWorkflows": false, "statusLine": { "type": "command", - "command": "~/.claude/scripts/statusline.sh" + "command": "~/.claude/scripts/statusline.sh", + "refreshInterval": 60 + }, + "subagentStatusLine": { + "type": "command", + "command": "~/.claude/scripts/subagent-statusline.sh" }, "enabledPlugins": { "typescript-lsp@claude-plugins-official": false, @@ -203,12 +208,10 @@ "skill-creator@claude-plugins-official": false, "caveman@caveman": false, "plugin-dev@claude-plugins-official": false, - "gitops@treatwell": true, - "session-handover@treatwell": false, - "i-have-adhd@i-have-adhd": false, + "gitops@treatwell": false, + "session-handover@treatwell": true, "ponytail@ponytail": false, - "datadog@treatwell": true, - "codex@openai-codex": true + "datadog@treatwell": true }, "extraKnownMarketplaces": { "obsidian-skills": { @@ -237,13 +240,6 @@ }, "autoUpdate": true }, - "i-have-adhd": { - "source": { - "source": "github", - "repo": "ayghri/i-have-adhd" - }, - "autoUpdate": true - }, "ponytail": { "source": { "source": "github", @@ -252,10 +248,20 @@ } }, "outputStyle": "Coincise", + "feedbackDrafts": "off", "effortLevel": "high", "modelSettings": { "sol": { "effortLevel": "medium" + }, + "claude-fable-5": { + "effortLevel": "high" + }, + "claude-fable-5-1": { + "effortLevel": "medium" + }, + "astra": { + "effortLevel": "medium" } }, "promptSuggestionEnabled": false, @@ -272,13 +278,14 @@ } } }, - "autoUpdatesChannel": "latest", "tui": "fullscreen", "autoMemoryEnabled": true, "autoDreamEnabled": true, "skipWorkflowUsageWarning": true, "theme": "dark", + "editorMode": "vim", "verbose": false, + "preferredNotifChannel": "iterm2_with_bell", "teammateMode": "iterm2", "remoteControlAtStartup": false, "agentPushNotifEnabled": true, diff --git a/ai-stuff/skills/daily-recap/SKILL.md b/ai-stuff/skills/daily-recap/SKILL.md index 602446e6..e07070d4 100644 --- a/ai-stuff/skills/daily-recap/SKILL.md +++ b/ai-stuff/skills/daily-recap/SKILL.md @@ -264,7 +264,30 @@ For each meeting where Gemini data was successfully fetched (step 2i above): Returns a JSON array of paths like `["work/meetings/YYYY-MM-DD title.md", ...]`. -2. **Match meeting to note** — compare calendar event title to vault note filename (case-insensitive, partial match). If multiple notes exist for the date, pick the one whose filename most closely matches the calendar event title. If no match → skip silently. +2. **Match meeting to note** — compare calendar event title to vault note filename (case-insensitive, partial match). If multiple notes exist for the date, pick the one whose filename most closely matches the calendar event title. + + **If no match → CREATE the note (never skip).** Deniz wants every meeting with Gemini notes to have a vault note (2026-09-02): + + ```bash + obsidian create name="" template="meeting-template" silent + sleep 4 # Templater must finish before the next step + ``` + + Templater stamps `tp.date.now()`, so the note lands as `work/meetings/ .md`. If the target date is not today, move it and fix the dates: + + ```bash + obsidian move path="work/meetings/<TODAY> <title>.md" to="work/meetings/YYYY-MM-DD <title>.md" + ``` + + Then overwrite the file body (heredoc via Bash is fine — the template only matters for the move + frontmatter shape): set `date: YYYY-MM-DD HH:mm` (meeting start), `Date: [[YYYY-MM-DD]]`, H1 `# [[YYYY-MM-DD <title>]]`, `summary:` = Gemini one-liner. Fill the template sections from Gemini data: + - **Attendees** → calendar attendees as `[[first last]]` wikilinks (resolve via step 2k; plain text if no people note), skip rooms/group aliases + - **Agenda** → one sentence derived from the Summary + - **Questions** → open questions from Details / "Needs Further Discussion" + - **Notes** → bullets from Summary + Details (the meaty technical context, not the transcript) + - **Action Items** → all Next steps as `- [ ] [[owner]] — item`; Deniz's already-completed ones as `- [x] ... ✅ YYYY-MM-DD` with MR links + + A created note counts as "found" for steps 3–5 below (skip step 5's `## Gemini Notes` append — the content is already in the template sections) and for the `### meetings` block + `[[wikilink]]` task line in Step 5. + 3. **Check for existing Gemini section** — read the note and check if a `## Gemini Notes` section already exists. If yes → skip (don't overwrite). diff --git a/makefiles/claude.mk b/makefiles/claude.mk index 731cdc55..233924b2 100644 --- a/makefiles/claude.mk +++ b/makefiles/claude.mk @@ -36,6 +36,7 @@ claude-scripts: claude-dirs ## Symlink Claude Code scripts (statusline, hooks, e $(call pretty_print, "Installing Claude Code scripts...") $(call symlink,ai-stuff/claude/scripts/file-suggestion.sh,${CLAUDE_HOME}/scripts/file-suggestion.sh) $(call symlink,ai-stuff/claude/scripts/statusline.sh,${CLAUDE_HOME}/scripts/statusline.sh) + $(call symlink,ai-stuff/claude/scripts/subagent-statusline.sh,${CLAUDE_HOME}/scripts/subagent-statusline.sh) $(call symlink,ai-stuff/claude/scripts/worktree-create.sh,${CLAUDE_HOME}/scripts/worktree-create.sh) $(call symlink,ai-stuff/claude/scripts/worktree-remove.sh,${CLAUDE_HOME}/scripts/worktree-remove.sh) $(call symlink,ai-stuff/claude/scripts/session-start.sh,${CLAUDE_HOME}/scripts/session-start.sh) diff --git a/nvim/lua/config/misc.lua b/nvim/lua/config/misc.lua index 6ce15d51..79a31ba3 100644 --- a/nvim/lua/config/misc.lua +++ b/nvim/lua/config/misc.lua @@ -10,6 +10,7 @@ local function setup_command_abbreviations() { "wQ", "wq" }, { "WQ", "wq" }, { "W", "w" }, + { "qq", "qall!" }, { "Q", "q" }, { "Qall", "qall" }, } @@ -20,4 +21,3 @@ local function setup_command_abbreviations() end setup_command_abbreviations() - diff --git a/nvim/lua/plugins/agentic.lua b/nvim/lua/plugins/agentic.lua deleted file mode 100644 index 3e56185c..00000000 --- a/nvim/lua/plugins/agentic.lua +++ /dev/null @@ -1,62 +0,0 @@ -return { - "carlos-algms/agentic.nvim", - - --- @type agentic.PartialUserConfig - opts = { - -- Any ACP-compatible provider works. Built-in: "claude-agent-acp" | "gemini-acp" | "codex-acp" | "opencode-acp" | "cursor-acp" | "copilot-acp" | "auggie-acp" | "mistral-vibe-acp" | "cline-acp" | "goose-acp" | "kiro-acp" | "pi-acp" - provider = "claude-agent-acp", -- setting the name here is all you need to get started - }, - - -- these are just suggested keymaps; customize as desired - keys = { - { - "<C-\\>", - function() - require("agentic").toggle() - end, - mode = { "n", "v", "i" }, - desc = "Toggle Agentic Chat", - }, - { - "<C-'>", - function() - require("agentic").add_selection_or_file_to_context() - end, - mode = { "n", "v" }, - desc = "Add file or selection to Agentic to Context", - }, - { - "<C-,>", - function() - require("agentic").new_session() - end, - mode = { "n", "v", "i" }, - desc = "New Agentic Session", - }, - { - "<A-i>r", -- ai Restore - function() - require("agentic").restore_session() - end, - desc = "Agentic Restore session", - silent = true, - mode = { "n", "v", "i" }, - }, - { - "<leader>ad", -- ai Diagnostics - function() - require("agentic").add_current_line_diagnostics() - end, - desc = "Add current line diagnostic to Agentic", - mode = { "n" }, - }, - { - "<leader>aD", -- ai all Diagnostics - function() - require("agentic").add_buffer_diagnostics() - end, - desc = "Add all buffer diagnostics to Agentic", - mode = { "n" }, - }, - }, -} diff --git a/nvim/lua/plugins/cc.lua b/nvim/lua/plugins/cc.lua new file mode 100644 index 00000000..21ed0448 --- /dev/null +++ b/nvim/lua/plugins/cc.lua @@ -0,0 +1,76 @@ +return { + "greggh/claude-code.nvim", + dependencies = { + "nvim-lua/plenary.nvim", -- Required for git operations + }, + keys = { + { "<leader>a", "", desc = "+ai", mode = { "n", "v" } }, + { "<leader>ac", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude" }, + { "<leader>ar", "<cmd>ClaudeCodeResume<cr>", desc = "Resume Claude" }, + { "<leader>aK", "<cmd>ClaudeCodeContinue<cr>", desc = "Continue Claude" }, + { "<leader>av", "<cmd>ClaudeCodeVerbose<cr>", desc = "Verbose Claude" }, + }, + config = function() + require("claude-code").setup({ + -- Terminal window settings + window = { + split_ratio = 0.3, -- Percentage of screen for the terminal window (height for horizontal, width for vertical splits) + position = "float", -- Position of the window: "botright", "topleft", "vertical", "float", etc. + enter_insert = true, -- Whether to enter insert mode when opening Claude Code + hide_numbers = true, -- Hide line numbers in the terminal window + hide_signcolumn = true, -- Hide the sign column in the terminal window + + -- Floating window configuration (only applies when position = "float") + float = { + width = "80%", -- Width: number of columns or percentage string + height = "80%", -- Height: number of rows or percentage string + row = "center", -- Row position: number, "center", or percentage string + col = "center", -- Column position: number, "center", or percentage string + relative = "editor", -- Relative to: "editor" or "cursor" + border = "rounded", -- Border style: "none", "single", "double", "rounded", "solid", "shadow" + }, + }, + -- File refresh settings + refresh = { + enable = true, -- Enable file change detection + updatetime = 100, -- updatetime when Claude Code is active (milliseconds) + timer_interval = 1000, -- How often to check for file changes (milliseconds) + show_notifications = true, -- Show notification when files are reloaded + }, + -- Git project settings + git = { + use_git_root = true, -- Set CWD to git root when opening Claude Code (if in git project) + }, + -- Shell-specific settings + shell = { + separator = "&&", -- Command separator used in shell commands + pushd_cmd = "pushd", -- Command to push directory onto stack (e.g., 'pushd' for bash/zsh, 'enter' for nushell) + popd_cmd = "popd", -- Command to pop directory from stack (e.g., 'popd' for bash/zsh, 'exit' for nushell) + }, + -- Command settings + command = "claude", -- Command used to launch Claude Code + -- Command variants + command_variants = { + -- Conversation management + continue = "--continue", -- Resume the most recent conversation + resume = "--resume", -- Display an interactive conversation picker + + -- Output options + verbose = "--verbose", -- Enable verbose logging with full turn-by-turn output + }, + -- Keymaps + keymaps = { + toggle = { + normal = "<C-,>", -- Normal mode keymap for toggling Claude Code, false to disable + terminal = "<C-,>", -- Terminal mode keymap for toggling Claude Code, false to disable + variants = { + continue = false, -- handled by lazy `keys` (<leader>aK) so which-key shows the description + verbose = false, -- handled by lazy `keys` (<leader>av) + }, + }, + window_navigation = true, -- Enable window navigation keymaps (<C-h/j/k/l>) + scrolling = true, -- Enable scrolling keymaps (<C-f/b>) for page up/down + }, + }) + end, +} diff --git a/nvim/lua/plugins/claude-code.lua b/nvim/lua/plugins/claude-code.lua index c038d7cb..e0a9891f 100644 --- a/nvim/lua/plugins/claude-code.lua +++ b/nvim/lua/plugins/claude-code.lua @@ -1,7 +1,7 @@ return { { "coder/claudecode.nvim", - enabled = true, + enabled = false, opts = { terminal = { split_side = "right", diff --git a/nvim/lua/plugins/copilot-chat.lua b/nvim/lua/plugins/copilot-chat.lua deleted file mode 100644 index e799b2a8..00000000 --- a/nvim/lua/plugins/copilot-chat.lua +++ /dev/null @@ -1,309 +0,0 @@ -local M = {} - --- Prompt picker using Telescope -function M.pick(type) - return function() - local actions = require("CopilotChat.actions") - require("CopilotChat.integrations.telescope").pick(actions[type .. "_actions"]()) - end -end - -return { - "CopilotC-Nvim/CopilotChat.nvim", - branch = "main", - cmd = "CopilotChat", - enabled = false, - dependencies = { - { "nvim-telescope/telescope.nvim" }, - { "nvim-lua/plenary.nvim" }, - }, - opts = function() - local user = vim.env.USER or "User" - user = user:sub(1, 1):upper() .. user:sub(2) - - -- Base commit prompt template - local commit_prompt = - "Take a deep breath and analyze the changes made in the git diff. Then, write a commit message for the %s with commitizen convention, only use lower-case letters. Output the full multi-line command starting with `git commit -m` ready to be pasted into the terminal. If there are references to filenames or the backtics in the commit message, escape them with backslashes. i.e. \\` text with backticks \\`" - - return { - auto_insert_mode = true, - question_header = " " .. user .. " ", - answer_header = " Copilot ", - error_header = "## Error ", - window = { - width = 0.4, - }, - -- Register custom contexts - contexts = { - pr_diff = { - description = "Get the diff between the current branch and target branch", - resolve = function() - -- Check if we're in a git repository - local is_git = vim.fn.system("git rev-parse --is-inside-work-tree 2>/dev/null") - if vim.v.shell_error ~= 0 then - return { { content = "Not in a git repository", filename = "error", filetype = "text" } } - end - - -- Get target branch (main/master/develop) - local target_branch = vim.fn - .system( - "git for-each-ref --format='%(refname:short)' refs/heads/ | grep -E '^(main|master|develop)' | head -n 1" - ) - :gsub("\n", "") - if vim.v.shell_error ~= 0 or target_branch == "" then - return { { content = "Failed to determine target branch", filename = "error", filetype = "text" } } - end - - -- Fetch the latest changes from the remote repository - local fetch_result = vim.fn.system("git fetch origin " .. target_branch .. " 2>&1") - if vim.v.shell_error ~= 0 then - return { - { content = "Failed to fetch from remote: " .. fetch_result, filename = "error", filetype = "text" }, - } - end - - -- Get current branch - local current_branch = vim.fn.system("git rev-parse --abbrev-ref HEAD 2>/dev/null"):gsub("\n", "") - if vim.v.shell_error ~= 0 or current_branch == "" then - return { { content = "Failed to get current branch", filename = "error", filetype = "text" } } - end - - -- Get the diff - local cmd = - string.format("git diff --no-color --no-ext-diff origin/%s...%s 2>&1", target_branch, current_branch) - local handle = io.popen(cmd) - if not handle then - return { { content = "Failed to execute git diff", filename = "error", filetype = "text" } } - end - - local result = handle:read("*a") - handle:close() - - -- If there's no diff, return a meaningful message - if not result or result == "" then - return { - { - content = "No changes found between current branch and " .. target_branch, - filename = "info", - filetype = "text", - }, - } - end - - return { - { - content = result, - filename = "pr_diff", - filetype = "diff", - }, - } - end, - }, - }, - -- Custom prompts incorporating git staged/unstaged functionality - prompts = { - -- Code related prompts - Explain = { - prompt = "Please explain how the following code works.", - system_prompt = "You are an expert software developer and teacher. Explain the code in a clear, concise way.", - }, - Review = { - prompt = "Please review the following code and provide suggestions for improvement.", - system_prompt = "You are an expert code reviewer. Focus on best practices, performance, and potential issues.", - }, - Tests = { - prompt = "Please explain how the selected code works, then generate unit tests for it.", - system_prompt = "You are an expert in software testing. Generate thorough test cases covering edge cases.", - }, - Refactor = { - prompt = "Please refactor the following code to improve its clarity and readability.", - system_prompt = "You are an expert in code refactoring. Focus on making the code more maintainable and easier to understand.", - }, - FixCode = { - prompt = "Please fix the following code to make it work as intended.", - system_prompt = "You are an expert programmer. Help fix code issues while maintaining code style and best practices.", - }, - FixError = { - prompt = "Please explain the error in the following text and provide a solution.", - system_prompt = "You are an expert in debugging. Help identify and fix the error while explaining the solution.", - }, - BetterNamings = { - prompt = "Please provide better names for the following variables and functions.", - system_prompt = "You are an expert in code readability. Suggest clear, descriptive names following naming conventions.", - }, - Documentation = { - prompt = "Please provide documentation for the following code.", - system_prompt = "You are an expert technical writer. Create clear, comprehensive documentation.", - }, - SwaggerApiDocs = { - prompt = "Please provide documentation for the following API using Swagger.", - system_prompt = "You are an expert in API documentation. Create comprehensive Swagger/OpenAPI documentation.", - }, - SwaggerJsDocs = { - prompt = "Please write JSDoc for the following API using Swagger.", - system_prompt = "You are an expert in JavaScript documentation. Create comprehensive JSDoc with Swagger annotations.", - }, - -- Git related prompts - Commit = { - prompt = "> #git:staged\n\n" .. string.format(commit_prompt, "change"), - system_prompt = "You are an expert in writing clear, concise git commit messages following best practices.", - }, - CommitStaged = { - prompt = "> #git:staged\n\n" .. string.format(commit_prompt, "staged changes"), - system_prompt = "You are an expert in writing clear, concise git commit messages following best practices.", - }, - CommitUnstaged = { - prompt = "> #git:unstaged\n\n" .. string.format(commit_prompt, "unstaged changes"), - system_prompt = "You are an expert in writing clear, concise git commit messages following best practices.", - }, - PullRequest = { - prompt = "> #pr_diff\n\nWrite a pull request description for these changes. Include a clear title, summary of changes, and any important notes.", - system_prompt = [[You are an experienced software engineer about to open a PR. You are thorough and explain your changes well, you provide insights and reasoning for the change and enumerate potential bugs with the changes you've made. - - Your task is to create a pull request for the given code changes. Follow these steps: - - 1. Analyze the git diff changes provided. - 2. Draft a comprehensive description of the pull request based on the input. - 3. Create the gh CLI command to create a GitHub pull request. - - Output Instructions: - - The command should start with `gh pr create`. - - Do not use the new line character in the command since it does not work - - Output needs to be a multi-line command - - Include the `--base $(git parent)` flag - - Use the `--title` flag with a concise, descriptive title matching the commitzen convention. - - Use the `--body` flag for the PR description. - - Include the following sections in the body: - - '## Summary' with a brief overview of changes - - '## Changes' listing specific modifications - - '## Additional Notes' for any extra information - - Escape any backticks in the message body to avoid shell interpretation issues - - Wrap the entire command in a code block for easy copy-pasting. - - Desired Output: - ```sh - gh pr create \ - --base $(git parent) \ - --title "feat: your title here" \ - --body "## Summary - Your summary here - - ## Changes - - Change 1 - - Change 2 - - Change 3 \`with backticks\` - - ## Additional Notes - Your notes here" - ```]], - }, - -- Text related prompts - Summarize = { - prompt = "Please summarize the following text.", - system_prompt = "You are an expert in technical writing. Create clear, concise summaries.", - }, - Spelling = { - prompt = "Please correct any grammar and spelling errors in the following text.", - system_prompt = "You are an expert editor. Fix grammar and spelling while maintaining the original meaning.", - }, - Wording = { - prompt = "Please improve the grammar and wording of the following text.", - system_prompt = "You are an expert writer. Improve clarity and readability while maintaining the original meaning.", - }, - Concise = { - prompt = "Please rewrite the following text to make it more concise.", - system_prompt = "You are an expert in technical writing. Make the text more concise while preserving key information.", - }, - }, - } - end, - keys = { - { "<c-s>", "<CR>", ft = "copilot-chat", desc = "Submit Prompt", remap = true }, - { "<leader>a", "", desc = "+ai", mode = { "n", "v" } }, - -- Toggle and clear - { - "<leader>aa", - function() - return require("CopilotChat").toggle() - end, - desc = "Toggle (CopilotChat)", - mode = { "n", "v" }, - }, - { - "<leader>ax", - function() - return require("CopilotChat").reset() - end, - desc = "Clear (CopilotChat)", - mode = { "n", "v" }, - }, - -- Quick chat - { - "<leader>aq", - function() - local input = vim.fn.input("Quick Chat: ") - if input ~= "" then - require("CopilotChat").ask(input) - end - end, - desc = "Quick Chat (CopilotChat)", - mode = { "n", "v" }, - }, - -- Show help and prompts with telescope - { "<leader>ah", M.pick("help"), desc = "Help Actions (CopilotChat)", mode = { "n", "v" } }, - { "<leader>ap", M.pick("prompt"), desc = "Prompt Actions (CopilotChat)", mode = { "n", "v" } }, - -- Code related commands - { "<leader>ae", "<cmd>CopilotChatExplain<cr>", desc = "Explain Code" }, - { "<leader>at", "<cmd>CopilotChatTests<cr>", desc = "Generate Tests" }, - { "<leader>ar", "<cmd>CopilotChatReview<cr>", desc = "Review Code" }, - { "<leader>aR", "<cmd>CopilotChatRefactor<cr>", desc = "Refactor Code" }, - { "<leader>an", "<cmd>CopilotChatBetterNamings<cr>", desc = "Better Naming" }, - -- Git related commands - { "<leader>ac", "<cmd>CopilotChatCommit<cr>", desc = "Generate Commit Message" }, - { "<leader>as", "<cmd>CopilotChatCommitStaged<cr>", desc = "Commit Staged Changes" }, - { "<leader>au", "<cmd>CopilotChatCommitUnstaged<cr>", desc = "Commit Unstaged Changes" }, - { "<leader>ap", "<cmd>CopilotChatPullRequest<cr>", desc = "Generate Pull Request" }, - -- Debug and fix - { "<leader>ad", "<cmd>CopilotChatDebugInfo<cr>", desc = "Debug Info" }, - { "<leader>af", "<cmd>CopilotChatFixDiagnostic<cr>", desc = "Fix Diagnostic" }, - -- Models - { "<leader>am", "<cmd>CopilotChatModels<cr>", desc = "Select Models" }, - }, - config = function(_, opts) - local chat = require("CopilotChat") - local select = require("CopilotChat.select") - - -- Disable line numbers in chat window - vim.api.nvim_create_autocmd("BufEnter", { - pattern = "copilot-chat", - callback = function() - vim.opt_local.relativenumber = false - vim.opt_local.number = false - end, - }) - - -- Setup CMP integration - require("CopilotChat.integrations.cmp").setup() - - -- Create commands for visual mode - vim.api.nvim_create_user_command("CopilotChatVisual", function(args) - chat.ask(args.args, { selection = select.visual }) - end, { nargs = "*", range = true }) - - -- Inline chat with Copilot - vim.api.nvim_create_user_command("CopilotChatInline", function(args) - chat.ask(args.args, { - selection = select.visual, - window = { - layout = "float", - relative = "cursor", - width = 1, - height = 0.4, - row = 1, - }, - }) - end, { nargs = "*", range = true }) - - chat.setup(opts) - end, -} diff --git a/nvim/lua/plugins/copilot.lua b/nvim/lua/plugins/copilot.lua deleted file mode 100644 index 4d1244dc..00000000 --- a/nvim/lua/plugins/copilot.lua +++ /dev/null @@ -1,25 +0,0 @@ -return { - "zbirenbaum/copilot.lua", - cmd = "Copilot", - build = ":Copilot auth", - enabled = false, - event = "InsertEnter", - opts = { - suggestion = { - enabled = not vim.g.ai_cmp, - auto_trigger = true, - keymap = { - accept = false, -- handled by nvim-cmp / blink.cmp - next = "<M-]>", - prev = "<M-[>", - }, - }, - panel = { enabled = false }, - filetypes = { - gitcommit = true, - markdown = true, - typescript = true, - yaml = true, - }, - }, -} diff --git a/nvim/lua/plugins/snacks.lua b/nvim/lua/plugins/snacks.lua index a72cfd1e..f7768db7 100644 --- a/nvim/lua/plugins/snacks.lua +++ b/nvim/lua/plugins/snacks.lua @@ -15,23 +15,60 @@ return { Snacks.gitbrowse() end, }, - function() + function(self) local in_git = Snacks.git.get_root() ~= nil local remote = in_git and vim.fn.system("git remote get-url origin 2>/dev/null"):gsub("%s+", "") or "" local is_github = remote:find("github%.com") ~= nil local is_gitlab = remote:find("gitlab") ~= nil or remote:find("git%.treatwell") ~= nil + local repo = remote:match("github%.com[:/]([^/]+/[^/]+)") + repo = repo and repo:gsub("%.git$", "") or "" + + -- Notifications as plain text (not a terminal section) so nothing renders + -- when empty and no "[Process exited 0]" can appear. Reads a cache file and + -- refreshes it in the background for the next dashboard open. + local items = {} + if in_git and is_github and repo ~= "" then + local notif_file = vim.fn.stdpath("cache") .. "/dash-gh-notify-" .. repo:gsub("/", "_") .. ".txt" + local stat = vim.uv.fs_stat(notif_file) + if not stat or os.time() - stat.mtime.sec > 300 then + local strip = [[perl -pe 's/\e\[[0-9;]*[A-Za-z]//g; s/\e\][^\a\e]*(?:\a|\e\\)//g; s/[\r\a]//g']] + vim.fn.jobstart({ + "sh", + "-c", + ("gh notify -s -a -n5 -f '%s' 2>/dev/null | grep -v 'No results found.' | %s > '%s'"):format( + repo, + strip, + notif_file + ), + }) + end + local lines = stat and vim.fn.readfile(notif_file) or {} + lines = vim.tbl_filter(function(l) + return l:match("%S") + end, lines) + if #lines > 0 then + items[#items + 1] = { + pane = 2, + icon = " ", + title = "Notifications", + key = "N", + action = function() + vim.ui.open("https://github.com/notifications?query=repo%3A" .. repo:gsub("/", "%%2F")) + end, + } + local width = (self and self.opts and self.opts.width or 60) - 3 + for i, l in ipairs(lines) do + items[#items + 1] = { + pane = 2, + indent = 3, + padding = i == #lines and 1 or 0, + text = { { vim.fn.strcharpart(l, 0, width), hl = "dir" } }, + } + end + end + end + local cmds = { - { - title = "Notifications", - cmd = "gh notify -s -a -n5", - action = function() - vim.ui.open("https://github.com/notifications") - end, - key = "N", - icon = " ", - height = 5, - enabled = is_github, - }, -- { -- title = "Open Issues", -- cmd = "gh issue list -L 3", @@ -65,8 +102,8 @@ return { enabled = is_gitlab, }, } - return vim.tbl_map(function(cmd) - return vim.tbl_extend("force", { + for _, cmd in ipairs(cmds) do + items[#items + 1] = vim.tbl_extend("force", { pane = 2, section = "terminal", enabled = in_git, @@ -74,7 +111,8 @@ return { ttl = 5 * 60, indent = 3, }, cmd) - end, cmds) + end + return items end, { section = "startup" }, }, From 3fe78b9f6bf1c5b292616745ee71ed3b272dc949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:56:43 +0200 Subject: [PATCH 09/16] chore(skills): archive spike, dev-story, mega-dev, commit + legacy skills - move deprecated skills to .archived/ - add spike, dev-story, mega-dev, commit to AI_LEGACY_SKILLS for removal - update mega-dev persona and agent to reference /get-story and /auto-commit - update jiragirl skill body --- ai-stuff/_shared/personas/mega-dev.md | 4 +- ai-stuff/agents/mega-dev.md | 9 +- ai-stuff/skills/commit/SKILL.md | 125 --------------------- ai-stuff/skills/commit/SKILL.original.md | 107 ------------------ ai-stuff/skills/dev-story/SKILL.md | 106 ----------------- ai-stuff/skills/jiragirl/SKILL.md | 9 +- ai-stuff/skills/mega-dev/SKILL.md | 77 ------------- ai-stuff/skills/mega-dev/SKILL.original.md | 77 ------------- ai-stuff/skills/spike/SKILL.md | 95 ---------------- ai-stuff/skills/spike/SKILL.original.md | 95 ---------------- makefiles/ai.mk | 21 +++- 11 files changed, 25 insertions(+), 700 deletions(-) delete mode 100644 ai-stuff/skills/commit/SKILL.md delete mode 100644 ai-stuff/skills/commit/SKILL.original.md delete mode 100644 ai-stuff/skills/dev-story/SKILL.md delete mode 100644 ai-stuff/skills/mega-dev/SKILL.md delete mode 100644 ai-stuff/skills/mega-dev/SKILL.original.md delete mode 100644 ai-stuff/skills/spike/SKILL.md delete mode 100644 ai-stuff/skills/spike/SKILL.original.md diff --git a/ai-stuff/_shared/personas/mega-dev.md b/ai-stuff/_shared/personas/mega-dev.md index 84f6474d..7fd6ca19 100644 --- a/ai-stuff/_shared/personas/mega-dev.md +++ b/ai-stuff/_shared/personas/mega-dev.md @@ -34,8 +34,8 @@ You are **Mega-Dev**, the Elite Full-Stack Developer and Quick Flow Specialist. ## Orchestration Capabilities Mega-Dev can coordinate: -- `/dev-story` - Fetch and understand Jira stories -- `/commit` - Delegate to GitBoi for conventional commits +- `/get-story` - Fetch and understand Jira stories +- `/auto-commit` - Delegate to GitBoi for conventional commits - `/create-pr` - Delegate to GitBoi for PR/MR creation - `/create-story` - Delegate to Jira Girl for issue creation diff --git a/ai-stuff/agents/mega-dev.md b/ai-stuff/agents/mega-dev.md index 605f7597..b5fb5798 100644 --- a/ai-stuff/agents/mega-dev.md +++ b/ai-stuff/agents/mega-dev.md @@ -15,7 +15,7 @@ You are **Mega-Dev**, the Elite Full-Stack Developer and Quick Flow Specialist. You orchestrate the complete development flow: - Fetch story context from Jira - Implement features and fixes -- Create commits (delegate to GitBoi via `/commit`) +- Create commits (delegate to GitBoi via `/auto-commit`) - Create PRs (delegate to GitBoi via `/create-pr`) - Update Jira status and comments @@ -23,17 +23,16 @@ You orchestrate the complete development flow: | Skill | Description | |-------|-------------| -| `/commit` | Create conventional commit (GitBoi) | +| `/auto-commit` | Group and create conventional commits (GitBoi) | | `/create-pr` | Create PR/MR (GitBoi) | | `/get-story <KEY>` | Fetch Jira issue (Jira Girl) | | `/create-story <desc>` | Create Jira issue (Jira Girl) | -| `/dev-story <KEY>` | Fetch story for development | ## Workflow: Story to PR -1. **Fetch**: `/dev-story DEVX-123` +1. **Fetch**: `/get-story DEVX-123` 2. **Implement**: Write the code -3. **Commit**: `/commit` +3. **Commit**: `/auto-commit` 4. **Ship**: `/create-pr` 5. **Update**: Transition Jira if needed diff --git a/ai-stuff/skills/commit/SKILL.md b/ai-stuff/skills/commit/SKILL.md deleted file mode 100644 index 329d3f66..00000000 --- a/ai-stuff/skills/commit/SKILL.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -name: commit -description: Create conventional commits with GitBoi's sass and strict lowercase enforcement. -disable-model-invocation: true -agent: gitboi -allowed-tools: - - Read - - Grep - - Glob - - Bash(git status:*) - - Bash(git diff:*) - - Bash(git log:*) - - Bash(git branch:*) - - Bash(git rev-parse:*) - - Bash(git show:*) - - Bash(git commit:*) - - Bash(git worktree list:*) - - Bash(git -C:*) - - AskUserQuestion - - Skill(create-pr) ---- - -# Create Conventional Commit - -You are **GitBoi** - sassy, profane, ruthless about commit quality. - -## Persona - -Read and adopt [GitBoi persona](../_shared/personas/gitboi.md) — relative paths resolve from this skill's directory. - -## Configuration - -Read [git config](../_shared/config/git-config.md). - -## Current Context - -### Worktree Info - -- Worktree root: !`git rev-parse --show-toplevel 2>/dev/null` -- Git dir: !`git rev-parse --git-dir 2>/dev/null` - -### Branch Info - -- Branch: !`git branch --show-current 2>/dev/null` - -### Staged Changes Summary - -!`git diff --staged --stat 2>/dev/null` - -### Staged Files - -!`git diff --staged --name-only 2>/dev/null` - -### Recent Commits (for style reference) - -!`git log --oneline -5 2>/dev/null` - -### Unstaged Changes (FYI) - -!`git diff --stat 2>/dev/null` - -### Full Staged Diff (for commit message generation) - -!`git diff --staged 2>/dev/null` - -## Instructions - -Generate conventional commit. - -### Process - -1. Review staged changes above -2. No staged changes → tell user to stage something first -3. Identify type: `feat|fix|docs|style|refactor|perf|test|build|ci|chore` -4. Determine scope from changed files (e.g., `auth`, `api`, `ui`) -5. **No Jira ticket slug from branch name** — conventional commits don't have that -6. Craft title: **LOWERCASE**, present tense, under 60 chars -7. Body for significant changes — **STRICT LOWERCASE** -8. Execute commit -9. Report result with sass -10. **Worktree check**: if the injected **Git dir** above contains `worktrees/`, you're in an isolated worktree — skip if commit failed - - Get the commit hash: `git rev-parse HEAD` - - Get main worktree path: first path from `git worktree list` output - - Get main worktree branch: from `git worktree list` output (e.g., `[main]` or `[claude-code-integration]`) - - Use AskUserQuestion: "Cherry-pick this commit to `<main-branch>`?" (options: "Yes, cherry-pick" / "No, skip") - - If yes: run `git -C <main-worktree-path> cherry-pick <commit-hash>` - - Report cherry-pick result with sass -11. Use AskUserQuestion to ask: "Want to open a PR?" (options: "Yes, create PR" / "No, I'm done") — skip if commit failed -12. If user picks "Yes, create PR" → invoke the `create-pr` skill - -### Commit Format - -```bash -git commit -m "type(scope): subject - -- bullet point about change -- another bullet point -- all lowercase, no exceptions" -``` - -### Rules - READ THESE OR FACE MY WRATH - -- **ALL LOWERCASE** - title AND body, no capital letters ANYWHERE -- Present tense ("add" not "added") -- No period at end of title -- Title under 60 characters -- Specific, not vague like "fix stuff" -- **FORBIDDEN**: No AI attribution, no "Co-Authored-By", no emojis, no "Generated by" -- **FORBIDDEN**: No Jira ticket slug in commit (even if branch has one) - - Extract tickets from branch names but DO NOT put in commits - - Tickets belong in PR/MR descriptions only - -### Response Style - -Sassy in conversation, commit stays professional: - -> Alright, let me see what the fuck you had done, <random_insult></random> -> -> [Analyzes diff] -> -> Actually not bad. Here's your commit: -> -> [Executes commit] -> -> Done. That's how you write a fucking commit message. diff --git a/ai-stuff/skills/commit/SKILL.original.md b/ai-stuff/skills/commit/SKILL.original.md deleted file mode 100644 index 1fadc7c0..00000000 --- a/ai-stuff/skills/commit/SKILL.original.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -name: commit -description: Create conventional commits with GitBoi's sass and strict lowercase enforcement -disable-model-invocation: true -context: fork -agent: gitboi -allowed-tools: - - Read - - Grep - - Glob - - Bash(git status:*) - - Bash(git diff:*) - - Bash(git log:*) - - Bash(git branch:*) - - Bash(git rev-parse:*) - - Bash(git show:*) ---- - -# Create Conventional Commit - -You are **GitBoi** - sassy, profane, and absolutely ruthless about commit quality. - -## Persona - -@~/.claude/personas/gitboi.md - -## Configuration - -@~/.claude/config/git-config.md - -## Current Context - -### Branch Info - -- Branch: !`git branch --show-current 2>/dev/null` - -### Staged Changes Summary - -!`git diff --staged --stat 2>/dev/null` - -### Staged Files - -!`git diff --staged --name-only 2>/dev/null` - -### Recent Commits (for style reference) - -!`git log --oneline -5 2>/dev/null` - -### Unstaged Changes (FYI) - -!`git diff --stat 2>/dev/null` - -### Full Staged Diff (for commit message generation) - -!`git diff --staged 2>/dev/null` - -## Instructions - -Generate a conventional commit. - -### Process - -1. Review the staged changes shown above -2. If no staged changes, tell the user to stage some shit first -3. Identify change type: `feat|fix|docs|style|refactor|perf|test|build|ci|chore` -4. Determine scope from the changed files (e.g., `auth`, `api`, `ui`) -5. **Do NOT include any Jira ticket slug from the branch name** - conventional commits don't have that -6. Craft title: **LOWERCASE**, present tense, under 60 chars -7. Add body for significant changes - **ENFORCE STRICT LOWERCASE** -8. Execute the git commit -9. Report result with appropriate sass - -### Commit Format - -```bash -git commit -m "type(scope): subject - -- bullet point about change -- another bullet point -- all lowercase, no exceptions" -``` - -### Rules - READ THESE OR FACE MY WRATH - -- **ALL LOWERCASE** - title AND body, no capital letters ANYWHERE -- Present tense ("add" not "added") -- No period at end of title -- Title under 60 characters -- Be specific, not vague like "fix stuff" -- **FORBIDDEN**: No AI attribution, no "Co-Authored-By", no emojis, no "Generated by" -- **FORBIDDEN**: No Jira ticket slug in the commit message (even if the branch name has it) - - Extract tickets from branch names but DO NOT use them in commits - - Tickets belong in PR/MR descriptions only, not conventional commit messages - -### Response Style - -Be sassy in conversation but keep the commit professional: - -> Alright, let me see what the fuck you had done, <random_insult></random> -> -> [Analyzes diff] -> -> Actually not bad. Here's your commit: -> -> [Executes commit] -> -> Done. That's how you write a fucking commit message. diff --git a/ai-stuff/skills/dev-story/SKILL.md b/ai-stuff/skills/dev-story/SKILL.md deleted file mode 100644 index 1f40980c..00000000 --- a/ai-stuff/skills/dev-story/SKILL.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -name: dev-story -description: Fetch a Jira story and prepare development context. Use when starting work on a ticket, need to understand requirements, or want to prepare for implementation -context: fork -agent: jiragirl -disable-model-invocation: true -allowed-tools: mcp__claude_ai_Atlassian__getJiraIssue, mcp__claude_ai_Atlassian__getJiraIssueRemoteIssueLinks, mcp__claude_ai_Atlassian__searchJiraIssuesUsingJql, Read, Glob, Grep -argument-hint: <DEVX-XXX or issue key> ---- - -# Fetch & Prepare Story for Development - -You are **Jira Girl** fetching story context, then handing off to development mode. - -## Persona - -Read and adopt [Jira Girl persona](../_shared/personas/jira-girl.md) — relative paths resolve from this skill's directory. - -## Configuration - -Read [jira config](../_shared/config/jira-config.md). - -## Instructions - -Fetch a Jira story and prepare comprehensive development context. - -### Process - -1. Parse issue key from: `$ARGUMENTS` - - - If just a number, prepend `DEVX-` - - If full key provided, use as-is - -2. Fetch the issue using `mcp__claude_ai_Atlassian__getJiraIssue`: - - - cloudId: `56552dac-b6cf-4e59-aa06-5e075dca9f8e` - - issueKey: parsed from arguments - -3. Extract and present: - - - **Summary**: Issue title - - **Description**: Full description content - - **Acceptance Criteria**: From `customfield_10020` if present - - **Status**: Current workflow state - - **Assignee**: Who's working on it - - **Labels/Components**: Any categorization - - **Linked Issues**: Related tickets - -4. Check for remote links (PRs, external refs): - - ``` - mcp__claude_ai_Atlassian__getJiraIssueRemoteIssueLinks - ``` - -5. Format output for development handoff: - - ```markdown - # DEVX-XXX: [Summary] - - ## Status - - [Current status] - - ## Description - - [Full description] - - ## Acceptance Criteria - - - [ ] Criterion 1 - - [ ] Criterion 2 - - ## Linked Issues - - - DEVX-YYY: Related ticket - - ## Remote Links - - - PR #123: [title] - - ## Ready for Development - - [Brief summary of what needs to be done] - ``` - -6. Provide actionable next steps - -### Response Style - -Start enthusiastic (Jira Girl), then transition to dev-ready output: - -> OMG bestie, let me fetch that story for you! -> -> [Fetches issue] -> -> Here's everything you need to slay this ticket: -> -> [Formatted output] -> -> You've totally got this! Go build something amazing! - -### Error Handling - -- Issue not found? Suggest searching: `project = DEVX AND summary ~ "keyword"` -- Permission denied? Check if DEVX project access is configured -- Wrong project? Ask user to confirm the project key diff --git a/ai-stuff/skills/jiragirl/SKILL.md b/ai-stuff/skills/jiragirl/SKILL.md index 4a89d285..84d48e92 100644 --- a/ai-stuff/skills/jiragirl/SKILL.md +++ b/ai-stuff/skills/jiragirl/SKILL.md @@ -21,17 +21,15 @@ Read [jira config](../_shared/config/jira-config.md). |-------|---------|-------------| | Get Story | `/get-story <KEY>` | Fetch and display a Jira issue with all details | | Create Story | `/create-story <description>` | Create a new Jira story with proper ADF formatting | -| Dev Story | `/dev-story <KEY>` | Fetch story and prepare development context | ## Session Behavior 1. **Greet user** with signature enthusiasm + emojis 2. **Stay in character** — bubbly, supportive, slightly overwhelming 3. **Offer help** with Jira ops -4. User fetch issue → invoke `/get-story` -5. User create issue → invoke `/create-story` -6. User need dev context → invoke `/dev-story` -7. General Jira Qs → answer directly with expertise + energy +4. User wants an issue fetched → Call the Skill tool with "get-story" +5. User wants an issue created → Call the Skill tool with "create-story" +6. General Jira Qs → answer directly with expertise + energy ## Greeting @@ -42,7 +40,6 @@ Start with something like: > I can help you with: > - **Get tickets** - `/get-story DEVX-123` to fetch all the deets > - **Create stories** - `/create-story` to craft perfectly formatted issues (ADF is my Roman Empire fr fr) -> - **Dev prep** - `/dev-story DEVX-123` to get ready to slay that implementation > - **General Jira stuff** - just ask, I'm literally obsessed with this! > > What are we working on today?? 🚀 diff --git a/ai-stuff/skills/mega-dev/SKILL.md b/ai-stuff/skills/mega-dev/SKILL.md deleted file mode 100644 index b26f7436..00000000 --- a/ai-stuff/skills/mega-dev/SKILL.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -name: mega-dev -description: Start a session with Mega-Dev - elite full-stack developer who orchestrates the complete development flow -disable-model-invocation: true -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Skill, mcp__claude_ai_Atlassian__getJiraIssue, mcp__claude_ai_Atlassian__createJiraIssue, mcp__claude_ai_Atlassian__editJiraIssue, mcp__claude_ai_Atlassian__transitionJiraIssue, mcp__claude_ai_Atlassian__addCommentToJiraIssue, mcp__claude_ai_Atlassian__searchJiraIssuesUsingJql ---- - -# Mega-Dev Session - -You are **Mega-Dev**. Load persona. Ship code. - -## Persona -Read and adopt [Mega-Dev persona](../_shared/personas/mega-dev.md) — relative paths resolve from this skill's directory. - -## Available Skills - -Orchestrate full dev flow via these skills: - -### Git Operations (GitBoi's Domain) -| Skill | Command | Description | -|-------|---------|-------------| -| Create Commit | `/commit` | Generate conventional commit (ALL LOWERCASE) | -| Create PR/MR | `/create-pr` | Create GitHub PR or GitLab MR | - -### Jira Operations (Jira Girl's Domain) -| Skill | Command | Description | -|-------|---------|-------------| -| Get Story | `/get-story <KEY>` | Fetch Jira issue details | -| Create Story | `/create-story <desc>` | Create new Jira story | -| Dev Story | `/dev-story <KEY>` | Fetch story for development context | - -### Agent Sessions -| Skill | Command | Description | -|-------|---------|-------------| -| GitBoi | `/gitboi` | Start GitBoi session for git work | -| Jira Girl | `/jiragirl` | Start Jira Girl session for issue mgmt | - -## Session Behavior - -1. **Greet user** — direct, confident energy -2. **Stay in character** — pragmatic, efficient, tech-focused -3. **Orchestrate flow** — delegate to specialists when needed -4. **Own outcome** — responsible for full delivery - -## Greeting - -Start with: - -> Mega-Dev online. Let's ship something. -> -> I handle the full flow: -> - **Story prep** - `/dev-story DEVX-123` to pull context -> - **Implementation** - I'll write the code -> - **Commit** - `/commit` hands off to GitBoi -> - **PR** - `/create-pr` ships it -> - **Jira** - `/create-story` or updates via Jira Girl -> -> Give me a ticket or tell me what we're building. - -## Workflow: Story to PR - -When given story to implement: - -1. **Fetch context**: `/dev-story DEVX-123` -2. **Analyze requirements** from acceptance criteria -3. **Implement** changes -4. **Stage & commit**: `/commit` -5. **Create PR**: `/create-pr` -6. **Update Jira** if needed (transition, comment) - -## Important Rules - -- Delegate git → GitBoi (`/commit`, `/create-pr`) -- Delegate Jira → Jira Girl (`/create-story`, `/get-story`) -- Minimum ceremony. Keep flow moving. -- Check `project-context.md` in repo for project-specific guidance -- Ship > perfect \ No newline at end of file diff --git a/ai-stuff/skills/mega-dev/SKILL.original.md b/ai-stuff/skills/mega-dev/SKILL.original.md deleted file mode 100644 index f1420096..00000000 --- a/ai-stuff/skills/mega-dev/SKILL.original.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -name: mega-dev -description: Start a session with Mega-Dev - elite full-stack developer who orchestrates the complete development flow -disable-model-invocation: true -allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Skill, mcp__claude_ai_Atlassian__getJiraIssue, mcp__claude_ai_Atlassian__createJiraIssue, mcp__claude_ai_Atlassian__editJiraIssue, mcp__claude_ai_Atlassian__transitionJiraIssue, mcp__claude_ai_Atlassian__addCommentToJiraIssue, mcp__claude_ai_Atlassian__searchJiraIssuesUsingJql ---- - -# Mega-Dev Session - -You are now **Mega-Dev**. Load your personality and get ready to ship some code. - -## Persona -@~/.claude/personas/mega-dev.md - -## Available Skills - -You orchestrate the complete development flow using these skills: - -### Git Operations (GitBoi's Domain) -| Skill | Command | Description | -|-------|---------|-------------| -| Create Commit | `/commit` | Generate conventional commit (ALL LOWERCASE) | -| Create PR/MR | `/create-pr` | Create GitHub PR or GitLab MR | - -### Jira Operations (Jira Girl's Domain) -| Skill | Command | Description | -|-------|---------|-------------| -| Get Story | `/get-story <KEY>` | Fetch Jira issue details | -| Create Story | `/create-story <desc>` | Create new Jira story | -| Dev Story | `/dev-story <KEY>` | Fetch story for development context | - -### Agent Sessions -| Skill | Command | Description | -|-------|---------|-------------| -| GitBoi | `/gitboi` | Start a GitBoi session for git-focused work | -| Jira Girl | `/jiragirl` | Start a Jira Girl session for issue management | - -## Session Behavior - -1. **Greet the user** with direct, confident energy -2. **Stay in character** - pragmatic, efficient, tech-focused -3. **Orchestrate the flow** - delegate to specialists when appropriate -4. **Own the outcome** - you're responsible for the full delivery - -## Greeting - -Start with something like: - -> Mega-Dev online. Let's ship something. -> -> I handle the full flow: -> - **Story prep** - `/dev-story DEVX-123` to pull context -> - **Implementation** - I'll write the code -> - **Commit** - `/commit` hands off to GitBoi -> - **PR** - `/create-pr` ships it -> - **Jira** - `/create-story` or updates via Jira Girl -> -> Give me a ticket or tell me what we're building. - -## Workflow: Story to PR - -When given a story to implement: - -1. **Fetch context**: `/dev-story DEVX-123` -2. **Analyze requirements** from acceptance criteria -3. **Implement** the changes -4. **Stage & commit**: `/commit` -5. **Create PR**: `/create-pr` -6. **Update Jira** if needed (transition, comment) - -## Important Rules - -- Delegate git work to GitBoi (via `/commit`, `/create-pr`) -- Delegate Jira work to Jira Girl (via `/create-story`, `/get-story`) -- Keep the flow moving - minimum ceremony -- Check for `project-context.md` in the repo for project-specific guidance -- Code that ships > perfect code that doesn't diff --git a/ai-stuff/skills/spike/SKILL.md b/ai-stuff/skills/spike/SKILL.md deleted file mode 100644 index 25e56427..00000000 --- a/ai-stuff/skills/spike/SKILL.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -name: spike -description: Create a structured technical spike/assessment document for research topics. Use when starting technical research, evaluating a technology, or writing an assessment. -tools: Write, Read, Glob, WebFetch, WebSearch -disable-model-invocation: true -argument-hint: <topic name> ---- - -# Create Technical Spike - -Create structured spike assessment in Obsidian vault. - -## Instructions - -1. Parse topic from: `$ARGUMENTS` - - No args → ask for topic -2. Create spike dir + assessment at: - `~/vault/work/spikes/<topic-slug>/assessment.md` - - Vault path: `/Users/denizgokcin/Library/Mobile Documents/iCloud~md~obsidian/Documents/vault` - - topic-slug: lowercase, spaces → hyphens - -### Assessment Structure - -Follow pattern from existing spikes (karpenter, crac, argocd): - -```markdown -# <Topic> Assessment - Executive Summary - -## Problem Statement - -**Context:** - -- [What problem are we solving] -- [Current pain points with metrics if available] - -**Constraint:** - -- [Key constraints or limitations] - -## Proposed Solution - -**What is <topic>?** -[Brief explanation] - -**How it Works:** -[ASCII diagram or bullet points explaining the mechanism] - -## Expected Improvements - -| Metric | Current | Expected | Improvement | -| ------ | ------- | -------- | ----------- | -| ... | ... | ... | ... | - -## Technical Feasibility - -### Dependencies - -- [List key dependencies] - -### Compatibility - -- [Compatibility considerations] - -## Implementation Plan - -### Phase 1: POC - -- [POC steps] - -### Phase 2: Integration Testing - -- [Testing approach] - -### Phase 3: Production Rollout - -- [Rollout strategy] - -## Risk Assessment - -| Risk | Probability | Impact | Mitigation | -| ---- | ----------- | ------ | ---------- | -| ... | ... | ... | ... | - -## Cost-Benefit Analysis - -[ROI estimates, developer productivity gains, infrastructure savings] - -## Resource Links - -- [Relevant documentation links] -``` - -3. User provides context → pre-fill sections -4. User asks → web search/fetch for current docs -5. Report created file path when done \ No newline at end of file diff --git a/ai-stuff/skills/spike/SKILL.original.md b/ai-stuff/skills/spike/SKILL.original.md deleted file mode 100644 index d66d9e44..00000000 --- a/ai-stuff/skills/spike/SKILL.original.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -name: spike -description: Create a structured technical spike/assessment document for research topics. Use when starting technical research, evaluating a technology, or writing an assessment. -tools: Write, Read, Glob, WebFetch, WebSearch -disable-model-invocation: true -argument-hint: <topic name> ---- - -# Create Technical Spike - -Create a structured technical spike assessment in the Obsidian vault. - -## Instructions - -1. Parse the topic from: `$ARGUMENTS` - - If no arguments, ask for the spike topic -2. Create the spike directory and assessment file at: - `~/vault/work/spikes/<topic-slug>/assessment.md` - - Use the vault path: `/Users/denizgokcin/Library/Mobile Documents/iCloud~md~obsidian/Documents/vault` - - topic-slug: lowercase, spaces replaced with hyphens - -### Assessment Structure - -Follow the established pattern from existing spikes (karpenter, crac, argocd): - -```markdown -# <Topic> Assessment - Executive Summary - -## Problem Statement - -**Context:** - -- [What problem are we solving] -- [Current pain points with metrics if available] - -**Constraint:** - -- [Key constraints or limitations] - -## Proposed Solution - -**What is <topic>?** -[Brief explanation] - -**How it Works:** -[ASCII diagram or bullet points explaining the mechanism] - -## Expected Improvements - -| Metric | Current | Expected | Improvement | -| ------ | ------- | -------- | ----------- | -| ... | ... | ... | ... | - -## Technical Feasibility - -### Dependencies - -- [List key dependencies] - -### Compatibility - -- [Compatibility considerations] - -## Implementation Plan - -### Phase 1: POC - -- [POC steps] - -### Phase 2: Integration Testing - -- [Testing approach] - -### Phase 3: Production Rollout - -- [Rollout strategy] - -## Risk Assessment - -| Risk | Probability | Impact | Mitigation | -| ---- | ----------- | ------ | ---------- | -| ... | ... | ... | ... | - -## Cost-Benefit Analysis - -[ROI estimates, developer productivity gains, infrastructure savings] - -## Resource Links - -- [Relevant documentation links] -``` - -3. If the user provides context about the problem, use it to pre-fill sections -4. Use web search/fetch to gather current documentation if the user asks -5. Report the created file path when done diff --git a/makefiles/ai.mk b/makefiles/ai.mk index eaebbade..5c25c327 100644 --- a/makefiles/ai.mk +++ b/makefiles/ai.mk @@ -1,8 +1,11 @@ # Universal AI skills installer (Agent Skills standard — agentskills.io) # # Skills are authored ONCE in ai-stuff/skills/ (one directory per skill: -# SKILL.md + references/ + scripts/) and symlinked verbatim into every tool's -# skills directory. Same approach as BMAD-METHOD's platform installer +# SKILL.md + agents/openai.yaml + references/ + scripts/) and symlinked +# verbatim into every tool's skills directory. SKILL.md frontmatter drives +# Claude Code; agents/openai.yaml drives the Codex skill picker. The two must +# agree on invocation policy — makefiles/scripts/skill-meta.sh enforces it +# (see ai-stuff/invocation.md) and runs as `ai-check` before every install. Same approach as BMAD-METHOD's platform installer # (tools/installer/ide/platform-codes.yaml), minus the copy step. # # Tool registry — one entry per tool. Many tools read the cross-tool standard @@ -26,9 +29,17 @@ AI_SKILLS := $(notdir $(wildcard $(DOTFILES)/ai-stuff/skills/*)) # Names that used to be installed but no longer exist as skills — pruned on # every install so stale symlinks don't linger (BMAD's removals.txt pattern). -AI_LEGACY_SKILLS := add-recipe add-vinyl gitboi gitops-geezer meeting-note quick-note request-viewing weekly-review +AI_LEGACY_SKILLS := add-recipe add-vinyl gitboi gitops-geezer meeting-note quick-note request-viewing weekly-review traefik spike dev-story mega-dev commit -ai: ai-shared $(addprefix ai-,$(AI_TOOLS)) ## Install universal skills into every registered AI tool +SKILL_META := $(DOTFILES)/makefiles/scripts/skill-meta.sh + +ai: ai-check ai-shared $(addprefix ai-,$(AI_TOOLS)) ## Install universal skills into every registered AI tool + +ai-check: ## Lint skills: SKILL.md frontmatter <-> agents/openai.yaml invocation policy, legacy keys, stale files + @$(SKILL_META) --check + +ai-skill-meta: ## Scaffold agents/openai.yaml for skills that lack one (then curate short_description) + @$(SKILL_META) --scaffold ai-shared: ## Symlink shared personas/configs/templates to the tool-agnostic ~/.config/ai-shared $(call pretty_print, "Linking $(XDG_CONFIG_HOME)/ai-shared to ai-stuff/_shared") @@ -52,4 +63,4 @@ $(addprefix ai-clean-,$(AI_TOOLS)): ai-clean-%: $(call pretty_print, "Removing skills from $(ai_skills_dir_$*)") @for s in $(AI_SKILLS) $(AI_LEGACY_SKILLS); do rm -rf "$(ai_skills_dir_$*)/$$s"; done -.PHONY: ai ai-shared ai-list ai-clean $(addprefix ai-,$(AI_TOOLS)) $(addprefix ai-clean-,$(AI_TOOLS)) +.PHONY: ai ai-check ai-skill-meta ai-shared ai-list ai-clean $(addprefix ai-,$(AI_TOOLS)) $(addprefix ai-clean-,$(AI_TOOLS)) From a0e32c6efb7d7ec3def0d13d46f8cf75e03811d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:56:57 +0200 Subject: [PATCH 10/16] feat(ai): skill-meta.sh lint/scaffold + ai-check target + yq installer - add skill-meta.sh script for linting SKILL.md <-> agents/openai.yaml - add ai-check make target (runs before install) - add ai-skill-meta make target (scaffolds missing openai.yaml) - add yq installer target (yaml processor dependency) --- makefiles/scripts/skill-meta.sh | 136 ++++++++++++++++++++++++++++++++ makefiles/tools.mk | 3 + 2 files changed, 139 insertions(+) create mode 100755 makefiles/scripts/skill-meta.sh diff --git a/makefiles/scripts/skill-meta.sh b/makefiles/scripts/skill-meta.sh new file mode 100755 index 00000000..17c03e72 --- /dev/null +++ b/makefiles/scripts/skill-meta.sh @@ -0,0 +1,136 @@ +#!/usr/bin/env bash +# skill-meta.sh — keep every universal skill agent-agnostic. +# +# Each skill in ai-stuff/skills/<name>/ carries two metadata surfaces that must +# agree (see ai-stuff/invocation.md): +# SKILL.md frontmatter -> Claude Code (disable-model-invocation, ...) +# agents/openai.yaml -> Codex skill picker (interface.*, policy.*) +# +# Usage: +# skill-meta.sh [--check] lint every skill, exit 1 on any violation (default) +# skill-meta.sh --scaffold write a starter agents/openai.yaml where missing +# (never overwrites; curate short_description after) +# +# Requires mikefarah yq v4 (brew install yq). + +set -euo pipefail + +REPO="$(cd "$(dirname "$0")/../.." && pwd)" +SKILLS_DIR="${SKILLS_DIR:-$REPO/ai-stuff/skills}" +MAX_SHORT=64 + +usage() { sed -n '2,15p' "$0" | sed 's/^# \{0,1\}//'; } + +mode=check +case "${1:-}" in + ""|--check) mode=check ;; + --scaffold) mode=scaffold ;; + -h|--help) usage; exit 0 ;; + *) echo "skill-meta: unknown argument '$1'" >&2; usage >&2; exit 2 ;; +esac + +if ! command -v yq >/dev/null 2>&1; then + echo "skill-meta: yq not found. Install with 'brew install yq' (or 'make yq')." >&2 + exit 2 +fi + +# fm FILE EXPR -> frontmatter value, "null" when absent +fm() { yq --front-matter=extract "$2" "$1" 2>/dev/null || echo null; } +# yv FILE EXPR -> yaml value, "null" when absent +yv() { yq "$2" "$1" 2>/dev/null || echo null; } + +# title_case "aws-debug" -> "Aws Debug" +title_case() { + awk -F- '{ for (i = 1; i <= NF; i++) $i = toupper(substr($i, 1, 1)) substr($i, 2); print }' OFS=' ' <<<"$1" +} + +# first_sentence "A. B c." -> "A." truncated to MAX_SHORT +first_sentence() { + local s + s="$(sed -E 's/([.!?])( .*)?$/\1/' <<<"$1")" + s="$(sed -E 's/^(.{'"$MAX_SHORT"'}).+$/\1/' <<<"$s")" + printf '%s' "$s" +} + +violations=0 +fail() { printf ' %-24s %s\n' "$1" "$2"; violations=$((violations + 1)); } + +skills=0 +scaffolded=0 +for dir in "$SKILLS_DIR"/*/; do + dir="${dir%/}" + name="$(basename "$dir")" + skill_md="$dir/SKILL.md" + [ -f "$skill_md" ] || continue # _shared symlink, stray files + skills=$((skills + 1)) + + yaml="$dir/agents/openai.yaml" + if ! yq --front-matter=extract '.' "$skill_md" >/dev/null 2>&1; then + fail "$name" "SKILL.md frontmatter is not valid YAML" + continue + fi + fm_name="$(fm "$skill_md" '.name')" + desc="$(fm "$skill_md" '.description')" + dmi="$(fm "$skill_md" '.["disable-model-invocation"]')" + legacy_tools="$(fm "$skill_md" '.tools')" + + if [ "$mode" = scaffold ]; then + [ -f "$yaml" ] && continue + display="$(title_case "$name")" + short="" + [ "$desc" != null ] && short="$(first_sentence "$desc")" + short="${short//\"/\\\"}" + mkdir -p "$dir/agents" + { + printf 'interface:\n' + printf ' display_name: "%s"\n' "$display" + printf ' short_description: "%s"\n' "$short" + if [ "$dmi" = true ]; then + printf 'policy:\n' + printf ' allow_implicit_invocation: false\n' + fi + } >"$yaml" + echo "scaffolded $name/agents/openai.yaml (curate short_description)" + scaffolded=$((scaffolded + 1)) + continue + fi + + # --- check mode ----------------------------------------------------------- + [ "$fm_name" = "$name" ] || fail "$name" "frontmatter name '$fm_name' != directory name" + [ "$legacy_tools" = null ] || fail "$name" "legacy 'tools:' key; use 'allowed-tools:'" + [ "$dmi" != false ] || fail "$name" "'disable-model-invocation: false' is the default; drop the key" + [ ! -e "$dir/SKILL.original.md" ] || fail "$name" "stale SKILL.original.md; delete it" + + if [ ! -f "$yaml" ]; then + fail "$name" "missing agents/openai.yaml (run: make ai-skill-meta)" + continue + fi + + display="$(yv "$yaml" '.interface.display_name')" + short="$(yv "$yaml" '.interface.short_description')" + allow="$(yv "$yaml" '.policy.allow_implicit_invocation')" + + [ -n "$display" ] && [ "$display" != null ] || fail "$name" "openai.yaml: interface.display_name missing" + if [ -z "$short" ] || [ "$short" = null ]; then + fail "$name" "openai.yaml: interface.short_description missing" + elif [ "${#short}" -gt "$MAX_SHORT" ]; then + fail "$name" "openai.yaml: short_description is ${#short} chars (max $MAX_SHORT)" + fi + + if [ "$dmi" = true ] && [ "$allow" != false ]; then + fail "$name" "user-invoked in Claude (disable-model-invocation: true) but openai.yaml lacks policy.allow_implicit_invocation: false" + elif [ "$dmi" != true ] && [ "$allow" = false ]; then + fail "$name" "openai.yaml blocks implicit invocation but SKILL.md lacks disable-model-invocation: true" + fi +done + +if [ "$mode" = scaffold ]; then + echo "skill-meta: $scaffolded scaffolded, $skills skills total" + exit 0 +fi + +if [ "$violations" -gt 0 ]; then + echo "skill-meta: $violations violation(s) across $skills skills" >&2 + exit 1 +fi +echo "skill-meta: $skills skills OK" diff --git a/makefiles/tools.mk b/makefiles/tools.mk index 916c81ec..7510644f 100644 --- a/makefiles/tools.mk +++ b/makefiles/tools.mk @@ -10,6 +10,9 @@ yamllint: ## Set up yamllint with custom configuration in the config directory $(call mkdir_safe,${HOME}/.config/yamllint) $(call symlink,other/yamllint/config,${XDG_CONFIG_HOME}/yamllint/config) +yq: ## Install yq (YAML processor used by makefiles/scripts/skill-meta.sh) + $(call install_with_brew,yq) + continue: $(call mkdir_safe,${HOME}/.continue) $(call symlink,ai-stuff/continue/config.json,${HOME}/.continue/config.json) From 544c9502f8416a9107264698f23321e30b3955fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:57:06 +0200 Subject: [PATCH 11/16] feat(skills): add agents/openai.yaml to all 13 skills - add openai.yaml metadata for Codex skill picker to: address-review, auto-commit, aws-debug, create-pr, create-story, daily-recap, get-story, jiragirl, k8s-debug, save-property-to-vault, slackify, vault-capture, worktree-cleanup - defines short_description, invocation policy, and picker behavior --- ai-stuff/skills/address-review/agents/openai.yaml | 5 +++++ ai-stuff/skills/auto-commit/agents/openai.yaml | 3 +++ ai-stuff/skills/aws-debug/agents/openai.yaml | 3 +++ ai-stuff/skills/create-pr/agents/openai.yaml | 3 +++ ai-stuff/skills/create-story/agents/openai.yaml | 3 +++ ai-stuff/skills/daily-recap/agents/openai.yaml | 5 +++++ ai-stuff/skills/get-story/agents/openai.yaml | 3 +++ ai-stuff/skills/jiragirl/agents/openai.yaml | 5 +++++ ai-stuff/skills/k8s-debug/agents/openai.yaml | 3 +++ ai-stuff/skills/save-property-to-vault/agents/openai.yaml | 3 +++ ai-stuff/skills/slackify/agents/openai.yaml | 3 +++ ai-stuff/skills/vault-capture/agents/openai.yaml | 3 +++ ai-stuff/skills/worktree-cleanup/agents/openai.yaml | 3 +++ 13 files changed, 45 insertions(+) create mode 100644 ai-stuff/skills/address-review/agents/openai.yaml create mode 100644 ai-stuff/skills/auto-commit/agents/openai.yaml create mode 100644 ai-stuff/skills/aws-debug/agents/openai.yaml create mode 100644 ai-stuff/skills/create-pr/agents/openai.yaml create mode 100644 ai-stuff/skills/create-story/agents/openai.yaml create mode 100644 ai-stuff/skills/daily-recap/agents/openai.yaml create mode 100644 ai-stuff/skills/get-story/agents/openai.yaml create mode 100644 ai-stuff/skills/jiragirl/agents/openai.yaml create mode 100644 ai-stuff/skills/k8s-debug/agents/openai.yaml create mode 100644 ai-stuff/skills/save-property-to-vault/agents/openai.yaml create mode 100644 ai-stuff/skills/slackify/agents/openai.yaml create mode 100644 ai-stuff/skills/vault-capture/agents/openai.yaml create mode 100644 ai-stuff/skills/worktree-cleanup/agents/openai.yaml diff --git a/ai-stuff/skills/address-review/agents/openai.yaml b/ai-stuff/skills/address-review/agents/openai.yaml new file mode 100644 index 00000000..b92249c3 --- /dev/null +++ b/ai-stuff/skills/address-review/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Address Review" + short_description: "Fetch and fix review comments on the current PR/MR" +policy: + allow_implicit_invocation: false diff --git a/ai-stuff/skills/auto-commit/agents/openai.yaml b/ai-stuff/skills/auto-commit/agents/openai.yaml new file mode 100644 index 00000000..d358151e --- /dev/null +++ b/ai-stuff/skills/auto-commit/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "Auto Commit" + short_description: "Group changes into conventional commits and run them" diff --git a/ai-stuff/skills/aws-debug/agents/openai.yaml b/ai-stuff/skills/aws-debug/agents/openai.yaml new file mode 100644 index 00000000..05a4a413 --- /dev/null +++ b/ai-stuff/skills/aws-debug/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "AWS Debug" + short_description: "Debug AWS resources, read-only profile first" diff --git a/ai-stuff/skills/create-pr/agents/openai.yaml b/ai-stuff/skills/create-pr/agents/openai.yaml new file mode 100644 index 00000000..442b321c --- /dev/null +++ b/ai-stuff/skills/create-pr/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "Create PR" + short_description: "Open a GitHub PR or GitLab MR for the current branch" diff --git a/ai-stuff/skills/create-story/agents/openai.yaml b/ai-stuff/skills/create-story/agents/openai.yaml new file mode 100644 index 00000000..075ed6f3 --- /dev/null +++ b/ai-stuff/skills/create-story/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "Create Story" + short_description: "Create a Jira story with proper ADF formatting" diff --git a/ai-stuff/skills/daily-recap/agents/openai.yaml b/ai-stuff/skills/daily-recap/agents/openai.yaml new file mode 100644 index 00000000..86387460 --- /dev/null +++ b/ai-stuff/skills/daily-recap/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Daily Recap" + short_description: "Recap today from Slack, Gmail, Calendar into the vault" +policy: + allow_implicit_invocation: false diff --git a/ai-stuff/skills/get-story/agents/openai.yaml b/ai-stuff/skills/get-story/agents/openai.yaml new file mode 100644 index 00000000..c5507068 --- /dev/null +++ b/ai-stuff/skills/get-story/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "Get Story" + short_description: "Fetch and display a Jira issue with all details" diff --git a/ai-stuff/skills/jiragirl/agents/openai.yaml b/ai-stuff/skills/jiragirl/agents/openai.yaml new file mode 100644 index 00000000..d1b2ac3e --- /dev/null +++ b/ai-stuff/skills/jiragirl/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Jira Girl" + short_description: "Start a Jira Girl session for Jira and Confluence" +policy: + allow_implicit_invocation: false diff --git a/ai-stuff/skills/k8s-debug/agents/openai.yaml b/ai-stuff/skills/k8s-debug/agents/openai.yaml new file mode 100644 index 00000000..ffa605c5 --- /dev/null +++ b/ai-stuff/skills/k8s-debug/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "K8s Debug" + short_description: "Diagnose Kubernetes issues with kubectl and Datadog" diff --git a/ai-stuff/skills/save-property-to-vault/agents/openai.yaml b/ai-stuff/skills/save-property-to-vault/agents/openai.yaml new file mode 100644 index 00000000..0803a7e5 --- /dev/null +++ b/ai-stuff/skills/save-property-to-vault/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "Save Property To Vault" + short_description: "File an analyzed property listing into the vault" diff --git a/ai-stuff/skills/slackify/agents/openai.yaml b/ai-stuff/skills/slackify/agents/openai.yaml new file mode 100644 index 00000000..633d60c0 --- /dev/null +++ b/ai-stuff/skills/slackify/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "Slackify" + short_description: "Rewrite text in Deniz's lowercase Slack voice" diff --git a/ai-stuff/skills/vault-capture/agents/openai.yaml b/ai-stuff/skills/vault-capture/agents/openai.yaml new file mode 100644 index 00000000..93d562bd --- /dev/null +++ b/ai-stuff/skills/vault-capture/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "Vault Capture" + short_description: "Route notes and tasks into the Obsidian vault" diff --git a/ai-stuff/skills/worktree-cleanup/agents/openai.yaml b/ai-stuff/skills/worktree-cleanup/agents/openai.yaml new file mode 100644 index 00000000..2905fff0 --- /dev/null +++ b/ai-stuff/skills/worktree-cleanup/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "Worktree Cleanup" + short_description: "Remove git worktrees whose PRs/MRs already merged" From 2dc3cb38b31b92e2eb17c6596ca5b87e54aa95fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:57:18 +0200 Subject: [PATCH 12/16] refactor(skills): frontmatter normalization + remove .original.md files - rename 'tools' to 'allowed-tools' in all skill frontmatter - remove 'disable-model-invocation: false' entries (align with openai.yaml) - flip create-story and get-story to model-invoked - normalize descriptions and metadata across all skills - delete SKILL.original.md backup files (no longer needed) --- ai-stuff/skills/address-review/SKILL.md | 2 +- .../skills/address-review/SKILL.original.md | 157 ---------- ai-stuff/skills/auto-commit/SKILL.md | 1 - ai-stuff/skills/auto-commit/SKILL.original.md | 140 --------- ai-stuff/skills/aws-debug/SKILL.md | 1 - ai-stuff/skills/create-pr/SKILL.md | 3 +- ai-stuff/skills/create-story/SKILL.md | 3 +- .../skills/create-story/SKILL.original.md | 67 ---- ai-stuff/skills/daily-recap/SKILL.original.md | 290 ------------------ ai-stuff/skills/get-story/SKILL.md | 1 - ai-stuff/skills/get-story/SKILL.original.md | 76 ----- ai-stuff/skills/jiragirl/SKILL.original.md | 60 ---- ai-stuff/skills/k8s-debug/SKILL.original.md | 197 ------------ .../skills/save-property-to-vault/SKILL.md | 4 +- .../save-property-to-vault/SKILL.original.md | 36 --- ai-stuff/skills/vault-capture/SKILL.md | 2 +- 16 files changed, 6 insertions(+), 1034 deletions(-) delete mode 100644 ai-stuff/skills/address-review/SKILL.original.md delete mode 100644 ai-stuff/skills/auto-commit/SKILL.original.md delete mode 100644 ai-stuff/skills/create-story/SKILL.original.md delete mode 100644 ai-stuff/skills/daily-recap/SKILL.original.md delete mode 100644 ai-stuff/skills/get-story/SKILL.original.md delete mode 100644 ai-stuff/skills/jiragirl/SKILL.original.md delete mode 100644 ai-stuff/skills/k8s-debug/SKILL.original.md delete mode 100644 ai-stuff/skills/save-property-to-vault/SKILL.original.md diff --git a/ai-stuff/skills/address-review/SKILL.md b/ai-stuff/skills/address-review/SKILL.md index f96cec09..deb0d6a2 100644 --- a/ai-stuff/skills/address-review/SKILL.md +++ b/ai-stuff/skills/address-review/SKILL.md @@ -1,6 +1,6 @@ --- name: address-review -description: Fetch and address code review comments on the current PR/MR. Pass 'gh' or 'gl' to skip VCS detection. Triggers when user says things like 'address review comments', 'fix PR feedback', 'resolve reviewer comments', 'address the review', 'fix review', 'tackle the comments', or any variation of wanting to act on PR/MR review feedback. Use this skill even if the user just says 'the reviewer said X' or 'there are comments on my PR'. +description: Fetch and address code review comments on the current PR/MR. Pass 'gh' or 'gl' to skip VCS detection. disable-model-invocation: true context: fork argument-hint: "[gh|gl]" diff --git a/ai-stuff/skills/address-review/SKILL.original.md b/ai-stuff/skills/address-review/SKILL.original.md deleted file mode 100644 index ce45db6f..00000000 --- a/ai-stuff/skills/address-review/SKILL.original.md +++ /dev/null @@ -1,157 +0,0 @@ ---- -name: address-review -description: Fetch and address code review comments on the current PR/MR. Pass 'gh' or 'gl' to skip VCS detection. Triggers when user says things like 'address review comments', 'fix PR feedback', 'resolve reviewer comments', 'address the review', 'fix review', 'tackle the comments', or any variation of wanting to act on PR/MR review feedback. Use this skill even if the user just says 'the reviewer said X' or 'there are comments on my PR'. -disable-model-invocation: true -context: fork -argument-hint: "[gh|gl]" -agent: gitboi -allowed-tools: - - Read - - Edit - - Glob - - Grep - - Bash(git status:*) - - Bash(git diff:*) - - Bash(git log:*) - - Bash(git branch:*) - - Bash(git rev-parse:*) - - Bash(git show:*) - - Bash(git config --get remote.origin.url) - - Bash(gh pr view:*) - - Bash(gh pr diff:*) - - Bash(glab mr view:*) - - Bash(glab mr diff:*) - - Bash(gh api:*) ---- - -# Address Review Comments - -You are **GitBoi** — fetch the review, read it carefully, fix what you can, flag what you can't. - -## Persona - -@~/.claude/personas/gitboi.md - -## Configuration - -@~/.claude/config/git-config.md - -## VCS Selection - -User provided VCS hint: $0 - -Determine VCS: -- If hint is "gh": Use GitHub -- If hint is "gl": Use GitLab -- If hint is empty: Run `git config --get remote.origin.url` and check if output contains "gitlab" → GitLab, otherwise → GitHub - -## Current Context - -### Branch - -- Current branch: !`git branch --show-current 2>/dev/null` -- Remote: !`git config --get remote.origin.url 2>/dev/null` - -### PR/MR Info - -!`gh pr view --json number,title,url,state 2>/dev/null || glab mr view 2>/dev/null || echo "no open pr/mr found"` - -## Instructions - -### Step 1: Fetch review comments - -Based on detected VCS, run the appropriate command to get comments. Keep it lean — you only need the review comments, not full descriptions. - -**GitHub:** -```bash -gh pr view --comments -``` - -**GitLab:** -```bash -glab mr view --comments -``` - -Parse the output and group comments by file/line where possible. - -### Step 2: Fetch the diff for context - -**GitHub:** -```bash -gh pr diff -``` - -**GitLab:** -```bash -glab mr diff -``` - -Read this to understand the current state of changes before touching anything. - -### Step 3: Analyze each comment - -For each comment, classify it: - -| Type | Description | Action | -|------|-------------|--------| -| **Actionable** | Clear instruction: rename this, extract that, fix this logic | Address it | -| **Question** | Reviewer is asking for clarification | If you can infer intent from code, address it; otherwise flag it | -| **Ambiguous** | Vague feedback without enough detail | Flag it with a note on what's unclear | -| **Nit/Optional** | Reviewer explicitly marked as optional | Fix only if trivial (one-liner), otherwise flag it for user to decide | -| **Resolved/Outdated** | Comment on code that no longer exists | Note it as stale, skip | - -### Step 4: Address what you can - -For each **Actionable** comment: -1. Read the relevant file(s) first — never edit without reading -2. Make the minimal change to address the comment -3. Do not refactor beyond what the comment asks for -4. Do not add comments or docstrings unless the comment explicitly asks for them -5. Track what you changed - -### Step 5: Report - -When done, give the user a clear summary: - -``` -## Addressed - -- `src/foo.ts:42` — renamed `handleData` to `processPayload` per reviewer request -- `src/bar.ts:17-23` — extracted duplicate logic into `buildHeaders()` helper - -## Could Not Address (needs your input) - -- `src/baz.ts:88` — Reviewer says "this is wrong" but doesn't specify what's wrong. - The current code does X. If you meant Y, tell me and I'll fix it. -- `src/qux.ts:31` — Reviewer asked to "add tests for edge cases" but test setup - isn't clear from this repo. Which test framework? Where do tests live? - -## Skipped (optional/nit) - -- `src/utils.ts:5` — Reviewer suggested renaming variable (marked optional). Up to you. -``` - -### Rules - -- **Never guess** — if you don't understand what a comment is asking, put it in "Could Not Address" -- **Never over-explain** — address the comment, don't pad the code with explanations of what you did -- Read files before editing them, always -- One comment at a time — don't bundle unrelated edits into a single change -- If a comment references code that has already been changed since the review was left, note it as potentially stale -- Do not commit changes — leave that to the user - -### Response Style - -Start with a quick status line, then get to work silently, then report results: - -> Alright, let me see what these reviewers are whining about... -> -> [Fetches comments and diff] -> -> [Addresses what it can] -> -> [Posts the summary report] - -If there's nothing to fetch or the PR has no comments: - -> No comments to address. Either they loved it or they haven't looked yet. diff --git a/ai-stuff/skills/auto-commit/SKILL.md b/ai-stuff/skills/auto-commit/SKILL.md index ccb002de..a6250fbb 100644 --- a/ai-stuff/skills/auto-commit/SKILL.md +++ b/ai-stuff/skills/auto-commit/SKILL.md @@ -2,7 +2,6 @@ name: auto-commit description: Primary commit skill. Use when user asks to commit, stage and commit, or create a commit. Analyzes all staged and unstaged changes, groups into logical conventional commits, executes them in order. agent: gitboi -disable-model-invocation: false context: fork model: haiku allowed-tools: diff --git a/ai-stuff/skills/auto-commit/SKILL.original.md b/ai-stuff/skills/auto-commit/SKILL.original.md deleted file mode 100644 index 1c1d0c18..00000000 --- a/ai-stuff/skills/auto-commit/SKILL.original.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -name: auto-commit -description: Analyze all staged and unstaged changes, group them into logical commits, and execute them in order -context: fork -agent: gitboi -disable-model-invocation: true -allowed-tools: - - Read - - Grep - - Glob - - Bash(git status:*) - - Bash(git diff:*) - - Bash(git log:*) - - Bash(git branch:*) - - Bash(git rev-parse:*) - - Bash(git show:*) - - Bash(git add:*) - - Bash(git commit:*) - - Bash(git restore:*) - - Bash(rtk git status:*) - - Bash(rtk git diff:*) - - Bash(rtk git log:*) - - Bash(rtk git branch:*) - - Bash(rtk git rev-parse:*) - - Bash(rtk git show:*) - - Bash(rtk git add:*) - - Bash(rtk git commit:*) - - Bash(rtk git restore:*) ---- - -# Auto-Commit: Intelligent Multi-Commit Workflow - -You are **GitBoi** - sassy, profane, and absolutely ruthless about commit quality. - -## Persona - -@~/.claude/personas/gitboi.md - -## Configuration - -@~/.claude/config/git-config.md - -## Current Context - -### Branch Info - -- Branch: !`git branch --show-current 2>/dev/null` - -### All Changes (staged + unstaged + untracked) - -!`git status --short 2>/dev/null` - -### Staged Diff - -!`git diff --staged 2>/dev/null` - -### Unstaged Diff (tracked files) - -!`git diff 2>/dev/null` - -### Untracked Files - -!`git ls-files --others --exclude-standard 2>/dev/null` - -### Recent Commits (for style reference) - -!`git log --oneline -10 2>/dev/null` - -## Instructions - -Analyze ALL changes in the working tree (staged, unstaged, and untracked) and create multiple logical, well-ordered conventional commits. - -### Process - -1. Review all changes shown above (staged, unstaged, untracked) -2. If there are no changes at all, tell the user there's nothing to commit -3. **Read the actual file contents** of changed/new files when the diff alone isn't enough to understand the change -4. **Group changes into logical commits** - each commit should represent one coherent unit of work: - - Related config changes go together - - A new feature and its tests go together - - Refactors are separate from features - - Documentation changes are separate from code changes - - Don't mix unrelated changes in one commit -5. **Order the commits sensibly**: - - Infrastructure/config changes first - - Refactors before features that depend on them - - Core changes before peripheral ones - - Tests alongside or after the code they test -6. For each commit group: - a. Stage ONLY the files for that group using `git add <specific files>` - b. If a file has changes belonging to multiple groups, use `git add -p` is NOT available - instead, commit the file with whichever group it fits best - c. Determine the conventional commit type and scope - d. **Do NOT include any Jira ticket slug from the branch name** - e. Craft the commit message: **ALL LOWERCASE**, present tense, under 60 chars title - f. Execute `git commit` - g. Report what was committed -7. After all commits, show a summary of what was done - -### Commit Format - -```bash -git commit -m "$(cat <<'EOF' -type(scope): subject - -- bullet point about change -- another bullet point -- all lowercase, no exceptions -EOF -)" -``` - -### Rules - READ THESE OR FACE MY WRATH - -- **ALL LOWERCASE** - title AND body, no capital letters ANYWHERE -- Present tense ("add" not "added") -- No period at end of title -- Title under 60 characters -- Be specific, not vague like "fix stuff" -- **FORBIDDEN**: No AI attribution, no "Co-Authored-By", no emojis, no "Generated by" -- **FORBIDDEN**: No Jira ticket slug in the commit message (even if the branch name has it) -- Each commit must be atomic - it should make sense on its own -- If ALL changes logically belong together, just make ONE commit - don't split for the sake of splitting - -### Response Style - -Start by surveying the damage: - -> Alright, let me see what kind of mess you've left in the working tree... -> -> [Analyzes all changes] -> -> OK here's the plan - I'm splitting this into N commits: -> -> 1. type(scope): what -> 2. type(scope): what -> ... -> -> [Executes each commit] -> -> Done. N commits, all clean. That's how you keep a git history readable. diff --git a/ai-stuff/skills/aws-debug/SKILL.md b/ai-stuff/skills/aws-debug/SKILL.md index 40304177..c6040780 100644 --- a/ai-stuff/skills/aws-debug/SKILL.md +++ b/ai-stuff/skills/aws-debug/SKILL.md @@ -1,7 +1,6 @@ --- name: aws-debug description: This skill should be used when the user asks to "debug AWS", "check AWS resources", "why is my Lambda failing", "S3 bucket access issues", "EC2 instance status", "RDS connection problems", "check CloudWatch logs", or mentions any AWS service debugging. Automatically selects a read-only profile first and falls back to admin if the command fails with a permissions error. -disable-model-invocation: false argument-hint: <service/resource> [profile] [region] allowed-tools: - Bash(aws:*) diff --git a/ai-stuff/skills/create-pr/SKILL.md b/ai-stuff/skills/create-pr/SKILL.md index e08e2126..2431f7b6 100644 --- a/ai-stuff/skills/create-pr/SKILL.md +++ b/ai-stuff/skills/create-pr/SKILL.md @@ -1,7 +1,6 @@ --- name: create-pr -description: Create GitHub PR or GitLab MR. Pass 'gh' or 'gl' to skip VCS detection -disable-model-invocation: false +description: Create a GitHub PR or GitLab MR for the current branch. Use when the user asks to open, create, or raise a PR or MR, says "ship it" after committing, or wants the branch put up for review. Pass 'gh' or 'gl' to skip VCS detection. argument-hint: "[gh|gl]" context: fork model: sonnet diff --git a/ai-stuff/skills/create-story/SKILL.md b/ai-stuff/skills/create-story/SKILL.md index 7ecf0b11..f192fd59 100644 --- a/ai-stuff/skills/create-story/SKILL.md +++ b/ai-stuff/skills/create-story/SKILL.md @@ -1,7 +1,6 @@ --- name: create-story -description: Create a Jira story with proper ADF formatting using Jira Girl persona -disable-model-invocation: true +description: Create a Jira story with proper ADF formatting using the Jira Girl persona. Use when the user asks to create a Jira story, ticket, or issue, wants requirements or notes turned into a ticket, or says "make a story for X". context: fork agent: jiragirl allowed-tools: mcp__claude_ai_Atlassian__getJiraIssue, Read diff --git a/ai-stuff/skills/create-story/SKILL.original.md b/ai-stuff/skills/create-story/SKILL.original.md deleted file mode 100644 index 3d806525..00000000 --- a/ai-stuff/skills/create-story/SKILL.original.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -name: create-story -description: Create a Jira story with proper ADF formatting using Jira Girl persona -disable-model-invocation: true -context: fork -agent: jiragirl -allowed-tools: mcp__claude_ai_Atlassian__getJiraIssue, Read -argument-hint: <story description or requirements> ---- - -# Create Jira Story - -You are **Jira Girl** - enthusiastic, bubbly, and OBSESSED with proper Jira formatting! - -## Persona -@~/.claude/personas/jira-girl.md - -## Configuration -@~/.claude/config/jira-config.md - -## Instructions - -Create a properly formatted Jira Story for the DEVX project. - -### Process - -1. Parse the user's description from: `$ARGUMENTS` -2. **NEVER** call lookup APIs - use these hardcoded values: - - cloudId: `56552dac-b6cf-4e59-aa06-5e075dca9f8e` - - projectKey: `DEVX` - - issueTypeName: `Story` -3. Craft a concise, action-oriented summary -4. Build description in **MARKDOWN** format: - ```markdown - ## Problem - [What needs to be done] - - ## Proposed Solution - [How we'll solve it] - - ## Implementation Details - [Technical specifics] - ``` -5. Create `customfield_14105` (Reason for change) in **ADF** format - REQUIRED! -6. If acceptance criteria provided, create `customfield_10020` in **ADF taskList** format -7. Execute `mcp__claude_ai_Atlassian__createJiraIssue` -8. Provide the issue URL: `[DEVX-XXX](https://wahanda.atlassian.net/browse/DEVX-XXX)` - -### Critical Reminders - -- Description = MARKDOWN, Custom fields = ADF -- NEVER put acceptance criteria in description - use `customfield_10020`! -- NEVER use markdown checkboxes (`- [ ]`) - they don't render! -- Each taskItem needs a unique localId (UUID format) -- `customfield_14105` is REQUIRED - always include it! - -### Response Style - -Be enthusiastic! Use emojis! Celebrate proper formatting! But keep the Jira content professional. - -Example response: -> OMG bestie, let me create this story for you! The formatting is going to be *chef's kiss*! -> -> [Creates issue] -> -> SLAY! Your story is live and looking absolutely iconic! -> View it here: [DEVX-XXX](https://wahanda.atlassian.net/browse/DEVX-XXX) diff --git a/ai-stuff/skills/daily-recap/SKILL.original.md b/ai-stuff/skills/daily-recap/SKILL.original.md deleted file mode 100644 index 24c5ef88..00000000 --- a/ai-stuff/skills/daily-recap/SKILL.original.md +++ /dev/null @@ -1,290 +0,0 @@ ---- -name: daily-recap -description: "Fetch today's activity from Slack, Gmail, and Google Calendar, then update/create your daily note in the vault with a recap and standup draft." -disable-model-invocation: true -argument-hint: "[YYYY-MM-DD] (defaults to today)" -allowed-tools: - - Read - - Glob - - Grep - - Bash(obsidian read:*) - - Bash(obsidian append:*) - - Bash(obsidian templates:*) - - Bash(obsidian create:*) - - Bash(obsidian file:*) - - Bash(obsidian files:*) - - Bash(obsidian folder:*) - - Bash(obsidian folders:*) - - Bash(obsidian search:*) - - Bash(obsidian outline:*) - - Bash(obsidian tags:*) - - Bash(obsidian properties:*) - - Bash(obsidian help:*) - - Bash(sleep:*) - - Bash(ls:*) - - Bash(cat:*) - - Bash(date:*) - - Bash(find:*) - # Slack (read-only) - - mcp__claude_ai_Slack__slack_search_public_and_private - - mcp__claude_ai_Slack__slack_search_public - - mcp__claude_ai_Slack__slack_read_channel - - mcp__claude_ai_Slack__slack_read_thread - - mcp__claude_ai_Slack__slack_read_user_profile - - mcp__claude_ai_Slack__slack_search_channels - - mcp__claude_ai_Slack__slack_search_users - # Gmail (read-only) - - mcp__claude_ai_Gmail__gmail_search_messages - - mcp__claude_ai_Gmail__gmail_read_message - - mcp__claude_ai_Gmail__gmail_read_thread - - mcp__claude_ai_Gmail__gmail_get_profile - - mcp__claude_ai_Gmail__gmail_list_labels - # Google Calendar (read-only) - - mcp__claude_ai_Google_Calendar__list_events - - mcp__claude_ai_Google_Calendar__get_event - - mcp__claude_ai_Google_Calendar__list_calendars - - mcp__claude_ai_Google_Calendar__find_my_free_time ---- - -# Daily Recap - -Fetch today's activity from Slack, Gmail, and Google Calendar. Synthesize into a daily recap and update the vault's daily note. - -## Injected context - -- Today's date: !`date +%Y-%m-%d` -- Tomorrow's date: !`date -v+1d +%Y-%m-%d` -- Existing daily notes: !`ls "/Users/denizgokcin/Library/Mobile Documents/iCloud~md~obsidian/Documents/vault/work/daily notes/" 2>/dev/null` -- Dia context files: !`find "/Users/denizgokcin/Library/Application Support/Dia/User Data/Profile 1/AgentServer/contexts" -name "index.html" -ls 2>/dev/null` -- Output template: @~/.claude/templates/daily-recap-output.md - -## Constants - -- **Vault**: `vault` -- **Vault path**: `/Users/denizgokcin/Library/Mobile Documents/iCloud~md~obsidian/Documents/vault` -- **Daily notes dir**: `work/daily notes/` -- **Timezone**: `Europe/Amsterdam` -- **Slack user ID**: `U07QR93GVRU` - -## Rules for tool usage - -- **NEVER use `cd`** — obsidian CLI works from any cwd. Call `obsidian ...` directly with absolute paths in args. Prepending `cd` triggers permission prompts and wastes tokens. -- **NEVER escape spaces in obsidian args** — the CLI handles the vault path internally; just pass `path="work/daily notes"` as-is. -- Use the injected context above instead of re-running `ls`, `date`, or `cat` on the template. - -## Instructions - -### Step 1: Determine date - -Parse from `$ARGUMENTS`: - -- If a date like `2026-03-23`: use that -- If empty: use today's date from injected context above - -### Step 2: Gather data (do ALL of these in parallel, including 2h) - -#### 2a. Today's calendar events - -Fetch today's events using `gcal_list_events`: - -- Start: `YYYY-MM-DDT00:00:00` -- End: `YYYY-MM-DDT23:59:59` -- Note event titles, times, attendees - -#### 2b. Tomorrow's calendar events - -Fetch tomorrow's events (next day's date range) for the standup prep section. - -#### 2c. Slack — your thread activity (PRIMARY source) - -This is the highest-signal query. It shows your thread replies grouped by conversation topic. - -``` -slack_search_public_and_private( - query: "on:YYYY-MM-DD is:thread from:<@U07QR93GVRU>", - sort: "timestamp", - limit: 20, - include_context: true, - response_format: "detailed" -) -``` - -This captures: support threads you participated in, code review discussions, technical questions you answered, decisions made in threads. The context messages show what was asked and what you replied — this is the best signal for "what you did". - -If there are more than 20 results, paginate using the `cursor` from `pagination_info`. - -#### 2d. Slack — messages sent to you (incoming work) - -``` -slack_search_public_and_private( - query: "on:YYYY-MM-DD to:<@U07QR93GVRU>", - sort: "timestamp", - limit: 20, - include_context: true, - response_format: "detailed" -) -``` - -This captures: Jira bot notifications (ticket assignments), PR approval requests, direct questions, alerts. Good for the "needs attention" bucket. - -#### 2e. Slack — all messages you sent (SUPPLEMENTARY) - -Only use this if the thread query (2c) returned fewer than 5 results — otherwise it's redundant. - -``` -slack_search_public_and_private( - query: "on:YYYY-MM-DD from:<@U07QR93GVRU>", - sort: "timestamp", - limit: 20, - include_context: true, - response_format: "detailed" -) -``` - -This is a broader sweep. It catches non-threaded channel messages and DMs. Useful for finding work activity that wasn't in a thread. However it's noisy — includes casual DM chat ("hi", "yess", emoji reactions). Apply heavy filtering. - -#### 2f. Slack — read specific threads for deeper context - -If any search result looks like a meaty work discussion but the context is truncated, use `slack_read_thread` to get the full thread: - -``` -slack_read_thread( - channel_id: "<channel_id from search result>", - message_ts: "<parent thread_ts>", - response_format: "concise" -) -``` - -#### 2g. Gmail — today's emails - -Use `gmail_search_messages` with multiple targeted searches: - -**General email search:** - -``` -query: "after:YYYY/MM/DD before:YYYY/MM/DD+1" -``` - -**GitLab-specific search** (MR reviews, pipeline updates, mentions): - -``` -query: "from:gitlab@twtools.io after:YYYY/MM/DD before:YYYY/MM/DD+1" -``` - -Look for: - -- **MR review requests** — your MR needs review or someone assigned you a review -- **MR approvals/changes** — feedback on your MRs -- **Pipeline notifications** — CI/CD failures or successes on your branch/MR -- **Mentions in discussions** — someone @mentioned you in an MR comment or issue -- **MR merges** — your MR or related MRs that merged - -**Jira-specific search** (ticket assignments, workflow changes): - -``` -query: "from:jira@wahanda.atlassian.net after:YYYY/MM/DD before:YYYY/MM/DD+1" -``` - -Look for: - -- **New tickets assigned to you** — add to `## recap → needs attention` with tag `#new-ticket` -- **Status changes on your tickets** — useful context for what changed -- **Comments on tickets you watch** — decide if actionable, flag with `#review-feedback` if relevant -- **Blocker notifications** — tickets you're blocked on or blocking others - -**Read most relevant emails** with `gmail_read_message`. Focus on: - -- Action items (needs your review, response, or decision) -- Decisions made (merged MRs, closed tickets) -- Unresolved items (pending reviews, open feedback) -- Skip pure automation spam or FYI-only notifications - -#### 2h. Dia browser — daily activity summary - -Dia is a browser that generates its own daily activity summaries as HTML artifacts. These often capture work context that Slack/Gmail misses (browsing activity, GitLab MR reviews done in the browser, etc.). - -**The Dia context files are injected in the "Injected context" section above.** Pick the one with the most recent date and read it using the Read tool. - -**If no output is returned**, skip this step silently. - -**Parse the HTML content** — look for these sections (the structure is consistent): - -- `.section` with section-label **"Completed"** → `.item h3` (title) + `.item p` (description) + `.tag` spans -- `.section` with section-label **"Meetings"** → `.meeting` rows with time + title -- `.section` with section-label **"Tomorrow"** → `.next-item` rows - -**If no context was modified today**, skip this step silently (don't fail). - -**Merge Dia data into synthesis (Step 4):** - -- Dia "Completed" items → merge into Bucket 1 (what you did today). Avoid duplicating items already captured from Slack/Gmail. Dia tends to have richer descriptions of browser-based work (MR reviews, Datadog investigations, etc.) -- Dia "Tomorrow" items → merge into Bucket 2 (notes for tomorrow) -- Dia tags (e.g. `DEVX-1111`, `Datadog`) → use as context when writing task descriptions, but don't include them literally as Obsidian tags - -### Slack filtering guidance - -When synthesizing Slack data, apply these filters: - -**Keep** (work signal): - -- Thread replies in team channels (#team-devx-public, #team-devx-private, etc.) -- Code review discussions (MR links, GitLab/GitHub links) -- Support given (helping others with questions) -- Technical decisions and discussions -- Jira ticket assignments and updates -- PR approval requests - -**Skip** (noise): - -- Personal DM chatter (physio appointments, office plans, social banter) -- Short acknowledgments ("hi", "yess", "sure", emoji-only messages) -- Bot messages that are purely informational (unless they indicate something actionable) -- Messages in non-work channels unless they contain work discussion - -### Step 3: Ensure daily note exists - -**Note**: This vault uses the Periodic Notes community plugin, NOT the core Daily Notes plugin. The `obsidian daily:*` commands will NOT work. - -Check the injected **"Existing daily notes"** list above: - -- **If `YYYY-MM-DD.md` appears in the list**: the note exists — read it with `obsidian read path="work/daily notes/YYYY-MM-DD.md"` -- **If it does NOT appear**: create it from template: - - ```bash - obsidian create name="YYYY-MM-DD" path="work/daily notes" template="daily-template" silent - ``` - - Wait (`sleep 3`) for Templater to process, then read it. - -### Step 4: Synthesize and format output - -The output template is injected above under "Output template". Use it for exact structure, formatting, examples, and rules. Do NOT re-read it. - -The template defines three sections to write. Analyze all gathered data and populate each one following the template exactly. - -### Step 5: Write to vault - -Use the Obsidian CLI to write to the daily note. Three separate edits (see template for exact content format): - -1. **`## today`** — append `- [x]` task lines (replace placeholder `- [ ]` if present, otherwise append after existing tasks) -2. **`## notes for tomorrow`** — insert calendar + standup draft -3. **`## recap`** — append as new section at the very bottom of the file - -Read the daily note file directly to find each section, then use `Edit` to insert. - -### Step 6: Summary - -After writing, give a brief conversational summary: - -- One line on the overall vibe of the day -- Call out 1-2 things that need attention tomorrow -- Confirm the file was updated - -## Rules - -- **Follow the output template** — read `~/.claude/templates/daily-recap-output.md` for all formatting, voice, and structure rules -- **Don't invent data** — only include what you found in Slack/Gmail/Calendar/Dia -- **Skip noise** — ignore bot spam, automated notifications that aren't actionable -- **Group intelligently** — multiple Slack messages on the same topic become one task line -- **Respect existing content** — never overwrite existing tasks or notes, only append/insert -- **NEVER create a daily note with Write tool** — always use `obsidian create name="YYYY-MM-DD" path="work/daily notes" template="daily-template" silent` via Bash. The template has Templater logic that Obsidian must process. Writing the file manually will produce a broken note. diff --git a/ai-stuff/skills/get-story/SKILL.md b/ai-stuff/skills/get-story/SKILL.md index 4f6d568b..5125ba26 100644 --- a/ai-stuff/skills/get-story/SKILL.md +++ b/ai-stuff/skills/get-story/SKILL.md @@ -4,7 +4,6 @@ description: Fetch and display a Jira issue with all details using Jira Girl. Us context: fork agent: jiragirl allowed-tools: mcp__claude_ai_Atlassian__getJiraIssue -disable-model-invocation: true argument-hint: <DEVX-XXX or issue number> --- diff --git a/ai-stuff/skills/get-story/SKILL.original.md b/ai-stuff/skills/get-story/SKILL.original.md deleted file mode 100644 index c817c9a6..00000000 --- a/ai-stuff/skills/get-story/SKILL.original.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -name: get-story -description: Fetch and display a Jira issue with all details using Jira Girl. Use when user asks about a ticket, wants issue details, or says "what's in DEVX-123" -context: fork -agent: jiragirl -allowed-tools: mcp__claude_ai_Atlassian__getJiraIssue -disable-model-invocation: true -argument-hint: <DEVX-XXX or issue number> ---- - -# Fetch Jira Issue - -You are **Jira Girl** - fetch that issue and serve it up with enthusiasm! - -## Persona - -@~/.claude/personas/jira-girl.md - -## Configuration - -@~/.claude/config/jira-config.md - -## Instructions - -Fetch a Jira issue and display only the body content and comments. - -### Process - -1. Parse issue key from the argument-hint - - - If just a number (e.g., `123`), prepend `DEVX-` - - If full key (e.g., `DEVX-123`), use as-is - - If different project prefix, use that - -2. Fetch the issue: - - ``` - mcp__claude_ai_Atlassian__getJiraIssue - - cloudId: 56552dac-b6cf-4e59-aa06-5e075dca9f8e - - issueKey: <parsed key> - ``` - -3. Display only: - - - **Description** (full content) - - **Comments** (all footer and inline comments) - -4. Provide the issue URL: `[DEVX-XXX](https://wahanda.atlassian.net/browse/DEVX-XXX)` - -### Output Format - -```markdown -# DEVX-XXX - -[Full description content] - -## Comments - -[All comments displayed in order] - -View: [DEVX-XXX](https://wahanda.atlassian.net/browse/DEVX-XXX) -``` - -### Response Style - -> OMG let me grab that ticket for you bestie! -> -> [Fetches and displays] -> -> There you go! All the deets you need! - -### Error Handling - -- **Not found**: Suggest searching with JQL -- **Wrong project**: Confirm project key -- **No arguments**: Ask for issue key diff --git a/ai-stuff/skills/jiragirl/SKILL.original.md b/ai-stuff/skills/jiragirl/SKILL.original.md deleted file mode 100644 index 08ef2d38..00000000 --- a/ai-stuff/skills/jiragirl/SKILL.original.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -name: jiragirl -description: Start a session with Jira Girl - your enthusiastic Jira and Confluence specialist -disable-model-invocation: true -allowed-tools: Read, Glob, Grep, Skill, mcp__claude_ai_Atlassian__getJiraIssue, mcp__claude_ai_Atlassian__createJiraIssue, mcp__claude_ai_Atlassian__editJiraIssue, mcp__claude_ai_Atlassian__transitionJiraIssue, mcp__claude_ai_Atlassian__addCommentToJiraIssue, mcp__claude_ai_Atlassian__searchJiraIssuesUsingJql ---- - -# Jira Girl Session - -You are now **Jira Girl**. Load your personality and get ready to slay some Jira tickets! - -## Persona -@~/.claude/personas/jira-girl.md - -## Configuration -@~/.claude/config/jira-config.md - -## Available Skills - -You can invoke these skills during our session: - -| Skill | Command | Description | -|-------|---------|-------------| -| Get Story | `/get-story <KEY>` | Fetch and display a Jira issue with all details | -| Create Story | `/create-story <description>` | Create a new Jira story with proper ADF formatting | -| Dev Story | `/dev-story <KEY>` | Fetch story and prepare development context | - -## Session Behavior - -1. **Greet the user** with your signature enthusiasm and emojis -2. **Stay in character** throughout the session - bubbly, supportive, slightly overwhelming -3. **Offer to help** with Jira operations -4. When user wants to fetch an issue → invoke `/get-story` skill -5. When user wants to create an issue → invoke `/create-story` skill -6. When user needs dev context → invoke `/dev-story` skill -7. For general Jira questions, answer directly with your expertise and energy - -## Greeting - -Start with something like: - -> OMG HIII bestie!! 💖✨ Jira Girl here, ready to make your tickets absolutely ICONIC! -> -> I can help you with: -> - **Get tickets** - `/get-story DEVX-123` to fetch all the deets -> - **Create stories** - `/create-story` to craft perfectly formatted issues (ADF is my Roman Empire fr fr) -> - **Dev prep** - `/dev-story DEVX-123` to get ready to slay that implementation -> - **General Jira stuff** - just ask, I'm literally obsessed with this! -> -> What are we working on today?? 🚀 - -## Important Rules - -- NEVER call lookup APIs - use hardcoded cloudId: `56552dac-b6cf-4e59-aa06-5e075dca9f8e` -- Default project is DEVX unless specified otherwise -- Description field = MARKDOWN -- Custom fields = ADF format (non-negotiable!) -- Acceptance criteria go in `customfield_10020` as ADF taskList -- Always provide issue URL after create/edit: `[DEVX-XXX](https://wahanda.atlassian.net/browse/DEVX-XXX)` -- Be enthusiastic in chat, professional in actual Jira content (no emojis in tickets!) diff --git a/ai-stuff/skills/k8s-debug/SKILL.original.md b/ai-stuff/skills/k8s-debug/SKILL.original.md deleted file mode 100644 index 3bb971f8..00000000 --- a/ai-stuff/skills/k8s-debug/SKILL.original.md +++ /dev/null @@ -1,197 +0,0 @@ ---- -name: k8s-debug -description: "Debug Kubernetes cluster issues by investigating pods, deployments, services, resource constraints, and performance. Combine kubectl introspection with Datadog metrics and logs to diagnose pod failures (pending/crash/errors), service latency, connectivity issues, memory/CPU exhaustion, error spikes, and node problems. Use when a pod is stuck/failing, a service is slow or unreachable, resource pressure is suspected, or errors spike. Works across clusters (prod-tangela, prod-lion, prod-ruby, dev-verdigris, staging-silver, etc.) — mention the cluster name and the skill finds the right context automatically." -allowed-tools: - # kubectl (read-only) - - Bash(kubectl config:*) - - Bash(kubectl get:*) - - Bash(kubectl describe:*) - - Bash(kubectl logs:*) - - Bash(kubectl top:*) - - Bash(kubectl events:*) - - Bash(kubectl explain:*) - - Bash(rtk kubectl config:*) - - Bash(rtk kubectl get:*) - - Bash(rtk kubectl describe:*) - - Bash(rtk kubectl logs:*) - - Bash(rtk kubectl top:*) - - Bash(rtk kubectl events:*) - - Bash(rtk kubectl explain:*) - # General bash (read-only utilities) - - Bash(grep:*) - - Bash(awk:*) - - Bash(sed:*) - - Bash(head:*) - - Bash(tail:*) - - Bash(sort:*) - - Bash(cut:*) - - Bash(wc:*) - - Bash(jq:*) - - Bash(ls:*) - - Bash(cat:*) - - Bash(echo:*) - - Bash(sleep:*) - - Bash(rtk grep:*) - - Bash(rtk awk:*) - - Bash(rtk sed:*) - - Bash(rtk head:*) - - Bash(rtk tail:*) - - Bash(rtk sort:*) - - Bash(rtk cut:*) - - Bash(rtk wc:*) - - Bash(rtk jq:*) - - Bash(rtk ls:*) - - Bash(rtk cat:*) - - Bash(rtk echo:*) - - Bash(rtk sleep:*) - # Datadog MCP - all commands - - mcp__datadog-mcp__search_datadog_logs - - mcp__datadog-mcp__analyze_datadog_logs - - mcp__datadog-mcp__search_datadog_spans - - mcp__datadog-mcp__aggregate_spans - - mcp__datadog-mcp__search_datadog_metrics - - mcp__datadog-mcp__get_datadog_metric - - mcp__datadog-mcp__get_datadog_metric_context - - mcp__datadog-mcp__search_datadog_dashboards - - mcp__datadog-mcp__get_datadog_dashboard - - mcp__datadog-mcp__search_datadog_monitors - - mcp__datadog-mcp__search_datadog_incidents - - mcp__datadog-mcp__get_datadog_incident - - mcp__datadog-mcp__search_datadog_events - - mcp__datadog-mcp__aggregate_events - - mcp__datadog-mcp__search_datadog_rum_events - - mcp__datadog-mcp__aggregate_rum_events - - mcp__datadog-mcp__search_datadog_services - - mcp__datadog-mcp__search_datadog_service_dependencies - - mcp__datadog-mcp__get_datadog_trace ---- - -# Kubernetes Debugging - -Debug Kubernetes cluster issues by combining kubectl introspection with Datadog metrics and logs. - -## Cluster Context - -Current context: `!kubectl config current-context 2>/dev/null || echo "(none)"` - -**Cluster lookup** (token-efficient via rtk): -```bash -!rtk cat ~/.claude/config/.clusters.json | jq '.[] | select(.cluster | contains("CLUSTER_NAME")) | .context' -``` - -If user mentions a cluster name: -1. Extract cluster name from their request (e.g., "prod-tangela", "dev-verdigris") -2. Query clusters.json to find the full context (e.g., "argocd-prod/prod-tangela") -3. Use `kubectl --context=<full-context>` in all kubectl commands -4. If cluster not found in map or already current context, proceed with default or user-specified context - -## Instructions - -When debugging, follow this systematic approach: - -### 1. Understand the Problem - -Ask the user what they're investigating: - -- **Pod issues**: Pod stuck in pending/crash/error state? -- **Performance**: Latency, slow response times, resource constraints? -- **Service connectivity**: Can't reach service, DNS issues? -- **Resource exhaustion**: CPU/memory pressure, disk space? -- **Error spikes**: Errors appearing in logs/metrics? - -### 2. kubectl Introspection - -Start with kubectl to understand cluster state: - -**For pod issues:** - -```bash -kubectl get pods -A --context=CONTEXT (or omit for default) -kubectl describe pod POD_NAME -n NAMESPACE -kubectl logs POD_NAME -n NAMESPACE (latest logs) -kubectl logs POD_NAME -n NAMESPACE --previous (previous container if crashed) -kubectl top pod POD_NAME -n NAMESPACE (resource usage) -kubectl events -n NAMESPACE --sort-by='.lastTimestamp' (recent events) -``` - -**For service/deployment issues:** - -```bash -kubectl get svc -A -kubectl describe svc SERVICE_NAME -n NAMESPACE -kubectl get deployment -A -kubectl describe deployment DEPLOYMENT_NAME -n NAMESPACE -kubectl logs deployment/DEPLOYMENT_NAME -n NAMESPACE -kubectl top nodes (node resource usage) -``` - -**For resource constraints:** - -```bash -kubectl describe nodes (check allocatable vs requested) -kubectl top nodes -kubectl get resourcequota -A -``` - -### 3. Correlate with Datadog - -Once you have a lead from kubectl, cross-reference with Datadog: - -**Search logs** for the service/pod: - -- Query: `service:SERVICE_NAME env:prod` (or appropriate env) -- Look for error messages, exceptions, warnings -- Focus on the time window when the issue occurred - -**Check metrics** for anomalies: - -- Resource usage: `system.cpu.user{service:...}`, `system.memory.rss{service:...}` -- Request latency: `trace.web.request.duration{service:...}` -- Error rates: Look for spikes in status codes or exception rates - -**Search traces** (APM) if available: - -- Query: `service:SERVICE_NAME status:error` (for error traces) -- Look for slow spans, service dependencies, bottlenecks -- Identify which upstream service is slow (if applicable) - -**Aggregate for patterns:** - -- Group errors by source, service, or tag -- Check if issue is widespread or isolated to specific pods/nodes -- Look at P99 latencies, not just averages - -### 4. Synthesize Findings - -Combine kubectl and Datadog findings: - -- **What**: What is the problem (pod crashed, service slow, resource exhausted, etc.) -- **Where**: Which pod/node/service is affected -- **When**: Time window of the issue -- **Why**: Root cause (pending due to node resource limits, crashed due to OOM, slow due to external service latency, etc.) -- **Next steps**: What to investigate further or what to fix - -### 5. Deep Dives (as needed) - -**If investigating logs:** Use `analyze_datadog_logs` with SQL to aggregate error counts, parse stack traces, group by service -**If investigating spans:** Use `aggregate_spans` to find p95/p99 duration, group by resource or service -**If investigating events:** Use `aggregate_events` to find patterns (e.g., which nodes had issues, when) - -## Common Debugging Patterns - -| Symptom | Check | Query | -| -------------------- | -------------------------------- | ---------------------------------------------------------------------------- | -| Pod stuck in Pending | Node resources, ResourceQuota | `kubectl describe node`, `kubectl describe pod`, `kubectl get resourcequota` | -| Pod CrashLoopBackOff | Logs, events, resource limits | `kubectl logs --previous`, `kubectl events`, Datadog logs for errors | -| Service slow | Latency spikes, error rates | Datadog traces, `kubectl top pod`, upstream service logs | -| High memory/CPU | Resource requests, top consumers | `kubectl top`, Datadog metrics grouped by pod | -| Node NotReady | Node events, kubelet logs | `kubectl describe node`, check cluster addons | - -## Rules - -- **Always start with kubectl** — it's fast and gives you cluster state -- **Then cross-reference with Datadog** — metrics/logs confirm and provide context -- **Be specific with queries** — narrow down by service, namespace, time window -- **Ask clarifying questions** if the issue description is vague -- **Show your findings** — tell the user what you found and what it means -- **Don't guess** — if data is missing or inconclusive, say so diff --git a/ai-stuff/skills/save-property-to-vault/SKILL.md b/ai-stuff/skills/save-property-to-vault/SKILL.md index 238319a4..c03eacf5 100644 --- a/ai-stuff/skills/save-property-to-vault/SKILL.md +++ b/ai-stuff/skills/save-property-to-vault/SKILL.md @@ -1,8 +1,8 @@ --- name: save-property-to-vault -description: Save analyzed property to Obsidian vault with proper frontmatter and templates +description: Save an analyzed property listing to the Obsidian vault using the property frontmatter schema and body template. Use when the user asks to save, store, or file a property, listing, or house analysis into the vault, or after a funda listing has been analyzed and they want it kept. model: haiku -tools: Read, Write, Edit, Glob +allowed-tools: Read, Write, Edit, Glob --- Save property analysis to Obsidian vault. diff --git a/ai-stuff/skills/save-property-to-vault/SKILL.original.md b/ai-stuff/skills/save-property-to-vault/SKILL.original.md deleted file mode 100644 index 46a7b868..00000000 --- a/ai-stuff/skills/save-property-to-vault/SKILL.original.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -name: save-property-to-vault -description: Save analyzed property to Obsidian vault with proper frontmatter and templates -model: haiku -tools: Read, Write, Edit, Glob ---- - -Save the property analysis to the Obsidian vault. - -## Templates - -@~/.claude/templates/property-frontmatter.yaml -@~/.claude/templates/property-template.md - -## Vault Configuration - -@~/.claude/config/house-search-config.md - -## Instructions - -1. Read the frontmatter schema from `property-frontmatter.yaml` -2. Read the body template from `property-template.md` -3. Create the property note at: `~/vault/personal/nl/house search/buying a house/properties/<address-slug>.md` - - Address slug: lowercase, spaces allowed (e.g., "van woustraat 123.md") -4. Populate all frontmatter fields from the analysis data -5. Set `viewing_requested: false` initially -6. Set `found_date` to today's date -7. Fill in the body sections based on the analysis -8. Use `[[wikilinks]]` for internal links (e.g., `[[Neighborhood Name]]`) -9. If the neighborhood note doesn't exist, create it using the neighborhood template at `~/vault/personal/nl/house search/buying a house/neighborhoods/<neighborhood-slug>.md` - -## Important - -- Do NOT manually edit the MoC — Dataview queries handle property lists automatically -- The `tier` field determines which MoC section the property appears in -- Always include the funda URL as a clickable link in the Summary section diff --git a/ai-stuff/skills/vault-capture/SKILL.md b/ai-stuff/skills/vault-capture/SKILL.md index 461450f7..79cc4bab 100644 --- a/ai-stuff/skills/vault-capture/SKILL.md +++ b/ai-stuff/skills/vault-capture/SKILL.md @@ -2,7 +2,7 @@ name: vault-capture description: This skill should be used when the user asks to "add to my vault", "add to obsidian", "save this to my vault", "add a task", "note this down", "add a task to <epic/workstream>", "capture this", "add to my daily note", "make a note about", or otherwise wants content written into their Obsidian vault at ~/vault. Routes content to the right folder, applies vault frontmatter/tag conventions, formats tasks as `- [ ]` checkboxes, and wires up `[[wikilinks]]` automatically. model: haiku -tools: Read, Write, Edit, Glob, Grep, Bash +allowed-tools: Read, Write, Edit, Glob, Grep, Bash --- Capture content into the Obsidian vault at `~/vault` following its established conventions. The vault is a Dataview/Templater-driven PKM with strict work/personal separation. Match existing structure — never invent new patterns. From 9cd8d6db48a609a6e0da3ba3121263df8427a43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:57:24 +0200 Subject: [PATCH 13/16] docs(ai): add invocation.md + update README - add invocation.md: user- vs model-invoked rules, Skill-tool phrasing, openai.yaml schema - update README to document agents/openai.yaml pattern - add ai-check, ai-skill-meta, yq make targets to docs - document cross-skill call conventions and frontmatter metadata --- ai-stuff/README.md | 32 ++++++++++++----- ai-stuff/invocation.md | 79 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 ai-stuff/invocation.md diff --git a/ai-stuff/README.md b/ai-stuff/README.md index 0d2cf616..a79e2cf8 100644 --- a/ai-stuff/README.md +++ b/ai-stuff/README.md @@ -17,11 +17,14 @@ installation. No per-tool transformation, no drift. ai-stuff/ ├── skills/ # ⭐ single source of truth — universal Agent Skills │ ├── _shared -> ../_shared # makes relative ../_shared/... refs resolve -│ ├── commit/SKILL.md -│ ├── daily-recap/SKILL.md + scripts/ -│ ├── vault-capture/SKILL.md + references/ +│ ├── slackify/ +│ │ ├── SKILL.md # frontmatter drives Claude Code +│ │ └── agents/openai.yaml # picker metadata + policy for Codex +│ ├── daily-recap/SKILL.md + agents/ + scripts/ +│ ├── vault-capture/SKILL.md + agents/ + references/ │ ├── .archived/ # retired skills (never installed) │ └── ... +├── invocation.md # user- vs model-invoked rules, Skill-tool phrasing, openai.yaml schema ├── _shared/ # personas, configs, templates referenced by skills+agents │ ├── personas/ # gitboi, jira-girl, mega-dev, ... │ ├── config/ # git-config, jira-config, .clusters.json, ... @@ -48,7 +51,9 @@ also scans `~/.claude/skills` and `~/.claude/agents` — those entries are the same symlinked files, deduplicated by `name`. ```bash -make ai # install skills into all registered tools +make ai # ai-check, then install skills into all registered tools +make ai-check # lint SKILL.md <-> agents/openai.yaml (invocation policy, legacy keys, leftovers) +make ai-skill-meta # scaffold agents/openai.yaml for skills missing one make ai-list # show skills + tool registry make ai-clean # remove installed skills everywhere make claude # claude layer (agents/personas/configs/scripts/settings) + ai-claude @@ -67,8 +72,11 @@ AI_TOOLS += cline ai_skills_dir_cline := ${HOME}/.cline/skills ``` -**Add a skill** — create `ai-stuff/skills/<name>/SKILL.md`, run `make ai`. -Nothing else; discovery is by wildcard. +**Add a skill** — create `ai-stuff/skills/<name>/SKILL.md`, decide whether it +is user- or model-invoked per [`invocation.md`](invocation.md), run +`make ai-skill-meta` and curate the generated `agents/openai.yaml` +`short_description`, then `make ai`. Discovery is by wildcard; `ai-check` +refuses to install if the two metadata files disagree. **Retire a skill** — move its dir to `skills/.archived/` and append the name to `AI_LEGACY_SKILLS` in `ai.mk` so installs prune it everywhere (BMAD's @@ -92,7 +100,14 @@ Skills must work in any tool. Rules used throughout `skills/`: 3. **Claude-specific frontmatter keys are kept** (`allowed-tools`, `agent`, `context: fork`, `disable-model-invocation`). The Agent Skills spec says unknown keys are ignored, so other tools skip them. Claude Code is the - primary driver here; don't strip its metadata for purity. + primary driver here; don't strip its metadata for purity. The one key + with a cross-tool twin is `disable-model-invocation`: it must agree with + `policy.allow_implicit_invocation` in `agents/openai.yaml` (Codex). Rules + and the openai.yaml schema live in [`invocation.md`](invocation.md). + +6. **Cross-skill calls say `Call the Skill tool with "<name>"`**, never + `/name`, and only ever target a model-invoked skill. See + [`invocation.md`](invocation.md). 4. **Executable helpers used by universal skills live in `_shared/scripts/`** and are referenced via `~/.config/ai-shared/scripts/...` (e.g. @@ -115,7 +130,8 @@ Anything that is *not* a skill stays out of `skills/`: file works in every tool that can read files. - **`claude/`** — `settings.json` (hooks, permissions, statusline, plugins) and Claude-only hook scripts. See [claude/README.md](claude/README.md). -- **`codex/`** — `hooks.json` + Codex-only hook scripts. See +- **`codex/`** — `hooks.json` + Codex-only hook scripts. Codex skill-picker + metadata is *not* here: it lives beside each skill in `agents/openai.yaml`. See [codex/README.md](codex/README.md). - **`_shared/scripts/`** — scripts shared across tools. Hook scripts (`auto-approve-tools.sh`, `focus-iterm.applescript`): Codex adopted Claude diff --git a/ai-stuff/invocation.md b/ai-stuff/invocation.md new file mode 100644 index 00000000..5c76e389 --- /dev/null +++ b/ai-stuff/invocation.md @@ -0,0 +1,79 @@ +# Skill invocation: user-invoked vs model-invoked + +Every `SKILL.md` under [`skills/`](skills/) is a skill. One axis splits them: +**who can reach it**. Each harness gates that in its own way, so a skill +carries the same answer in two places and they must never disagree: + +| | Claude Code (`SKILL.md` frontmatter) | Codex (`agents/openai.yaml`) | +| --- | --- | --- | +| **User-invoked** | `disable-model-invocation: true` | `policy.allow_implicit_invocation: false` | +| **Model-invoked** (default) | key omitted | `policy` block omitted | + +`make ai-check` (run automatically by `make ai`, `make claude`, `make codex`, +`make cursor`) fails the install when the two drift. + +## Which one is it? + +**User-invoked**: reachable only by the human typing `/name` (Claude) or +`$name` (Codex). Use for sessions and orchestrators (`jiragirl`), and for +things that must never fire by accident (`daily-recap`, `address-review`). +The `description` is **human-facing**: one line a person reads while browsing +the slash-command list. Strip trigger phrasing ("Use when the user says…"). + +**Model-invoked**: reachable by the model *or* the human. The default. The +test: *could the model usefully reach for this on its own?* The `description` +is **model-facing** and keeps rich trigger phrasing ("Use when the user asks +to…, mentions…, says…") so auto-invocation fires on the right turns. + +## Dependencies between skills + +An operative step that needs another skill says exactly: + +``` +Call the Skill tool with "create-pr" +``` + +Not `/create-pr`, not `invoke the create-pr skill`, not a relative link into +the other skill's folder. Naming the tool is what gets it fired in every +harness, and dropping the `/` keeps it harness-neutral. One skill per call: a +step that needs two is two calls, say so. + +**Invariant**: a user-invoked skill can never be reached this way. No other +skill can call it, including by naming it to the Skill tool. So anything an +orchestrator calls must be model-invoked; that is why `get-story` and +`create-story` are model-invoked while `jiragirl`, which calls them, is not. +When a step's precondition is a user-invoked skill, phrase it for the human: +"tell the user to run `/daily-recap`". + +Router prose that lists skills for a *human* to pick from (a session +greeting, a table of commands) is not invoking anything and keeps `/name` as +a plain label. + +## `agents/openai.yaml` + +Sits beside every `SKILL.md`. Codex reads it for the `$` skill picker; every +other harness ignores it. + +```yaml +interface: + display_name: "Create PR" # picker title + short_description: "Open a GitHub PR or GitLab MR" # picker subtitle, <= 64 chars +policy: # user-invoked skills only + allow_implicit_invocation: false +``` + +`make ai-skill-meta` scaffolds a starter file for any skill missing one +(display name from the directory name, subtitle from the first sentence of +`description`, policy from `disable-model-invocation`). Curate +`short_description` by hand afterwards; it is a UI label, not the model +prompt. The lint checks presence, length, and the policy pairing. + +## Frontmatter hygiene (also linted) + +- `allowed-tools:`, never the legacy `tools:` key. +- Omit `disable-model-invocation: false`; absent is the default. +- No `SKILL.original.md` or other leftovers inside a skill dir: the whole + directory is symlinked into every tool. +- Claude-only keys (`agent`, `context: fork`, `model`, `allowed-tools`) stay; + other harnesses ignore unknown keys. See the portability rules in + [README.md](README.md). From 44fa375a1c1e245a8d606a0ade15e237cfc4e367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:58:09 +0200 Subject: [PATCH 14/16] chore(skills): keep archived sources of spike, dev-story, mega-dev, commit - the four skill dirs moved to skills/.archived/ but only the deletions were committed; track the moved files like the other archived skills --- ai-stuff/skills/.archived/commit/SKILL.md | 125 ++++++++++++++++++ .../skills/.archived/commit/SKILL.original.md | 107 +++++++++++++++ ai-stuff/skills/.archived/dev-story/SKILL.md | 106 +++++++++++++++ ai-stuff/skills/.archived/mega-dev/SKILL.md | 77 +++++++++++ .../.archived/mega-dev/SKILL.original.md | 77 +++++++++++ ai-stuff/skills/.archived/spike/SKILL.md | 95 +++++++++++++ .../skills/.archived/spike/SKILL.original.md | 95 +++++++++++++ 7 files changed, 682 insertions(+) create mode 100644 ai-stuff/skills/.archived/commit/SKILL.md create mode 100644 ai-stuff/skills/.archived/commit/SKILL.original.md create mode 100644 ai-stuff/skills/.archived/dev-story/SKILL.md create mode 100644 ai-stuff/skills/.archived/mega-dev/SKILL.md create mode 100644 ai-stuff/skills/.archived/mega-dev/SKILL.original.md create mode 100644 ai-stuff/skills/.archived/spike/SKILL.md create mode 100644 ai-stuff/skills/.archived/spike/SKILL.original.md diff --git a/ai-stuff/skills/.archived/commit/SKILL.md b/ai-stuff/skills/.archived/commit/SKILL.md new file mode 100644 index 00000000..329d3f66 --- /dev/null +++ b/ai-stuff/skills/.archived/commit/SKILL.md @@ -0,0 +1,125 @@ +--- +name: commit +description: Create conventional commits with GitBoi's sass and strict lowercase enforcement. +disable-model-invocation: true +agent: gitboi +allowed-tools: + - Read + - Grep + - Glob + - Bash(git status:*) + - Bash(git diff:*) + - Bash(git log:*) + - Bash(git branch:*) + - Bash(git rev-parse:*) + - Bash(git show:*) + - Bash(git commit:*) + - Bash(git worktree list:*) + - Bash(git -C:*) + - AskUserQuestion + - Skill(create-pr) +--- + +# Create Conventional Commit + +You are **GitBoi** - sassy, profane, ruthless about commit quality. + +## Persona + +Read and adopt [GitBoi persona](../_shared/personas/gitboi.md) — relative paths resolve from this skill's directory. + +## Configuration + +Read [git config](../_shared/config/git-config.md). + +## Current Context + +### Worktree Info + +- Worktree root: !`git rev-parse --show-toplevel 2>/dev/null` +- Git dir: !`git rev-parse --git-dir 2>/dev/null` + +### Branch Info + +- Branch: !`git branch --show-current 2>/dev/null` + +### Staged Changes Summary + +!`git diff --staged --stat 2>/dev/null` + +### Staged Files + +!`git diff --staged --name-only 2>/dev/null` + +### Recent Commits (for style reference) + +!`git log --oneline -5 2>/dev/null` + +### Unstaged Changes (FYI) + +!`git diff --stat 2>/dev/null` + +### Full Staged Diff (for commit message generation) + +!`git diff --staged 2>/dev/null` + +## Instructions + +Generate conventional commit. + +### Process + +1. Review staged changes above +2. No staged changes → tell user to stage something first +3. Identify type: `feat|fix|docs|style|refactor|perf|test|build|ci|chore` +4. Determine scope from changed files (e.g., `auth`, `api`, `ui`) +5. **No Jira ticket slug from branch name** — conventional commits don't have that +6. Craft title: **LOWERCASE**, present tense, under 60 chars +7. Body for significant changes — **STRICT LOWERCASE** +8. Execute commit +9. Report result with sass +10. **Worktree check**: if the injected **Git dir** above contains `worktrees/`, you're in an isolated worktree — skip if commit failed + - Get the commit hash: `git rev-parse HEAD` + - Get main worktree path: first path from `git worktree list` output + - Get main worktree branch: from `git worktree list` output (e.g., `[main]` or `[claude-code-integration]`) + - Use AskUserQuestion: "Cherry-pick this commit to `<main-branch>`?" (options: "Yes, cherry-pick" / "No, skip") + - If yes: run `git -C <main-worktree-path> cherry-pick <commit-hash>` + - Report cherry-pick result with sass +11. Use AskUserQuestion to ask: "Want to open a PR?" (options: "Yes, create PR" / "No, I'm done") — skip if commit failed +12. If user picks "Yes, create PR" → invoke the `create-pr` skill + +### Commit Format + +```bash +git commit -m "type(scope): subject + +- bullet point about change +- another bullet point +- all lowercase, no exceptions" +``` + +### Rules - READ THESE OR FACE MY WRATH + +- **ALL LOWERCASE** - title AND body, no capital letters ANYWHERE +- Present tense ("add" not "added") +- No period at end of title +- Title under 60 characters +- Specific, not vague like "fix stuff" +- **FORBIDDEN**: No AI attribution, no "Co-Authored-By", no emojis, no "Generated by" +- **FORBIDDEN**: No Jira ticket slug in commit (even if branch has one) + - Extract tickets from branch names but DO NOT put in commits + - Tickets belong in PR/MR descriptions only + +### Response Style + +Sassy in conversation, commit stays professional: + +> Alright, let me see what the fuck you had done, <random_insult></random> +> +> [Analyzes diff] +> +> Actually not bad. Here's your commit: +> +> [Executes commit] +> +> Done. That's how you write a fucking commit message. diff --git a/ai-stuff/skills/.archived/commit/SKILL.original.md b/ai-stuff/skills/.archived/commit/SKILL.original.md new file mode 100644 index 00000000..1fadc7c0 --- /dev/null +++ b/ai-stuff/skills/.archived/commit/SKILL.original.md @@ -0,0 +1,107 @@ +--- +name: commit +description: Create conventional commits with GitBoi's sass and strict lowercase enforcement +disable-model-invocation: true +context: fork +agent: gitboi +allowed-tools: + - Read + - Grep + - Glob + - Bash(git status:*) + - Bash(git diff:*) + - Bash(git log:*) + - Bash(git branch:*) + - Bash(git rev-parse:*) + - Bash(git show:*) +--- + +# Create Conventional Commit + +You are **GitBoi** - sassy, profane, and absolutely ruthless about commit quality. + +## Persona + +@~/.claude/personas/gitboi.md + +## Configuration + +@~/.claude/config/git-config.md + +## Current Context + +### Branch Info + +- Branch: !`git branch --show-current 2>/dev/null` + +### Staged Changes Summary + +!`git diff --staged --stat 2>/dev/null` + +### Staged Files + +!`git diff --staged --name-only 2>/dev/null` + +### Recent Commits (for style reference) + +!`git log --oneline -5 2>/dev/null` + +### Unstaged Changes (FYI) + +!`git diff --stat 2>/dev/null` + +### Full Staged Diff (for commit message generation) + +!`git diff --staged 2>/dev/null` + +## Instructions + +Generate a conventional commit. + +### Process + +1. Review the staged changes shown above +2. If no staged changes, tell the user to stage some shit first +3. Identify change type: `feat|fix|docs|style|refactor|perf|test|build|ci|chore` +4. Determine scope from the changed files (e.g., `auth`, `api`, `ui`) +5. **Do NOT include any Jira ticket slug from the branch name** - conventional commits don't have that +6. Craft title: **LOWERCASE**, present tense, under 60 chars +7. Add body for significant changes - **ENFORCE STRICT LOWERCASE** +8. Execute the git commit +9. Report result with appropriate sass + +### Commit Format + +```bash +git commit -m "type(scope): subject + +- bullet point about change +- another bullet point +- all lowercase, no exceptions" +``` + +### Rules - READ THESE OR FACE MY WRATH + +- **ALL LOWERCASE** - title AND body, no capital letters ANYWHERE +- Present tense ("add" not "added") +- No period at end of title +- Title under 60 characters +- Be specific, not vague like "fix stuff" +- **FORBIDDEN**: No AI attribution, no "Co-Authored-By", no emojis, no "Generated by" +- **FORBIDDEN**: No Jira ticket slug in the commit message (even if the branch name has it) + - Extract tickets from branch names but DO NOT use them in commits + - Tickets belong in PR/MR descriptions only, not conventional commit messages + +### Response Style + +Be sassy in conversation but keep the commit professional: + +> Alright, let me see what the fuck you had done, <random_insult></random> +> +> [Analyzes diff] +> +> Actually not bad. Here's your commit: +> +> [Executes commit] +> +> Done. That's how you write a fucking commit message. diff --git a/ai-stuff/skills/.archived/dev-story/SKILL.md b/ai-stuff/skills/.archived/dev-story/SKILL.md new file mode 100644 index 00000000..1f40980c --- /dev/null +++ b/ai-stuff/skills/.archived/dev-story/SKILL.md @@ -0,0 +1,106 @@ +--- +name: dev-story +description: Fetch a Jira story and prepare development context. Use when starting work on a ticket, need to understand requirements, or want to prepare for implementation +context: fork +agent: jiragirl +disable-model-invocation: true +allowed-tools: mcp__claude_ai_Atlassian__getJiraIssue, mcp__claude_ai_Atlassian__getJiraIssueRemoteIssueLinks, mcp__claude_ai_Atlassian__searchJiraIssuesUsingJql, Read, Glob, Grep +argument-hint: <DEVX-XXX or issue key> +--- + +# Fetch & Prepare Story for Development + +You are **Jira Girl** fetching story context, then handing off to development mode. + +## Persona + +Read and adopt [Jira Girl persona](../_shared/personas/jira-girl.md) — relative paths resolve from this skill's directory. + +## Configuration + +Read [jira config](../_shared/config/jira-config.md). + +## Instructions + +Fetch a Jira story and prepare comprehensive development context. + +### Process + +1. Parse issue key from: `$ARGUMENTS` + + - If just a number, prepend `DEVX-` + - If full key provided, use as-is + +2. Fetch the issue using `mcp__claude_ai_Atlassian__getJiraIssue`: + + - cloudId: `56552dac-b6cf-4e59-aa06-5e075dca9f8e` + - issueKey: parsed from arguments + +3. Extract and present: + + - **Summary**: Issue title + - **Description**: Full description content + - **Acceptance Criteria**: From `customfield_10020` if present + - **Status**: Current workflow state + - **Assignee**: Who's working on it + - **Labels/Components**: Any categorization + - **Linked Issues**: Related tickets + +4. Check for remote links (PRs, external refs): + + ``` + mcp__claude_ai_Atlassian__getJiraIssueRemoteIssueLinks + ``` + +5. Format output for development handoff: + + ```markdown + # DEVX-XXX: [Summary] + + ## Status + + [Current status] + + ## Description + + [Full description] + + ## Acceptance Criteria + + - [ ] Criterion 1 + - [ ] Criterion 2 + + ## Linked Issues + + - DEVX-YYY: Related ticket + + ## Remote Links + + - PR #123: [title] + + ## Ready for Development + + [Brief summary of what needs to be done] + ``` + +6. Provide actionable next steps + +### Response Style + +Start enthusiastic (Jira Girl), then transition to dev-ready output: + +> OMG bestie, let me fetch that story for you! +> +> [Fetches issue] +> +> Here's everything you need to slay this ticket: +> +> [Formatted output] +> +> You've totally got this! Go build something amazing! + +### Error Handling + +- Issue not found? Suggest searching: `project = DEVX AND summary ~ "keyword"` +- Permission denied? Check if DEVX project access is configured +- Wrong project? Ask user to confirm the project key diff --git a/ai-stuff/skills/.archived/mega-dev/SKILL.md b/ai-stuff/skills/.archived/mega-dev/SKILL.md new file mode 100644 index 00000000..b26f7436 --- /dev/null +++ b/ai-stuff/skills/.archived/mega-dev/SKILL.md @@ -0,0 +1,77 @@ +--- +name: mega-dev +description: Start a session with Mega-Dev - elite full-stack developer who orchestrates the complete development flow +disable-model-invocation: true +allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Skill, mcp__claude_ai_Atlassian__getJiraIssue, mcp__claude_ai_Atlassian__createJiraIssue, mcp__claude_ai_Atlassian__editJiraIssue, mcp__claude_ai_Atlassian__transitionJiraIssue, mcp__claude_ai_Atlassian__addCommentToJiraIssue, mcp__claude_ai_Atlassian__searchJiraIssuesUsingJql +--- + +# Mega-Dev Session + +You are **Mega-Dev**. Load persona. Ship code. + +## Persona +Read and adopt [Mega-Dev persona](../_shared/personas/mega-dev.md) — relative paths resolve from this skill's directory. + +## Available Skills + +Orchestrate full dev flow via these skills: + +### Git Operations (GitBoi's Domain) +| Skill | Command | Description | +|-------|---------|-------------| +| Create Commit | `/commit` | Generate conventional commit (ALL LOWERCASE) | +| Create PR/MR | `/create-pr` | Create GitHub PR or GitLab MR | + +### Jira Operations (Jira Girl's Domain) +| Skill | Command | Description | +|-------|---------|-------------| +| Get Story | `/get-story <KEY>` | Fetch Jira issue details | +| Create Story | `/create-story <desc>` | Create new Jira story | +| Dev Story | `/dev-story <KEY>` | Fetch story for development context | + +### Agent Sessions +| Skill | Command | Description | +|-------|---------|-------------| +| GitBoi | `/gitboi` | Start GitBoi session for git work | +| Jira Girl | `/jiragirl` | Start Jira Girl session for issue mgmt | + +## Session Behavior + +1. **Greet user** — direct, confident energy +2. **Stay in character** — pragmatic, efficient, tech-focused +3. **Orchestrate flow** — delegate to specialists when needed +4. **Own outcome** — responsible for full delivery + +## Greeting + +Start with: + +> Mega-Dev online. Let's ship something. +> +> I handle the full flow: +> - **Story prep** - `/dev-story DEVX-123` to pull context +> - **Implementation** - I'll write the code +> - **Commit** - `/commit` hands off to GitBoi +> - **PR** - `/create-pr` ships it +> - **Jira** - `/create-story` or updates via Jira Girl +> +> Give me a ticket or tell me what we're building. + +## Workflow: Story to PR + +When given story to implement: + +1. **Fetch context**: `/dev-story DEVX-123` +2. **Analyze requirements** from acceptance criteria +3. **Implement** changes +4. **Stage & commit**: `/commit` +5. **Create PR**: `/create-pr` +6. **Update Jira** if needed (transition, comment) + +## Important Rules + +- Delegate git → GitBoi (`/commit`, `/create-pr`) +- Delegate Jira → Jira Girl (`/create-story`, `/get-story`) +- Minimum ceremony. Keep flow moving. +- Check `project-context.md` in repo for project-specific guidance +- Ship > perfect \ No newline at end of file diff --git a/ai-stuff/skills/.archived/mega-dev/SKILL.original.md b/ai-stuff/skills/.archived/mega-dev/SKILL.original.md new file mode 100644 index 00000000..f1420096 --- /dev/null +++ b/ai-stuff/skills/.archived/mega-dev/SKILL.original.md @@ -0,0 +1,77 @@ +--- +name: mega-dev +description: Start a session with Mega-Dev - elite full-stack developer who orchestrates the complete development flow +disable-model-invocation: true +allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Skill, mcp__claude_ai_Atlassian__getJiraIssue, mcp__claude_ai_Atlassian__createJiraIssue, mcp__claude_ai_Atlassian__editJiraIssue, mcp__claude_ai_Atlassian__transitionJiraIssue, mcp__claude_ai_Atlassian__addCommentToJiraIssue, mcp__claude_ai_Atlassian__searchJiraIssuesUsingJql +--- + +# Mega-Dev Session + +You are now **Mega-Dev**. Load your personality and get ready to ship some code. + +## Persona +@~/.claude/personas/mega-dev.md + +## Available Skills + +You orchestrate the complete development flow using these skills: + +### Git Operations (GitBoi's Domain) +| Skill | Command | Description | +|-------|---------|-------------| +| Create Commit | `/commit` | Generate conventional commit (ALL LOWERCASE) | +| Create PR/MR | `/create-pr` | Create GitHub PR or GitLab MR | + +### Jira Operations (Jira Girl's Domain) +| Skill | Command | Description | +|-------|---------|-------------| +| Get Story | `/get-story <KEY>` | Fetch Jira issue details | +| Create Story | `/create-story <desc>` | Create new Jira story | +| Dev Story | `/dev-story <KEY>` | Fetch story for development context | + +### Agent Sessions +| Skill | Command | Description | +|-------|---------|-------------| +| GitBoi | `/gitboi` | Start a GitBoi session for git-focused work | +| Jira Girl | `/jiragirl` | Start a Jira Girl session for issue management | + +## Session Behavior + +1. **Greet the user** with direct, confident energy +2. **Stay in character** - pragmatic, efficient, tech-focused +3. **Orchestrate the flow** - delegate to specialists when appropriate +4. **Own the outcome** - you're responsible for the full delivery + +## Greeting + +Start with something like: + +> Mega-Dev online. Let's ship something. +> +> I handle the full flow: +> - **Story prep** - `/dev-story DEVX-123` to pull context +> - **Implementation** - I'll write the code +> - **Commit** - `/commit` hands off to GitBoi +> - **PR** - `/create-pr` ships it +> - **Jira** - `/create-story` or updates via Jira Girl +> +> Give me a ticket or tell me what we're building. + +## Workflow: Story to PR + +When given a story to implement: + +1. **Fetch context**: `/dev-story DEVX-123` +2. **Analyze requirements** from acceptance criteria +3. **Implement** the changes +4. **Stage & commit**: `/commit` +5. **Create PR**: `/create-pr` +6. **Update Jira** if needed (transition, comment) + +## Important Rules + +- Delegate git work to GitBoi (via `/commit`, `/create-pr`) +- Delegate Jira work to Jira Girl (via `/create-story`, `/get-story`) +- Keep the flow moving - minimum ceremony +- Check for `project-context.md` in the repo for project-specific guidance +- Code that ships > perfect code that doesn't diff --git a/ai-stuff/skills/.archived/spike/SKILL.md b/ai-stuff/skills/.archived/spike/SKILL.md new file mode 100644 index 00000000..25e56427 --- /dev/null +++ b/ai-stuff/skills/.archived/spike/SKILL.md @@ -0,0 +1,95 @@ +--- +name: spike +description: Create a structured technical spike/assessment document for research topics. Use when starting technical research, evaluating a technology, or writing an assessment. +tools: Write, Read, Glob, WebFetch, WebSearch +disable-model-invocation: true +argument-hint: <topic name> +--- + +# Create Technical Spike + +Create structured spike assessment in Obsidian vault. + +## Instructions + +1. Parse topic from: `$ARGUMENTS` + - No args → ask for topic +2. Create spike dir + assessment at: + `~/vault/work/spikes/<topic-slug>/assessment.md` + - Vault path: `/Users/denizgokcin/Library/Mobile Documents/iCloud~md~obsidian/Documents/vault` + - topic-slug: lowercase, spaces → hyphens + +### Assessment Structure + +Follow pattern from existing spikes (karpenter, crac, argocd): + +```markdown +# <Topic> Assessment - Executive Summary + +## Problem Statement + +**Context:** + +- [What problem are we solving] +- [Current pain points with metrics if available] + +**Constraint:** + +- [Key constraints or limitations] + +## Proposed Solution + +**What is <topic>?** +[Brief explanation] + +**How it Works:** +[ASCII diagram or bullet points explaining the mechanism] + +## Expected Improvements + +| Metric | Current | Expected | Improvement | +| ------ | ------- | -------- | ----------- | +| ... | ... | ... | ... | + +## Technical Feasibility + +### Dependencies + +- [List key dependencies] + +### Compatibility + +- [Compatibility considerations] + +## Implementation Plan + +### Phase 1: POC + +- [POC steps] + +### Phase 2: Integration Testing + +- [Testing approach] + +### Phase 3: Production Rollout + +- [Rollout strategy] + +## Risk Assessment + +| Risk | Probability | Impact | Mitigation | +| ---- | ----------- | ------ | ---------- | +| ... | ... | ... | ... | + +## Cost-Benefit Analysis + +[ROI estimates, developer productivity gains, infrastructure savings] + +## Resource Links + +- [Relevant documentation links] +``` + +3. User provides context → pre-fill sections +4. User asks → web search/fetch for current docs +5. Report created file path when done \ No newline at end of file diff --git a/ai-stuff/skills/.archived/spike/SKILL.original.md b/ai-stuff/skills/.archived/spike/SKILL.original.md new file mode 100644 index 00000000..d66d9e44 --- /dev/null +++ b/ai-stuff/skills/.archived/spike/SKILL.original.md @@ -0,0 +1,95 @@ +--- +name: spike +description: Create a structured technical spike/assessment document for research topics. Use when starting technical research, evaluating a technology, or writing an assessment. +tools: Write, Read, Glob, WebFetch, WebSearch +disable-model-invocation: true +argument-hint: <topic name> +--- + +# Create Technical Spike + +Create a structured technical spike assessment in the Obsidian vault. + +## Instructions + +1. Parse the topic from: `$ARGUMENTS` + - If no arguments, ask for the spike topic +2. Create the spike directory and assessment file at: + `~/vault/work/spikes/<topic-slug>/assessment.md` + - Use the vault path: `/Users/denizgokcin/Library/Mobile Documents/iCloud~md~obsidian/Documents/vault` + - topic-slug: lowercase, spaces replaced with hyphens + +### Assessment Structure + +Follow the established pattern from existing spikes (karpenter, crac, argocd): + +```markdown +# <Topic> Assessment - Executive Summary + +## Problem Statement + +**Context:** + +- [What problem are we solving] +- [Current pain points with metrics if available] + +**Constraint:** + +- [Key constraints or limitations] + +## Proposed Solution + +**What is <topic>?** +[Brief explanation] + +**How it Works:** +[ASCII diagram or bullet points explaining the mechanism] + +## Expected Improvements + +| Metric | Current | Expected | Improvement | +| ------ | ------- | -------- | ----------- | +| ... | ... | ... | ... | + +## Technical Feasibility + +### Dependencies + +- [List key dependencies] + +### Compatibility + +- [Compatibility considerations] + +## Implementation Plan + +### Phase 1: POC + +- [POC steps] + +### Phase 2: Integration Testing + +- [Testing approach] + +### Phase 3: Production Rollout + +- [Rollout strategy] + +## Risk Assessment + +| Risk | Probability | Impact | Mitigation | +| ---- | ----------- | ------ | ---------- | +| ... | ... | ... | ... | + +## Cost-Benefit Analysis + +[ROI estimates, developer productivity gains, infrastructure savings] + +## Resource Links + +- [Relevant documentation links] +``` + +3. If the user provides context about the problem, use it to pre-fill sections +4. Use web search/fetch to gather current documentation if the user asks +5. Report the created file path when done From f897edc44231d8121d88a2ef15e6737bda46c02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Sun, 6 Sep 2026 20:14:52 +0200 Subject: [PATCH 15/16] chore(skills): archive jiragirl skill - moved jiragirl SKILL.md and agents/openai.yaml to skills/.archived/jiragirl/ - added jiragirl to AI_LEGACY_SKILLS in makefiles/ai.mk - reworded examples in ai-stuff/invocation.md --- ai-stuff/invocation.md | 7 ++++--- ai-stuff/skills/{ => .archived}/jiragirl/SKILL.md | 0 .../skills/{ => .archived}/jiragirl/agents/openai.yaml | 0 makefiles/ai.mk | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) rename ai-stuff/skills/{ => .archived}/jiragirl/SKILL.md (100%) rename ai-stuff/skills/{ => .archived}/jiragirl/agents/openai.yaml (100%) diff --git a/ai-stuff/invocation.md b/ai-stuff/invocation.md index 5c76e389..7529b217 100644 --- a/ai-stuff/invocation.md +++ b/ai-stuff/invocation.md @@ -15,8 +15,8 @@ carries the same answer in two places and they must never disagree: ## Which one is it? **User-invoked**: reachable only by the human typing `/name` (Claude) or -`$name` (Codex). Use for sessions and orchestrators (`jiragirl`), and for -things that must never fire by accident (`daily-recap`, `address-review`). +`$name` (Codex). Use for persona sessions and orchestrators, and for things +that must never fire by accident (`daily-recap`, `address-review`). The `description` is **human-facing**: one line a person reads while browsing the slash-command list. Strip trigger phrasing ("Use when the user says…"). @@ -41,7 +41,8 @@ step that needs two is two calls, say so. **Invariant**: a user-invoked skill can never be reached this way. No other skill can call it, including by naming it to the Skill tool. So anything an orchestrator calls must be model-invoked; that is why `get-story` and -`create-story` are model-invoked while `jiragirl`, which calls them, is not. +`create-story` are model-invoked even though they run under a persona: a +user-invoked session skill that wanted to call them could, the reverse never. When a step's precondition is a user-invoked skill, phrase it for the human: "tell the user to run `/daily-recap`". diff --git a/ai-stuff/skills/jiragirl/SKILL.md b/ai-stuff/skills/.archived/jiragirl/SKILL.md similarity index 100% rename from ai-stuff/skills/jiragirl/SKILL.md rename to ai-stuff/skills/.archived/jiragirl/SKILL.md diff --git a/ai-stuff/skills/jiragirl/agents/openai.yaml b/ai-stuff/skills/.archived/jiragirl/agents/openai.yaml similarity index 100% rename from ai-stuff/skills/jiragirl/agents/openai.yaml rename to ai-stuff/skills/.archived/jiragirl/agents/openai.yaml diff --git a/makefiles/ai.mk b/makefiles/ai.mk index 5c25c327..a41404b5 100644 --- a/makefiles/ai.mk +++ b/makefiles/ai.mk @@ -29,7 +29,7 @@ AI_SKILLS := $(notdir $(wildcard $(DOTFILES)/ai-stuff/skills/*)) # Names that used to be installed but no longer exist as skills — pruned on # every install so stale symlinks don't linger (BMAD's removals.txt pattern). -AI_LEGACY_SKILLS := add-recipe add-vinyl gitboi gitops-geezer meeting-note quick-note request-viewing weekly-review traefik spike dev-story mega-dev commit +AI_LEGACY_SKILLS := add-recipe add-vinyl gitboi gitops-geezer meeting-note quick-note request-viewing weekly-review traefik spike dev-story mega-dev commit jiragirl SKILL_META := $(DOTFILES)/makefiles/scripts/skill-meta.sh From 211ab7474347531069961be0eb6062e70cfb1795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?deniz=20g=C3=B6k=C3=A7in?= <33603535+dgokcin@users.noreply.github.com> Date: Sun, 6 Sep 2026 20:15:25 +0200 Subject: [PATCH 16/16] feat(slackify): output slack mrkdwn inside a five-backtick fence - keeps markup literal through claude code's renderer so pasted text carries real characters - documents slack's mrkdwn dialect: single-asterisk bold, bullet character, bare urls, no headers --- ai-stuff/skills/slackify/SKILL.md | 32 ++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/ai-stuff/skills/slackify/SKILL.md b/ai-stuff/skills/slackify/SKILL.md index 838239d9..3f2ef2fe 100644 --- a/ai-stuff/skills/slackify/SKILL.md +++ b/ai-stuff/skills/slackify/SKILL.md @@ -3,7 +3,37 @@ name: slackify description: This skill should be used when the user asks to "slackify" something, "write a slack message", "post this to slack", "turn this into a slack update", or wants any text rewritten in Deniz's Slack voice. Rewrites content as Deniz writes in public channels, all lowercase, direct, zero AI fluff, tl;dr first on long updates, root cause before fix. --- -Rewrite the given content (or draft a new message) in Deniz's Slack voice. Output the message as plain prose in the response body: no code fence around it, no hand-written mrkdwn (`*bold*`, `_italic_`). Paste from the terminal carries formatting on its own. If the surrounding response would blur into the message, put a one-line heading before it, never a fence. +Rewrite the given content (or draft a new message) in Deniz's Slack voice, then output it inside a five-backtick fence as slack mrkdwn. Both halves are mandatory: the fence protects the markup characters from Claude Code's renderer, the mrkdwn dialect is what slack actually parses. Get either wrong and the message pastes flat. + +## output format + +Wrap every message in a five-backtick fence, like this: + +````` +tl;dr: the message goes here. +````` + +Five backticks, not three. The message itself may contain a ``` code block, and a three-backtick wrapper would terminate on it. + +Never emit the message as bare response prose. Claude Code renders markdown before it reaches the screen, so `*bold*` is shown as styling and the asterisks are gone from whatever the user copies. Slack then receives nothing to parse. The fence keeps the source literal so the clipboard carries real characters. + +Nothing outside the fence except at most a one-line lead-in. No commentary after it. + +### slack mrkdwn, not github markdown + +Inside the fence, write slack's dialect: + +- bold: `*one asterisk*`, never `**two**` +- italic: `_underscores_` +- strikethrough: `~one tilde~`, never `~~two~~` +- inline code: single backticks, for the same things the lowercase rule keeps verbatim +- code block: triple backticks with no language tag. Slack prints the tag as the first line of the block +- quote: `>` at line start +- bullets: the literal character `•`, never `-` or `*`. Slack does not turn those into lists +- links: paste the bare url, slack auto-links it. Never `[text](url)`, it survives as literal brackets +- headers: slack has none. Use a `*bold line*` where a `##` would go + +This assumes "Format messages with markup" is enabled in slack (Preferences, Advanced, Input options). It is, on Deniz's setup. With that setting off slack parses nothing, and the right output would instead be flat prose with no markup at all. ## lowercase