[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6C6JBTBA968YV9B4RGSEA2M":3,"skill-same:01M6C6JBTBA968YV9B4RGSEA2M":71},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":35,"linkOnly":36,"markdownContent":37,"markdownBody":38,"frontMatter":39,"refName":43,"commitSha":44,"skillDirectory":45,"forksCount":46,"repositoryHtmlUrl":47,"repositoryHomepageUrl":6,"ownerHtmlUrl":48,"ownerBlogUrl":6,"ownerDescription":49,"updatedAt":50,"install":51,"resources":64},"01M6C6JBTBA968YV9B4RGSEA2M","zsh-gotchas",null,"Four zsh expansions that silently rewrite a command: $VAR:word modifiers, a leading =, no word splitting, `path` tied to PATH. Use when a zsh one-liner gives a wrong result or a tool seems missing.","laurigates\u002Fclaude-plugins","laurigates","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F13014001?v=4","01M6C59YHWS9C7KMXKSRX1YXNP","Lauri Gates","01M6C59YP2APG9YAM4DWYQYGFJ",59,"MIT","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Ftools-plugin\u002Fskills\u002Fzsh-gotchas\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34],"zsh","zsh gotchas","Bash","tool","Word","command","read","use","missing","rewrite","sep","path","Wrong","result","when","2026","2026-11-10 10:12:30",false,"---\nname: zsh-gotchas\ndescription: \"Four zsh expansions that silently rewrite a command: $VAR:word modifiers, a leading =, no word splitting, `path` tied to PATH. Use when a zsh one-liner gives a wrong result or a tool seems missing.\"\nallowed-tools: Bash, Read\ncreated: 2026-09-21\nmodified: 2026-10-24\nreviewed: 2026-09-21\n---\n\n# Zsh Gotchas — Four Expansions That Rewrite Your Command\n\nFour zsh behaviours with no bash equivalent. Each one fires on **ordinary\ncommands**, including the one-liners an agent runs through the Bash tool — not\njust on `.zsh` files — so a snippet lifted from a bash-tested doc breaks only\nhere.\n\nWhat makes them expensive is that three of the four **fail silently or\nmisattribute**: the command runs, exits, and reports something that looks like a\nreal answer about the world. Every one below was diagnosed the wrong way first.\n\n| Symptom | Mechanism | Section |\n|---|---|---|\n| A URL\u002Fpath with `$var:` hits the wrong endpoint; fast empty 404 | `$VAR:x` is a history modifier | [1](#1-varword-is-a-modifier-not-a-colon-after-a-variable) |\n| A later command in a `;` chain produced no output | a word starting with `=` is a command lookup | [2](#2-a-word-starting-with--is-a-command-lookup) |\n| `$2` empty after `set -- $spec`; tool prints its usage text | zsh does not word-split | [3](#3-zsh-does-not-word-split-an-unquoted-parameter) |\n| `command not found` for a tool that is installed | `path` is tied to `PATH` | [4](#4-path-is-not-a-free-variable-name) |\n\nOut of scope: zsh-vs-POSIX pattern expansion and extended glob. Those bite when\nwriting `.zsh` \u002F `zshrc` files, not on every command, and are not covered here.\n\n## When to Use This Skill\n\n| Use this skill when... | Use `shell-expert` instead when... |\n|---|---|\n| A zsh command ran and returned a result that does not match what you typed | Writing a shell script, function, or pipeline from scratch |\n| An unexpected 404, an empty positional, or a missing chunk of output from a chain | Choosing portable constructs across bash \u002F zsh \u002F POSIX |\n| `command not found` names a tool you know is installed | Structuring error handling, `set` flags, or CLI argument parsing |\n| A bash-tested snippet behaves differently once run through the Bash tool | The question is shell *style* rather than a wrong runtime result |\n\nThe split is runtime versus authoring: this skill covers four expansions that\nmake a correct-looking zsh command do something else, three of them silently.\n\n## 1. `$VAR:word` Is a Modifier, Not a Colon After a Variable\n\nZsh applies history-style **modifiers** directly to a bare parameter expansion:\n`$f:h` (dirname), `$f:t` (basename), `$f:r`, `$f:e`, `$f:s\u002Fa\u002Fb\u002F`, `$f:g…`. So a\nURL that puts a variable straight before a colon is not the URL you wrote:\n\n```zsh\n# Wrong — `:g` is read as the start of a global-substitution modifier\ncurl \"https:\u002F\u002F…\u002Fv1beta\u002Fmodels\u002F$MODEL:generateContent\"\n```\n\nObserved 2026-09-05 (robocar-unified, probing a replacement Gemini model): three\nrequests came back `HTTP 404` in **60 ms with an empty body**, and were nearly\nreported as \"the new model does not support generateContent\". The empty body and\nthe sub-100 ms turnaround were the tell — a real API 404 carries a JSON error and\ntakes a round trip. The same request with braces returned 200.\n\n### The fix\n\nBrace the expansion. Braces end the parameter name, so the colon is literal:\n\n```zsh\ncurl \"https:\u002F\u002F…\u002Fv1beta\u002Fmodels\u002F${MODEL}:generateContent\"\n```\n\nDouble quotes do **not** protect you — modifiers apply inside them.\n\n### When it bites\n\n- Gemini-style `model:method` REST paths, `host:port`, `user:group`,\n  `file:line`, `scp`\u002F`rsync` `host:path` targets — any `$var:` with a letter\n  after the colon.\n- A modifier letter that zsh does not recognise errors loudly\n  (`unrecognized modifier`); the recognised ones (`g`, `h`, `t`, `r`, `e`, `s`,\n  `a`, `A`, `l`, `u`, `q`, `Q`, `x`, `c`, `P`) fail silently by rewriting the\n  string.\n\n## 2. A Word Starting With `=` Is a Command Lookup\n\nWith `EQUALS` set (the zsh default), an unquoted word that begins with `=` is\nreplaced by the path of the command named after it: `=ls` becomes `\u002Fbin\u002Fls`.\nWhen no such command exists, the expansion is a **fatal error that aborts the\nrest of the command line**, not just that word, and `;` does not contain it:\n\n```zsh\nzsh -fc 'echo a; echo ======; echo b'\n# a\n# zsh:1: ===== not found        ← `echo b` never runs, exit 1\n```\n\nObserved 2026-09-15 (claude-plugins, session-end): `survey.sh …; echo ======;\ndistill-survey.sh …` printed the survey, then `(eval):1: ===== not found`, and\nthe second collector silently never ran. The error names the word minus its\nleading `=`, which reads like a missing command rather than a separator.\n\n### The fix\n\nQuote the word (`echo '======'`), or use a separator that does not start with\n`=` (`echo ---`). `setopt noequals` also works but changes the shell for\neverything after it.\n\n### When it bites\n\n- Section separators in chained diagnostics (`echo =====`, `print ==== x`).\n- Arguments that start with `=`: `--flag =value`, `git log =main`, a jq or awk\n  program passed unquoted.\n- Mid-chain placement: everything after the bad word is lost, so the symptom is\n  missing output from a later command, not an error at the one you wrote.\n\n## 3. Zsh Does Not Word-Split an Unquoted Parameter\n\nBash splits an unquoted `$var` on `IFS`; zsh does not, because `SH_WORD_SPLIT`\nis off by default. The whole string stays one word, so `$1` is everything and\n`$2` is empty:\n\n```zsh\n# Wrong — $2 is empty, so gh runs without a PR number\nfor spec in \"ForumViriumHelsinki\u002Finfrastructure 2379\" \"ForumViriumHelsinki\u002F.github 127\"; do\n  set -- $spec\n  gh pr view \"$2\" -R \"$1\" --json state\ndone\n```\n\nObserved 2026-09-16 (verifying three PRs after a merge): the loop printed gh's\nusage text three times — *\"argument required when using the --repo flag\"* — and\nverified nothing. The message names a **flag**, so it reads as a wrong invocation\nrather than an empty variable, and the obvious next move is to rewrite the `gh`\ncall that was already correct.\n\n### The fix\n\nForce splitting with `${=var}`, or read into named variables:\n\n```zsh\nfor spec in \"ForumViriumHelsinki\u002Finfrastructure 2379\"; do read -r repo num \u003C\u003C\u003C \"$spec\"; gh pr view \"$num\" -R \"$repo\" --json state; done\n```\n\nNamed variables are the better habit: they survive a copy into a bash script,\nand they say what each field is.\n\n### When it bites\n\n- `set -- $line` \u002F `set -- $spec` over a list of space-separated records — the\n  natural way to unpack \"repo number\" or \"host port\" pairs.\n- `cmd $args` where `args` holds several flags. Zsh passes them as **one**\n  argument; the tool reports an unknown option containing spaces.\n- Splitting on something other than whitespace: `${(s:,:)csv}` in zsh, not\n  `IFS=, read`.\n- **Over ssh, when the remote login shell is zsh.** `ssh host '…'` hands the\n  command string to the remote user's login shell, so a bash-tested\n  `C=\"apptainer exec … colmap\"; $C image_undistorter …` exits **127** there: the\n  whole string is looked up as one command name. Observed 2026-10-23 driving a\n  GPU box whose login shell was zsh — the same script body ran fine once fed to\n  bash. Run multi-line remote work as `ssh host bash -s \u003C\u003C'EOF' … EOF` (or\n  `ssh host bash script.sh`), and hold a command in a shell **function**\n  (`colmap() { apptainer exec … colmap \"$@\"; }`), never a string.\n\n### The failure looks like a clean result, not an error\n\nBoth halves of that session's evidence were silent. The `gh` loop printed usage\ntext, and a malformed taskwarrior query minutes later (`task export\nstatus:pending` — taskwarrior wants the filter **before** the command) returned\nthree empty lists that read exactly like an empty queue. A control re-run with\nthe correct order returned 457 tasks. Control-test any negative that gates an\naction.\n\n## 4. `path` Is Not a Free Variable Name\n\nZsh **ties `path` to `PATH`**: `path` is the array view, `PATH` the scalar view,\nand writing either rewrites the other. Assigning a string to `path` therefore\ndestroys the search path for the rest of the shell.\n\nThe usual way in is a loop variable chosen for readability:\n\n```zsh\n# Wrong — `path` is special; PATH is destroyed on the FIRST iteration\nwhile IFS=$'\\t' read -r key title labels path; do\n  gh issue create --title \"$title\" --body-file \"$path\" ...\ndone \u003C list.tsv\n```\n\nObserved 2026-09-02 (silverbucket-helper, filing eight issues): every iteration\nprinted `command not found: tail`, and **nothing was created** — `gh` was already\nunreachable by the time the body ran.\n\nZsh's tied variables are a small set, and the rest are just as ordinary looking:\n`path`, `cdpath`, `fpath`, `manpath`, `fignore`, `mailpath`, `module_path`,\n`prompt`, `psvar`, `status`, `argv`. `path` and `fpath` are the two a script is\nmost likely to reach for by accident.\n\n### The fix\n\nPick a name that is not tied. Any of `bodyfile`, `file`, `p`, `target` works; the\nrename is the whole fix.\n\n```zsh\nwhile IFS=$'\\t' read -r key title labels bodyfile; do gh issue create --title \"$title\" --body-file \"$bodyfile\"; done \u003C list.tsv\n```\n\n`typeset` does not rescue you — `local path` inside a function still shadows the\ntied parameter and still breaks command lookup for that function's body.\n\n### Check whether anything actually ran\n\nThe failure is loud but **misattributed**: zsh reports the missing command, not\nthe cause, so the obvious next move is to fix the \"missing\" tool. Before retrying\na loop that had side effects, establish whether the side effects happened — a\npartially-completed run retried from the top creates duplicates.\n\n```zsh\ngh issue list --state open --limit 30 --json number,createdAt\n```\n\nIn the case above the answer was none, because `PATH` died on iteration one\nbefore `gh` was reached. Had it died later, some issues would exist and a blind\nretry would have double-filed them.\n\n## Verifying a Suspected Hit\n\nAll four are testable in one line against a pristine shell (`zsh -f` skips\nrc files, so the result is the language's behaviour and not this machine's):\n\n```zsh\nzsh -fc 'M=models\u002Fx; echo \"$M:generateContent\"; echo \"${M}:generateContent\"'\n```\n\n```zsh\nzsh -fc 'v=\"a b\"; set -- $v; echo \"bare: 1=[$1] 2=[$2]\"; set -- ${=v}; echo \"split: 1=[$1] 2=[$2]\"'\n```\n\nIf the braced or `${=…}` form differs from the bare one, the expansion is the\nbug — not the tool you were calling.\n","# Zsh Gotchas — Four Expansions That Rewrite Your Command\n\nFour zsh behaviours with no bash equivalent. Each one fires on **ordinary\ncommands**, including the one-liners an agent runs through the Bash tool — not\njust on `.zsh` files — so a snippet lifted from a bash-tested doc breaks only\nhere.\n\nWhat makes them expensive is that three of the four **fail silently or\nmisattribute**: the command runs, exits, and reports something that looks like a\nreal answer about the world. Every one below was diagnosed the wrong way first.\n\n| Symptom | Mechanism | Section |\n|---|---|---|\n| A URL\u002Fpath with `$var:` hits the wrong endpoint; fast empty 404 | `$VAR:x` is a history modifier | [1](#1-varword-is-a-modifier-not-a-colon-after-a-variable) |\n| A later command in a `;` chain produced no output | a word starting with `=` is a command lookup | [2](#2-a-word-starting-with--is-a-command-lookup) |\n| `$2` empty after `set -- $spec`; tool prints its usage text | zsh does not word-split | [3](#3-zsh-does-not-word-split-an-unquoted-parameter) |\n| `command not found` for a tool that is installed | `path` is tied to `PATH` | [4](#4-path-is-not-a-free-variable-name) |\n\nOut of scope: zsh-vs-POSIX pattern expansion and extended glob. Those bite when\nwriting `.zsh` \u002F `zshrc` files, not on every command, and are not covered here.\n\n## When to Use This Skill\n\n| Use this skill when... | Use `shell-expert` instead when... |\n|---|---|\n| A zsh command ran and returned a result that does not match what you typed | Writing a shell script, function, or pipeline from scratch |\n| An unexpected 404, an empty positional, or a missing chunk of output from a chain | Choosing portable constructs across bash \u002F zsh \u002F POSIX |\n| `command not found` names a tool you know is installed | Structuring error handling, `set` flags, or CLI argument parsing |\n| A bash-tested snippet behaves differently once run through the Bash tool | The question is shell *style* rather than a wrong runtime result |\n\nThe split is runtime versus authoring: this skill covers four expansions that\nmake a correct-looking zsh command do something else, three of them silently.\n\n## 1. `$VAR:word` Is a Modifier, Not a Colon After a Variable\n\nZsh applies history-style **modifiers** directly to a bare parameter expansion:\n`$f:h` (dirname), `$f:t` (basename), `$f:r`, `$f:e`, `$f:s\u002Fa\u002Fb\u002F`, `$f:g…`. So a\nURL that puts a variable straight before a colon is not the URL you wrote:\n\n```zsh\n# Wrong — `:g` is read as the start of a global-substitution modifier\ncurl \"https:\u002F\u002F…\u002Fv1beta\u002Fmodels\u002F$MODEL:generateContent\"\n```\n\nObserved 2026-09-05 (robocar-unified, probing a replacement Gemini model): three\nrequests came back `HTTP 404` in **60 ms with an empty body**, and were nearly\nreported as \"the new model does not support generateContent\". The empty body and\nthe sub-100 ms turnaround were the tell — a real API 404 carries a JSON error and\ntakes a round trip. The same request with braces returned 200.\n\n### The fix\n\nBrace the expansion. Braces end the parameter name, so the colon is literal:\n\n```zsh\ncurl \"https:\u002F\u002F…\u002Fv1beta\u002Fmodels\u002F${MODEL}:generateContent\"\n```\n\nDouble quotes do **not** protect you — modifiers apply inside them.\n\n### When it bites\n\n- Gemini-style `model:method` REST paths, `host:port`, `user:group`,\n  `file:line`, `scp`\u002F`rsync` `host:path` targets — any `$var:` with a letter\n  after the colon.\n- A modifier letter that zsh does not recognise errors loudly\n  (`unrecognized modifier`); the recognised ones (`g`, `h`, `t`, `r`, `e`, `s`,\n  `a`, `A`, `l`, `u`, `q`, `Q`, `x`, `c`, `P`) fail silently by rewriting the\n  string.\n\n## 2. A Word Starting With `=` Is a Command Lookup\n\nWith `EQUALS` set (the zsh default), an unquoted word that begins with `=` is\nreplaced by the path of the command named after it: `=ls` becomes `\u002Fbin\u002Fls`.\nWhen no such command exists, the expansion is a **fatal error that aborts the\nrest of the command line**, not just that word, and `;` does not contain it:\n\n```zsh\nzsh -fc 'echo a; echo ======; echo b'\n# a\n# zsh:1: ===== not found        ← `echo b` never runs, exit 1\n```\n\nObserved 2026-09-15 (claude-plugins, session-end): `survey.sh …; echo ======;\ndistill-survey.sh …` printed the survey, then `(eval):1: ===== not found`, and\nthe second collector silently never ran. The error names the word minus its\nleading `=`, which reads like a missing command rather than a separator.\n\n### The fix\n\nQuote the word (`echo '======'`), or use a separator that does not start with\n`=` (`echo ---`). `setopt noequals` also works but changes the shell for\neverything after it.\n\n### When it bites\n\n- Section separators in chained diagnostics (`echo =====`, `print ==== x`).\n- Arguments that start with `=`: `--flag =value`, `git log =main`, a jq or awk\n  program passed unquoted.\n- Mid-chain placement: everything after the bad word is lost, so the symptom is\n  missing output from a later command, not an error at the one you wrote.\n\n## 3. Zsh Does Not Word-Split an Unquoted Parameter\n\nBash splits an unquoted `$var` on `IFS`; zsh does not, because `SH_WORD_SPLIT`\nis off by default. The whole string stays one word, so `$1` is everything and\n`$2` is empty:\n\n```zsh\n# Wrong — $2 is empty, so gh runs without a PR number\nfor spec in \"ForumViriumHelsinki\u002Finfrastructure 2379\" \"ForumViriumHelsinki\u002F.github 127\"; do\n  set -- $spec\n  gh pr view \"$2\" -R \"$1\" --json state\ndone\n```\n\nObserved 2026-09-16 (verifying three PRs after a merge): the loop printed gh's\nusage text three times — *\"argument required when using the --repo flag\"* — and\nverified nothing. The message names a **flag**, so it reads as a wrong invocation\nrather than an empty variable, and the obvious next move is to rewrite the `gh`\ncall that was already correct.\n\n### The fix\n\nForce splitting with `${=var}`, or read into named variables:\n\n```zsh\nfor spec in \"ForumViriumHelsinki\u002Finfrastructure 2379\"; do read -r repo num \u003C\u003C\u003C \"$spec\"; gh pr view \"$num\" -R \"$repo\" --json state; done\n```\n\nNamed variables are the better habit: they survive a copy into a bash script,\nand they say what each field is.\n\n### When it bites\n\n- `set -- $line` \u002F `set -- $spec` over a list of space-separated records — the\n  natural way to unpack \"repo number\" or \"host port\" pairs.\n- `cmd $args` where `args` holds several flags. Zsh passes them as **one**\n  argument; the tool reports an unknown option containing spaces.\n- Splitting on something other than whitespace: `${(s:,:)csv}` in zsh, not\n  `IFS=, read`.\n- **Over ssh, when the remote login shell is zsh.** `ssh host '…'` hands the\n  command string to the remote user's login shell, so a bash-tested\n  `C=\"apptainer exec … colmap\"; $C image_undistorter …` exits **127** there: the\n  whole string is looked up as one command name. Observed 2026-10-23 driving a\n  GPU box whose login shell was zsh — the same script body ran fine once fed to\n  bash. Run multi-line remote work as `ssh host bash -s \u003C\u003C'EOF' … EOF` (or\n  `ssh host bash script.sh`), and hold a command in a shell **function**\n  (`colmap() { apptainer exec … colmap \"$@\"; }`), never a string.\n\n### The failure looks like a clean result, not an error\n\nBoth halves of that session's evidence were silent. The `gh` loop printed usage\ntext, and a malformed taskwarrior query minutes later (`task export\nstatus:pending` — taskwarrior wants the filter **before** the command) returned\nthree empty lists that read exactly like an empty queue. A control re-run with\nthe correct order returned 457 tasks. Control-test any negative that gates an\naction.\n\n## 4. `path` Is Not a Free Variable Name\n\nZsh **ties `path` to `PATH`**: `path` is the array view, `PATH` the scalar view,\nand writing either rewrites the other. Assigning a string to `path` therefore\ndestroys the search path for the rest of the shell.\n\nThe usual way in is a loop variable chosen for readability:\n\n```zsh\n# Wrong — `path` is special; PATH is destroyed on the FIRST iteration\nwhile IFS=$'\\t' read -r key title labels path; do\n  gh issue create --title \"$title\" --body-file \"$path\" ...\ndone \u003C list.tsv\n```\n\nObserved 2026-09-02 (silverbucket-helper, filing eight issues): every iteration\nprinted `command not found: tail`, and **nothing was created** — `gh` was already\nunreachable by the time the body ran.\n\nZsh's tied variables are a small set, and the rest are just as ordinary looking:\n`path`, `cdpath`, `fpath`, `manpath`, `fignore`, `mailpath`, `module_path`,\n`prompt`, `psvar`, `status`, `argv`. `path` and `fpath` are the two a script is\nmost likely to reach for by accident.\n\n### The fix\n\nPick a name that is not tied. Any of `bodyfile`, `file`, `p`, `target` works; the\nrename is the whole fix.\n\n```zsh\nwhile IFS=$'\\t' read -r key title labels bodyfile; do gh issue create --title \"$title\" --body-file \"$bodyfile\"; done \u003C list.tsv\n```\n\n`typeset` does not rescue you — `local path` inside a function still shadows the\ntied parameter and still breaks command lookup for that function's body.\n\n### Check whether anything actually ran\n\nThe failure is loud but **misattributed**: zsh reports the missing command, not\nthe cause, so the obvious next move is to fix the \"missing\" tool. Before retrying\na loop that had side effects, establish whether the side effects happened — a\npartially-completed run retried from the top creates duplicates.\n\n```zsh\ngh issue list --state open --limit 30 --json number,createdAt\n```\n\nIn the case above the answer was none, because `PATH` died on iteration one\nbefore `gh` was reached. Had it died later, some issues would exist and a blind\nretry would have double-filed them.\n\n## Verifying a Suspected Hit\n\nAll four are testable in one line against a pristine shell (`zsh -f` skips\nrc files, so the result is the language's behaviour and not this machine's):\n\n```zsh\nzsh -fc 'M=models\u002Fx; echo \"$M:generateContent\"; echo \"${M}:generateContent\"'\n```\n\n```zsh\nzsh -fc 'v=\"a b\"; set -- $v; echo \"bare: 1=[$1] 2=[$2]\"; set -- ${=v}; echo \"split: 1=[$1] 2=[$2]\"'\n```\n\nIf the braced or `${=…}` form differs from the bare one, the expansion is the\nbug — not the tool you were calling.\n",{"name":5,"created":40,"modified":41,"reviewed":40,"description":7,"allowed-tools":42},1789948800000,1792800000000,"Bash, Read","main","bdd0582f1a2ba53d21061835bfd72d45f2f954f4","tools-plugin\u002Fskills\u002Fzsh-gotchas",6,"https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins","https:\u002F\u002Fgithub.com\u002Flaurigates","Linux enthusiast, cloud engineer, neovim addict, electronics hobbyist.","2026-11-11 01:25:01",{"source":8,"skillName":5,"commands":52,"prompt":62,"zipAvailable":63},[53,56,59],{"tool":54,"command":55},"npx","npx skills add laurigates\u002Fclaude-plugins --skill zsh-gotchas",{"tool":57,"command":58},"bunx","bunx skills add laurigates\u002Fclaude-plugins --skill zsh-gotchas",{"tool":60,"command":61},"pnpm","pnpm dlx skills add laurigates\u002Fclaude-plugins --skill zsh-gotchas","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Ftools-plugin\u002Fskills\u002Fzsh-gotchas\u002FSKILL.md",true,[65],{"path":66,"resourceType":67,"resourceTypeDesc":68,"sizeBytes":69,"sourceHtmlUrl":70},"requires.yaml","REFERENCE","参考文档",29,"https:\u002F\u002Fgithub.com\u002Fjthorare\u002Fagentic-workflow\u002Fblob\u002Fmain\u002Fskills\u002Fdesign-implement\u002Frequires.yaml",[72,99,120,136,159,189],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":83,"publishedAt":35},"01M70PFHMH9ADY0CRE6047Y4B2","kitty-show-image","Show the user an image with a note on what to judge, via a file send or a labelled kitty tab. Use when the user must see an image, or icat fails with no \u002Fdev\u002Ftty.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fkitty-plugin\u002Fskills\u002Fkitty-show-image\u002FSKILL.md",[78],{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[84,85,86,87,88,89,90,91,92,93,26,33,21,94,95,96,97,98,34,25],"show","kitty show image","image","kitty","show image","ls","get","send","open","dev","file","text","with","xdg","via",{"skillNo":100,"name":101,"nameZh":6,"description":102,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":105,"publishedAt":35},"01M70PFEN18HKQ4RCQ1VPGMPTB","kitty-session-persistence","Snapshot and restore kitty terminal sessions on macOS. Use when surviving WindowServer hangs without losing tabs, configuring snapshots, or restoring after a force-reboot.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fkitty-plugin\u002Fskills\u002Fkitty-session-persistence\u002FSKILL.md",[],[87,106,107,108,109,110,33,21,111,112,113,34,25,114,115,116,117,118,119,26],"kitty session persistence","session","persistence","false","snapshots","uname","reboot","terminal","write","edit","snapshot","macos","sessions","restore",{"skillNo":121,"name":122,"nameZh":6,"description":123,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":124,"categories":125,"keywords":126,"publishedAt":35},"01M70PFC77XGXCVQ1543VGZHYR","kitty-remote-control","Safe kitty remote control from an agent — read panes with kitty @ ls\u002Fget-text, notify, and never mutate the live terminal unasked. Use when running inside kitty.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fkitty-plugin\u002Fskills\u002Fkitty-remote-control\u002FSKILL.md",[],[127,128,87,129,130,89,131,132,90,133,134,26,33,135,21,95,96,113,34,25],"kitty remote control","remote","control","remote control","running","never","panes","notify","query",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":142,"publishedAt":35},"01M70P6WVMCT5JG4SACTM69AF9","docs-reference-check","Dangling doc-reference gate: flag markdown naming repo paths or relative links that no longer exist. Use when docs cite moved\u002Fdeleted files, or wiring a doc-drift lint.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fdocumentation-plugin\u002Fskills\u002Fdocs-reference-check\u002FSKILL.md",[],[143,144,145,146,147,148,149,150,151,152,26,33,21,153,94,154,155,156,157,158],"docs reference check","check","reference check","reference","docs","links","python3","repo","files","auto","drift","lint","wiring","chezmoi","references","cp",{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":174,"publishedAt":35},"01M6C6NDE7DAQGNWSF22J5CJ0Z","youtube-upload","Upload a video to YouTube via the Data API v3 and edit its title, description, tags or thumbnail afterwards. Use when publishing or retitling a YouTube video.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fyoutube-plugin\u002Fskills\u002Fyoutube-upload\u002FSKILL.md",[165,168,169],{"categoryNo":166,"categoryName":167,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":79,"categoryName":80,"taxonomyType":81,"taxonomyTypeDesc":82},{"categoryNo":170,"categoryName":171,"taxonomyType":172,"taxonomyTypeDesc":173},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[175,176,177,178,149,179,25,180,115,181,182,183,26,21,94,184,185,33,186,187,188,98,34],"youtube upload","upload","youtube","Video","run","uv run","publishing","data","uv","api","v3","tags","id","title",{"skillNo":190,"name":191,"nameZh":6,"description":192,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":193,"categories":194,"keywords":198,"publishedAt":35},"01M6C6NABWW1X58KJJM4F6GQMQ","youtube-studio-share","Share a private YouTube video with a whole Google Workspace organization by scripting YouTube Studio in the browser. Use when a video must be org-only.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fyoutube-plugin\u002Fskills\u002Fyoutube-studio-share\u002FSKILL.md",[195],{"categoryNo":196,"categoryName":197,"taxonomyType":81,"taxonomyTypeDesc":82},"01JBSEEDCAT000000000000023","Skill与智能体开发",[199,200,201,202,177,178,203,204,205,206,207,25,22,208,209,210,26,211,33,96,212,34],"youtube studio share","share","youtube studio","studio","browser","javascript","scripting","google workspace","workspace","google","only","MCP","chrome","organization"]