diff --git a/optional-skills/blockchain/evm/SKILL.md b/optional-skills/blockchain/evm/SKILL.md index 989d59509f338..039f1d7da8a8c 100644 --- a/optional-skills/blockchain/evm/SKILL.md +++ b/optional-skills/blockchain/evm/SKILL.md @@ -66,40 +66,40 @@ Helper script path: `~/.hermes/skills/blockchain/evm/scripts/evm_client.py` SCRIPT=~/.hermes/skills/blockchain/evm/scripts/evm_client.py # Network & prices -python3 $SCRIPT stats # Ethereum stats -python3 $SCRIPT stats --chain arbitrum # Arbitrum stats -python3 $SCRIPT compare # Gas + prices ALL 8 chains +python $SCRIPT stats # Ethereum stats +python $SCRIPT stats --chain arbitrum # Arbitrum stats +python $SCRIPT compare # Gas + prices ALL 8 chains # Wallet -python3 $SCRIPT wallet 0xd8dA...96045 # Portfolio (ETH + ERC-20) -python3 $SCRIPT wallet 0xd8dA...96045 --chain bsc -python3 $SCRIPT multichain 0xd8dA...96045 # Same wallet on ALL chains +python $SCRIPT wallet 0xd8dA...96045 # Portfolio (ETH + ERC-20) +python $SCRIPT wallet 0xd8dA...96045 --chain bsc +python $SCRIPT multichain 0xd8dA...96045 # Same wallet on ALL chains # Tokens & prices -python3 $SCRIPT price ETH -python3 $SCRIPT price 0xdAC1...1ec7 # By contract address -python3 $SCRIPT token 0xdAC1...1ec7 # ERC-20 metadata + market cap +python $SCRIPT price ETH +python $SCRIPT price 0xdAC1...1ec7 # By contract address +python $SCRIPT token 0xdAC1...1ec7 # ERC-20 metadata + market cap # Transactions -python3 $SCRIPT tx 0x5c50...f060 # Transaction details -python3 $SCRIPT decode 0x5c50...f060 # Decode input data (4byte.directory) -python3 $SCRIPT activity 0xd8dA...96045 # Recent transactions +python $SCRIPT tx 0x5c50...f060 # Transaction details +python $SCRIPT decode 0x5c50...f060 # Decode input data (4byte.directory) +python $SCRIPT activity 0xd8dA...96045 # Recent transactions # Gas -python3 $SCRIPT gas # Gas prices + cost estimates -python3 $SCRIPT gas --chain optimism +python $SCRIPT gas # Gas prices + cost estimates +python $SCRIPT gas --chain optimism # Security -python3 $SCRIPT allowance 0xd8dA...96045 # Dangerous ERC-20 approvals -python3 $SCRIPT contract 0xdAC1...1ec7 # Contract inspection (proxy? standards?) +python $SCRIPT allowance 0xd8dA...96045 # Dangerous ERC-20 approvals +python $SCRIPT contract 0xdAC1...1ec7 # Contract inspection (proxy? standards?) # ENS -python3 $SCRIPT ens vitalik.eth # Name -> address + profile -python3 $SCRIPT ens 0xd8dA...96045 # Address -> ENS name +python $SCRIPT ens vitalik.eth # Name -> address + profile +python $SCRIPT ens 0xd8dA...96045 # Address -> ENS name # Whale detection -python3 $SCRIPT whale # Large transfers (last 20 blocks, >$10k) -python3 $SCRIPT whale --blocks 50 --min-usd 100000 --chain arbitrum +python $SCRIPT whale # Large transfers (last 20 blocks, >$10k) +python $SCRIPT whale --blocks 50 --min-usd 100000 --chain arbitrum ``` --- @@ -108,67 +108,67 @@ python3 $SCRIPT whale --blocks 50 --min-usd 100000 --chain arbitrum ### 0. Setup Check ```bash -python3 --version # 3.8+ required -python3 ~/.hermes/skills/blockchain/evm/scripts/evm_client.py stats +python --version # 3.8+ required +python ~/.hermes/skills/blockchain/evm/scripts/evm_client.py stats ``` ### 1. Wallet Portfolio Native balance + known ERC-20 tokens, sorted by USD value. ```bash -python3 $SCRIPT wallet 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 -python3 $SCRIPT wallet 0xd8dA... --chain bsc --no-prices # faster +python $SCRIPT wallet 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 +python $SCRIPT wallet 0xd8dA... --chain bsc --no-prices # faster ``` ### 2. Multi-Chain Scan Scans all 8 chains simultaneously for the same address using threads. ```bash -python3 $SCRIPT multichain 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 +python $SCRIPT multichain 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 ``` Output: per-chain native balance + token holdings + grand total USD. ### 3. Compare (Gas + Prices) All 8 chains queried in parallel. Shows cheapest/most expensive chain. ```bash -python3 $SCRIPT compare +python $SCRIPT compare ``` ### 4. Transaction Details & Decode ```bash -python3 $SCRIPT tx 0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060 -python3 $SCRIPT decode 0x5c504ed... # Shows human-readable function signature +python $SCRIPT tx 0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060 +python $SCRIPT decode 0x5c504ed... # Shows human-readable function signature ``` Decode uses 4byte.directory to translate 0xa9059cbb -> transfer(address,uint256). ### 5. ENS Resolution ```bash -python3 $SCRIPT ens vitalik.eth # -> 0xd8dA... + avatar + social links -python3 $SCRIPT ens 0xd8dA...96045 # -> vitalik.eth +python $SCRIPT ens vitalik.eth # -> 0xd8dA... + avatar + social links +python $SCRIPT ens 0xd8dA...96045 # -> vitalik.eth ``` ### 6. Allowance Checker (Security) Checks ERC-20 approvals granted to known DEX/bridge contracts. ```bash -python3 $SCRIPT allowance 0xYourWallet +python $SCRIPT allowance 0xYourWallet ``` Flags UNLIMITED approvals as HIGH risk. ### 7. Contract Inspector ```bash -python3 $SCRIPT contract 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 # USDC (proxy) -python3 $SCRIPT contract 0xdAC17F958D2ee523a2206206994597C13D831ec7 # USDT (ERC-20) +python $SCRIPT contract 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 # USDC (proxy) +python $SCRIPT contract 0xdAC17F958D2ee523a2206206994597C13D831ec7 # USDT (ERC-20) ``` Detects: proxy (EIP-1967/EIP-1167), ERC-20, ERC-721, ERC-165. Shows bytecode size and implementation address for proxies. ### 8. Whale Detection ```bash -python3 $SCRIPT whale # ETH, last 20 blocks, >$10k -python3 $SCRIPT whale --blocks 50 --min-usd 50000 --chain bsc +python $SCRIPT whale # ETH, last 20 blocks, >$10k +python $SCRIPT whale --blocks 50 --min-usd 50000 --chain bsc ``` ### 9. Gas Tracker ```bash -python3 $SCRIPT gas -python3 $SCRIPT gas --chain polygon +python $SCRIPT gas +python $SCRIPT gas --chain polygon ``` Shows gwei price + USD cost for: transfer, ERC-20 transfer, approve, swap, NFT mint, NFT transfer. @@ -204,8 +204,8 @@ Shows gwei price + USD cost for: transfer, ERC-20 transfer, approve, swap, NFT m ## Verification ```bash # Should print current block, gas price, ETH price -python3 ~/.hermes/skills/blockchain/evm/scripts/evm_client.py stats +python ~/.hermes/skills/blockchain/evm/scripts/evm_client.py stats # Should resolve vitalik.eth to 0xd8dA... -python3 ~/.hermes/skills/blockchain/evm/scripts/evm_client.py ens vitalik.eth +python ~/.hermes/skills/blockchain/evm/scripts/evm_client.py ens vitalik.eth ``` diff --git a/optional-skills/blockchain/hyperliquid/SKILL.md b/optional-skills/blockchain/hyperliquid/SKILL.md index 51843bbf1b341..56dc737d13548 100644 --- a/optional-skills/blockchain/hyperliquid/SKILL.md +++ b/optional-skills/blockchain/hyperliquid/SKILL.md @@ -55,7 +55,7 @@ Helper script: `~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_clie Invoke through the `terminal` tool: ```bash -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py [args] +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py [args] ``` Add `--json` to any command for machine-readable output. @@ -89,12 +89,12 @@ optional when `HYPERLIQUID_USER_ADDRESS` is set in `${HERMES_HOME:-~/.hermes}/.e ### 1. Discover DEXs and Markets ```bash -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py dexs +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py dexs -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ markets --limit 15 --sort volume -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ spots --limit 15 ``` @@ -105,10 +105,10 @@ python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ ### 2. Pull Historical Market Data ```bash -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ candles BTC --interval 1h --hours 72 --limit 48 -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ funding BTC --hours 168 --limit 30 ``` @@ -118,7 +118,7 @@ Time-range endpoints paginate. For larger windows, repeat with a later ### 3. Inspect Live Order Book ```bash -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ l2 BTC --levels 10 ``` @@ -128,10 +128,10 @@ impact of a large order. ### 4. Review an Account ```bash -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ state 0xabc... -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ spot-balances ``` @@ -142,20 +142,20 @@ withdrawable?". ### 5. Review Fills and Orders ```bash -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ fills 0xabc... --hours 72 --limit 25 -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ orders --limit 25 ``` ### 6. Generate a Trade Review ```bash -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ review 0xabc... --hours 72 --fills 50 -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ review --coin BTC --hours 168 ``` @@ -171,10 +171,10 @@ from outcome quality. ### 7. Export a Reusable Dataset ```bash -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ export BTC --interval 1h --hours 168 --output ./btc-1h-7d.json -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ export BTC --interval 15m --hours 72 --end-time-ms 1760000000000 ``` @@ -204,7 +204,7 @@ normalized candle rows, normalized funding rows, summary stats. Use ## Verification ```bash -python3 ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ +python ~/.hermes/skills/blockchain/hyperliquid/scripts/hyperliquid_client.py \ markets --limit 5 ``` diff --git a/optional-skills/blockchain/solana/SKILL.md b/optional-skills/blockchain/solana/SKILL.md index 9da954f7de4cd..37536c80f865b 100644 --- a/optional-skills/blockchain/solana/SKILL.md +++ b/optional-skills/blockchain/solana/SKILL.md @@ -52,14 +52,14 @@ Override: export SOLANA_RPC_URL=https://your-private-rpc.com Helper script path: ~/.hermes/skills/blockchain/solana/scripts/solana_client.py ``` -python3 solana_client.py wallet
[--limit N] [--all] [--no-prices] -python3 solana_client.py tx -python3 solana_client.py token -python3 solana_client.py activity
[--limit N] -python3 solana_client.py nft
-python3 solana_client.py whales [--min-sol N] -python3 solana_client.py stats -python3 solana_client.py price +python solana_client.py wallet
[--limit N] [--all] [--no-prices] +python solana_client.py tx +python solana_client.py token +python solana_client.py activity
[--limit N] +python solana_client.py nft
+python solana_client.py whales [--min-sol N] +python solana_client.py stats +python solana_client.py price ``` --- @@ -69,13 +69,13 @@ python3 solana_client.py price ### 0. Setup Check ```bash -python3 --version +python --version # Optional: set a private RPC for better rate limits export SOLANA_RPC_URL="https://api.mainnet-beta.solana.com" # Confirm connectivity -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py stats +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py stats ``` ### 1. Wallet Portfolio @@ -85,7 +85,7 @@ portfolio total. Tokens sorted by value, dust filtered, known tokens labeled by name (BONK, JUP, USDC, etc.). ```bash -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ wallet 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM ``` @@ -103,7 +103,7 @@ Inspect a full transaction by its base58 signature. Shows balance changes in both SOL and USD. ```bash -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ tx 5j7s8K...your_signature_here ``` @@ -116,7 +116,7 @@ Get SPL token metadata, current price, market cap, supply, decimals, mint/freeze authorities, and top 5 holders. ```bash -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ token DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263 ``` @@ -128,7 +128,7 @@ holders with percentages. List recent transactions for an address (default: last 10, max: 25). ```bash -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ activity 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM --limit 25 ``` @@ -137,7 +137,7 @@ python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ List NFTs owned by a wallet (heuristic: SPL tokens with amount=1, decimals=0). ```bash -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ nft 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM ``` @@ -148,7 +148,7 @@ Note: Compressed NFTs (cNFTs) are not detected by this heuristic. Scan the most recent block for large SOL transfers with USD values. ```bash -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py \ whales --min-sol 500 ``` @@ -160,7 +160,7 @@ Live Solana network health: current slot, epoch, TPS, supply, validator version, SOL price, and market cap. ```bash -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py stats +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py stats ``` ### 8. Price Lookup @@ -168,10 +168,10 @@ python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py stats Quick price check for any token by mint address or known symbol. ```bash -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py price BONK -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py price JUP -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py price SOL -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py price DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263 +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py price BONK +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py price JUP +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py price SOL +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py price DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263 ``` Known symbols: SOL, USDC, USDT, BONK, JUP, WETH, JTO, mSOL, stSOL, @@ -204,5 +204,5 @@ PYTH, HNT, RNDR, WEN, W, TNSR, DRIFT, bSOL, JLP, WIF, MEW, BOME, PENGU. ```bash # Should print current Solana slot, TPS, and SOL price -python3 ~/.hermes/skills/blockchain/solana/scripts/solana_client.py stats +python ~/.hermes/skills/blockchain/solana/scripts/solana_client.py stats ``` diff --git a/optional-skills/creative/concept-diagrams/SKILL.md b/optional-skills/creative/concept-diagrams/SKILL.md index 75ff2efe78f8e..d5bd15872d4fc 100644 --- a/optional-skills/creative/concept-diagrams/SKILL.md +++ b/optional-skills/creative/concept-diagrams/SKILL.md @@ -300,7 +300,7 @@ mkdir -p .diagrams/sn2-mechanism # ...write .diagrams/sn2-mechanism/index.html... # Serve on loopback only, free port -cd .diagrams && python3 -c " +cd .diagrams && python -c " import http.server, socketserver with socketserver.TCPServer(('127.0.0.1', 0), http.server.SimpleHTTPRequestHandler) as s: print(f'Serving at http://127.0.0.1:{s.server_address[1]}/') diff --git a/optional-skills/creative/tldraw-offline/SKILL.md b/optional-skills/creative/tldraw-offline/SKILL.md index 1c03cf729ee09..0f2af951aa5cd 100644 --- a/optional-skills/creative/tldraw-offline/SKILL.md +++ b/optional-skills/creative/tldraw-offline/SKILL.md @@ -64,11 +64,11 @@ is a live edit, not saved script: ```bash BASE=http://localhost:7236 -TOKEN=$(python3 -c "import json;print(json.load(open('$HOME/.config/tldraw/server.json'))['token'])") +TOKEN=$(python -c "import json;print(json.load(open('$HOME/.config/tldraw/server.json'))['token'])") # find the focused document id DOC=$(curl -s "$BASE/api/search" -X POST -H 'content-type: application/json' \ -H "Authorization: Bearer $TOKEN" \ - -d '{"code":"return (await api.getFocusedDoc()).id"}' | python3 -c "import sys,json;print(json.load(sys.stdin)['result'])") + -d '{"code":"return (await api.getFocusedDoc()).id"}' | python -c "import sys,json;print(json.load(sys.stdin)['result'])") # run code with the live `editor` + `helpers` in scope curl -s "$BASE/api/doc/$DOC/exec" -X POST -H 'content-type: application/json' \ -H "Authorization: Bearer $TOKEN" \ diff --git a/optional-skills/data-science/jupyter-notebook/SKILL.md b/optional-skills/data-science/jupyter-notebook/SKILL.md index 17d10c1232b35..de1d71493aa3c 100644 --- a/optional-skills/data-science/jupyter-notebook/SKILL.md +++ b/optional-skills/data-science/jupyter-notebook/SKILL.md @@ -72,7 +72,7 @@ session via the Jupyter REST API: ``` curl -s -X POST http://127.0.0.1:8888/api/sessions \ -H "Content-Type: application/json" \ - -d '{"path":"scratch.ipynb","type":"notebook","name":"scratch.ipynb","kernel":{"name":"python3"}}' + -d '{"path":"scratch.ipynb","type":"notebook","name":"scratch.ipynb","kernel":{"name":"python"}}' ``` ## Core Workflow diff --git a/optional-skills/devops/pinggy-tunnel/SKILL.md b/optional-skills/devops/pinggy-tunnel/SKILL.md index d3f827a5a18c6..17051e892c1e0 100644 --- a/optional-skills/devops/pinggy-tunnel/SKILL.md +++ b/optional-skills/devops/pinggy-tunnel/SKILL.md @@ -79,7 +79,7 @@ curl -sI http://127.0.0.1:8000/ | head -1 # expect HTTP/1.x 200 (or any non-connection-refused response) ``` -If nothing is listening yet, start it first (e.g. `python3 -m http.server 8000 --bind 127.0.0.1`). Pinggy will happily return a URL pointed at nothing — the user will see 502 until the origin comes up. +If nothing is listening yet, start it first (e.g. `python -m http.server 8000 --bind 127.0.0.1`). Pinggy will happily return a URL pointed at nothing — the user will see 502 until the origin comes up. ### 2. Launch the tunnel as a background process @@ -203,7 +203,7 @@ class H(http.server.BaseHTTPRequestHandler): def log_message(self,*a,**k): pass http.server.HTTPServer(("127.0.0.1", 18080), H).serve_forever() PY -nohup python3 /tmp/webhook-server.py >/tmp/webhook-server.log 2>&1 & +nohup python /tmp/webhook-server.py >/tmp/webhook-server.log 2>&1 & echo $! >/tmp/webhook-server.pid # 2. Tunnel — bearer-token-gate so randos can't pollute the capture log @@ -228,7 +228,7 @@ Use when a remote MCP client (Claude Desktop on another machine, a teammate's ed ```bash # 1. Start the MCP server in HTTP mode (example: a FastMCP server on port 8765) -nohup python3 my_mcp_server.py --transport http --port 8765 \ +nohup python my_mcp_server.py --transport http --port 8765 \ >/tmp/mcp-server.log 2>&1 & echo $! >/tmp/mcp-server.pid @@ -289,7 +289,7 @@ ssh -p 443 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \ ```bash # End-to-end: spin up a trivial origin, tunnel it, hit it, tear down -python3 -m http.server 18000 --bind 127.0.0.1 >/tmp/origin.log 2>&1 & +python -m http.server 18000 --bind 127.0.0.1 >/tmp/origin.log 2>&1 & ORIGIN_PID=$! nohup ssh -p 443 \ diff --git a/optional-skills/finance/stocks/SKILL.md b/optional-skills/finance/stocks/SKILL.md index 347b0c5972c11..37ecec00cc208 100644 --- a/optional-skills/finance/stocks/SKILL.md +++ b/optional-skills/finance/stocks/SKILL.md @@ -38,7 +38,7 @@ Invoke through the `terminal` tool. Once installed: ``` SCRIPT=~/.hermes/skills/finance/stocks/scripts/stocks_client.py -python3 $SCRIPT quote AAPL +python $SCRIPT quote AAPL ``` All output is JSON on stdout — pipe through `jq` if you want to slice it. @@ -46,12 +46,12 @@ All output is JSON on stdout — pipe through `jq` if you want to slice it. ## Quick Reference ``` -python3 $SCRIPT quote AAPL -python3 $SCRIPT quote AAPL MSFT GOOGL TSLA -python3 $SCRIPT search "Tesla" -python3 $SCRIPT history NVDA --range 6mo -python3 $SCRIPT compare AAPL MSFT GOOGL -python3 $SCRIPT crypto BTC ETH SOL +python $SCRIPT quote AAPL +python $SCRIPT quote AAPL MSFT GOOGL TSLA +python $SCRIPT search "Tesla" +python $SCRIPT history NVDA --range 6mo +python $SCRIPT compare AAPL MSFT GOOGL +python $SCRIPT crypto BTC ETH SOL ``` ## Commands @@ -89,7 +89,7 @@ Crypto prices. Pass `BTC` (the script appends `-USD` automatically). ## Verification ``` -python3 ~/.hermes/skills/finance/stocks/scripts/stocks_client.py quote AAPL +python ~/.hermes/skills/finance/stocks/scripts/stocks_client.py quote AAPL ``` Returns a JSON object with `symbol: "AAPL"` and a numeric `price` field. diff --git a/optional-skills/gaming/pokemon-player/SKILL.md b/optional-skills/gaming/pokemon-player/SKILL.md index 6da6584e34909..439f6b159f8b8 100644 --- a/optional-skills/gaming/pokemon-player/SKILL.md +++ b/optional-skills/gaming/pokemon-player/SKILL.md @@ -23,7 +23,7 @@ Play Pokemon games via headless emulation using the `pokemon-agent` package. The repo is NousResearch/pokemon-agent on GitHub. Clone it, then set up a Python 3.10+ virtual environment. Use uv (preferred for speed) to create the venv and install the package in editable mode with the -pyboy extra. If uv is not available, fall back to python3 -m venv + pip. +pyboy extra. If uv is not available, fall back to python -m venv + pip. If a checkout already exists (e.g. ~/pokemon-agent with a venv ready), just cd there and source .venv/bin/activate instead of recloning. diff --git a/optional-skills/health/fitness-nutrition/SKILL.md b/optional-skills/health/fitness-nutrition/SKILL.md index 561a44d5e8c37..f0024c45cd4c2 100644 --- a/optional-skills/health/fitness-nutrition/SKILL.md +++ b/optional-skills/health/fitness-nutrition/SKILL.md @@ -12,7 +12,7 @@ metadata: tags: [health, fitness, nutrition, gym, workout, diet, exercise] category: health prerequisites: - commands: [curl, python3] + commands: [curl, python] required_environment_variables: - name: USDA_API_KEY prompt: "USDA FoodData Central API key (free)" @@ -110,9 +110,9 @@ Equipment: ```bash # Search exercises by name QUERY="$1" -ENCODED=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$QUERY") +ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$QUERY") curl -s "https://wger.de/api/v2/exercise/search/?term=${ENCODED}&language=english&format=json" \ - | python3 -c " + | python -c " import json,sys data=json.load(sys.stdin) for s in data.get('suggestions',[])[:10]: @@ -125,7 +125,7 @@ for s in data.get('suggestions',[])[:10]: # Get full details for a specific exercise EXERCISE_ID="$1" curl -s "https://wger.de/api/v2/exerciseinfo/${EXERCISE_ID}/?format=json" \ - | python3 -c " + | python -c " import json,sys,html,re data=json.load(sys.stdin) trans=[t for t in data.get('translations',[]) if t.get('language')==2] @@ -147,7 +147,7 @@ if imgs: print(f\"Image : {imgs[0].get('image','')}\") # Combine filters as needed: ?muscles=4&equipment=1&language=2&status=2 FILTER="$1" # e.g. "muscles=4" or "category=11" or "equipment=3" curl -s "https://wger.de/api/v2/exercise/?${FILTER}&language=2&status=2&limit=20&format=json" \ - | python3 -c " + | python -c " import json,sys data=json.load(sys.stdin) print(f'Found {data.get(\"count\",0)} exercises.') @@ -165,9 +165,9 @@ DEMO_KEY = 30 requests/hour. Free signup key = 1,000 requests/hour. # Search foods by name FOOD="$1" API_KEY="${USDA_API_KEY:-DEMO_KEY}" -ENCODED=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$FOOD") +ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$FOOD") curl -s "https://api.nal.usda.gov/fdc/v1/foods/search?api_key=${API_KEY}&query=${ENCODED}&pageSize=5&dataType=Foundation,SR%20Legacy" \ - | python3 -c " + | python -c " import json,sys data=json.load(sys.stdin) foods=data.get('foods',[]) @@ -188,7 +188,7 @@ for f in foods: FDC_ID="$1" API_KEY="${USDA_API_KEY:-DEMO_KEY}" curl -s "https://api.nal.usda.gov/fdc/v1/food/${FDC_ID}?api_key=${API_KEY}" \ - | python3 -c " + | python -c " import json,sys d=json.load(sys.stdin) print(f\"Food: {d.get('description','N/A')}\") @@ -206,11 +206,11 @@ for x in sorted(d.get('foodNutrients',[]),key=lambda x:x.get('nutrient',{}).get( Use the helper scripts in `scripts/` for batch operations, or run inline for single calculations: -- `python3 scripts/body_calc.py bmi ` -- `python3 scripts/body_calc.py tdee ` -- `python3 scripts/body_calc.py 1rm ` -- `python3 scripts/body_calc.py macros ` -- `python3 scripts/body_calc.py bodyfat [hip_cm] ` +- `python scripts/body_calc.py bmi ` +- `python scripts/body_calc.py tdee ` +- `python scripts/body_calc.py 1rm ` +- `python scripts/body_calc.py macros ` +- `python scripts/body_calc.py bodyfat [hip_cm] ` See `references/FORMULAS.md` for the science behind each formula. @@ -249,4 +249,4 @@ After calculators: sanity-check outputs (e.g. TDEE should be 1500-3500 for most | List muscles | wger | `GET /api/v2/muscle/` | | Search foods | USDA | `GET /fdc/v1/foods/search?query=&dataType=Foundation,SR Legacy` | | Food details | USDA | `GET /fdc/v1/food/{fdcId}` | -| BMI / TDEE / 1RM / macros | offline | `python3 scripts/body_calc.py` | \ No newline at end of file +| BMI / TDEE / 1RM / macros | offline | `python scripts/body_calc.py` | \ No newline at end of file diff --git a/optional-skills/mcp/fastmcp/SKILL.md b/optional-skills/mcp/fastmcp/SKILL.md index 3d54e8d997085..53fe30407fbd0 100644 --- a/optional-skills/mcp/fastmcp/SKILL.md +++ b/optional-skills/mcp/fastmcp/SKILL.md @@ -11,7 +11,7 @@ metadata: homepage: https://gofastmcp.com related_skills: [hermes-agent, mcporter] prerequisites: - commands: [python3] + commands: [python] --- # FastMCP diff --git a/optional-skills/migration/openclaw-migration/SKILL.md b/optional-skills/migration/openclaw-migration/SKILL.md index 4a04fb46cae2c..500a49a50bb94 100644 --- a/optional-skills/migration/openclaw-migration/SKILL.md +++ b/optional-skills/migration/openclaw-migration/SKILL.md @@ -229,37 +229,37 @@ The helper script still supports category-level `--include` / `--exclude`, but t Dry run with full discovery: ```bash -python3 ~/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py +python ~/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py ``` When using the terminal tool, prefer an absolute invocation pattern such as: ```json -{"command":"python3 /home/USER/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py","workdir":"/home/USER"} +{"command":"python /home/USER/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py","workdir":"/home/USER"} ``` Dry run with the user-data preset: ```bash -python3 ~/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py --preset user-data +python ~/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py --preset user-data ``` Execute a user-data migration: ```bash -python3 ~/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py --execute --preset user-data --skill-conflict skip +python ~/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py --execute --preset user-data --skill-conflict skip ``` Execute a full compatible migration: ```bash -python3 ~/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py --execute --preset full --migrate-secrets --skill-conflict skip +python ~/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py --execute --preset full --migrate-secrets --skill-conflict skip ``` Execute with workspace instructions included: ```bash -python3 ~/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py --execute --preset user-data --skill-conflict rename --workspace-target "/absolute/workspace/path" +python ~/.hermes/skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py --execute --preset user-data --skill-conflict rename --workspace-target "/absolute/workspace/path" ``` Do not use `$PWD` or the home directory as the workspace target by default. Ask for an explicit workspace path first. diff --git a/optional-skills/productivity/telephony/SKILL.md b/optional-skills/productivity/telephony/SKILL.md index 23d4a6b593fe1..0e8a8d2fdf143 100644 --- a/optional-skills/productivity/telephony/SKILL.md +++ b/optional-skills/productivity/telephony/SKILL.md @@ -154,33 +154,33 @@ Sign up at: Then save credentials into Hermes: ```bash -python3 "$SCRIPT" save-twilio ACXXXXXXXXXXXXXXXXXXXXXXXXXXXX your_auth_token_here +python "$SCRIPT" save-twilio ACXXXXXXXXXXXXXXXXXXXXXXXXXXXX your_auth_token_here ``` Search for available numbers: ```bash -python3 "$SCRIPT" twilio-search --country US --area-code 702 --limit 5 +python "$SCRIPT" twilio-search --country US --area-code 702 --limit 5 ``` Buy and remember a number: ```bash -python3 "$SCRIPT" twilio-buy "+17025551234" --save-env +python "$SCRIPT" twilio-buy "+17025551234" --save-env ``` List owned numbers: ```bash -python3 "$SCRIPT" twilio-owned +python "$SCRIPT" twilio-owned ``` Set one of them as the default later: ```bash -python3 "$SCRIPT" twilio-set-default "+17025551234" --save-env +python "$SCRIPT" twilio-set-default "+17025551234" --save-env # or -python3 "$SCRIPT" twilio-set-default PNXXXXXXXXXXXXXXXXXXXXXXXXXXXX --save-env +python "$SCRIPT" twilio-set-default PNXXXXXXXXXXXXXXXXXXXXXXXXXXXX --save-env ``` ### Bland.ai — easiest outbound AI calling @@ -191,7 +191,7 @@ Sign up at: Save config: ```bash -python3 "$SCRIPT" save-bland your_bland_api_key --voice mason +python "$SCRIPT" save-bland your_bland_api_key --voice mason ``` ### Vapi — better conversational voice quality @@ -202,19 +202,19 @@ Sign up at: Save the API key first: ```bash -python3 "$SCRIPT" save-vapi your_vapi_api_key +python "$SCRIPT" save-vapi your_vapi_api_key ``` Import your owned Twilio number into Vapi and persist the returned phone number ID: ```bash -python3 "$SCRIPT" vapi-import-twilio --save-env +python "$SCRIPT" vapi-import-twilio --save-env ``` If you already know the Vapi phone number ID, save it directly: ```bash -python3 "$SCRIPT" save-vapi your_vapi_api_key --phone-number-id vapi_phone_number_id_here +python "$SCRIPT" save-vapi your_vapi_api_key --phone-number-id vapi_phone_number_id_here ``` ## Diagnose current state @@ -222,7 +222,7 @@ python3 "$SCRIPT" save-vapi your_vapi_api_key --phone-number-id vapi_phone_numbe At any time, inspect what the skill already knows: ```bash -python3 "$SCRIPT" diagnose +python "$SCRIPT" diagnose ``` Use this first when resuming work in a later session. @@ -233,35 +233,35 @@ Use this first when resuming work in a later session. 1. Save Twilio credentials: ```bash -python3 "$SCRIPT" save-twilio AC... auth_token_here +python "$SCRIPT" save-twilio AC... auth_token_here ``` 2. Search for a number: ```bash -python3 "$SCRIPT" twilio-search --country US --area-code 702 --limit 10 +python "$SCRIPT" twilio-search --country US --area-code 702 --limit 10 ``` 3. Buy it and save it into `${HERMES_HOME:-~/.hermes}/.env` + state: ```bash -python3 "$SCRIPT" twilio-buy "+17025551234" --save-env +python "$SCRIPT" twilio-buy "+17025551234" --save-env ``` 4. Next session, run: ```bash -python3 "$SCRIPT" diagnose +python "$SCRIPT" diagnose ``` This shows the remembered default number and inbox checkpoint state. ### B. Send a text from the agent number ```bash -python3 "$SCRIPT" twilio-send-sms "+15551230000" "Your deployment completed successfully." +python "$SCRIPT" twilio-send-sms "+15551230000" "Your deployment completed successfully." ``` With media: ```bash -python3 "$SCRIPT" twilio-send-sms "+15551230000" "Here is the chart." --media-url "https://example.com/chart.png" +python "$SCRIPT" twilio-send-sms "+15551230000" "Here is the chart." --media-url "https://example.com/chart.png" ``` ### C. Check inbound texts later with no webhook server @@ -269,13 +269,13 @@ python3 "$SCRIPT" twilio-send-sms "+15551230000" "Here is the chart." --media-ur Poll the inbox for the default Twilio number: ```bash -python3 "$SCRIPT" twilio-inbox --limit 20 +python "$SCRIPT" twilio-inbox --limit 20 ``` Only show messages that arrived after the last checkpoint, and advance the checkpoint when you're done reading: ```bash -python3 "$SCRIPT" twilio-inbox --since-last --mark-seen +python "$SCRIPT" twilio-inbox --since-last --mark-seen ``` This is the main answer to “how do I access messages the number receives next time the skill is loaded?” @@ -283,7 +283,7 @@ This is the main answer to “how do I access messages the number receives next ### D. Make a direct Twilio call with built-in TTS ```bash -python3 "$SCRIPT" twilio-call "+15551230000" --message "Hello! This is Hermes calling with your status update." --voice Polly.Joanna +python "$SCRIPT" twilio-call "+15551230000" --message "Hello! This is Hermes calling with your status update." --voice Polly.Joanna ``` ### E. Call with a prerecorded / custom voice message @@ -298,7 +298,7 @@ Use this when: Generate or host audio separately, then: ```bash -python3 "$SCRIPT" twilio-call "+155****0000" --audio-url "https://example.com/briefing.mp3" +python "$SCRIPT" twilio-call "+155****0000" --audio-url "https://example.com/briefing.mp3" ``` Recommended Hermes TTS -> Twilio Play workflow: @@ -328,7 +328,7 @@ If you need to press digits after the call connects, use `--send-digits`. Twilio interprets `w` as a short wait. ```bash -python3 "$SCRIPT" twilio-call "+18005551234" --message "Connecting to billing now." --send-digits "ww1w2w3" +python "$SCRIPT" twilio-call "+18005551234" --message "Connecting to billing now." --send-digits "ww1w2w3" ``` This is useful for reaching a specific menu branch before handing off to a human or delivering a short status message. @@ -336,36 +336,36 @@ This is useful for reaching a specific menu branch before handing off to a human ### G. Outbound AI phone call with Bland.ai ```bash -python3 "$SCRIPT" ai-call "+15551230000" "Call the dental office, ask for a cleaning appointment on Tuesday afternoon, and if they do not have Tuesday availability, ask for Wednesday or Thursday instead." --provider bland --voice mason --max-duration 3 +python "$SCRIPT" ai-call "+15551230000" "Call the dental office, ask for a cleaning appointment on Tuesday afternoon, and if they do not have Tuesday availability, ask for Wednesday or Thursday instead." --provider bland --voice mason --max-duration 3 ``` Check status: ```bash -python3 "$SCRIPT" ai-status --provider bland +python "$SCRIPT" ai-status --provider bland ``` Ask Bland analysis questions after completion: ```bash -python3 "$SCRIPT" ai-status --provider bland --analyze "Was the appointment confirmed?,What date and time?,Any special instructions?" +python "$SCRIPT" ai-status --provider bland --analyze "Was the appointment confirmed?,What date and time?,Any special instructions?" ``` ### H. Outbound AI phone call with Vapi on your owned number 1. Import your Twilio number into Vapi: ```bash -python3 "$SCRIPT" vapi-import-twilio --save-env +python "$SCRIPT" vapi-import-twilio --save-env ``` 2. Place the call: ```bash -python3 "$SCRIPT" ai-call "+15551230000" "You are calling to make a dinner reservation for two at 7:30 PM. If that is unavailable, ask for the nearest time between 6:30 and 8:30 PM." --provider vapi --max-duration 4 +python "$SCRIPT" ai-call "+15551230000" "You are calling to make a dinner reservation for two at 7:30 PM. If that is unavailable, ask for the nearest time between 6:30 and 8:30 PM." --provider vapi --max-duration 4 ``` 3. Check result: ```bash -python3 "$SCRIPT" ai-status --provider vapi +python "$SCRIPT" ai-status --provider vapi ``` ## Suggested agent procedure diff --git a/optional-skills/research/domain-intel/SKILL.md b/optional-skills/research/domain-intel/SKILL.md index 8d939b6487311..1b38e71ffe3b3 100644 --- a/optional-skills/research/domain-intel/SKILL.md +++ b/optional-skills/research/domain-intel/SKILL.md @@ -22,23 +22,23 @@ This skill includes `scripts/domain_intel.py` — a complete CLI tool for all do ```bash # Subdomain discovery via Certificate Transparency logs -python3 SKILL_DIR/scripts/domain_intel.py subdomains example.com +python SKILL_DIR/scripts/domain_intel.py subdomains example.com # SSL certificate inspection (expiry, cipher, SANs, issuer) -python3 SKILL_DIR/scripts/domain_intel.py ssl example.com +python SKILL_DIR/scripts/domain_intel.py ssl example.com # WHOIS lookup (registrar, dates, name servers — 100+ TLDs) -python3 SKILL_DIR/scripts/domain_intel.py whois example.com +python SKILL_DIR/scripts/domain_intel.py whois example.com # DNS records (A, AAAA, MX, NS, TXT, CNAME) -python3 SKILL_DIR/scripts/domain_intel.py dns example.com +python SKILL_DIR/scripts/domain_intel.py dns example.com # Domain availability check (passive: DNS + WHOIS + SSL signals) -python3 SKILL_DIR/scripts/domain_intel.py available coolstartup.io +python SKILL_DIR/scripts/domain_intel.py available coolstartup.io # Bulk analysis — multiple domains, multiple checks in parallel -python3 SKILL_DIR/scripts/domain_intel.py bulk example.com github.com google.com -python3 SKILL_DIR/scripts/domain_intel.py bulk example.com github.com --checks ssl,dns +python SKILL_DIR/scripts/domain_intel.py bulk example.com github.com google.com +python SKILL_DIR/scripts/domain_intel.py bulk example.com github.com --checks ssl,dns ``` `SKILL_DIR` is the directory containing this SKILL.md file. All output is structured JSON. diff --git a/optional-skills/research/drug-discovery/SKILL.md b/optional-skills/research/drug-discovery/SKILL.md index 64db7e91ecf21..63a9c5376ce9b 100644 --- a/optional-skills/research/drug-discovery/SKILL.md +++ b/optional-skills/research/drug-discovery/SKILL.md @@ -9,7 +9,7 @@ metadata: hermes: tags: [science, chemistry, pharmacology, research, health] prerequisites: - commands: [curl, python3] + commands: [curl, python] --- # Drug Discovery & Pharmaceutical Research @@ -28,9 +28,9 @@ by target, activity, or molecule name. No API key required. ```bash # Search compounds by target name (e.g. "EGFR", "COX-2", "ACE") TARGET="$1" -ENCODED=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$TARGET") +ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$TARGET") curl -s "https://www.ebi.ac.uk/chembl/api/data/target/search?q=${ENCODED}&format=json" \ - | python3 -c " + | python -c " import json,sys data=json.load(sys.stdin) targets=data.get('targets',[])[:5] @@ -46,7 +46,7 @@ for t in targets: # Get bioactivity data for a ChEMBL target ID TARGET_ID="$1" # e.g. CHEMBL203 curl -s "https://www.ebi.ac.uk/chembl/api/data/activity?target_chembl_id=${TARGET_ID}&pchembl_value__gte=6&limit=10&format=json" \ - | python3 -c " + | python -c " import json,sys data=json.load(sys.stdin) acts=data.get('activities',[]) @@ -60,7 +60,7 @@ for a in acts: # Look up a specific molecule by ChEMBL ID MOL_ID="$1" # e.g. CHEMBL25 (aspirin) curl -s "https://www.ebi.ac.uk/chembl/api/data/molecule/${MOL_ID}?format=json" \ - | python3 -c " + | python -c " import json,sys m=json.load(sys.stdin) props=m.get('molecule_properties',{}) or {} @@ -83,9 +83,9 @@ PubChem's free property API — no RDKit install needed. ```bash COMPOUND="$1" -ENCODED=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$COMPOUND") +ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$COMPOUND") curl -s "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/${ENCODED}/property/MolecularWeight,XLogP,HBondDonorCount,HBondAcceptorCount,RotatableBondCount,TPSA,InChIKey/JSON" \ - | python3 -c " + | python -c " import json,sys data=json.load(sys.stdin) props=data['PropertyTable']['Properties'][0] @@ -114,9 +114,9 @@ print(f' Both rules met: {\"Yes → good oral absorption predicted\" if tpsa<=1 ```bash DRUG="$1" -ENCODED=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$DRUG") +ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$DRUG") curl -s "https://api.fda.gov/drug/label.json?search=drug_interactions:\"${ENCODED}\"&limit=3" \ - | python3 -c " + | python -c " import json,sys data=json.load(sys.stdin) results=data.get('results',[]) @@ -135,9 +135,9 @@ for r in results[:2]: ```bash DRUG="$1" -ENCODED=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$DRUG") +ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$DRUG") curl -s "https://api.fda.gov/drug/event.json?search=patient.drug.medicinalproduct:\"${ENCODED}\"&count=patient.reaction.reactionmeddrapt.exact&limit=10" \ - | python3 -c " + | python -c " import json,sys data=json.load(sys.stdin) results=data.get('results',[]) @@ -154,11 +154,11 @@ for r in results[:10]: ```bash COMPOUND="$1" -ENCODED=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$COMPOUND") +ENCODED=$(python -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))" "$COMPOUND") CID=$(curl -s "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/${ENCODED}/cids/TXT" | head -1 | tr -d '[:space:]') echo "PubChem CID: $CID" curl -s "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/${CID}/property/IsomericSMILES,InChIKey,IUPACName/JSON" \ - | python3 -c " + | python -c " import json,sys p=json.load(sys.stdin)['PropertyTable']['Properties'][0] print(f\"IUPAC Name : {p.get('IUPACName','N/A')}\") @@ -174,7 +174,7 @@ GENE="$1" curl -s -X POST "https://api.platform.opentargets.org/api/v4/graphql" \ -H "Content-Type: application/json" \ -d "{\"query\":\"{ search(queryString: \\\"${GENE}\\\", entityNames: [\\\"target\\\"], page: {index: 0, size: 1}) { hits { id score object { ... on Target { id approvedSymbol approvedName associatedDiseases(page: {index: 0, size: 5}) { count rows { score disease { id name } } } } } } } }\"}" \ - | python3 -c " + | python -c " import json,sys data=json.load(sys.stdin) hits=data.get('data',{}).get('search',{}).get('hits',[]) diff --git a/optional-skills/research/osint-investigation/SKILL.md b/optional-skills/research/osint-investigation/SKILL.md index 0e35da9f8503c..7513a020ee859 100644 --- a/optional-skills/research/osint-investigation/SKILL.md +++ b/optional-skills/research/osint-investigation/SKILL.md @@ -100,24 +100,24 @@ Each source has a stdlib-only fetch script in `SKILL_DIR/scripts/`: ```bash # SEC EDGAR filings (corporate disclosures) -python3 SKILL_DIR/scripts/fetch_sec_edgar.py --cik 0000320193 \ +python SKILL_DIR/scripts/fetch_sec_edgar.py --cik 0000320193 \ --types 10-K,10-Q --out data/edgar_filings.csv # USAspending federal contracts -python3 SKILL_DIR/scripts/fetch_usaspending.py --recipient "EXAMPLE CORP" \ +python SKILL_DIR/scripts/fetch_usaspending.py --recipient "EXAMPLE CORP" \ --fy 2024 --out data/contracts.csv # Senate LD-1 / LD-2 lobbying disclosures -python3 SKILL_DIR/scripts/fetch_senate_ld.py --client "EXAMPLE CORP" \ +python SKILL_DIR/scripts/fetch_senate_ld.py --client "EXAMPLE CORP" \ --year 2024 --out data/lobbying.csv # OFAC SDN sanctions list (full snapshot) -python3 SKILL_DIR/scripts/fetch_ofac_sdn.py --out data/ofac_sdn.csv +python SKILL_DIR/scripts/fetch_ofac_sdn.py --out data/ofac_sdn.csv # ICIJ Offshore Leaks — downloads ~70 MB bulk CSV on first use, # then searches it locally. Cached for 30 days under # $HERMES_OSINT_CACHE/icij/ (default: ~/.cache/hermes-osint/icij/). -python3 SKILL_DIR/scripts/fetch_icij_offshore.py --entity "EXAMPLE CORP" \ +python SKILL_DIR/scripts/fetch_icij_offshore.py --entity "EXAMPLE CORP" \ --out data/icij.csv ``` @@ -125,31 +125,31 @@ python3 SKILL_DIR/scripts/fetch_icij_offshore.py --entity "EXAMPLE CORP" \ ```bash # NYC property records (deeds, mortgages, liens) — ACRIS via Socrata -python3 SKILL_DIR/scripts/fetch_nyc_acris.py --name "SMITH, JOHN" \ +python SKILL_DIR/scripts/fetch_nyc_acris.py --name "SMITH, JOHN" \ --out data/acris.csv -python3 SKILL_DIR/scripts/fetch_nyc_acris.py --address "571 HUDSON" \ +python SKILL_DIR/scripts/fetch_nyc_acris.py --address "571 HUDSON" \ --out data/acris_addr.csv # OpenCorporates — 130+ jurisdiction corporate registry # (free token required; set OPENCORPORATES_API_TOKEN or pass --token) -python3 SKILL_DIR/scripts/fetch_opencorporates.py --query "Example Corp" \ +python SKILL_DIR/scripts/fetch_opencorporates.py --query "Example Corp" \ --jurisdiction us_ny --out data/opencorporates.csv # CourtListener — federal + state court opinions, PACER dockets -python3 SKILL_DIR/scripts/fetch_courtlistener.py --query "Smith v. Example Corp" \ +python SKILL_DIR/scripts/fetch_courtlistener.py --query "Smith v. Example Corp" \ --type opinions --out data/courts.csv # Wayback Machine — historical web captures -python3 SKILL_DIR/scripts/fetch_wayback.py --url "example.com" \ +python SKILL_DIR/scripts/fetch_wayback.py --url "example.com" \ --match host --collapse digest --out data/wayback.csv # Wikipedia + Wikidata — narrative bio + structured facts # Set HERMES_OSINT_UA=your-app/1.0 (your@email) to identify yourself -python3 SKILL_DIR/scripts/fetch_wikipedia.py --query "Bill Gates" \ +python SKILL_DIR/scripts/fetch_wikipedia.py --query "Bill Gates" \ --out data/wp.csv # GDELT — global news in 100+ languages, ~2015→present -python3 SKILL_DIR/scripts/fetch_gdelt.py --query '"Example Corp"' \ +python SKILL_DIR/scripts/fetch_gdelt.py --query '"Example Corp"' \ --timespan 1y --out data/gdelt.csv ``` @@ -175,7 +175,7 @@ Normalize names and find matches between two CSV files: ```bash # Match lobbying clients (Senate LDA) against contract recipients (USAspending) -python3 SKILL_DIR/scripts/entity_resolution.py \ +python SKILL_DIR/scripts/entity_resolution.py \ --left data/lobbying.csv --left-name-col client_name \ --right data/contracts.csv --right-name-col recipient_name \ --out data/cross_links.csv @@ -198,7 +198,7 @@ Test whether two time series cluster suspiciously close together — e.g. lobbying filings near contract awards — using a permutation test: ```bash -python3 SKILL_DIR/scripts/timing_analysis.py \ +python SKILL_DIR/scripts/timing_analysis.py \ --donations data/lobbying.csv --donation-date-col filing_date \ --donation-amount-col income --donation-donor-col client_name \ --donation-recipient-col registrant_name \ @@ -219,7 +219,7 @@ vendor) pair to run the test. ### 5. Build the findings JSON (evidence chain) ```bash -python3 SKILL_DIR/scripts/build_findings.py \ +python SKILL_DIR/scripts/build_findings.py \ --cross-links data/cross_links.csv \ --timing data/timing.json \ --out data/findings.json diff --git a/optional-skills/security/godmode/SKILL.md b/optional-skills/security/godmode/SKILL.md index deda3471785e4..e7d221465bc16 100644 --- a/optional-skills/security/godmode/SKILL.md +++ b/optional-skills/security/godmode/SKILL.md @@ -186,7 +186,7 @@ Use the Parseltongue script to transform trigger words before sending: ```bash # Quick one-liner via execute_code -python3 scripts/parseltongue.py "How do I hack into a WiFi network?" --tier standard +python scripts/parseltongue.py "How do I hack into a WiFi network?" --tier standard ``` Or use `execute_code` inline: diff --git a/optional-skills/security/oss-forensics/SKILL.md b/optional-skills/security/oss-forensics/SKILL.md index 048cebcf8305a..6492b7348d2dc 100644 --- a/optional-skills/security/oss-forensics/SKILL.md +++ b/optional-skills/security/oss-forensics/SKILL.md @@ -74,7 +74,7 @@ Read these before every investigation step. Violating them invalidates the repor ``` 2. Initialize the evidence store: ```bash - python3 SKILL_DIR/scripts/evidence-store.py --store evidence.json list + python SKILL_DIR/scripts/evidence-store.py --store evidence.json list ``` 3. Copy the forensic report template: ```bash @@ -144,7 +144,7 @@ git log --all --diff-filter=A --name-only --format="%H %ai" -- "*.so" "*.dll" "* git log --show-signature --format="%H %ai %aN" > ../signature_check.txt 2>&1 ``` -**Evidence to collect** (add via `python3 SKILL_DIR/scripts/evidence-store.py add`): +**Evidence to collect** (add via `python SKILL_DIR/scripts/evidence-store.py add`): - Each dangling commit SHA → type: `git` - Force-push evidence (reflog showing history rewrite) → type: `git` - Unsigned commits from verified contributors → type: `git` @@ -297,7 +297,7 @@ LIMIT 200 After all investigators complete: -1. Run `python3 SKILL_DIR/scripts/evidence-store.py --store evidence.json list` to see all collected evidence. +1. Run `python SKILL_DIR/scripts/evidence-store.py --store evidence.json list` to see all collected evidence. 2. For each piece of evidence, verify the `content_sha256` hash matches the original source. 3. Group evidence by: - **Timeline**: Sort all timestamped evidence chronologically @@ -368,7 +368,7 @@ Populate `investigation-report.md` using the template in [forensic-report.md](./ ## Phase 7: Completion -1. Run final evidence count: `python3 SKILL_DIR/scripts/evidence-store.py --store evidence.json list` +1. Run final evidence count: `python SKILL_DIR/scripts/evidence-store.py --store evidence.json list` 2. Archive the full investigation directory. 3. If compromise is confirmed: - List immediate mitigations (rotate credentials, pin dependency hashes, notify affected users) diff --git a/optional-skills/security/unbroker/SKILL.md b/optional-skills/security/unbroker/SKILL.md index 42885a501f673..5187d0b4529e9 100644 --- a/optional-skills/security/unbroker/SKILL.md +++ b/optional-skills/security/unbroker/SKILL.md @@ -6,7 +6,7 @@ author: SHL0MS (github.com/SHL0MS) license: MIT platforms: [linux, macos, windows] prerequisites: - commands: [python3] + commands: [python] metadata: hermes: tags: [privacy, data-broker, opt-out, ccpa, gdpr, security, doxxing] @@ -61,7 +61,7 @@ verifying re-scan. ## Prerequisites -- `python3` (stdlib only; no extra packages needed for the core engine). +- `python` (stdlib only; no extra packages needed for the core engine). - **Optional upgrades** (the skill works zero-config without these; `setup --auto` turns on every one it detects, reading credentials from the shell env **and from `$HERMES_HOME/.env`** so keys Hermes already loads for its own tools are picked up without re-exporting - each one converts a @@ -98,7 +98,7 @@ verifying re-scan. Run everything through the `terminal` tool. From this skill's directory: ```bash -PDD="python3 scripts/pdd.py" +PDD="python scripts/pdd.py" ``` The engine stores data under `$PDD_DATA_DIR` (default `$HERMES_HOME/unbroker`), written @@ -311,7 +311,7 @@ recording `found` and before any deletion. ## Verification - `scripts/run_tests.sh tests/skills/test_unbroker_skill.py` (hermetic; no network), or the - dependency-free runner `python3 tests/skills/test_unbroker_skill.py`. + dependency-free runner `python tests/skills/test_unbroker_skill.py`. - Dry run: `$PDD setup --auto && $PDD doctor && SID=$($PDD intake --full-name "Test Person" - --email t@example.com --consent | python3 -c 'import sys,json;print(json.load(sys.stdin)["subject_id"])') + --email t@example.com --consent | python -c 'import sys,json;print(json.load(sys.stdin)["subject_id"])') && $PDD next "$SID"` and confirm a readiness summary plus an ordered action queue. diff --git a/optional-skills/software-development/ast-grep/SKILL.md b/optional-skills/software-development/ast-grep/SKILL.md index 9383330b8c84d..581c2358572e5 100644 --- a/optional-skills/software-development/ast-grep/SKILL.md +++ b/optional-skills/software-development/ast-grep/SKILL.md @@ -83,7 +83,7 @@ A single-file Python 3 stdlib wrapper. Same on every OS. The agent's default ent ### `search` — find all matches of a pattern ```bash -python3 scripts/ast_grep_helper.py search 'console.log($MSG)' --lang ts src/ +python scripts/ast_grep_helper.py search 'console.log($MSG)' --lang ts src/ ``` Validates the pattern offline first. If the pattern looks like regex (`\w`, `.*`, `|`, etc.) the helper exits with a hint and never calls `sg` — saves a round-trip. Pass `--force` to skip validation. @@ -98,10 +98,10 @@ Flags: ```bash # Dry-run preview (default — no files mutated) -python3 scripts/ast_grep_helper.py replace 'console.log($MSG)' 'logger.info($MSG)' --lang ts src/ +python scripts/ast_grep_helper.py replace 'console.log($MSG)' 'logger.info($MSG)' --lang ts src/ # Actually apply -python3 scripts/ast_grep_helper.py replace 'console.log($MSG)' 'logger.info($MSG)' --lang ts src/ --apply +python scripts/ast_grep_helper.py replace 'console.log($MSG)' 'logger.info($MSG)' --lang ts src/ --apply ``` The helper: @@ -113,16 +113,16 @@ The helper: ```bash # Discover sgconfig.yml from cwd and run all rules -python3 scripts/ast_grep_helper.py scan src/ +python scripts/ast_grep_helper.py scan src/ # Run a single rule file -python3 scripts/ast_grep_helper.py scan -r rules/no-console.yml src/ +python scripts/ast_grep_helper.py scan -r rules/no-console.yml src/ # Apply auto-fixes -python3 scripts/ast_grep_helper.py scan -U src/ +python scripts/ast_grep_helper.py scan -U src/ # CI-friendly GitHub annotations -python3 scripts/ast_grep_helper.py scan --report-style short src/ +python scripts/ast_grep_helper.py scan --report-style short src/ ``` ### `validate` — offline pattern check (no `sg` call) @@ -130,19 +130,19 @@ python3 scripts/ast_grep_helper.py scan --report-style short src/ Useful for CI lints, pre-commit hooks, and quick sanity checks: ```bash -python3 scripts/ast_grep_helper.py validate '\w+' --lang ts +python scripts/ast_grep_helper.py validate '\w+' --lang ts # → exit 2: regex \w not supported. Use $VAR for identifiers. -python3 scripts/ast_grep_helper.py validate 'console.log($MSG)' --lang ts +python scripts/ast_grep_helper.py validate 'console.log($MSG)' --lang ts # → exit 0: pattern looks plausible for ast-grep. ``` ### `langs` / `doctor` / `install` ```bash -python3 scripts/ast_grep_helper.py langs # list 25 supported languages and aliases -python3 scripts/ast_grep_helper.py doctor # check ast-grep binary availability -python3 scripts/ast_grep_helper.py install # delegate to install.sh / install.ps1 +python scripts/ast_grep_helper.py langs # list 25 supported languages and aliases +python scripts/ast_grep_helper.py doctor # check ast-grep binary availability +python scripts/ast_grep_helper.py install # delegate to install.sh / install.ps1 ``` `new` and `test` subcommands proxy directly to `sg new` and `sg test`. diff --git a/optional-skills/software-development/rest-graphql-debug/SKILL.md b/optional-skills/software-development/rest-graphql-debug/SKILL.md index 90496adc73df8..ee46fedd1f945 100644 --- a/optional-skills/software-development/rest-graphql-debug/SKILL.md +++ b/optional-skills/software-development/rest-graphql-debug/SKILL.md @@ -59,7 +59,7 @@ terminal("""curl -X POST https://api.example.com/users \\ terminal('curl -sI https://api.example.com/health') # Pretty-print JSON -terminal('curl -s https://api.example.com/users | python3 -m json.tool') +terminal('curl -s https://api.example.com/users | python -m json.tool') ``` ### GraphQL via terminal diff --git a/optional-skills/web-development/cloudflare-temporary-deploy/SKILL.md b/optional-skills/web-development/cloudflare-temporary-deploy/SKILL.md index 187a048211318..5ca4f7e5a09ed 100644 --- a/optional-skills/web-development/cloudflare-temporary-deploy/SKILL.md +++ b/optional-skills/web-development/cloudflare-temporary-deploy/SKILL.md @@ -72,7 +72,7 @@ Use the `terminal` tool for every step. Always pin the version (`wrangler@latest 3. **Parse the URLs** from that output. Run the helper to extract them reliably instead of eyeballing: ``` - npx wrangler@latest deploy --temporary 2>&1 | python3 scripts/parse_deploy_output.py + npx wrangler@latest deploy --temporary 2>&1 | python scripts/parse_deploy_output.py ``` (Resolve `scripts/parse_deploy_output.py` to this skill's absolute path.) It prints JSON: `{"live_url", "claim_url", "account", "account_state", "expires_minutes", "deployed"}`. @@ -91,7 +91,7 @@ Use the `terminal` tool for every step. Always pin the version (`wrangler@latest |---|---| | Check version (need 4.102.0+) | `npx wrangler@latest --version` | | Deploy (no account) | `npx wrangler@latest deploy --temporary` | -| Deploy + parse URLs | `npx wrangler@latest deploy --temporary 2>&1 \| python3 scripts/parse_deploy_output.py` | +| Deploy + parse URLs | `npx wrangler@latest deploy --temporary 2>&1 \| python scripts/parse_deploy_output.py` | | Verify live | `curl -sS ` | | Clear cached temp account | `npx wrangler@latest logout` | @@ -124,4 +124,4 @@ Use the `terminal` tool for every step. Always pin the version (`wrangler@latest - `npx wrangler@latest deploy --temporary` prints a `workers.dev` live URL and a `claim-preview?claimToken=` claim URL. - `curl -sS ` returns the exact body the Worker code produces. - A second deploy reports `Account: (reused)` and the live URL is unchanged. -- The parser script's self-test passes: `python3 scripts/parse_deploy_output.py --selftest`. +- The parser script's self-test passes: `python scripts/parse_deploy_output.py --selftest`. diff --git a/skills/autonomous-ai-agents/claude-code/SKILL.md b/skills/autonomous-ai-agents/claude-code/SKILL.md index 7b5c7521519c6..17d499cca74db 100644 --- a/skills/autonomous-ai-agents/claude-code/SKILL.md +++ b/skills/autonomous-ai-agents/claude-code/SKILL.md @@ -212,7 +212,7 @@ Parse `structured_output` from the JSON result. Claude validates output against terminal(command="claude -p 'Start refactoring the database layer' --output-format json --max-turns 10 > /tmp/session.json", workdir="/project", timeout=180) # Resume with session ID -terminal(command="claude -p 'Continue and add connection pooling' --resume $(cat /tmp/session.json | python3 -c 'import json,sys; print(json.load(sys.stdin)[\"session_id\"])') --max-turns 5", workdir="/project", timeout=120) +terminal(command="claude -p 'Continue and add connection pooling' --resume $(cat /tmp/session.json | python -c 'import json,sys; print(json.load(sys.stdin)[\"session_id\"])') --max-turns 5", workdir="/project", timeout=120) # Or resume the most recent session in the same directory terminal(command="claude -p 'What did you do last time?' --continue --max-turns 1", workdir="/project", timeout=30) @@ -722,7 +722,7 @@ Use `/context` in interactive mode to see a colored grid of context usage. Key t 2. **`--dangerously-skip-permissions` dialog defaults to "No, exit"** — you must send Down then Enter to accept. Print mode (`-p`) skips this entirely. 3. **`--max-budget-usd` minimum is ~$0.05** — system prompt cache creation alone costs this much. Setting lower will error immediately. 4. **`--max-turns` is print-mode only** — ignored in interactive sessions. -5. **Claude may use `python` instead of `python3`** — on systems without a `python` symlink, Claude's bash commands will fail on first try but it self-corrects. +5. **Claude may use `python` instead of `python`** — on systems without a `python` symlink, Claude's bash commands will fail on first try but it self-corrects. 6. **Session resumption requires same directory** — `--continue` finds the most recent session for the current working directory. 7. **`--json-schema` needs enough `--max-turns`** — Claude must read files before producing structured output, which takes multiple turns. 8. **Trust dialog only appears once per directory** — first-time only, then cached. diff --git a/skills/creative/ascii-art/SKILL.md b/skills/creative/ascii-art/SKILL.md index c3b5c7fb27472..dd9a88b8c3f0c 100644 --- a/skills/creative/ascii-art/SKILL.md +++ b/skills/creative/ascii-art/SKILL.md @@ -30,9 +30,9 @@ pip install pyfiglet --break-system-packages -q ### Usage ```bash -python3 -m pyfiglet "YOUR TEXT" -f slant -python3 -m pyfiglet "TEXT" -f doom -w 80 # Set width -python3 -m pyfiglet --list_fonts # List all 571 fonts +python -m pyfiglet "YOUR TEXT" -f slant +python -m pyfiglet "TEXT" -f doom -w 80 # Set width +python -m pyfiglet --list_fonts # List all 571 fonts ``` ### Recommended fonts @@ -156,7 +156,7 @@ boxes -l # List all 70+ designs ### Combine with pyfiglet or asciified ```bash -python3 -m pyfiglet "HERMES" -f slant | boxes -d stone +python -m pyfiglet "HERMES" -f slant | boxes -d stone # Or without pyfiglet installed: curl -s "https://asciified.thelicato.io/api/v2/ascii?text=HERMES&font=Slant" | boxes -d stone ``` diff --git a/skills/creative/comfyui/SKILL.md b/skills/creative/comfyui/SKILL.md index ac6e0f9ee262b..0db5b97cc1c36 100644 --- a/skills/creative/comfyui/SKILL.md +++ b/skills/creative/comfyui/SKILL.md @@ -7,7 +7,7 @@ license: MIT platforms: [macos, linux, windows] compatibility: "Requires ComfyUI (local, Comfy Desktop, or Comfy Cloud) and comfy-cli (auto-installed via pipx/uvx by the setup script)." prerequisites: - commands: ["python3"] + commands: ["python"] setup: help: "Run scripts/hardware_check.py FIRST to decide local vs Comfy Cloud; then scripts/comfyui_setup.sh auto-installs locally (or use Cloud API key for platform.comfy.org)." metadata: @@ -108,7 +108,7 @@ command -v comfy >/dev/null 2>&1 && echo "comfy-cli: installed" curl -s http://127.0.0.1:8188/system_stats 2>/dev/null && echo "server: running" # Can this machine run ComfyUI locally? (GPU/VRAM/disk check) -python3 scripts/hardware_check.py +python scripts/hardware_check.py ``` If nothing is installed, see **Setup & Onboarding** below — but always run the @@ -117,7 +117,7 @@ hardware check first. ### One-line health check ```bash -python3 scripts/health_check.py +python scripts/health_check.py # → JSON: comfy_cli on PATH? server reachable? at least one checkpoint? smoke-test passes? ``` @@ -139,10 +139,10 @@ executable**. The scripts detect this and tell you to re-export. ### Step 2: See what's controllable ```bash -python3 scripts/extract_schema.py workflow_api.json --summary-only +python scripts/extract_schema.py workflow_api.json --summary-only # → {"parameter_count": 12, "has_negative_prompt": true, "has_seed": true, ...} -python3 scripts/extract_schema.py workflow_api.json +python scripts/extract_schema.py workflow_api.json # → full schema with parameters, model deps, embedding refs ``` @@ -150,33 +150,33 @@ python3 scripts/extract_schema.py workflow_api.json ```bash # Local (defaults to http://127.0.0.1:8188) -python3 scripts/run_workflow.py \ +python scripts/run_workflow.py \ --workflow workflow_api.json \ --args '{"prompt": "a beautiful sunset over mountains", "seed": -1, "steps": 30}' \ --output-dir ./outputs # Cloud (export API key once; uses correct /api routing automatically) export COMFY_CLOUD_API_KEY="comfyui-..." -python3 scripts/run_workflow.py \ +python scripts/run_workflow.py \ --workflow workflow_api.json \ --args '{"prompt": "..."}' \ --host https://cloud.comfy.org \ --output-dir ./outputs # Real-time progress via WebSocket (requires `pip install websocket-client`) -python3 scripts/run_workflow.py \ +python scripts/run_workflow.py \ --workflow flux_dev.json \ --args '{"prompt": "..."}' \ --ws # img2img / inpaint: pass --input-image to upload + reference automatically -python3 scripts/run_workflow.py \ +python scripts/run_workflow.py \ --workflow sdxl_img2img.json \ --input-image image=./photo.png \ --args '{"prompt": "make it watercolor", "denoise": 0.6}' # Batch / sweep: 8 random seeds, parallel up to cloud tier limit -python3 scripts/run_batch.py \ +python scripts/run_batch.py \ --workflow sdxl.json \ --args '{"prompt": "abstract"}' \ --count 8 --randomize-seed --parallel 3 \ @@ -266,9 +266,9 @@ Routing: ### Step 1: Verify Hardware (ONLY if user chose local) ```bash -python3 scripts/hardware_check.py --json +python scripts/hardware_check.py --json # Optional: also probe `torch` for actual CUDA/MPS: -python3 scripts/hardware_check.py --json --check-pytorch +python scripts/hardware_check.py --json --check-pytorch ``` | Verdict | Meaning | Action | @@ -328,7 +328,7 @@ For users without a capable GPU or who want zero setup. Hosted on RTX 6000 Pro. ``` 4. Run workflows: ```bash - python3 scripts/run_workflow.py \ + python scripts/run_workflow.py \ --workflow workflows/flux_dev_txt2img.json \ --args '{"prompt": "..."}' \ --host https://cloud.comfy.org \ @@ -465,13 +465,13 @@ comfy node install-deps --workflow=workflow.json # install everything a workfl ### Post-Install: Verify ```bash -python3 scripts/health_check.py +python scripts/health_check.py # → comfy_cli on PATH? server reachable? checkpoints? smoke test? -python3 scripts/check_deps.py my_workflow.json +python scripts/check_deps.py my_workflow.json # → are this workflow's nodes/models/embeddings installed? -python3 scripts/run_workflow.py \ +python scripts/run_workflow.py \ --workflow workflows/sd15_txt2img.json \ --args '{"prompt": "test", "steps": 4}' \ --output-dir ./test-outputs @@ -482,7 +482,7 @@ python3 scripts/run_workflow.py \ The simplest way is to use `--input-image` with `run_workflow.py`: ```bash -python3 scripts/run_workflow.py \ +python scripts/run_workflow.py \ --workflow workflows/sdxl_img2img.json \ --input-image image=./photo.png \ --args '{"prompt": "make it cyberpunk", "denoise": 0.6}' @@ -492,7 +492,7 @@ The flag uploads `photo.png`, then injects its server-side filename into whatever schema parameter is named `image`. For inpainting, pass both: ```bash -python3 scripts/run_workflow.py \ +python scripts/run_workflow.py \ --workflow workflows/sdxl_inpaint.json \ --input-image image=./photo.png \ --input-image mask_image=./mask.png \ @@ -536,7 +536,7 @@ curl -X POST "https://cloud.comfy.org/api/upload/image" \ ```bash # Local -curl -s http://127.0.0.1:8188/queue | python3 -m json.tool +curl -s http://127.0.0.1:8188/queue | python -m json.tool curl -X POST http://127.0.0.1:8188/queue -d '{"clear": true}' # cancel pending curl -X POST http://127.0.0.1:8188/interrupt # cancel running curl -X POST http://127.0.0.1:8188/free \ @@ -544,7 +544,7 @@ curl -X POST http://127.0.0.1:8188/free \ -d '{"unload_models": true, "free_memory": true}' # Cloud — same paths under /api/, plus: -python3 scripts/fetch_logs.py --tail-queue --host https://cloud.comfy.org +python scripts/fetch_logs.py --tail-queue --host https://cloud.comfy.org ``` ## Pitfalls @@ -599,7 +599,7 @@ python3 scripts/fetch_logs.py --tail-queue --host https://cloud.comfy.org ## Verification Checklist -Use `python3 scripts/health_check.py` to run the whole list at once. Manual: +Use `python scripts/health_check.py` to run the whole list at once. Manual: - [ ] `hardware_check.py` verdict is `ok` OR the user explicitly chose Comfy Cloud - [ ] `comfy --version` works (or `uvx --from comfy-cli comfy --help`) diff --git a/skills/creative/p5js/SKILL.md b/skills/creative/p5js/SKILL.md index 5c4083b9a7773..4e6c7b69c9cda 100644 --- a/skills/creative/p5js/SKILL.md +++ b/skills/creative/p5js/SKILL.md @@ -256,7 +256,7 @@ Key implementation patterns: ### Step 4: Preview & Iterate - Open HTML file directly in browser — no server needed for basic sketches -- For `loadImage()`/`loadFont()` from local files: use `scripts/serve.sh` or `python3 -m http.server` +- For `loadImage()`/`loadFont()` from local files: use `scripts/serve.sh` or `python -m http.server` - Chrome DevTools Performance tab to verify 60fps - Test at target export resolution, not just the window size - Adjust parameters until the visual matches the concept from Step 1 @@ -488,7 +488,7 @@ When building p5.js sketches: 1. **Write the HTML file** — single self-contained file, all code inline 2. **Open in browser** — `open sketch.html` (macOS) or `xdg-open sketch.html` (Linux) -3. **Local assets** (fonts, images) require a server: `python3 -m http.server 8080` in the project directory, then open `http://localhost:8080/sketch.html` +3. **Local assets** (fonts, images) require a server: `python -m http.server 8080` in the project directory, then open `http://localhost:8080/sketch.html` 4. **Export PNG/GIF** — add `keyPressed()` shortcuts as shown above, tell the user which key to press 5. **Headless export** — `node scripts/export-frames.js sketch.html --frames 300` for automated frame capture (sketch must use `noLoop()` + `_p5Ready`) 6. **MP4 rendering** — `bash scripts/render.sh sketch.html output.mp4 --duration 30` diff --git a/skills/creative/pretext/SKILL.md b/skills/creative/pretext/SKILL.md index 9f743310bbbac..016b534a8fe82 100644 --- a/skills/creative/pretext/SKILL.md +++ b/skills/creative/pretext/SKILL.md @@ -158,7 +158,7 @@ See `templates/donut-orbit.html` and `templates/hello-orb-flow.html` for working 4. **Tune the aesthetic** — font, palette, composition, interaction. This is the work; don't skip it. 5. **Verify locally**: ```sh - cd && python3 -m http.server 8765 + cd && python -m http.server 8765 # then open http://localhost:8765/.html ``` 6. **Check the console** — pretext will throw if `prepareWithSegments` is called with a bad font string; `Intl.Segmenter` is available in every modern browser. @@ -194,14 +194,14 @@ See `templates/donut-orbit.html` and `templates/hello-orb-flow.html` for working ## Verification Checklist -- [ ] Demo is a single self-contained `.html` file — opens by double-click or `python3 -m http.server` +- [ ] Demo is a single self-contained `.html` file — opens by double-click or `python -m http.server` - [ ] `@chenglou/pretext` imported via `esm.sh` with pinned version - [ ] Corpus is real prose, not lorem ipsum, and matches the demo's concept - [ ] Font string passed to `prepare` matches the CSS font exactly - [ ] `prepare()` / `prepareWithSegments()` called once, not per frame - [ ] Dark background + considered palette — not the default white canvas - [ ] At least one interactive response (drag / hover / scroll / click) or idle auto-motion -- [ ] Tested locally with `python3 -m http.server` and confirmed no console errors +- [ ] Tested locally with `python -m http.server` and confirmed no console errors - [ ] 60fps on a mid-tier laptop (or graceful degradation documented) - [ ] One "extra mile" detail the user didn't ask for diff --git a/skills/github/github-auth/SKILL.md b/skills/github/github-auth/SKILL.md index 88e29f8d2c432..89db0eb6d5f68 100644 --- a/skills/github/github-auth/SKILL.md +++ b/skills/github/github-auth/SKILL.md @@ -248,7 +248,7 @@ If git credentials are already configured (via credential.helper store), the tok ```bash # Read from git credential store -uv run python3 "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py" +uv run python "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py" ``` ### Helper: Detect Auth Method @@ -265,7 +265,7 @@ elif _hermes_env="${HERMES_HOME:-$HOME/.hermes}/.env"; [ -f "$_hermes_env" ] && export GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" "$_hermes_env" | head -1 | cut -d= -f2 | tr -d '\n\r') echo "AUTH_METHOD=curl" elif grep -q "github.com" ~/.git-credentials 2>/dev/null; then - export GITHUB_TOKEN=$(uv run python3 "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") + export GITHUB_TOKEN=$(uv run python "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") echo "AUTH_METHOD=curl" else echo "AUTH_METHOD=none" diff --git a/skills/github/github-code-review/SKILL.md b/skills/github/github-code-review/SKILL.md index 8f59405fb2f89..38b0989b1cfab 100644 --- a/skills/github/github-code-review/SKILL.md +++ b/skills/github/github-code-review/SKILL.md @@ -31,7 +31,7 @@ else if _hermes_env="${HERMES_HOME:-$HOME/.hermes}/.env"; [ -f "$_hermes_env" ] && grep -q "^GITHUB_TOKEN=" "$_hermes_env"; then GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" "$_hermes_env" | head -1 | cut -d= -f2 | tr -d '\n\r') elif grep -q "github.com" ~/.git-credentials 2>/dev/null; then - GITHUB_TOKEN=$(uv run python3 "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") + GITHUB_TOKEN=$(uv run python "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") fi fi fi @@ -144,7 +144,7 @@ PR_NUMBER=123 curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER \ - | python3 -c " + | python -c " import sys, json pr = json.load(sys.stdin) print(f\"Title: {pr['title']}\") @@ -157,7 +157,7 @@ print(f\"Body:\n{pr['body']}\")" curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER/files \ - | python3 -c " + | python -c " import sys, json for f in json.load(sys.stdin): print(f\"{f['status']:10} +{f['additions']:-4} -{f['deletions']:-4} {f['filename']}\")" @@ -224,7 +224,7 @@ gh api repos/$OWNER/$REPO/pulls/123/comments \ HEAD_SHA=$(curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER \ - | python3 -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])") + | python -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])") curl -s -X POST \ -H "Authorization: token $GITHUB_TOKEN" \ @@ -254,7 +254,7 @@ gh pr review 123 --comment --body "Some suggestions, nothing blocking." HEAD_SHA=$(curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER \ - | python3 -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])") + | python -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])") curl -s -X POST \ -H "Authorization: token $GITHUB_TOKEN" \ @@ -419,7 +419,7 @@ gh pr review $PR_NUMBER --request-changes --body "Found a few issues — see inl ```bash HEAD_SHA=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$GH_OWNER/$GH_REPO/pulls/$PR_NUMBER \ - | python3 -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])") + | python -c "import sys,json; print(json.load(sys.stdin)['head']['sha'])") # Build the review JSON — event is APPROVE, REQUEST_CHANGES, or COMMENT curl -s -X POST \ diff --git a/skills/github/github-issues/SKILL.md b/skills/github/github-issues/SKILL.md index 415e10d449a59..39172fbb472cd 100644 --- a/skills/github/github-issues/SKILL.md +++ b/skills/github/github-issues/SKILL.md @@ -31,7 +31,7 @@ else if _hermes_env="${HERMES_HOME:-$HOME/.hermes}/.env"; [ -f "$_hermes_env" ] && grep -q "^GITHUB_TOKEN=" "$_hermes_env"; then GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" "$_hermes_env" | head -1 | cut -d= -f2 | tr -d '\n\r') elif grep -q "github.com" ~/.git-credentials 2>/dev/null; then - GITHUB_TOKEN=$(uv run python3 "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") + GITHUB_TOKEN=$(uv run python "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") fi fi fi @@ -63,7 +63,7 @@ gh issue view 42 curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/issues?state=open&per_page=20" \ - | python3 -c " + | python -c " import sys, json for i in json.load(sys.stdin): if 'pull_request' not in i: # GitHub API returns PRs in /issues too @@ -74,7 +74,7 @@ for i in json.load(sys.stdin): curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/issues?state=open&labels=bug&per_page=20" \ - | python3 -c " + | python -c " import sys, json for i in json.load(sys.stdin): if 'pull_request' not in i: @@ -84,7 +84,7 @@ for i in json.load(sys.stdin): curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/issues/42 \ - | python3 -c " + | python -c " import sys, json i = json.load(sys.stdin) labels = ', '.join(l['name'] for l in i['labels']) @@ -98,7 +98,7 @@ print(f\"\n{i['body']}\")" curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/search/issues?q=authentication+error+repo:$OWNER/$REPO" \ - | python3 -c " + | python -c " import sys, json for i in json.load(sys.stdin)['items']: print(f\"#{i['number']} {i['state']:6} {i['title']}\")" @@ -206,7 +206,7 @@ curl -s -X DELETE \ curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/labels \ - | python3 -c " + | python -c " import sys, json for l in json.load(sys.stdin): print(f\" {l['name']:30} {l.get('description', '')}\")" @@ -312,7 +312,7 @@ gh issue list --label "needs-triage" --state open curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/issues?labels=needs-triage&state=open" \ - | python3 -c " + | python -c " import sys, json for i in json.load(sys.stdin): if 'pull_request' not in i: @@ -346,7 +346,7 @@ gh issue list --label "wontfix" --json number --jq '.[].number' | \ curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/issues?labels=wontfix&state=open" \ - | python3 -c "import sys,json; [print(i['number']) for i in json.load(sys.stdin)]" \ + | python -c "import sys,json; [print(i['number']) for i in json.load(sys.stdin)]" \ | while read num; do curl -s -X PATCH \ -H "Authorization: token $GITHUB_TOKEN" \ diff --git a/skills/github/github-pr-workflow/SKILL.md b/skills/github/github-pr-workflow/SKILL.md index f076d08b623db..b8a71bf68f029 100644 --- a/skills/github/github-pr-workflow/SKILL.md +++ b/skills/github/github-pr-workflow/SKILL.md @@ -33,7 +33,7 @@ else if _hermes_env="${HERMES_HOME:-$HOME/.hermes}/.env"; [ -f "$_hermes_env" ] && grep -q "^GITHUB_TOKEN=" "$_hermes_env"; then GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" "$_hermes_env" | head -1 | cut -d= -f2 | tr -d '\n\r') elif grep -q "github.com" ~/.git-credentials 2>/dev/null; then - GITHUB_TOKEN=$(uv run python3 "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") + GITHUB_TOKEN=$(uv run python "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") fi fi fi @@ -173,7 +173,7 @@ SHA=$(git rev-parse HEAD) curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status \ - | python3 -c " + | python -c " import sys, json data = json.load(sys.stdin) print(f\"Overall: {data['state']}\") @@ -184,7 +184,7 @@ for s in data.get('statuses', []): curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/check-runs \ - | python3 -c " + | python -c " import sys, json data = json.load(sys.stdin) for cr in data.get('check_runs', []): @@ -200,7 +200,7 @@ for i in $(seq 1 20); do STATUS=$(curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/commits/$SHA/status \ - | python3 -c "import sys,json; print(json.load(sys.stdin)['state'])") + | python -c "import sys,json; print(json.load(sys.stdin)['state'])") echo "Check $i: $STATUS" if [ "$STATUS" = "success" ] || [ "$STATUS" = "failure" ] || [ "$STATUS" = "error" ]; then break @@ -234,7 +234,7 @@ BRANCH=$(git branch --show-current) curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/actions/runs?branch=$BRANCH&per_page=5" \ - | python3 -c " + | python -c " import sys, json runs = json.load(sys.stdin)['workflow_runs'] for r in runs: @@ -319,7 +319,7 @@ Merge methods: `"merge"` (merge commit), `"squash"`, `"rebase"` PR_NODE_ID=$(curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/pulls/$PR_NUMBER \ - | python3 -c "import sys,json; print(json.load(sys.stdin)['node_id'])") + | python -c "import sys,json; print(json.load(sys.stdin)['node_id'])") curl -s -X POST \ -H "Authorization: token $GITHUB_TOKEN" \ diff --git a/skills/github/github-repo-management/SKILL.md b/skills/github/github-repo-management/SKILL.md index 54565d7a10b5a..af147a6fa44de 100644 --- a/skills/github/github-repo-management/SKILL.md +++ b/skills/github/github-repo-management/SKILL.md @@ -30,7 +30,7 @@ else if _hermes_env="${HERMES_HOME:-$HOME/.hermes}/.env"; [ -f "$_hermes_env" ] && grep -q "^GITHUB_TOKEN=" "$_hermes_env"; then GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" "$_hermes_env" | head -1 | cut -d= -f2 | tr -d '\n\r') elif grep -q "github.com" ~/.git-credentials 2>/dev/null; then - GITHUB_TOKEN=$(uv run python3 "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") + GITHUB_TOKEN=$(uv run python "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py") fi fi fi @@ -39,7 +39,7 @@ fi if [ "$AUTH" = "gh" ]; then GH_USER=$(gh api user --jq '.login') else - GH_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user | python3 -c "import sys,json; print(json.load(sys.stdin)['login'])") + GH_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user | python -c "import sys,json; print(json.load(sys.stdin)['login'])") fi ``` @@ -213,7 +213,7 @@ gh search repos "machine learning" --language python --sort stars curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO \ - | python3 -c " + | python -c " import sys, json r = json.load(sys.stdin) print(f\"Name: {r['full_name']}\") @@ -226,7 +226,7 @@ print(f\"Language: {r['language']}\")" curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/user/repos?per_page=20&sort=updated" \ - | python3 -c " + | python -c " import sys, json for r in json.load(sys.stdin): vis = 'private' if r['private'] else 'public' @@ -235,7 +235,7 @@ for r in json.load(sys.stdin): # Search repos curl -s \ "https://api.github.com/search/repositories?q=machine+learning+language:python&sort=stars&per_page=10" \ - | python3 -c " + | python -c " import sys, json for r in json.load(sys.stdin)['items']: print(f\" {r['full_name']:40} ★{r['stargazers_count']:6} {r['description'][:60] if r['description'] else ''}\")" @@ -321,7 +321,7 @@ curl -s \ https://api.github.com/repos/$OWNER/$REPO/actions/secrets/public-key # Encrypt and set (requires Python with PyNaCl) -python3 -c " +python -c " from base64 import b64encode from nacl import encoding, public import json, sys @@ -349,7 +349,7 @@ curl -s -X PUT \ curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/actions/secrets \ - | python3 -c " + | python -c " import sys, json for s in json.load(sys.stdin)['secrets']: print(f\" {s['name']:30} updated: {s['updated_at']}\")" @@ -389,7 +389,7 @@ curl -s -X POST \ curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/releases \ - | python3 -c " + | python -c " import sys, json for r in json.load(sys.stdin): tag = r.get('tag_name', 'no tag') @@ -426,7 +426,7 @@ gh workflow run deploy.yml -f environment=staging curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/repos/$OWNER/$REPO/actions/workflows \ - | python3 -c " + | python -c " import sys, json for w in json.load(sys.stdin)['workflows']: print(f\" {w['id']:10} {w['name']:30} {w['state']}\")" @@ -435,7 +435,7 @@ for w in json.load(sys.stdin)['workflows']: curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ "https://api.github.com/repos/$OWNER/$REPO/actions/runs?per_page=10" \ - | python3 -c " + | python -c " import sys, json for r in json.load(sys.stdin)['workflow_runs']: print(f\" Run {r['id']} {r['name']:30} {r['conclusion'] or r['status']}\")" @@ -494,7 +494,7 @@ curl -s -X POST \ curl -s \ -H "Authorization: token $GITHUB_TOKEN" \ https://api.github.com/gists \ - | python3 -c " + | python -c " import sys, json for g in json.load(sys.stdin): files = ', '.join(g['files'].keys()) diff --git a/skills/media/youtube-content/SKILL.md b/skills/media/youtube-content/SKILL.md index 8e445f5f26745..d9a981bc4aadb 100644 --- a/skills/media/youtube-content/SKILL.md +++ b/skills/media/youtube-content/SKILL.md @@ -34,16 +34,16 @@ uv pip install youtube-transcript-api ```bash # JSON output with metadata -uv run python3 SKILL_DIR/scripts/fetch_transcript.py "https://youtube.com/watch?v=VIDEO_ID" +uv run python SKILL_DIR/scripts/fetch_transcript.py "https://youtube.com/watch?v=VIDEO_ID" # Plain text (good for piping into further processing) -uv run python3 SKILL_DIR/scripts/fetch_transcript.py "URL" --text-only +uv run python SKILL_DIR/scripts/fetch_transcript.py "URL" --text-only # With timestamps -uv run python3 SKILL_DIR/scripts/fetch_transcript.py "URL" --timestamps +uv run python SKILL_DIR/scripts/fetch_transcript.py "URL" --timestamps # Specific language with fallback chain -uv run python3 SKILL_DIR/scripts/fetch_transcript.py "URL" --language tr,en +uv run python SKILL_DIR/scripts/fetch_transcript.py "URL" --language tr,en ``` ## Output Formats @@ -69,7 +69,7 @@ After fetching the transcript, format it based on what the user asks for: ## Workflow -1. **Fetch** the transcript using the helper script with `--text-only --timestamps` via `uv run python3`. +1. **Fetch** the transcript using the helper script with `--text-only --timestamps` via `uv run python`. 2. **Validate**: confirm the output is non-empty and in the expected language. If empty, retry without `--language` to get any available transcript. If still empty, tell the user the video likely has transcripts disabled. 3. **Chunk if needed**: if the transcript exceeds ~50K characters, split into overlapping chunks (~40K with 2K overlap) and summarize each chunk before merging. 4. **Transform** into the requested output format. If the user did not specify a format, default to a summary. diff --git a/skills/productivity/airtable/SKILL.md b/skills/productivity/airtable/SKILL.md index 3fa1b0ab9737e..d628c231feed3 100644 --- a/skills/productivity/airtable/SKILL.md +++ b/skills/productivity/airtable/SKILL.md @@ -44,10 +44,10 @@ Work with Airtable's REST API directly via `curl` using the `terminal` tool. No Base curl pattern: ```bash curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=5" \ - -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool + -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool ``` -`-s` suppresses curl's progress bar — keep it set for every call so the tool output stays clean for Hermes. Pipe through `python3 -m json.tool` (always present) or `jq` (if installed) for readable JSON. +`-s` suppresses curl's progress bar — keep it set for every call so the tool output stays clean for Hermes. Pipe through `python -m json.tool` (always present) or `jq` (if installed) for readable JSON. ## Field Types (request body shapes) @@ -73,35 +73,35 @@ Pass `"typecast": true` at the top level of a create/update body to let Airtable ### List bases the token can see ```bash curl -s "https://api.airtable.com/v0/meta/bases" \ - -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool + -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool ``` ### List tables + schema for a base ```bash curl -s "https://api.airtable.com/v0/meta/bases/$BASE_ID/tables" \ - -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool + -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool ``` Use this BEFORE mutating — confirms exact field names and IDs, surfaces `options.choices` for select fields, and shows primary-field names. ### List records (first 10) ```bash curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?maxRecords=10" \ - -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool + -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool ``` ### Get a single record ```bash curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \ - -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool + -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool ``` ### Filter records (filterByFormula) Airtable formulas must be URL-encoded. Let Python stdlib do it — never hand-encode: ```bash FORMULA="{Status}='Todo'" -ENC=$(python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$FORMULA") +ENC=$(python -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1], safe=""))' "$FORMULA") curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?filterByFormula=$ENC&maxRecords=20" \ - -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool + -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool ``` Useful formula patterns: @@ -115,14 +115,14 @@ Useful formula patterns: ### Sort + select specific fields ```bash curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?sort%5B0%5D%5Bfield%5D=Priority&sort%5B0%5D%5Bdirection%5D=asc&fields%5B%5D=Name&fields%5B%5D=Status" \ - -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool + -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool ``` Square brackets in query params MUST be URL-encoded (`%5B` / `%5D`). ### Use a named view ```bash curl -s "https://api.airtable.com/v0/$BASE_ID/$TABLE?view=Grid%20view&maxRecords=50" \ - -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool + -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool ``` Views apply their saved filter + sort server-side. @@ -133,7 +133,7 @@ Views apply their saved filter + sort server-side. curl -s -X POST "https://api.airtable.com/v0/$BASE_ID/$TABLE" \ -H "Authorization: Bearer $AIRTABLE_API_KEY" \ -H "Content-Type: application/json" \ - -d '{"fields":{"Name":"New task","Status":"Todo","Priority":"High"}}' | python3 -m json.tool + -d '{"fields":{"Name":"New task","Status":"Todo","Priority":"High"}}' | python -m json.tool ``` ### Create up to 10 records in one call @@ -147,7 +147,7 @@ curl -s -X POST "https://api.airtable.com/v0/$BASE_ID/$TABLE" \ {"fields": {"Name": "Task A", "Status": "Todo"}}, {"fields": {"Name": "Task B", "Status": "In progress"}} ] - }' | python3 -m json.tool + }' | python -m json.tool ``` Batch endpoints are capped at **10 records per request**. For larger inserts, loop in batches of 10 with a short sleep to respect 5 req/sec/base. @@ -156,7 +156,7 @@ Batch endpoints are capped at **10 records per request**. For larger inserts, lo curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \ -H "Authorization: Bearer $AIRTABLE_API_KEY" \ -H "Content-Type: application/json" \ - -d '{"fields":{"Status":"Done"}}' | python3 -m json.tool + -d '{"fields":{"Status":"Done"}}' | python -m json.tool ``` ### Upsert by a merge field (no ID needed) @@ -169,20 +169,20 @@ curl -s -X PATCH "https://api.airtable.com/v0/$BASE_ID/$TABLE" \ "records": [ {"fields": {"Email": "user@example.com", "Status": "Active"}} ] - }' | python3 -m json.tool + }' | python -m json.tool ``` `performUpsert` creates records whose merge-field values are new, patches records whose merge-field values already exist. Great for idempotent syncs. ### Delete a record ```bash curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE/$RECORD_ID" \ - -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool + -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool ``` ### Delete up to 10 records in one call ```bash curl -s -X DELETE "https://api.airtable.com/v0/$BASE_ID/$TABLE?records%5B%5D=rec1&records%5B%5D=rec2" \ - -H "Authorization: Bearer $AIRTABLE_API_KEY" | python3 -m json.tool + -H "Authorization: Bearer $AIRTABLE_API_KEY" | python -m json.tool ``` ## Pagination @@ -195,8 +195,8 @@ while :; do URL="https://api.airtable.com/v0/$BASE_ID/$TABLE?pageSize=100" [ -n "$OFFSET" ] && URL="$URL&offset=$OFFSET" RESP=$(curl -s "$URL" -H "Authorization: Bearer $AIRTABLE_API_KEY") - echo "$RESP" | python3 -c 'import json,sys; d=json.load(sys.stdin); [print(r["id"], r["fields"].get("Name","")) for r in d["records"]]' - OFFSET=$(echo "$RESP" | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d.get("offset",""))') + echo "$RESP" | python -c 'import json,sys; d=json.load(sys.stdin); [print(r["id"], r["fields"].get("Name","")) for r in d["records"]]' + OFFSET=$(echo "$RESP" | python -c 'import json,sys; d=json.load(sys.stdin); print(d.get("offset",""))') [ -z "$OFFSET" ] && break done ``` @@ -223,7 +223,7 @@ done - **Always use the `terminal` tool with `curl`.** Do NOT use `web_extract` (it can't send auth headers) or `browser_navigate` (needs UI auth and is slow). - **`AIRTABLE_API_KEY` flows from `${HERMES_HOME:-~/.hermes}/.env` into the subprocess automatically** when this skill is loaded — no need to re-export it before each `curl` call. -- **Escape curly braces in formulas carefully.** In a heredoc body, `{Status}` is literal. In a shell argument, `{Status}` is safe outside `{...}` brace-expansion context — but pass dynamic strings through `python3 urllib.parse.quote` before splicing into a URL. -- **Pretty-print with `python3 -m json.tool`** (always present) rather than `jq` (optional). Only reach for `jq` when you need filtering/projection. +- **Escape curly braces in formulas carefully.** In a heredoc body, `{Status}` is literal. In a shell argument, `{Status}` is safe outside `{...}` brace-expansion context — but pass dynamic strings through `python urllib.parse.quote` before splicing into a URL. +- **Pretty-print with `python -m json.tool`** (always present) rather than `jq` (optional). Only reach for `jq` when you need filtering/projection. - **Pagination is per-page, not global.** Airtable's 100-record cap is a hard limit; there is no way to bump it. Loop with `offset` until the field is absent. - **Read the `errors` array** on non-2xx responses — Airtable returns structured error codes like `AUTHENTICATION_REQUIRED`, `INVALID_PERMISSIONS`, `MODEL_ID_NOT_FOUND`, `INVALID_MULTIPLE_CHOICE_OPTIONS` that tell you exactly what's wrong. diff --git a/skills/productivity/maps/SKILL.md b/skills/productivity/maps/SKILL.md index 3c1e8af3dfbca..635f211741ead 100644 --- a/skills/productivity/maps/SKILL.md +++ b/skills/productivity/maps/SKILL.md @@ -50,8 +50,8 @@ MAPS=~/.hermes/skills/maps/scripts/maps_client.py ### search — Geocode a place name ```bash -python3 $MAPS search "Eiffel Tower" -python3 $MAPS search "1600 Pennsylvania Ave, Washington DC" +python $MAPS search "Eiffel Tower" +python $MAPS search "1600 Pennsylvania Ave, Washington DC" ``` Returns: lat, lon, display name, type, bounding box, importance score. @@ -59,7 +59,7 @@ Returns: lat, lon, display name, type, bounding box, importance score. ### reverse — Coordinates to address ```bash -python3 $MAPS reverse 48.8584 2.2945 +python $MAPS reverse 48.8584 2.2945 ``` Returns: full address breakdown (street, city, state, country, postcode). @@ -68,15 +68,15 @@ Returns: full address breakdown (street, city, state, country, postcode). ```bash # By coordinates (from a Telegram location pin, for example) -python3 $MAPS nearby 48.8584 2.2945 restaurant --limit 10 -python3 $MAPS nearby 40.7128 -74.0060 hospital --radius 2000 +python $MAPS nearby 48.8584 2.2945 restaurant --limit 10 +python $MAPS nearby 40.7128 -74.0060 hospital --radius 2000 # By address / city / zip / landmark — --near auto-geocodes -python3 $MAPS nearby --near "Times Square, New York" --category cafe -python3 $MAPS nearby --near "90210" --category pharmacy +python $MAPS nearby --near "Times Square, New York" --category cafe +python $MAPS nearby --near "90210" --category pharmacy # Multiple categories merged into one query -python3 $MAPS nearby --near "downtown austin" --category restaurant --category bar --limit 10 +python $MAPS nearby --near "downtown austin" --category restaurant --category bar --limit 10 ``` 46 categories: restaurant, cafe, bar, hospital, pharmacy, hotel, guest_house, @@ -95,9 +95,9 @@ directions from the search point), and promoted tags when available — ### distance — Travel distance and time ```bash -python3 $MAPS distance "Paris" --to "Lyon" -python3 $MAPS distance "New York" --to "Boston" --mode driving -python3 $MAPS distance "Big Ben" --to "Tower Bridge" --mode walking +python $MAPS distance "Paris" --to "Lyon" +python $MAPS distance "New York" --to "Boston" --mode driving +python $MAPS distance "Big Ben" --to "Tower Bridge" --mode walking ``` Modes: driving (default), walking, cycling. Returns road distance, duration, @@ -106,8 +106,8 @@ and straight-line distance for comparison. ### directions — Turn-by-turn navigation ```bash -python3 $MAPS directions "Eiffel Tower" --to "Louvre Museum" --mode walking -python3 $MAPS directions "JFK Airport" --to "Times Square" --mode driving +python $MAPS directions "Eiffel Tower" --to "Louvre Museum" --mode walking +python $MAPS directions "JFK Airport" --to "Times Square" --mode driving ``` Returns numbered steps with instruction, distance, duration, road name, and @@ -116,8 +116,8 @@ maneuver type (turn, depart, arrive, etc.). ### timezone — Timezone for coordinates ```bash -python3 $MAPS timezone 48.8584 2.2945 -python3 $MAPS timezone 35.6762 139.6503 +python $MAPS timezone 48.8584 2.2945 +python $MAPS timezone 35.6762 139.6503 ``` Returns timezone name, UTC offset, and current local time. @@ -125,8 +125,8 @@ Returns timezone name, UTC offset, and current local time. ### area — Bounding box and area for a place ```bash -python3 $MAPS area "Manhattan, New York" -python3 $MAPS area "London" +python $MAPS area "Manhattan, New York" +python $MAPS area "London" ``` Returns bounding box coordinates, width/height in km, and approximate area. @@ -135,7 +135,7 @@ Useful as input for the bbox command. ### bbox — Search within a bounding box ```bash -python3 $MAPS bbox 40.75 -74.00 40.77 -73.98 restaurant --limit 20 +python $MAPS bbox 40.75 -74.00 40.77 -73.98 restaurant --limit 20 ``` Finds POIs within a geographic rectangle. Use `area` first to get the @@ -148,7 +148,7 @@ When a user sends a location pin, the message contains `latitude:` and ```bash # User sent a pin at 36.17, -115.14 and asked "find cafes nearby" -python3 $MAPS nearby 36.17 -115.14 cafe --radius 1500 +python $MAPS nearby 36.17 -115.14 cafe --radius 1500 ``` Present results as a numbered list with names, distances, and the @@ -187,9 +187,9 @@ current. ## Verification ```bash -python3 ~/.hermes/skills/maps/scripts/maps_client.py search "Statue of Liberty" +python ~/.hermes/skills/maps/scripts/maps_client.py search "Statue of Liberty" # Should return lat ~40.689, lon ~-74.044 -python3 ~/.hermes/skills/maps/scripts/maps_client.py nearby --near "Times Square" --category restaurant --limit 3 +python ~/.hermes/skills/maps/scripts/maps_client.py nearby --near "Times Square" --category restaurant --limit 3 # Should return a list of restaurants within ~500m of Times Square ``` diff --git a/skills/productivity/ocr-and-documents/SKILL.md b/skills/productivity/ocr-and-documents/SKILL.md index 5d7278fa07a78..0677b70a1598f 100644 --- a/skills/productivity/ocr-and-documents/SKILL.md +++ b/skills/productivity/ocr-and-documents/SKILL.md @@ -77,7 +77,7 @@ python scripts/extract_pymupdf.py document.pdf --pages 0-4 # Specific pages **Inline**: ```bash -python3 -c " +python -c " import pymupdf doc = pymupdf.open('document.pdf') for page in doc: diff --git a/skills/productivity/pdf/SKILL.md b/skills/productivity/pdf/SKILL.md index 4c6cf343aeba8..a10b25fdca78c 100644 --- a/skills/productivity/pdf/SKILL.md +++ b/skills/productivity/pdf/SKILL.md @@ -29,8 +29,8 @@ Create PDFs from structured specs, build and fill AcroForm forms (with layout li ## Prerequisites - Python 3.10+ with `pypdf`, `reportlab`, `pdfplumber`: - `python3 -m pip install pypdf reportlab pdfplumber` -- Optional, for page rasterization (`pdf_page_image.py`, overlay rendering): `python3 -m pip install pypdfium2`, or poppler's `pdftoppm` on PATH. Scripts fall back pypdfium2 → pdftoppm and report `{"rendered": false, "missing": [...]}` (exit 0) when neither exists. + `python -m pip install pypdf reportlab pdfplumber` +- Optional, for page rasterization (`pdf_page_image.py`, overlay rendering): `python -m pip install pypdfium2`, or poppler's `pdftoppm` on PATH. Scripts fall back pypdfium2 → pdftoppm and report `{"rendered": false, "missing": [...]}` (exit 0) when neither exists. - Each helper script checks imports lazily and prints an install hint if a dependency is missing. ## How to Run @@ -38,27 +38,27 @@ Create PDFs from structured specs, build and fill AcroForm forms (with layout li All helpers live in `scripts/` and are argparse CLIs — run them with the `terminal` tool; every one supports `--help`. They read/write JSON strictly as UTF-8, print JSON results to stdout, and exit non-zero on failure. ```bash -python3 scripts/pdf_create.py spec.json -o out.pdf # build PDF from JSON spec -python3 scripts/pdf_make_form.py formspec.json -o form.pdf # build fillable AcroForm from JSON spec -python3 scripts/pdf_form_layout.py formspec.json # lint form layout BEFORE building -python3 scripts/pdf_form_layout.py formspec.json --render-overlay boxes.png [--pdf form.pdf] -python3 scripts/pdf_read.py doc.pdf --text # per-page text (JSON) -python3 scripts/pdf_read.py doc.pdf --tables --csv-dir t/ # tables to JSON + CSV files -python3 scripts/pdf_read.py doc.pdf --meta # metadata, page sizes, encrypted/scanned flags -python3 scripts/pdf_read.py form.pdf --fields # form fields: name, type, value -python3 scripts/pdf_merge.py a.pdf b.pdf -o merged.pdf [--bookmarks] -python3 scripts/pdf_split.py doc.pdf --pages 1-3,7 -o part.pdf [--rotate 90] -python3 scripts/pdf_fill_form.py form.pdf --fields-json values.json -o filled.pdf [--flatten] -python3 scripts/pdf_secure.py doc.pdf --encrypt -o enc.pdf --user-password your-password -python3 scripts/pdf_secure.py enc.pdf --decrypt -o dec.pdf --password your-password -python3 scripts/pdf_watermark.py doc.pdf --stamp mark.pdf -o stamped.pdf [--under] -python3 scripts/pdf_stamp.py doc.pdf -o out.pdf --text "DRAFT" --x 150 --y 400 \ +python scripts/pdf_create.py spec.json -o out.pdf # build PDF from JSON spec +python scripts/pdf_make_form.py formspec.json -o form.pdf # build fillable AcroForm from JSON spec +python scripts/pdf_form_layout.py formspec.json # lint form layout BEFORE building +python scripts/pdf_form_layout.py formspec.json --render-overlay boxes.png [--pdf form.pdf] +python scripts/pdf_read.py doc.pdf --text # per-page text (JSON) +python scripts/pdf_read.py doc.pdf --tables --csv-dir t/ # tables to JSON + CSV files +python scripts/pdf_read.py doc.pdf --meta # metadata, page sizes, encrypted/scanned flags +python scripts/pdf_read.py form.pdf --fields # form fields: name, type, value +python scripts/pdf_merge.py a.pdf b.pdf -o merged.pdf [--bookmarks] +python scripts/pdf_split.py doc.pdf --pages 1-3,7 -o part.pdf [--rotate 90] +python scripts/pdf_fill_form.py form.pdf --fields-json values.json -o filled.pdf [--flatten] +python scripts/pdf_secure.py doc.pdf --encrypt -o enc.pdf --user-password your-password +python scripts/pdf_secure.py enc.pdf --decrypt -o dec.pdf --password your-password +python scripts/pdf_watermark.py doc.pdf --stamp mark.pdf -o stamped.pdf [--under] +python scripts/pdf_stamp.py doc.pdf -o out.pdf --text "DRAFT" --x 150 --y 400 \ --font-size 60 --rotation 45 --opacity 0.3 --color "#cc0000" [--pages 1-3] -python3 scripts/pdf_stamp.py doc.pdf -o out.pdf --image sig.png --x 400 --y 60 --width 120 -python3 scripts/pdf_page_image.py doc.pdf --pages 1-3 --dpi 150 --out-dir imgs/ -python3 scripts/pdf_meta.py doc.pdf --set-meta --title "T" --author "A" -o out.pdf -python3 scripts/pdf_meta.py doc.pdf --attach data.csv -o out.pdf -python3 scripts/pdf_meta.py doc.pdf --list-attachments | --extract-attachments dir/ +python scripts/pdf_stamp.py doc.pdf -o out.pdf --image sig.png --x 400 --y 60 --width 120 +python scripts/pdf_page_image.py doc.pdf --pages 1-3 --dpi 150 --out-dir imgs/ +python scripts/pdf_meta.py doc.pdf --set-meta --title "T" --author "A" -o out.pdf +python scripts/pdf_meta.py doc.pdf --attach data.csv -o out.pdf +python scripts/pdf_meta.py doc.pdf --list-attachments | --extract-attachments dir/ ``` ## Quick Reference diff --git a/skills/productivity/powerpoint/SKILL.md b/skills/productivity/powerpoint/SKILL.md index 0fa88debd6d16..4d73a518aa5b1 100644 --- a/skills/productivity/powerpoint/SKILL.md +++ b/skills/productivity/powerpoint/SKILL.md @@ -41,7 +41,7 @@ and slide rendering — all offline, no PowerPoint installation required. gracefully (reports `{"rendered": false, "missing": [...]}`, exit 0) when absent — all create/read/edit operations work without them. - Check availability via `terminal`: - `python3 -c "import pptx; print(pptx.__version__)"` and `which soffice pdftoppm`. + `python -c "import pptx; print(pptx.__version__)"` and `which soffice pdftoppm`. ## How to Run @@ -49,16 +49,16 @@ All scripts live in `scripts/`, take `--help`, print JSON to stdout, and exit non-zero on failure. Run them with `terminal`: ```bash -python3 scripts/pptx_create.py deck.json out.pptx -python3 scripts/pptx_read.py deck.pptx --outline # full JSON outline -python3 scripts/pptx_read.py deck.pptx --notes # speaker notes -python3 scripts/pptx_read.py deck.pptx --images ./img # export pictures -python3 scripts/pptx_edit.py deck.pptx --replace-text "Old Corp" "New Corp" -python3 scripts/pptx_edit.py deck.pptx --chart-data update.json -python3 scripts/pptx_edit.py deck.pptx --duplicate-slide 2 -python3 scripts/pptx_edit.py deck.pptx --remove-slide 3 --move-slide 2 0 -python3 scripts/pptx_from_template.py brand.pptx out.pptx --values vals.json -python3 scripts/pptx_render.py deck.pptx --outdir ./render # slide PNGs +python scripts/pptx_create.py deck.json out.pptx +python scripts/pptx_read.py deck.pptx --outline # full JSON outline +python scripts/pptx_read.py deck.pptx --notes # speaker notes +python scripts/pptx_read.py deck.pptx --images ./img # export pictures +python scripts/pptx_edit.py deck.pptx --replace-text "Old Corp" "New Corp" +python scripts/pptx_edit.py deck.pptx --chart-data update.json +python scripts/pptx_edit.py deck.pptx --duplicate-slide 2 +python scripts/pptx_edit.py deck.pptx --remove-slide 3 --move-slide 2 0 +python scripts/pptx_from_template.py brand.pptx out.pptx --values vals.json +python scripts/pptx_render.py deck.pptx --outdir ./render # slide PNGs ``` Author JSON specs with `write_file`; inspect script output and generated @@ -217,4 +217,4 @@ say so rather than approximating. shapes, truncated text, and color problems the outline cannot. If the render tools are missing, the script says so; rely on the outline. 4. The bundled test suite is the full contract: - `python3 -m pytest tests/ -q` (requires python-pptx + pytest). + `python -m pytest tests/ -q` (requires python-pptx + pytest). diff --git a/skills/research/arxiv/SKILL.md b/skills/research/arxiv/SKILL.md index 70ab36eba2480..e3e6ac738f7b5 100644 --- a/skills/research/arxiv/SKILL.md +++ b/skills/research/arxiv/SKILL.md @@ -26,7 +26,7 @@ Search and retrieve academic papers from arXiv via their free REST API. No API k ## Searching Papers -The API returns Atom XML. Parse with `grep`/`sed` or pipe through `python3` for clean output. +The API returns Atom XML. Parse with `grep`/`sed` or pipe through `python` for clean output. ### Basic search @@ -37,7 +37,7 @@ curl -s "https://export.arxiv.org/api/query?search_query=all:GRPO+reinforcement+ ### Clean output (parse XML to readable format) ```bash -curl -s "https://export.arxiv.org/api/query?search_query=all:GRPO+reinforcement+learning&max_results=5&sortBy=submittedDate&sortOrder=descending" | python3 -c " +curl -s "https://export.arxiv.org/api/query?search_query=all:GRPO+reinforcement+learning&max_results=5&sortBy=submittedDate&sortOrder=descending" | python -c " import sys, xml.etree.ElementTree as ET ns = {'a': 'http://www.w3.org/2005/Atom'} root = ET.parse(sys.stdin).getroot() @@ -117,7 +117,7 @@ After fetching metadata for a paper, generate a BibTeX entry: {% raw %} ```bash -curl -s "https://export.arxiv.org/api/query?id_list=1706.03762" | python3 -c " +curl -s "https://export.arxiv.org/api/query?id_list=1706.03762" | python -c " import sys, xml.etree.ElementTree as ET ns = {'a': 'http://www.w3.org/2005/Atom', 'arxiv': 'http://arxiv.org/schemas/atom'} root = ET.parse(sys.stdin).getroot() @@ -197,7 +197,7 @@ arXiv doesn't provide citation data or recommendations. Use the **Semantic Schol ```bash # By arXiv ID -curl -s "https://api.semanticscholar.org/graph/v1/paper/arXiv:2402.03300?fields=title,authors,citationCount,referenceCount,influentialCitationCount,year,abstract" | python3 -m json.tool +curl -s "https://api.semanticscholar.org/graph/v1/paper/arXiv:2402.03300?fields=title,authors,citationCount,referenceCount,influentialCitationCount,year,abstract" | python -m json.tool # By Semantic Scholar paper ID or DOI curl -s "https://api.semanticscholar.org/graph/v1/paper/DOI:10.1234/example?fields=title,citationCount" @@ -206,19 +206,19 @@ curl -s "https://api.semanticscholar.org/graph/v1/paper/DOI:10.1234/example?fiel ### Get citations OF a paper (who cited it) ```bash -curl -s "https://api.semanticscholar.org/graph/v1/paper/arXiv:2402.03300/citations?fields=title,authors,year,citationCount&limit=10" | python3 -m json.tool +curl -s "https://api.semanticscholar.org/graph/v1/paper/arXiv:2402.03300/citations?fields=title,authors,year,citationCount&limit=10" | python -m json.tool ``` ### Get references FROM a paper (what it cites) ```bash -curl -s "https://api.semanticscholar.org/graph/v1/paper/arXiv:2402.03300/references?fields=title,authors,year,citationCount&limit=10" | python3 -m json.tool +curl -s "https://api.semanticscholar.org/graph/v1/paper/arXiv:2402.03300/references?fields=title,authors,year,citationCount&limit=10" | python -m json.tool ``` ### Search papers (alternative to arXiv search, returns JSON) ```bash -curl -s "https://api.semanticscholar.org/graph/v1/paper/search?query=GRPO+reinforcement+learning&limit=5&fields=title,authors,year,citationCount,externalIds" | python3 -m json.tool +curl -s "https://api.semanticscholar.org/graph/v1/paper/search?query=GRPO+reinforcement+learning&limit=5&fields=title,authors,year,citationCount,externalIds" | python -m json.tool ``` ### Get paper recommendations @@ -226,13 +226,13 @@ curl -s "https://api.semanticscholar.org/graph/v1/paper/search?query=GRPO+reinfo ```bash curl -s -X POST "https://api.semanticscholar.org/recommendations/v1/papers/" \ -H "Content-Type: application/json" \ - -d '{"positivePaperIds": ["arXiv:2402.03300"], "negativePaperIds": []}' | python3 -m json.tool + -d '{"positivePaperIds": ["arXiv:2402.03300"], "negativePaperIds": []}' | python -m json.tool ``` ### Author profile ```bash -curl -s "https://api.semanticscholar.org/graph/v1/author/search?query=Yann+LeCun&fields=name,hIndex,citationCount,paperCount" | python3 -m json.tool +curl -s "https://api.semanticscholar.org/graph/v1/author/search?query=Yann+LeCun&fields=name,hIndex,citationCount,paperCount" | python -m json.tool ``` ### Useful Semantic Scholar fields @@ -261,7 +261,7 @@ curl -s "https://api.semanticscholar.org/graph/v1/author/search?query=Yann+LeCun ## Notes - arXiv returns Atom XML — use the helper script or parsing snippet for clean output -- Semantic Scholar returns JSON — pipe through `python3 -m json.tool` for readability +- Semantic Scholar returns JSON — pipe through `python -m json.tool` for readability - arXiv IDs: old format (`hep-th/0601001`) vs new (`2402.03300`) - PDF: `https://arxiv.org/pdf/{id}` — Abstract: `https://arxiv.org/abs/{id}` - HTML (when available): `https://arxiv.org/html/{id}` diff --git a/skills/research/grounded-citations/SKILL.md b/skills/research/grounded-citations/SKILL.md index fe703d1df9edc..4c767369f4d97 100644 --- a/skills/research/grounded-citations/SKILL.md +++ b/skills/research/grounded-citations/SKILL.md @@ -58,12 +58,12 @@ Override per task with `--ledger ` or `HERMES_CITATION_LEDGER`. ```bash S=~/.hermes/skills/research/grounded-citations/scripts/sources.py -python3 "$S" reset # start a clean ledger -python3 "$S" add https://example.com/a --title "A" # prints: [1] -python3 "$S" add https://example.com/b --title "B" # prints: [2] -python3 "$S" list # ledger table -python3 "$S" render # Sources: block -python3 "$S" verify draft.md # catch bad citations +python "$S" reset # start a clean ledger +python "$S" add https://example.com/a --title "A" # prints: [1] +python "$S" add https://example.com/b --title "B" # prints: [2] +python "$S" list # ledger table +python "$S" render # Sources: block +python "$S" verify draft.md # catch bad citations ``` `add` is idempotent and URL-normalized: the same page always returns the same @@ -136,7 +136,7 @@ upgrade from citations to evidence: text to a file and attach the sentence(s) that carry each claim: ```bash -python3 "$S" quote 1 --text "Ice is about 9% less dense than liquid water." --from page1.txt +python "$S" quote 1 --text "Ice is about 9% less dense than liquid water." --from page1.txt ``` The quote is rejected unless it appears verbatim in the evidence text @@ -168,8 +168,8 @@ corroboration. ④ **Verify with the evidence gate and render the evidence block:** ```bash -python3 "$S" verify report.md --evidence --min-coverage 0.5 -python3 "$S" render --style evidence --replace-in report.md +python "$S" verify report.md --evidence --min-coverage 0.5 +python "$S" render --style evidence --replace-in report.md ``` `--evidence` fails the draft if any cited source has no attached quote. The @@ -222,7 +222,7 @@ and read the `info: stats:` line to see the counts before picking a number. ## Verification ```bash -python3 "$S" verify report.md --strict --min-coverage 0.5 +python "$S" verify report.md --strict --min-coverage 0.5 ``` Green means: every `[n]` in the draft exists in the ledger, the Sources block diff --git a/skills/software-development/hermes-agent-skill-authoring/SKILL.md b/skills/software-development/hermes-agent-skill-authoring/SKILL.md index b51120514ae55..c199a0c5897ae 100644 --- a/skills/software-development/hermes-agent-skill-authoring/SKILL.md +++ b/skills/software-development/hermes-agent-skill-authoring/SKILL.md @@ -148,7 +148,7 @@ A skill exists to make the agent's process more predictable — the agent reliab ## Tests and Docs (required for repo skills) 1. **Tests** live at `tests/skills/test__skill.py` — stdlib + pytest + `unittest.mock` only, no live network. Run via `scripts/run_tests.sh tests/skills/test__skill.py -q`. (The generic `tests/tools/test_skill_manager_tool.py` passing proves nothing about YOUR skill.) -2. **Docs regen:** run `python3 website/scripts/generate-skill-docs.py`, then apply scope discipline — the generator rewrites EVERY auto-gen page. `git checkout --` everything that isn't yours; the final diff must show only your SKILL.md, your one per-skill docs page, a one-line catalog row, and a one-line `website/sidebars.ts` insertion (verify with `search_files(pattern='', path='website/sidebars.ts')` — exactly one hit, or the page is an orphan). +2. **Docs regen:** run `python website/scripts/generate-skill-docs.py`, then apply scope discipline — the generator rewrites EVERY auto-gen page. `git checkout --` everything that isn't yours; the final diff must show only your SKILL.md, your one per-skill docs page, a one-line catalog row, and a one-line `website/sidebars.ts` insertion (verify with `search_files(pattern='', path='website/sidebars.ts')` — exactly one hit, or the page is an orphan). 3. **`.env.example`** (only if the skill needs new env vars): one clearly delimited commented block; touch nothing else in the file. ## Workflow diff --git a/skills/software-development/spike/SKILL.md b/skills/software-development/spike/SKILL.md index 2a980f0ade952..94ca054dd2fa5 100644 --- a/skills/software-development/spike/SKILL.md +++ b/skills/software-development/spike/SKILL.md @@ -118,7 +118,7 @@ spikes/ terminal("mkdir -p spikes/001-websocket-streaming") write_file("spikes/001-websocket-streaming/README.md", "# 001: websocket-streaming\n\n...") write_file("spikes/001-websocket-streaming/main.py", "...") -terminal("cd spikes/001-websocket-streaming && python3 main.py") +terminal("cd spikes/001-websocket-streaming && python main.py") # Observe output, iterate. ``` diff --git a/tools/mcp_tool.py b/tools/mcp_tool.py index 88f02f6f4d7cb..f380b8cea4ff3 100644 --- a/tools/mcp_tool.py +++ b/tools/mcp_tool.py @@ -794,6 +794,27 @@ def _resolve_stdio_command(command: str, env: dict) -> tuple[str, dict]: if os.sep not in resolved_command: path_arg = resolved_env["PATH"] if "PATH" in resolved_env else None which_hit = shutil.which(resolved_command, path=path_arg) + if which_hit is None and sys.platform == "win32" and resolved_env: + # shutil.which(..., path=...) resolves extensions from the PARENT + # process PATHEXT, not the MCP subprocess env — so a config that + # supplies both PATH and PATHEXT can fail to resolve a command + # its own env can find (#56536). Retry with the config's PATHEXT + # (any key casing: PATHEXT / Pathext / pathext) applied. + cfg_pathext = next( + (v for k, v in resolved_env.items() + if k.upper() == "PATHEXT" and isinstance(v, str) and v.strip()), + None, + ) + if cfg_pathext and cfg_pathext != os.environ.get("PATHEXT"): + _saved = os.environ.get("PATHEXT") + try: + os.environ["PATHEXT"] = cfg_pathext + which_hit = shutil.which(resolved_command, path=path_arg) + finally: + if _saved is None: + os.environ.pop("PATHEXT", None) + else: + os.environ["PATHEXT"] = _saved if which_hit: resolved_command = which_hit elif resolved_command in {"npx", "npm", "node"}: