feat: create skill variable helper
This commit is contained in:
@@ -45,6 +45,7 @@ description: "<One-liner: what it does and when to trigger. Keep under ~200 char
|
||||
|
||||
- **Be concise.** Skills are injected into agent context — every line costs tokens. Aim for the minimum needed to reliably guide the agent.
|
||||
- **Use scripts for repeatable logic.** If a step involves a multi-line shell command, `jq` pipeline, or API call that won't change between runs, put it in a `.sh` file next to `SKILL.md` and reference it from the workflow. See `address-gh-review/` for an example.
|
||||
- **Needs configurable values (paths, identifiers, etc.; not secrets — values are stored as plaintext files)?** Copy `assets/variable.sh` into the new skill's `scripts/` dir as-is. Callers use `variable.sh --get NAME [--require-exec RELPATH]`; the helper prints self-explaining `--set` instructions on "unset" or "set-but-invalid" and exits non-zero, so callers just propagate. The helper self-ignores its `.vars/` store on first `--set`, so no `.gitignore` setup is needed.
|
||||
- **Frontmatter is required.** `name` and `description` fields. The description is what the agent uses to decide whether to load the skill, so make it specific about trigger conditions.
|
||||
- **Don't over-specify.** Trust the agent to fill gaps. Document the _what_ and _when_, not every micro-step.
|
||||
- **Split workflow from reference when the reference surface grows.** If a skill accumulates lookup tables, mapping rules, or capability references that the workflow consults, move them into a sibling `<skill>/<category>/` directory (e.g. `mappings/`, `references/`) with one sub-doc per category and an index `README.md`. Keep `SKILL.md` focused on the hot path — workflow, hard rules, and a short table pointing at the sub-docs. Include a brief style guide in the index README covering (a) defer to authoritative sources (stubs, schemas, generated docs) whenever possible, (b) row/entry formatting conventions, (c) when to create a new sub-doc vs. extend an existing one.
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
# Skill-local variable store. Values live in <skill-dir>/.vars/<NAME>.
|
||||
#
|
||||
# Usage:
|
||||
# variable.sh --get NAME # prints value to stdout, exits 0
|
||||
# # or prints a self-explaining hint to
|
||||
# # stderr and exits 2 if unset.
|
||||
# variable.sh --set NAME VALUE # writes value, exits 0.
|
||||
#
|
||||
# Callers should treat a non-zero exit as fatal; the stderr message tells
|
||||
# the caller (agent or user) exactly how to populate the missing value.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
STORE="$SKILL_DIR/.vars"
|
||||
SELF="$0"
|
||||
|
||||
usage() {
|
||||
cat >&2 <<EOF
|
||||
Usage:
|
||||
$SELF --get NAME
|
||||
$SELF --set NAME VALUE
|
||||
EOF
|
||||
exit 2
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
--get)
|
||||
[[ $# -eq 2 ]] || usage
|
||||
name="$2"
|
||||
file="$STORE/$name"
|
||||
if [[ ! -f "$file" ]]; then
|
||||
cat >&2 <<EOF
|
||||
$SELF: $name is not set.
|
||||
Ask the user for the value, then set it:
|
||||
$SELF --set $name <value>
|
||||
EOF
|
||||
exit 2
|
||||
fi
|
||||
cat "$file"
|
||||
;;
|
||||
--set)
|
||||
[[ $# -eq 3 ]] || usage
|
||||
name="$2"; value="$3"
|
||||
[[ "$name" =~ ^[A-Z][A-Z0-9_]*$ ]] || {
|
||||
echo >&2 "$SELF: invalid name '$name' (must match [A-Z][A-Z0-9_]*)"
|
||||
exit 2
|
||||
}
|
||||
mkdir -p "$STORE"
|
||||
# Self-ignore the store so values never get committed, even if the
|
||||
# skill root lacks a .gitignore entry for .vars/.
|
||||
[[ -f "$STORE/.gitignore" ]] || printf '*\n' > "$STORE/.gitignore"
|
||||
printf '%s' "$value" > "$STORE/$name"
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user