Repository navigation
Update: product-verified catalog skill content #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
29470d3
85d8363
56eaeac
f180a59
cd36546
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,18 +7,21 @@ manifest_name=".corvid-skills.json" | |
|
|
||
| usage() { | ||
| cat <<'EOF' | ||
| Manage shared CorvidLabs agent skills in one repository. | ||
| Manage shared CorvidLabs agent skills (repository-local or machine-global). | ||
|
|
||
| Usage: | ||
| fledge skills list [--json] | ||
| fledge skills install <skill> [--repo <path>] [--host <auto|codex|claude|cursor|gemini|grok|openai>] [--link] [--dry-run] | ||
| fledge skills status [--repo <path>] [--json] | ||
| fledge skills update <skill>|--all [--repo <path>] [--host <codex|claude|cursor|gemini|grok|openai>] [--dry-run] | ||
| fledge skills uninstall <skill> [--repo <path>] [--host <codex|claude|cursor|gemini|grok|openai>] [--dry-run] | ||
| fledge skills install <skill> [--repo <path>|--global] [--host <auto|codex|claude|cursor|gemini|grok|openai>] [--link] [--dry-run] | ||
| fledge skills status [--repo <path>|--global] [--json] | ||
| fledge skills update <skill>|--all [--repo <path>|--global] [--host <codex|claude|cursor|gemini|grok|openai>] [--dry-run] | ||
| fledge skills uninstall <skill> [--repo <path>|--global] [--host <codex|claude|cursor|gemini|grok|openai>] [--dry-run] | ||
|
|
||
| Install copies a selected skill into a repository-local agent directory and | ||
| records the exact source revision and content digest in .corvid-skills.json. | ||
| It never overwrites an existing directory. | ||
| Install copies (or links) a selected skill into either: | ||
| • a repository-local agent directory, or | ||
| • a machine-global host directory under $HOME (or $CORVID_SKILLS_HOME) | ||
|
|
||
| and records the exact source revision and content digest in .corvid-skills.json | ||
| (next to that target root). It never overwrites an existing directory. | ||
|
|
||
| Update and uninstall operate only on unmodified managed copies or exact manifest-owned links. | ||
| EOF | ||
|
|
@@ -51,6 +54,33 @@ repository_root() { | |
| git -C "$requested" rev-parse --show-toplevel 2>/dev/null || fail "not a Git repository: $requested" | ||
| } | ||
|
|
||
| # Machine-global install root. Override with CORVID_SKILLS_HOME for tests. | ||
| skills_home() { | ||
| local home="${CORVID_SKILLS_HOME:-${HOME:-}}" | ||
| [[ -n "$home" ]] || fail "HOME is unset; cannot use --global" | ||
| [[ -d "$home" ]] || fail "skills home is not a directory: $home" | ||
| printf '%s' "$home" | ||
| } | ||
|
|
||
| # Parent of host skills dir, e.g. .claude/skills -> .claude | ||
| host_agent_root() { | ||
| dirname "$(host_directory "$1")" | ||
| } | ||
|
|
||
| # Parse shared --repo / --global options. Sets: scope_root, is_global | ||
| # Remaining args are left in parse_remaining for the caller via a name ref pattern: | ||
| # resolve_target_from_flags is called after collecting flags into variables. | ||
| resolve_target_root() { | ||
| local is_global="$1" | ||
| local repo_arg="$2" | ||
| if [[ "$is_global" == "true" ]]; then | ||
| [[ "$repo_arg" == "." ]] || fail "--global cannot be combined with --repo" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a caller explicitly supplies Useful? React with 👍 / 👎. |
||
| skills_home | ||
| else | ||
| repository_root "$repo_arg" | ||
| fi | ||
| } | ||
|
|
||
| ensure_safe_install_paths() { | ||
| local repo="$1" | ||
| local destination_rel="$2" | ||
|
|
@@ -123,7 +153,9 @@ resolve_host() { | |
| local candidates=() | ||
| local host | ||
| for host in codex claude cursor gemini grok openai; do | ||
| [[ -d "$repo/$(host_directory "$host")" ]] && candidates+=("$host") | ||
| if [[ -d "$repo/$(host_directory "$host")" || -d "$repo/$(host_agent_root "$host")" ]]; then | ||
| candidates+=("$host") | ||
| fi | ||
| done | ||
| if [[ ${#candidates[@]} -eq 1 ]]; then | ||
| printf '%s' "${candidates[0]}" | ||
|
|
@@ -458,10 +490,12 @@ install_skill() { | |
| local host_arg="auto" | ||
| local link="false" | ||
| local dry_run="false" | ||
| local is_global="false" | ||
|
|
||
| while [[ $# -gt 0 ]]; do | ||
| case "$1" in | ||
| --repo) [[ $# -ge 2 ]] || fail "--repo needs a path"; repo_arg="$2"; shift 2 ;; | ||
| --global) is_global="true"; shift ;; | ||
| --host) [[ $# -ge 2 ]] || fail "--host needs a value"; host_arg="$2"; shift 2 ;; | ||
| --link) link="true"; shift ;; | ||
| --dry-run) dry_run="true"; shift ;; | ||
|
|
@@ -471,7 +505,7 @@ install_skill() { | |
|
|
||
| validate_skill_source "$skill" | ||
| local repo host destination destination_rel revision digest manifest | ||
| repo="$(repository_root "$repo_arg")" | ||
| repo="$(resolve_target_root "$is_global" "$repo_arg")" | ||
| host="$(resolve_host "$repo" "$host_arg")" | ||
| destination_rel="$(host_directory "$host")/$skill" | ||
| destination="$repo/$destination_rel" | ||
|
|
@@ -515,9 +549,11 @@ update_skills() { | |
| local repo_arg="." | ||
| local host_filter="" | ||
| local dry_run="false" | ||
| local is_global="false" | ||
| while [[ $# -gt 0 ]]; do | ||
| case "$1" in | ||
| --repo) [[ $# -ge 2 ]] || fail "--repo needs a path"; repo_arg="$2"; shift 2 ;; | ||
| --global) is_global="true"; shift ;; | ||
| --host) [[ $# -ge 2 ]] || fail "--host needs a value"; host_filter="$2"; shift 2 ;; | ||
| --dry-run) dry_run="true"; shift ;; | ||
| *) fail "unknown option: $1" ;; | ||
|
|
@@ -528,7 +564,7 @@ update_skills() { | |
| [[ -z "$host_filter" ]] || host_directory "$host_filter" >/dev/null | ||
|
|
||
| local repo manifest revision | ||
| repo="$(repository_root "$repo_arg")" | ||
| repo="$(resolve_target_root "$is_global" "$repo_arg")" | ||
| manifest="$repo/$manifest_name" | ||
| [[ -f "$manifest" && ! -L "$manifest" ]] || fail "managed-skills manifest not found: $manifest" | ||
| revision="$(git -C "$root_dir" rev-parse --verify HEAD 2>/dev/null || printf 'working-tree')" | ||
|
|
@@ -607,9 +643,11 @@ uninstall_skill() { | |
| local repo_arg="." | ||
| local host_filter="" | ||
| local dry_run="false" | ||
| local is_global="false" | ||
| while [[ $# -gt 0 ]]; do | ||
| case "$1" in | ||
| --repo) [[ $# -ge 2 ]] || fail "--repo needs a path"; repo_arg="$2"; shift 2 ;; | ||
| --global) is_global="true"; shift ;; | ||
| --host) [[ $# -ge 2 ]] || fail "--host needs a value"; host_filter="$2"; shift 2 ;; | ||
| --dry-run) dry_run="true"; shift ;; | ||
| *) fail "unknown option: $1" ;; | ||
|
|
@@ -618,7 +656,7 @@ uninstall_skill() { | |
| [[ -z "$host_filter" ]] || host_directory "$host_filter" >/dev/null | ||
|
|
||
| local repo manifest | ||
| repo="$(repository_root "$repo_arg")" | ||
| repo="$(resolve_target_root "$is_global" "$repo_arg")" | ||
| manifest="$repo/$manifest_name" | ||
| [[ -f "$manifest" && ! -L "$manifest" ]] || fail "managed-skills manifest not found: $manifest" | ||
| local manifest_output="" | ||
|
|
@@ -683,22 +721,28 @@ uninstall_skill() { | |
| status_skills() { | ||
| local repo_arg="." | ||
| local json="false" | ||
| local is_global="false" | ||
| while [[ $# -gt 0 ]]; do | ||
| case "$1" in | ||
| --repo) [[ $# -ge 2 ]] || fail "--repo needs a path"; repo_arg="$2"; shift 2 ;; | ||
| --global) is_global="true"; shift ;; | ||
| --json) json="true"; shift ;; | ||
| *) fail "unknown option: $1" ;; | ||
| esac | ||
| done | ||
| local repo manifest | ||
| repo="$(repository_root "$repo_arg")" | ||
| repo="$(resolve_target_root "$is_global" "$repo_arg")" | ||
| manifest="$repo/$manifest_name" | ||
| [[ ! -L "$manifest" ]] || fail "refusing symlinked manifest: $manifest" | ||
| if [[ ! -f "$manifest" ]]; then | ||
| if [[ "$json" == "true" ]]; then | ||
| printf '{"schema_version":1,"installs":[]}\n' | ||
| else | ||
| echo "No managed CorvidLabs skills are installed in $repo" | ||
| if [[ "$is_global" == "true" ]]; then | ||
| echo "No managed CorvidLabs skills are installed globally in $repo" | ||
| else | ||
| echo "No managed CorvidLabs skills are installed in $repo" | ||
| fi | ||
| fi | ||
| return | ||
| fi | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following this documented preview-and-remove sequence checks the repository-local manifest during the dry run, but then removes the machine-global installation in the next command. When
augurexists in both scopes, the preview provides no evidence about the copy that will actually be deleted; add--globalto the dry-run command (or keep both commands repository-local).Useful? React with 👍 / 👎.