From 5ff9e5eae79203a884cb96cf871a75c066de1ded Mon Sep 17 00:00:00 2001 From: joelazar Date: Mon, 25 May 2026 11:22:30 +0000 Subject: [PATCH] :recycle: migrate to skills CLI global lock file and add gcx, reddit, simplify skills --- .chezmoiignore | 1 - README.md | 8 ++------ run_onchange_after_install_skills.sh.tmpl | 38 -------------------------------------- run_onchange_after_patch_skills.sh.tmpl | 56 -------------------------------------------------------- dot_agents/dot_skill-lock.json | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dot_agents/skills-lock.json | 89 ----------------------------------------------------------------------------------------- dot_pi/agent/AGENTS.md | 25 +++++++++++++++++++++++++ dot_agents/skills/gcx/SKILL.md | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dot_agents/skills/reddit/SKILL.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ dot_agents/skills/reddit/reddit.js | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ dot_agents/skills/simplify/SKILL.md | 33 +++++++++++++++++++++++++++++++++ 11 file(s) changed, 736 insertion(s)(+), 190 deletion(s)(-) diff --git a/.chezmoiignore b/.chezmoiignore --- a/.chezmoiignore +++ b/.chezmoiignore @@ -22,4 +22,3 @@ .pi/agent/auth.json .pi/agent/pi-fff/ .git -.agents/.skill-lock.json diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -181,13 +181,9 @@ ### Local skills 🎯 -The skill library under [`dot_agents/`](dot_agents/) is organized into three directories: `skills/` for general-purpose tools, `frontend-skills/` for web UI work, and `python-skills/` for Python tooling. Around 21 skills total, tracked by [`dot_skill-lock.json`](dot_skill-lock.json). +The skill library under [`dot_agents/`](dot_agents/) uses the `skills` CLI's global lock file, tracked as [`dot_agents/dot_skill-lock.json`](dot_agents/dot_skill-lock.json) and applied to `~/.agents/.skill-lock.json`. -General skills cover research and external systems (`ai-search`, `kagi`, `perplexity-search`, `web-search`, `pdf`, `linear-cli`, `mermaid`), workflow helpers (`github`, `humanizer`, `session-analyzer`, `summarize`, `tmux`, `gcx`), and Google Workspace access (calendar, docs, drive, gmail, sheets). - -Frontend skills live under `frontend-skills/` and are anchored by `impeccable` — a v3.0 subcommand system with a large reference library covering `live`, `harden`, `document`, `onboard`, `shape`, `teach`, `brand`, `product`, and more. `frontend-design` and `web-browser` round out that category. - -Python tooling lives under `python-skills/` and currently just has `uv`. +Local skills live under [`dot_agents/skills/`](dot_agents/skills/). Remote skills are tracked in the lock file and updated with `skills update -g`. Two meta-tools, `improve-skill` and `skill-creator`, live at the `dot_agents/` level. They're for building and evaluating new skills rather than using them directly. diff --git a/run_onchange_after_install_skills.sh.tmpl b/run_onchange_after_install_skills.sh.tmpl deleted file mode 100644 --- a/run_onchange_after_install_skills.sh.tmpl +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash -# -# Restore third-party agent skills from skills-lock.json using the `skills` CLI -# (https://www.npmjs.com/package/skills). -# -# This script re-runs whenever the lockfile content changes, thanks to the -# embedded hash below. -# -# skills-lock.json hash: {{ include "dot_agents/skills-lock.json" | sha256sum }} - -set -euo pipefail - -. "{{ joinPath .chezmoi.sourceDir "scripts/utils" }}" - -LOCKFILE="${HOME}/.agents/skills-lock.json" - -if [[ ! -f "$LOCKFILE" ]]; then - show_message "⚠️ $LOCKFILE not found; skipping skill restore." "$ORANGE" - exit 0 -fi - -if ! cmd_exists "skills"; then - show_message "⚠️ 'skills' CLI not installed; run install_packages first." "$ORANGE" - exit 0 -fi - -show_section "🧩 Restoring third-party skills from skills-lock.json" "$CYAN" - -# `skills experimental_install` resolves the lockfile from the cwd and writes -# skills into /.agents/skills/ (and friends), so we run it from $HOME with -# a temporary symlink to the canonical lockfile. -TMP_LINK="${HOME}/skills-lock.json" -cleanup() { [[ -L "$TMP_LINK" ]] && rm -f "$TMP_LINK"; } -trap cleanup EXIT - -ln -sf "$LOCKFILE" "$TMP_LINK" -cd "$HOME" -skills experimental_install -y diff --git a/run_onchange_after_patch_skills.sh.tmpl b/run_onchange_after_patch_skills.sh.tmpl deleted file mode 100644 --- a/run_onchange_after_patch_skills.sh.tmpl +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -# -# Patch SKILL.md frontmatter for vendor-managed skills after they have been -# (re)installed by `skills experimental_install` or `gcx skills install`. -# -# Each entry is `==`. The patch is applied to -# `~/.agents/skills//SKILL.md` only — `~/.claude/skills/` is a -# symlink to it, and pi reads from there too, so one patch covers everything. -# -# Idempotent: skips when the key is already present in the frontmatter. - -set -euo pipefail - -. "{{ joinPath .chezmoi.sourceDir "scripts/utils" }}" - -PATCHES=( - "frontend-design=disable-model-invocation=true" - "impeccable=disable-model-invocation=true" - "web-browser=disable-model-invocation=true" -) - -patch_frontmatter() { - local skill="$1" key="$2" value="$3" - local file="${HOME}/.agents/skills/${skill}/SKILL.md" - - if [[ ! -f "$file" ]]; then - echo " ⚠️ ${skill}: SKILL.md not found at $file" - return 0 - fi - - if rg -q "^${key}:" "$file"; then - echo " ✓ ${skill}: ${key} already set" - return 0 - fi - - # Insert ": " right before the closing `---` of the frontmatter. - awk -v k="$key" -v v="$value" ' - BEGIN { dashes = 0; inserted = 0 } - /^---[[:space:]]*$/ { - dashes++ - if (dashes == 2 && !inserted) { - print k ": " v - inserted = 1 - } - } - { print } - ' "$file" > "${file}.tmp" && mv "${file}.tmp" "$file" - echo " ✏️ ${skill}: added ${key}: ${value}" -} - -show_section "🩹 Patching vendor skill frontmatter" "$CYAN" - -for entry in "${PATCHES[@]}"; do - IFS='=' read -r skill key value <<< "$entry" - patch_frontmatter "$skill" "$key" "$value" -done diff --git a/dot_agents/dot_skill-lock.json b/dot_agents/dot_skill-lock.json new file mode 100644 --- /dev/null +++ b/dot_agents/dot_skill-lock.json @@ -0,0 +1,269 @@ +{ + "version": 3, + "skills": { + "ai-search": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/ai-search", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "d927635e0c4934c2b620dec5e7174cfed3c71068818848636cfa7ddbc5ee1c0e", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/ai-search" + }, + "exe-dev": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/exe-dev", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "21d78d55a704bbe4064e401512fa13505b332c48e332339fa348ac847f7911d0", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/exe-dev" + }, + "frontend-design": { + "source": "anthropics/skills", + "sourceType": "github", + "skillPath": "skills/frontend-design/SKILL.md", + "skillFolderHash": "063a0e6448123cd359ad0044cc46b0e490cc7964d45ef4bb9fd842bd2ffbca67", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/anthropics/skills.git" + }, + "gcx": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/gcx", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "5dd1192db9d2c63bbd4a356e29937595facf385f0716b0ab1edcd417e321674c", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/gcx" + }, + "github": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/github", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "b7120307b838bb55164ead25a13d07380801da2063bbd66af964cc9542495413", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/github" + }, + "gws-calendar": { + "source": "googleworkspace/cli", + "sourceType": "github", + "skillPath": "skills/gws-calendar/SKILL.md", + "skillFolderHash": "0c5956e1069552444b00bf45381f08ffa9a7bca9810fefb1801866216008bcfc", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/googleworkspace/cli.git" + }, + "gws-docs": { + "source": "googleworkspace/cli", + "sourceType": "github", + "skillPath": "skills/gws-docs/SKILL.md", + "skillFolderHash": "10dc2a8aa8cb28524a9d285ddba5602c24c21cbb640718fce522b58d90ee7b97", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/googleworkspace/cli.git" + }, + "gws-drive": { + "source": "googleworkspace/cli", + "sourceType": "github", + "skillPath": "skills/gws-drive/SKILL.md", + "skillFolderHash": "d637ff849b82a9fc195bcfedea260cffe94eaa31b843b28cd04313b1720bb153", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/googleworkspace/cli.git" + }, + "gws-gmail": { + "source": "googleworkspace/cli", + "sourceType": "github", + "skillPath": "skills/gws-gmail/SKILL.md", + "skillFolderHash": "5e5b5fdb4b4f347310d929657ed773abcaf528b5ac0a68deee12d3d38d307642", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/googleworkspace/cli.git" + }, + "gws-shared": { + "source": "googleworkspace/cli", + "sourceType": "github", + "skillPath": "skills/gws-shared/SKILL.md", + "skillFolderHash": "b197590681ce3d5a52e9c15a68652b5445d111dbfc0dc453f68fb0785aac443c", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/googleworkspace/cli.git" + }, + "gws-sheets": { + "source": "googleworkspace/cli", + "sourceType": "github", + "skillPath": "skills/gws-sheets/SKILL.md", + "skillFolderHash": "21c951f8bf399bb941740ab8b048157b43088ad96b743976e88abb0046d263d2", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/googleworkspace/cli.git" + }, + "humanizer": { + "source": "blader/humanizer", + "sourceType": "github", + "skillPath": "SKILL.md", + "skillFolderHash": "b813857f183da05d08d5a80adac671df94c139f855809bd47ab8b7bb245546a2", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/blader/humanizer.git" + }, + "impeccable": { + "source": "pbakaus/impeccable", + "sourceType": "github", + "skillPath": "skill/SKILL.md", + "skillFolderHash": "34e59a34b9705187e87039faa5d9585aebe0056ef657f761b905afef276a3362", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/pbakaus/impeccable.git" + }, + "kagi-cli": { + "source": "/Users/joelazar/Code/rust/kagi-cli/docs", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "c0f78d71728e660a42bebef552b88e2250238de358e69feeb4def8fcfb4ae4d5", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/Code/rust/kagi-cli/docs" + }, + "linear-cli": { + "source": "schpet/linear-cli", + "sourceType": "github", + "skillPath": "skills/linear-cli/SKILL.md", + "skillFolderHash": "5f8516b9aa8157e7710ec5d029e1c44a0e55be1c3f834f844d0c7f27dae62580", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/schpet/linear-cli.git" + }, + "listen-later": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/listen-later", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "8eb3f99602be304eeefcc379af447f72113841899ff3c487b2c39fc0539fc60a", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/listen-later" + }, + "mermaid": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/mermaid", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "55e6edaf8d27d683b406fb0c2f1a8e3f12be16d0cfa4c937a0180fe179d01543", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/mermaid" + }, + "pdf": { + "source": "anthropics/skills", + "sourceType": "github", + "skillPath": "skills/pdf/SKILL.md", + "skillFolderHash": "cfbc539377088ca7e44a813b30c306327385bbd973cd7a721e1743f60837dd62", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/anthropics/skills.git" + }, + "perplexity-search": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/perplexity-search", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "46cf3b8c616a6b629a7d527f3d38762e08a1a03b9e5efccaf26a17a8459586fe", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/perplexity-search" + }, + "reddit": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/reddit", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "4138cd18b344fa2243f806fe9d50371cf20843483ec4e22a9b1424001ac3fc57", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/reddit" + }, + "save-to-spotify": { + "source": "/Users/joelazar/.local/share/save-to-spotify/skills/save-to-spotify", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "f5f513f0f480f4e7469c3b6aab557727cc32161d419fc0290a4f1ed9a01f51f0", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/save-to-spotify/skills/save-to-spotify" + }, + "session-analyzer": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/session-analyzer", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "fd6bda892861eef8153ceee8ada257ddd741328ee5adaf7896ded9a24623c72d", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/session-analyzer" + }, + "simplify": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/simplify", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "7c0add94952762e5b0a6b1a6e9aab776534371e630069bfca0a9d78ed30b7384", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/simplify" + }, + "summarize": { + "source": "steipete/clawdis", + "sourceType": "github", + "skillPath": "skills/summarize/SKILL.md", + "skillFolderHash": "67b9a5d86c3d9675e53e8bdb3f336661d55ccc689ecaaa3c99d984aa991458b6", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/steipete/clawdis.git" + }, + "supaterm": { + "source": "supabitapp/supaterm-skills", + "sourceType": "github", + "skillPath": "skills/supaterm/SKILL.md", + "skillFolderHash": "755701053bdd773b67172ae7ed1235c2ae428483", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/supabitapp/supaterm-skills.git" + }, + "tmux": { + "source": "steipete/clawdis", + "sourceType": "github", + "skillPath": "skills/tmux/SKILL.md", + "skillFolderHash": "ac61fad44978a9a2ca345f4c7de49de3f2b27cdb0096cbddf21f817c99d2fbce", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/steipete/clawdis.git" + }, + "uv": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/uv", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "19402c65ae90e373da59d70f2769c0843558d404335f7bf50509521187252192", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/uv" + }, + "web-browser": { + "source": "mitsuhiko/agent-stuff", + "sourceType": "github", + "skillPath": "skills/web-browser/SKILL.md", + "skillFolderHash": "e6c498ce130df429d35478732ac63be9c6caa35441484efbea786adf29117c26", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "https://github.com/mitsuhiko/agent-stuff.git" + }, + "web-search": { + "source": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/web-search", + "sourceType": "local", + "skillPath": "SKILL.md", + "skillFolderHash": "9cd144f8984e39e76a0a69bb296a91a180b3290588c39b09bd75fec273c70f9d", + "installedAt": "2026-05-25T13:30:00.000Z", + "updatedAt": "2026-05-25T13:30:00.000Z", + "sourceUrl": "/Users/joelazar/.local/share/chezmoi/dot_agents/skills/web-search" + } + }, + "dismissed": { + "findSkillsPrompt": true + } +} diff --git a/dot_agents/skills-lock.json b/dot_agents/skills-lock.json deleted file mode 100644 --- a/dot_agents/skills-lock.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "version": 1, - "skills": { - "frontend-design": { - "source": "anthropics/skills", - "sourceType": "github", - "skillPath": "skills/frontend-design/SKILL.md", - "computedHash": "063a0e6448123cd359ad0044cc46b0e490cc7964d45ef4bb9fd842bd2ffbca67" - }, - "gws-calendar": { - "source": "googleworkspace/cli", - "sourceType": "github", - "skillPath": "skills/gws-calendar/SKILL.md", - "computedHash": "0c5956e1069552444b00bf45381f08ffa9a7bca9810fefb1801866216008bcfc" - }, - "gws-docs": { - "source": "googleworkspace/cli", - "sourceType": "github", - "skillPath": "skills/gws-docs/SKILL.md", - "computedHash": "10dc2a8aa8cb28524a9d285ddba5602c24c21cbb640718fce522b58d90ee7b97" - }, - "gws-drive": { - "source": "googleworkspace/cli", - "sourceType": "github", - "skillPath": "skills/gws-drive/SKILL.md", - "computedHash": "d637ff849b82a9fc195bcfedea260cffe94eaa31b843b28cd04313b1720bb153" - }, - "gws-gmail": { - "source": "googleworkspace/cli", - "sourceType": "github", - "skillPath": "skills/gws-gmail/SKILL.md", - "computedHash": "5e5b5fdb4b4f347310d929657ed773abcaf528b5ac0a68deee12d3d38d307642" - }, - "gws-shared": { - "source": "googleworkspace/cli", - "sourceType": "github", - "skillPath": "skills/gws-shared/SKILL.md", - "computedHash": "b197590681ce3d5a52e9c15a68652b5445d111dbfc0dc453f68fb0785aac443c" - }, - "gws-sheets": { - "source": "googleworkspace/cli", - "sourceType": "github", - "skillPath": "skills/gws-sheets/SKILL.md", - "computedHash": "21c951f8bf399bb941740ab8b048157b43088ad96b743976e88abb0046d263d2" - }, - "humanizer": { - "source": "blader/humanizer", - "sourceType": "github", - "skillPath": "SKILL.md", - "computedHash": "b813857f183da05d08d5a80adac671df94c139f855809bd47ab8b7bb245546a2" - }, - "impeccable": { - "source": "pbakaus/impeccable", - "sourceType": "github", - "skillPath": "skill/SKILL.md", - "computedHash": "34e59a34b9705187e87039faa5d9585aebe0056ef657f761b905afef276a3362" - }, - "linear-cli": { - "source": "schpet/linear-cli", - "sourceType": "github", - "skillPath": "skills/linear-cli/SKILL.md", - "computedHash": "5f8516b9aa8157e7710ec5d029e1c44a0e55be1c3f834f844d0c7f27dae62580" - }, - "pdf": { - "source": "anthropics/skills", - "sourceType": "github", - "skillPath": "skills/pdf/SKILL.md", - "computedHash": "cfbc539377088ca7e44a813b30c306327385bbd973cd7a721e1743f60837dd62" - }, - "summarize": { - "source": "steipete/clawdis", - "sourceType": "github", - "skillPath": "skills/summarize/SKILL.md", - "computedHash": "67b9a5d86c3d9675e53e8bdb3f336661d55ccc689ecaaa3c99d984aa991458b6" - }, - "tmux": { - "source": "steipete/clawdis", - "sourceType": "github", - "skillPath": "skills/tmux/SKILL.md", - "computedHash": "ac61fad44978a9a2ca345f4c7de49de3f2b27cdb0096cbddf21f817c99d2fbce" - }, - "web-browser": { - "source": "mitsuhiko/agent-stuff", - "sourceType": "github", - "skillPath": "skills/web-browser/SKILL.md", - "computedHash": "e6c498ce130df429d35478732ac63be9c6caa35441484efbea786adf29117c26" - } - } -} diff --git a/dot_pi/agent/AGENTS.md b/dot_pi/agent/AGENTS.md new file mode 100644 --- /dev/null +++ b/dot_pi/agent/AGENTS.md @@ -0,0 +1,25 @@ +# Instructions + +## General preferences + +- Always address me using my name 'Joe' + +## Shell tool preferences + +- Always use `rg` instead of `grep`. +- Always use `fd` instead of `find`. +- Use `jq` for JSON processing +- Fish shell is the primary shell + +## Coding fundamental principles + +- Always have a bird's eye view of the code - "See the forest, not just the trees" +- Never do backwards compatibility, we move only forward +- Do not have any dead code, unused code should be cleaned up +- Do not write any comments, code is truth +- Do not store what you can compute. Do not send what can be derived. Each piece of data exists in one please +- Paul Dirac's beauty in code +- Duplication is decay, decay is corruption, corruption is death +- Expose what must be exposed, hide what must be hidden +- Every line will be judged at the scales +- Occam's Razor in code diff --git a/dot_agents/skills/gcx/SKILL.md b/dot_agents/skills/gcx/SKILL.md new file mode 100644 --- /dev/null +++ b/dot_agents/skills/gcx/SKILL.md @@ -0,0 +1,213 @@ +--- +name: gcx +description: > + Use gcx CLI to manage Grafana Cloud resources. Trigger when the user wants to + inspect, create, update, delete, query, or automate any Grafana resource — + dashboards, datasources, alerts, SLOs, synthetic checks, oncall, incidents, + fleet, k6, knowledge graph, or adaptive telemetry. +user-invocable: true +disable-model-invocation: false +allowed-tools: Bash, Read, Write, Edit, Glob, Grep, Agent, AskUserQuestion +--- + +# gcx — Grafana Cloud CLI + +gcx is a unified CLI for Grafana Cloud, organized like kubectl: named contexts, +structured output, and a consistent verb model across all resource types. + +## Discover Before You Act + +gcx has a built-in command catalog. Never guess a command — discover it first. +Use **progressive disclosure** to minimize token cost: + +**Step 1 — Orient** (30 lines, all top-level groups): +```bash +gcx help-tree --depth 1 -o text +``` + +**Step 2 — Drill down** (5-20 lines per group): +```bash +gcx help-tree -o text # full subtree for one group +gcx --help # exact flags and args +``` + +**Build payloads:** +```bash +gcx resources schemas # JSON schema for a resource type +gcx resources examples # example manifest +``` + +Only fall back to `gcx commands --flat -o json` when you need structured metadata +for automation — it is 255KB and should not be used for orientation. + +### Intent-to-Group Quick Reference + +When you already know the user's intent, skip discovery and go straight to the +right group: + +| Intent | Group | Example | +|--------|-------|---------| +| Dashboards, folders, K8s resources | `resources` | `gcx resources get dashboards` | +| SLO definitions and reports | `slo` | `gcx slo definitions list` | +| Alert rules and groups | `alert` | `gcx alert rules list` | +| Synthetic Monitoring checks | `synthetic-monitoring` | `gcx synthetic-monitoring checks list` | +| IRM (OnCall + Incidents) | `irm` | `gcx irm oncall schedules list`, `gcx irm incidents list` | +| k6 load tests, projects, runs | `k6` | `gcx k6 load-tests list` | +| PromQL / Adaptive Metrics | `metrics` | `gcx metrics query -d 'up'` | +| LogQL / Adaptive Logs | `logs` | `gcx logs query -d '{app="foo"}'` | +| Profiling (Pyroscope) | `profiles` | `gcx profiles query` | +| Tracing (Tempo) | `traces` | `gcx traces query -d '{ status = error }'` | +| Datasource info and queries | `datasources` | `gcx datasources list` | +| Fleet pipelines, collectors | `fleet` | `gcx fleet pipelines list` | +| Knowledge Graph (Asserts) | `kg` | `gcx kg entities list` | +| Frontend Observability | `frontend` | `gcx frontend apps list` | +| App Observability | `appo11y` | `gcx appo11y overrides list` | + +If no command exists for the requested operation, say so and propose the nearest +supported flow. + +### Avoid Raw API Passthrough + +**Do not use `gcx api`** when a dedicated command exists. `gcx api` is a low-level +fallback for endpoints not yet covered by dedicated commands. Dedicated commands +provide proper output formatting, pagination, error handling, and token-efficient +output. Check the intent-to-group table above first. + +Similarly, prefer `gcx metrics query` over `gcx datasources query ` +for PromQL queries — the signal-specific command handles datasource resolution +automatically. + +## Verify Context First + +Before any operation, confirm which environment is targeted: +- `gcx config check` — validates the active context and tests connectivity +- `gcx config view` — shows full config (secrets redacted; use `--raw` to reveal) +- `gcx config current-context` — shows just the active context name +- `gcx config use-context ` — switch contexts +- `--context ` flag on any command — target a specific context without switching + +## Output Control + +| Intent | Flag | +|--------|------| +| Structured output for parsing | `-o json` | +| Field selection | `--json ` (use `--json list` or `--json ?` to discover fields) | +| Full table output (no truncation) | `--no-truncate` | +| YAML output | `-o yaml` | +| Wide table with extra columns | `-o wide` | + +Default to `-o json` when working programmatically. + +## Safe Mutation Workflow + +Follow this sequence for any change. Skip steps only when the user explicitly +asks for speed. + +1. **Verify context** — confirm which environment is targeted +2. **Read current state** — list or get the resource first +3. **Build from template** — use schemas/examples output, not hand-crafted payloads +4. **Preview** — use `--dry-run` where available before applying +5. **Apply** — create, update, or delete +6. **Verify** — re-read the resource to confirm the change landed + +## Key Flags for Operations + +| Intent | Flag | +|--------|------| +| Preview without changing anything | `--dry-run` | +| Target a specific context | `--context ` | +| Continue on errors vs stop | `--on-error fail\|ignore\|abort` | +| Control concurrency | `--max-concurrent ` (default 10) | + +## Resource Operations + +The `gcx resources` group handles CRUD for Grafana's K8s-tier resources: +- `get` — list or fetch resources +- `push` — create or update from local files +- `pull` — export resources to local files +- `delete` — remove resources +- `edit` — edit resources interactively +- `validate` — validate local files against a live instance +- `schemas` — discover available resource types and their schemas +- `examples` — get example manifests for resource types + +All resource commands accept selectors: `gcx resources get dashboards`, +`gcx resources get dashboards/my-dash`, `gcx resources get dashboards folders`. + +## Datasource Queries + +The `gcx datasources` group provides typed query interfaces: +- `list` / `get` — discover available datasources +- `prometheus` — PromQL queries (query, labels, metadata, targets) +- `loki` — LogQL queries (query, labels, series) +- `pyroscope` — profiling queries +- `tempo` — trace queries +- `generic` — auto-detect datasource type + +Use `gcx datasources --help` to discover type-specific flags. + +## Grafana Assistant + +gcx provides direct access to the Grafana Assistant — use it for **reasoning +and exploration**, not data retrieval. Deterministic commands are faster and +cheaper for known queries; the Assistant adds value when you need intelligence. + +| Situation | Use | Example | +|-----------|-----|---------| +| You know the exact query | Deterministic command | `gcx metrics query 'rate(http_requests_total[5m])'` | +| You don't know which metrics/labels exist | `gcx assistant prompt` | `"What metrics exist for the checkout service?"` | +| You need cross-signal root cause analysis | `gcx assistant investigations` | Multi-agent parallel exploration across metrics, logs, traces, profiles | +| You need a precise, repeatable data point | Deterministic command | `gcx slo definitions status`, `gcx alert instances list --state firing` | +| You need to understand service dependencies | `gcx assistant prompt` | `"How are services in namespace X connected?"` — Assistant Memories know your stack topology | + +### Commands + +```bash +# Ask a question (Assistant uses Infrastructure Memories for context) +gcx assistant prompt "What services are unhealthy in namespace checkout?" + +# Follow up on the previous conversation +gcx assistant prompt "Dig into the database connection issue" --continue + +# Launch a deep investigation (multi-agent, parallel signal exploration) +gcx assistant investigations create --title="Checkout latency spike" + +# Monitor and read results +gcx assistant investigations timeline +gcx assistant investigations report +``` + +### Recommended Workflow: Interleave Both + +1. **Detect** with deterministic commands — `gcx alert instances list --state firing` +2. **Understand** with the Assistant — `gcx assistant prompt "Why is checkout-latency firing?"` +3. **Investigate** if needed — `gcx assistant investigations create --title="..."` +4. **Verify fix** with deterministic commands — `gcx slo definitions status ` + +## Provider Commands + +Product-specific providers register their own top-level command groups. +Discover them with `gcx providers`, then explore with `gcx --help`. + +Each provider adds domain-specific subcommands for managing that product's +resources. The set of providers grows over time — always discover rather than +hardcode. + +## Parallelism + +gcx commands are stateless API calls. When multiple operations are independent +(no output dependency between them), issue them as parallel Bash tool calls in +a single message. This applies to: + +- Multiple list/get calls across different resource types +- Multiple schema/example fetches +- Independent create/update operations +- Concurrent datasource queries + +Only sequence commands when a later call needs output from an earlier one. + +## Secret Safety + +Never read raw config files — they contain plaintext tokens. Use `gcx config view` +(which redacts secrets) for inspection. When passing tokens to external tools, +use shell variables rather than inline values. diff --git a/dot_agents/skills/reddit/SKILL.md b/dot_agents/skills/reddit/SKILL.md new file mode 100644 --- /dev/null +++ b/dot_agents/skills/reddit/SKILL.md @@ -0,0 +1,52 @@ +--- +name: reddit +description: Search Reddit and browse subreddit posts using the public JSON API. Use when you need to find Reddit discussions, community reactions, or story leads from specific subreddits. +--- + +# Reddit + +Search Reddit, browse subreddit top posts, and read individual posts with comments. No API key required. + +## Tool + +Use `reddit.js` from this skill directory: + +```bash +node reddit.js [options] +``` + +## Commands + +### Search all of Reddit +```bash +reddit.js search "query" [-n count] [-t period] [-s sort] +``` + +### Top posts from a subreddit +```bash +reddit.js top [-n count] [-t period] +``` + +### Read a post with top comments +```bash +reddit.js post [-c comment_count] +``` + +## Options + +| Flag | Default | Values | +|------|---------|--------| +| `-n` | 10 | Number of results (max 100) | +| `-t` | year | `hour`, `day`, `week`, `month`, `year`, `all` | +| `-s` | top | `relevance`, `hot`, `top`, `new`, `comments` | +| `-c` | 5 | Number of comments to show | + +## Output + +Each post shows: score, comment count, title, subreddit, author, date, link, and a text preview. The `post` command additionally shows top comments with scores. + +## Notes + +- **Rate limiting**: Reddit rate-limits unauthenticated requests. Add a small delay between rapid successive calls if needed. +- **Search relevance**: Global search can be noisy. Subreddit-specific `top` browsing tends to surface better results for niche research. +- **Subreddit names**: Pass without the `r/` prefix (e.g., `cybersecurity` not `r/cybersecurity`). diff --git a/dot_agents/skills/reddit/reddit.js b/dot_agents/skills/reddit/reddit.js new file mode 100644 --- /dev/null +++ b/dot_agents/skills/reddit/reddit.js @@ -0,0 +1,142 @@ +#!/usr/bin/env node + +const USAGE = `Usage: reddit.js [options] + +Commands: + search "query" Search all of Reddit + top Top posts from a subreddit + post Fetch a post with top comments + +Options: + -n Number of results (default: 10, max: 100) + -t Time period: hour, day, week, month, year, all (default: year) + -s Sort: relevance, hot, top, new, comments (default: top) + -c Number of comments to show for 'post' command (default: 5) + +Examples: + reddit.js search "insider threat cybercrime" -n 10 -t year + reddit.js top cybersecurity -t month -n 5 + reddit.js post "https://www.reddit.com/r/cybersecurity/comments/1rbnwlf"`; + +const UA = "pi-agent:1.0 (by /u/pi-coding-agent)"; + +function parseArgs(argv) { + const opts = { command: null, target: null, n: 10, t: "year", s: "top", c: 5 }; + const args = argv.slice(2); + if (!args.length) { console.error(USAGE); process.exit(1); } + opts.command = args[0]; + let i = 1; + // Grab target (next non-flag arg) + if (i < args.length && !args[i].startsWith("-")) { + opts.target = args[i++]; + } + while (i < args.length) { + const flag = args[i]; + const val = args[i + 1]; + if (flag === "-n" && val) { opts.n = Math.min(parseInt(val, 10), 100); i += 2; } + else if (flag === "-t" && val) { opts.t = val; i += 2; } + else if (flag === "-s" && val) { opts.s = val; i += 2; } + else if (flag === "-c" && val) { opts.c = parseInt(val, 10); i += 2; } + else if (!opts.target) { opts.target = args[i]; i++; } + else { i++; } + } + return opts; +} + +async function reddit(url) { + const sep = url.includes("?") ? "&" : "?"; + const fullUrl = `https://www.reddit.com${url}${sep}raw_json=1`; + const res = await fetch(fullUrl, { headers: { "User-Agent": UA } }); + if (!res.ok) throw new Error(`Reddit API ${res.status}: ${res.statusText}`); + return res.json(); +} + +function truncate(str, len) { + if (!str) return ""; + str = str.replace(/\n+/g, " ").trim(); + return str.length > len ? str.slice(0, len) + "…" : str; +} + +function formatPost(p, i) { + const lines = []; + lines.push(`${i}. [${p.score}pts | ${p.num_comments} comments] ${p.title}`); + lines.push(` r/${p.subreddit} • u/${p.author} • ${new Date(p.created_utc * 1000).toISOString().slice(0, 10)}`); + if (p.url && !p.is_self) { + lines.push(` Link: ${p.url}`); + } + lines.push(` https://reddit.com${p.permalink}`); + if (p.selftext) { + lines.push(` ${truncate(p.selftext, 300)}`); + } + return lines.join("\n"); +} + +async function cmdSearch(opts) { + if (!opts.target) { console.error("Error: search requires a query string"); process.exit(1); } + const params = new URLSearchParams({ + q: opts.target, + sort: opts.s, + t: opts.t, + limit: String(opts.n), + }); + const data = await reddit(`/search.json?${params}`); + const posts = data.data.children; + if (!posts.length) { console.log("No results found."); return; } + posts.forEach((p, i) => console.log(formatPost(p.data, i + 1) + "\n")); +} + +async function cmdTop(opts) { + if (!opts.target) { console.error("Error: top requires a subreddit name"); process.exit(1); } + const sub = opts.target.replace(/^r\//, ""); + const data = await reddit(`/r/${sub}/top.json?t=${opts.t}&limit=${opts.n}`); + const posts = data.data.children; + if (!posts.length) { console.log("No posts found."); return; } + posts.forEach((p, i) => console.log(formatPost(p.data, i + 1) + "\n")); +} + +async function cmdPost(opts) { + if (!opts.target) { console.error("Error: post requires a URL or post path"); process.exit(1); } + // Extract path from full URL or use as-is + let path = opts.target; + try { + const u = new URL(path); + path = u.pathname; + } catch {} + // Ensure path ends cleanly + path = path.replace(/\/$/, ""); + + const data = await reddit(`${path}.json?limit=${opts.c}&sort=top`); + const post = data[0].data.children[0].data; + + console.log(`# ${post.title}`); + console.log(`r/${post.subreddit} • u/${post.author} • ${new Date(post.created_utc * 1000).toISOString().slice(0, 10)}`); + console.log(`Score: ${post.score} | Comments: ${post.num_comments} | Upvote ratio: ${post.upvote_ratio}`); + if (post.url && !post.is_self) { + console.log(`Link: ${post.url}`); + } + console.log(`https://reddit.com${post.permalink}`); + if (post.selftext) { + console.log(`\n${truncate(post.selftext, 1000)}`); + } + + const comments = data[1].data.children.filter(c => c.kind === "t1"); + if (comments.length) { + console.log(`\n--- Top ${comments.length} comments ---\n`); + comments.forEach((c, i) => { + const d = c.data; + console.log(`${i + 1}. [${d.score}pts] u/${d.author}`); + console.log(` ${truncate(d.body, 400)}\n`); + }); + } +} + +const opts = parseArgs(process.argv); +try { + if (opts.command === "search") await cmdSearch(opts); + else if (opts.command === "top") await cmdTop(opts); + else if (opts.command === "post") await cmdPost(opts); + else { console.error(`Unknown command: ${opts.command}\n\n${USAGE}`); process.exit(1); } +} catch (e) { + console.error(`Error: ${e.message}`); + process.exit(1); +} diff --git a/dot_agents/skills/simplify/SKILL.md b/dot_agents/skills/simplify/SKILL.md new file mode 100644 --- /dev/null +++ b/dot_agents/skills/simplify/SKILL.md @@ -0,0 +1,33 @@ +--- +name: simplify +description: Use when the user wants recently modified code simplified without changing behavior. Apply the repository's current standards, improve clarity, remove unnecessary complexity, and keep the work scoped to code touched in the current session unless the user asks for a broader pass. +--- + +# Simplify + +Use this skill to refine recently changed code without expanding scope. + +Default rules: + +- work on code touched in the current task +- preserve behavior exactly +- prefer readability over shorter code +- follow the active `AGENTS.md` and local conventions + +Priorities: + +1. Remove unnecessary branching, nesting, abstraction, and duplication. +2. Prefer explicit names and straightforward control flow. +3. Consolidate related logic when that makes the code easier to read. +4. Remove comments that restate the code. +5. Avoid dense one-liners and nested ternaries. + +Process: + +1. Identify the changed files or hunks. +2. Read enough surrounding code to understand the local pattern. +3. Make the smallest forward-only change that improves clarity. +4. Re-run relevant validation after edits. +5. Summarize only meaningful simplifications. + +Do not widen the pass into untouched areas unless the user asks for it. -- tangled.sh