awesome-agents 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -5
- package/README.md +13 -10
- package/docs/cli.md +4 -7
- package/docs/product/README.md +1 -1
- package/docs/product/command-model.md +4 -5
- package/docs/product/harness-targets.md +1 -25
- package/docs/product/product-scope.md +1 -1
- package/docs/product/profile-source-format.md +4 -1
- package/package.json +2 -2
- package/src/cli.js +2 -2
- package/src/constants.js +4 -8
- package/src/help.js +7 -8
- package/src/installer.js +16 -20
- package/src/renderers.js +16 -156
- package/src/skills.js +46 -24
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
This file is maintained by `npm run changelog` and `npm run release`. Release entries are generated from git commit history.
|
|
4
4
|
|
|
5
|
+
## 0.1.10 - 2026-07-21
|
|
6
|
+
|
|
7
|
+
Changes since `v0.1.9`.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Remove retired harness support (63915b1)
|
|
12
|
+
|
|
13
|
+
## 0.1.9 - 2026-07-16
|
|
14
|
+
|
|
15
|
+
Changes since `v0.1.8`.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Add create-agent-profile skill (f5dcfe0)
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Expose agent-owned support to installed profiles (#12) (832094e)
|
|
24
|
+
- Name awesome-agents profiles directly (9640910)
|
|
25
|
+
- Remove agents nav link (3ad6bb3)
|
|
26
|
+
- Restore coral site accent (ba2ec5c)
|
|
27
|
+
- Refresh site agent directory (2268134)
|
|
28
|
+
- Make skill dependency resolution fault-tolerant instead of fatal (78aea64)
|
|
29
|
+
|
|
5
30
|
## 0.1.8 - 2026-07-08
|
|
6
31
|
|
|
7
32
|
Changes since `v0.1.6`.
|
|
@@ -19,7 +44,6 @@ Changes since `v0.1.6`.
|
|
|
19
44
|
|
|
20
45
|
- Prepare 0.1.7 release (342e93d)
|
|
21
46
|
- Link hosted artifacts for public-builder-profiles-agent-model-cards (0f76238)
|
|
22
|
-
- Update tenex-edge launch commands (cc304e2)
|
|
23
47
|
|
|
24
48
|
### Documentation
|
|
25
49
|
|
|
@@ -33,10 +57,6 @@ Changes since `v0.1.6`.
|
|
|
33
57
|
|
|
34
58
|
- Add generated docs site (8eb21ba)
|
|
35
59
|
|
|
36
|
-
### Changed
|
|
37
|
-
|
|
38
|
-
- Update tenex-edge launch commands (cc304e2)
|
|
39
|
-
|
|
40
60
|
## 0.1.6 - 2026-07-06
|
|
41
61
|
|
|
42
62
|
Changes since `v0.1.5`.
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ agent profile instead of a skill.
|
|
|
7
7
|
Supported sources are GitHub repos, Git URLs, or local checkouts that use the
|
|
8
8
|
agent-profile source layout. Profiles are read from YAML or Markdown files under
|
|
9
9
|
`agents/<slug>/`, adapted for the selected harness, and installed into the
|
|
10
|
-
right place for Codex, Claude Code, OpenCode,
|
|
10
|
+
right place for Codex, Claude Code, OpenCode, or Goose.
|
|
11
11
|
|
|
12
12
|
## Install And Run
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ Use the CLI with `npx`:
|
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
17
|
npx awesome-agents add owner/repo --agent triage-agent
|
|
18
|
-
npx awesome-agents add owner/repo --agent triage-agent --harness
|
|
18
|
+
npx awesome-agents add owner/repo --agent triage-agent --harness goose
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
From this repo during development:
|
|
@@ -46,22 +46,22 @@ Useful install options:
|
|
|
46
46
|
- omit a profile selector in an interactive terminal to choose source profiles
|
|
47
47
|
from a checkbox list; every profile is selected by default
|
|
48
48
|
- `--yes` to accept detected profile and harness selections without opening selectors
|
|
49
|
-
- `--harness codex|claude-code|opencode|goose
|
|
49
|
+
- `--harness codex|claude-code|opencode|goose|*` to select target harnesses;
|
|
50
50
|
without it, the CLI detects harness CLIs on `PATH`; interactive multi-detect
|
|
51
51
|
opens a checkbox selector with every detected harness selected, and
|
|
52
52
|
noninteractive installs use every detected harness. If none are detected, pass
|
|
53
53
|
`--harness`.
|
|
54
54
|
- `--all` to install all profiles to all supported harnesses
|
|
55
55
|
- `--dry-run` to preview writes
|
|
56
|
-
- `--project` for project-level install where supported; Codex
|
|
56
|
+
- `--project` for project-level install where supported; Codex installs globally
|
|
57
57
|
- `--global` for user-level install
|
|
58
58
|
- `--list` to inspect available source profiles without installing
|
|
59
59
|
|
|
60
60
|
Human-readable output uses subtle ANSI color. Set `NO_COLOR=1` to disable color,
|
|
61
61
|
or pass `--json` for machine-readable output. After an install, the CLI groups
|
|
62
62
|
run commands by profile for target harness CLIs it finds on `PATH`, such as
|
|
63
|
-
`codex --profile <profile>`, `claude --agent <profile>`,
|
|
64
|
-
|
|
63
|
+
`codex --profile <profile>`, `claude --agent <profile>`, or `goose session`
|
|
64
|
+
then `@<profile>`.
|
|
65
65
|
|
|
66
66
|
## Harness Targets
|
|
67
67
|
|
|
@@ -71,7 +71,6 @@ Project installs write to:
|
|
|
71
71
|
- Claude Code: `.claude/agents/<profile>.md`
|
|
72
72
|
- OpenCode: `.opencode/agents/<profile>.md`
|
|
73
73
|
- Goose: `.agents/agents/<profile>.md`
|
|
74
|
-
- tenex-edge: not supported; tenex-edge agents are machine-local
|
|
75
74
|
|
|
76
75
|
Global installs write to:
|
|
77
76
|
|
|
@@ -79,13 +78,17 @@ Global installs write to:
|
|
|
79
78
|
- Claude Code: `$CLAUDE_HOME/agents/<profile>.md`, or `~/.claude/agents/<profile>.md`
|
|
80
79
|
- OpenCode: `$OPENCODE_CONFIG_DIR/agents/<profile>.md`, or `~/.config/opencode/agents/<profile>.md`
|
|
81
80
|
- Goose: `$GOOSE_HOME/agents/<profile>.md`, or `~/.agents/agents/<profile>.md`
|
|
82
|
-
- tenex-edge: `$TENEX_EDGE_HOME/agents/<profile>.json`, or `~/.tenex-edge/agents/<profile>.json`
|
|
83
81
|
|
|
84
82
|
The CLI keeps its own registry at `.awesome-agents/installed.json` for project
|
|
85
83
|
installs or `~/.awesome-agents/installed.json` for global installs. `list`,
|
|
86
84
|
`remove`, and `update` use this registry and refuse to overwrite or delete files
|
|
87
85
|
that do not contain the generated marker unless `--force` is passed.
|
|
88
86
|
|
|
87
|
+
Agent-owned references and scripts are installed under
|
|
88
|
+
`~/.agents/homes/<profile>/`. Every installed harness profile receives the exact
|
|
89
|
+
agent-home and support-root paths in its operating context, so profile instructions
|
|
90
|
+
can refer to bundled resources by relative path without becoming harness-specific.
|
|
91
|
+
|
|
89
92
|
Run Codex profiles with:
|
|
90
93
|
|
|
91
94
|
```bash
|
|
@@ -123,7 +126,7 @@ Profiles may also declare immediately relevant skills:
|
|
|
123
126
|
```yaml
|
|
124
127
|
skills:
|
|
125
128
|
- gh-pages-publisher
|
|
126
|
-
-
|
|
129
|
+
- owner/agent-skills release-checklist
|
|
127
130
|
```
|
|
128
131
|
|
|
129
132
|
Bare skill names are resolved from the profile directory, then the source
|
|
@@ -138,7 +141,7 @@ listed with complete paths in the installed agent prompt.
|
|
|
138
141
|
npx awesome-agents add owner/repo --list
|
|
139
142
|
npx awesome-agents add owner/repo --agent triage-agent
|
|
140
143
|
npx awesome-agents add owner/repo --agent triage-agent --harness codex --global
|
|
141
|
-
npx awesome-agents add owner/repo --agent triage-agent --harness
|
|
144
|
+
npx awesome-agents add owner/repo --agent triage-agent --harness goose
|
|
142
145
|
npx awesome-agents add owner/repo --all --dry-run
|
|
143
146
|
npx awesome-agents use owner/repo --agent triage-agent --harness claude-code
|
|
144
147
|
npx awesome-agents list --json
|
package/docs/cli.md
CHANGED
|
@@ -16,10 +16,8 @@ selected by default. When no target harness is provided, `add` detects supported
|
|
|
16
16
|
harness CLIs on `PATH`; multiple detected harnesses open a checkbox selector
|
|
17
17
|
with every harness selected by default. Non-TTY runs, `--json`, and `--yes` use
|
|
18
18
|
all detected selections without prompting. Installs default to project scope
|
|
19
|
-
where the selected harness supports project-local profiles. Codex
|
|
20
|
-
|
|
21
|
-
while tenex-edge agents live in its machine keystore under
|
|
22
|
-
`$TENEX_EDGE_HOME/agents/` or `~/.tenex-edge/agents/`. Goose uses
|
|
19
|
+
where the selected harness supports project-local profiles. Codex is the
|
|
20
|
+
exception: Codex `--profile` loads named config layers from `CODEX_HOME`. Goose uses
|
|
23
21
|
`~/.agents/agents/<profile>.md` (global) or `.agents/agents/<profile>.md`
|
|
24
22
|
(project).
|
|
25
23
|
|
|
@@ -59,11 +57,11 @@ npx awesome-agents add owner/repo --agent triage-agent --harness opencode
|
|
|
59
57
|
```
|
|
60
58
|
|
|
61
59
|
For backward compatibility, `--agent codex`, `--agent claude-code`,
|
|
62
|
-
`--agent opencode`,
|
|
60
|
+
`--agent opencode`, and `--agent goose` are still accepted as harness
|
|
63
61
|
selectors.
|
|
64
62
|
|
|
65
63
|
When no harness selector is provided, `add` detects `codex`, `claude`,
|
|
66
|
-
`opencode`,
|
|
64
|
+
`opencode`, and `goose` on `PATH`. If none are found, the command fails and
|
|
67
65
|
asks for `--harness`.
|
|
68
66
|
|
|
69
67
|
When no profile selector is provided in an interactive terminal, `add` prompts
|
|
@@ -86,7 +84,6 @@ installed profile through any matching harness CLI found on `PATH`. Examples:
|
|
|
86
84
|
codex --profile triage-agent
|
|
87
85
|
claude --agent triage-agent
|
|
88
86
|
goose session
|
|
89
|
-
tenex-edge launch triage-agent
|
|
90
87
|
```
|
|
91
88
|
|
|
92
89
|
For Goose, start `goose session` and invoke the agent by name with `@<profile>`.
|
package/docs/product/README.md
CHANGED
|
@@ -12,7 +12,7 @@ unless the user confirms them.
|
|
|
12
12
|
- `command-model.md`: Command shape, `npx skills` parity, defaults, and scriptability.
|
|
13
13
|
- `profile-source-format.md`: Source repositories, canonical profiles, adapters, and install sources.
|
|
14
14
|
- `site-profiles-and-model-cards.md`: Public builder profiles, agent model cards, GitHub login, and README-backed site content.
|
|
15
|
-
- `harness-targets.md`: Codex, Claude Code, OpenCode,
|
|
15
|
+
- `harness-targets.md`: Codex, Claude Code, OpenCode, and Goose rendering/target behavior.
|
|
16
16
|
- `safety-and-publishing.md`: Install safety, registry behavior, verification, and npm/GitHub publish state.
|
|
17
17
|
- `open-questions.md`: Unresolved product questions.
|
|
18
18
|
|
|
@@ -24,8 +24,8 @@ The CLI supports:
|
|
|
24
24
|
language such as `npx awesome-agents add owner/repo --agent triage-agent`.
|
|
25
25
|
- `--profile <slug>` to select profiles explicitly.
|
|
26
26
|
- `--skill <slug>` as a compatibility alias, even though the artifact is a profile.
|
|
27
|
-
- `--harness <codex|claude-code|opencode|goose
|
|
28
|
-
- `--agent <codex|claude-code|opencode|goose
|
|
27
|
+
- `--harness <codex|claude-code|opencode|goose|*>` to select target harnesses.
|
|
28
|
+
- `--agent <codex|claude-code|opencode|goose|*>` remains accepted as a
|
|
29
29
|
legacy harness selector when the value is a known harness or harness alias.
|
|
30
30
|
- `--all` to install every profile.
|
|
31
31
|
- `--list` to inspect source profiles before installing.
|
|
@@ -36,11 +36,10 @@ Accepted implementation decision:
|
|
|
36
36
|
|
|
37
37
|
- Install scope defaults to project where the target harness supports project-local profiles.
|
|
38
38
|
- Codex is an exception because `codex --profile <name>` loads
|
|
39
|
-
`$CODEX_HOME/<name>.config.toml`.
|
|
40
|
-
local agents live under `$TENEX_EDGE_HOME/agents/` or `~/.tenex-edge/agents/`.
|
|
39
|
+
`$CODEX_HOME/<name>.config.toml`.
|
|
41
40
|
- When no `--harness` or legacy harness-valued `--agent` is provided, the CLI
|
|
42
41
|
detects supported harness CLIs on `PATH` (`codex`, `claude`, `opencode`,
|
|
43
|
-
|
|
42
|
+
and `goose`).
|
|
44
43
|
- If one harness is detected, install to it. If multiple harnesses are detected,
|
|
45
44
|
interactive installs open a checkbox selector with every detected harness
|
|
46
45
|
selected by default; noninteractive, `--json`, and `--yes` installs use every
|
|
@@ -10,7 +10,6 @@ Initial harness targets:
|
|
|
10
10
|
- Claude Code
|
|
11
11
|
- OpenCode
|
|
12
12
|
- Goose
|
|
13
|
-
- tenex-edge
|
|
14
13
|
|
|
15
14
|
## Codex
|
|
16
15
|
|
|
@@ -78,32 +77,9 @@ Goose output is Markdown with YAML frontmatter (`name`, `description`, optional
|
|
|
78
77
|
`model`) and a generated marker. The agent body reuses the Claude Code adapter
|
|
79
78
|
when a Goose-specific adapter is not present.
|
|
80
79
|
|
|
81
|
-
## tenex-edge
|
|
82
|
-
|
|
83
|
-
Generated tenex-edge agents install to:
|
|
84
|
-
|
|
85
|
-
- Project: not supported; tenex-edge agents are machine-local
|
|
86
|
-
- Global: `$TENEX_EDGE_HOME/agents/<profile>.json`, or `~/.tenex-edge/agents/<profile>.json`
|
|
87
|
-
|
|
88
|
-
Run with:
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
tenex-edge launch <profile>
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
The generated JSON is a tenex-edge local agent keystore entry with:
|
|
95
|
-
|
|
96
|
-
- a generated Nostr keypair, preserved across reinstalls
|
|
97
|
-
- `commands` entries with launch argv that load the installed profile, such as
|
|
98
|
-
`codex --profile <profile>` or `claude --agent <profile>`
|
|
99
|
-
- an inline Claude `agent` definition passed by tenex-edge as `--agents` for
|
|
100
|
-
the generated fallback command when no Claude Code profile command is present
|
|
101
|
-
- a byline derived from the profile summary
|
|
102
|
-
|
|
103
80
|
## Adapter Gaps
|
|
104
81
|
|
|
105
82
|
Some source repositories may provide Codex adapters first. Claude Code and
|
|
106
83
|
OpenCode use generated defaults unless a source repository adds native adapters
|
|
107
84
|
for those harnesses. Goose reuses the Claude Code adapter when no Goose-specific
|
|
108
|
-
adapter is present.
|
|
109
|
-
reuses the Claude Code adapter before falling back to the base profile.
|
|
85
|
+
adapter is present.
|
|
@@ -9,7 +9,7 @@ These notes capture what `awesome-agents` is and why it exists.
|
|
|
9
9
|
- Its command structure should mirror `npx skills`, but for agent profiles.
|
|
10
10
|
- It should install profiles from any explicit source repository that follows
|
|
11
11
|
the `agents/<slug>/agent.yaml` source layout.
|
|
12
|
-
- Harness targets are Codex, Claude Code, OpenCode,
|
|
12
|
+
- Harness targets are Codex, Claude Code, OpenCode, and Goose.
|
|
13
13
|
- The package should be published after the scaffold works.
|
|
14
14
|
|
|
15
15
|
## Product Boundary
|
|
@@ -45,7 +45,7 @@ Immediately relevant skills can be declared in the profile definition:
|
|
|
45
45
|
```yaml
|
|
46
46
|
skills:
|
|
47
47
|
- gh-pages-publisher
|
|
48
|
-
-
|
|
48
|
+
- owner/agent-skills release-checklist
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
Bare skill names resolve from the profile directory, then the source checkout,
|
|
@@ -72,6 +72,9 @@ Agent-owned scripts and references should be installed into
|
|
|
72
72
|
`~/.agents/homes/<profile>/references`.
|
|
73
73
|
Declared skills should be installed into
|
|
74
74
|
`~/.agents/homes/<profile>/skills/<skill>`.
|
|
75
|
+
Installed harness profiles receive the exact agent-home, references, and scripts
|
|
76
|
+
paths in their operating context. Source instructions should refer to these resources
|
|
77
|
+
by relative path instead of embedding a harness-specific or checkout-specific path.
|
|
75
78
|
|
|
76
79
|
Profile source files are intentionally under `agents/`, not `skills/`, because
|
|
77
80
|
the source format models agent profiles separately from loadable skills.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "awesome-agents",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Install reusable agent profiles into Codex, Claude Code, OpenCode,
|
|
3
|
+
"version": "0.1.10",
|
|
4
|
+
"description": "Install reusable agent profiles into Codex, Claude Code, OpenCode, and Goose.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"awesome-agents": "bin/awesome-agents.js"
|
package/src/cli.js
CHANGED
|
@@ -17,7 +17,7 @@ export async function run(argv = process.argv) {
|
|
|
17
17
|
const program = new Command();
|
|
18
18
|
program
|
|
19
19
|
.name(PACKAGE_NAME)
|
|
20
|
-
.description("Install reusable agent profiles into Codex, Claude Code, OpenCode,
|
|
20
|
+
.description("Install reusable agent profiles into Codex, Claude Code, OpenCode, and Goose.")
|
|
21
21
|
.version(PACKAGE_VERSION, "-v, --version")
|
|
22
22
|
.helpOption("-h, --help", "Show this help message")
|
|
23
23
|
.showHelpAfterError();
|
|
@@ -142,7 +142,7 @@ function addInstallCommand(program, commandName) {
|
|
|
142
142
|
.argument("[source]", "Local path, GitHub owner/repo, or GitHub URL")
|
|
143
143
|
.description(commandName === "install" ? "Alias for add" : "Install agent profiles from a source")
|
|
144
144
|
.option("-g, --global", "Install globally")
|
|
145
|
-
.option("-p, --project", "Install into the current project; not supported for Codex
|
|
145
|
+
.option("-p, --project", "Install into the current project; not supported for Codex profiles")
|
|
146
146
|
.option("-a, --agent <agents...>", "Agent profile slugs to install; accepts harness names for backward compatibility")
|
|
147
147
|
.option("--harness <harnesses...>", `Target harnesses (${SUPPORTED_AGENTS.join(", ")}, or *)`)
|
|
148
148
|
.option("--target <harnesses...>", "Compatibility alias for --harness")
|
package/src/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const PACKAGE_NAME = "awesome-agents";
|
|
2
|
-
export const PACKAGE_VERSION = "0.1.
|
|
2
|
+
export const PACKAGE_VERSION = "0.1.10";
|
|
3
3
|
export const DEFAULT_AGENT = "codex";
|
|
4
|
-
export const SUPPORTED_AGENTS = ["codex", "claude-code", "opencode", "goose"
|
|
4
|
+
export const SUPPORTED_AGENTS = ["codex", "claude-code", "opencode", "goose"];
|
|
5
5
|
export const REGISTRY_DIRNAME = ".awesome-agents";
|
|
6
6
|
export const REGISTRY_FILENAME = "installed.json";
|
|
7
7
|
export const GENERATED_MARKER = "Generated by awesome-agents";
|
|
@@ -15,10 +15,7 @@ export const AGENT_ALIASES = new Map([
|
|
|
15
15
|
["claudecode", "claude-code"],
|
|
16
16
|
["opencode", "opencode"],
|
|
17
17
|
["open-code", "opencode"],
|
|
18
|
-
["goose", "goose"]
|
|
19
|
-
["tenex", "tenex-edge"],
|
|
20
|
-
["tenex-edge", "tenex-edge"],
|
|
21
|
-
["tenexedge", "tenex-edge"]
|
|
18
|
+
["goose", "goose"]
|
|
22
19
|
]);
|
|
23
20
|
|
|
24
21
|
// The CLI binary used to detect whether a harness is available on PATH.
|
|
@@ -26,6 +23,5 @@ export const HARNESS_COMMANDS = new Map([
|
|
|
26
23
|
["codex", "codex"],
|
|
27
24
|
["claude-code", "claude"],
|
|
28
25
|
["opencode", "opencode"],
|
|
29
|
-
["goose", "goose"]
|
|
30
|
-
["tenex-edge", "tenex-edge"]
|
|
26
|
+
["goose", "goose"]
|
|
31
27
|
]);
|
package/src/help.js
CHANGED
|
@@ -188,13 +188,13 @@ const banner = [
|
|
|
188
188
|
color(" | (_| | (_| | __/ | | | |_\\__ \\ ", codes.bannerB),
|
|
189
189
|
color(" \\__,_|\\__, |\\___|_| |_|\\__|___/ ", codes.bannerA),
|
|
190
190
|
color(" |___/ ", codes.bannerA),
|
|
191
|
-
` ${ui.dim("Operational profiles for Codex, Claude Code, OpenCode,
|
|
191
|
+
` ${ui.dim("Operational profiles for Codex, Claude Code, OpenCode, and Goose")}`
|
|
192
192
|
];
|
|
193
193
|
|
|
194
194
|
const mainHelp = {
|
|
195
195
|
banner,
|
|
196
196
|
usage: `${PACKAGE_NAME} <command> [options]`,
|
|
197
|
-
description: "Install reusable operational agent profiles into Codex, Claude Code, OpenCode,
|
|
197
|
+
description: "Install reusable operational agent profiles into Codex, Claude Code, OpenCode, and Goose.",
|
|
198
198
|
sections: [
|
|
199
199
|
{
|
|
200
200
|
title: "Manage Profiles:",
|
|
@@ -270,7 +270,7 @@ const mainHelp = {
|
|
|
270
270
|
examples: [
|
|
271
271
|
{ command: `${PACKAGE_NAME} add ${exampleSource} --list`, comment: "inspect source profiles" },
|
|
272
272
|
{ command: `${PACKAGE_NAME} add ${exampleSource} --agent ${exampleProfile}` },
|
|
273
|
-
{ command: `${PACKAGE_NAME} add ${exampleSource} --agent ${exampleProfile} --harness
|
|
273
|
+
{ command: `${PACKAGE_NAME} add ${exampleSource} --agent ${exampleProfile} --harness goose` },
|
|
274
274
|
{ command: `${PACKAGE_NAME} add ${exampleSource} --all --dry-run`, comment: "preview every write" },
|
|
275
275
|
{ command: `${PACKAGE_NAME} use ${exampleSource}@${exampleProfile} --harness claude-code` },
|
|
276
276
|
{ command: `${PACKAGE_NAME} list --json`, comment: "machine-readable output" },
|
|
@@ -290,7 +290,7 @@ const commandHelp = {
|
|
|
290
290
|
rows: [
|
|
291
291
|
"1. Read canonical definitions from agents/<slug>/agent.yaml or compatible variants.",
|
|
292
292
|
"2. Install agent-owned scripts, references, and declared skills into ~/.agents/homes/<slug>/.",
|
|
293
|
-
"3. Render Codex, Claude Code, OpenCode,
|
|
293
|
+
"3. Render Codex, Claude Code, OpenCode, or Goose files and record them in the registry."
|
|
294
294
|
]
|
|
295
295
|
},
|
|
296
296
|
{
|
|
@@ -318,7 +318,7 @@ const commandHelp = {
|
|
|
318
318
|
rows: [
|
|
319
319
|
{ term: ui.option("(auto-detect)"), description: "Every harness detected on PATH; interactive multi-detect opens a checked selector; pass --harness when none are detected" },
|
|
320
320
|
{ term: ui.option("--harness opencode"), description: "Render for one harness" },
|
|
321
|
-
{ term: ui.option("--harness codex
|
|
321
|
+
{ term: ui.option("--harness codex goose"), description: "Render for multiple harnesses" },
|
|
322
322
|
{ term: ui.option("--harness *"), description: "Render for every supported harness" },
|
|
323
323
|
{ term: ui.option("--global"), description: "Install into the user-level harness directory" },
|
|
324
324
|
{ term: ui.option("--project"), description: "Install project-local files where the harness supports it" }
|
|
@@ -331,7 +331,6 @@ const commandHelp = {
|
|
|
331
331
|
{ term: ui.command("claude-code"), description: `${ui.path("~/.claude/agents/<profile>.md")} or ${ui.path(".claude/agents/<profile>.md")}` },
|
|
332
332
|
{ term: ui.command("opencode"), description: `${ui.path("~/.config/opencode/agents/<profile>.md")} or ${ui.path(".opencode/agents/<profile>.md")}` },
|
|
333
333
|
{ term: ui.command("goose"), description: `${ui.path("~/.agents/agents/<profile>.md")} or ${ui.path(".agents/agents/<profile>.md")}` },
|
|
334
|
-
{ term: ui.command("tenex-edge"), description: `${ui.path("~/.tenex-edge/agents/<profile>.json")} (project-local tenex-edge agents are not supported)` },
|
|
335
334
|
{ term: ui.command("registry"), description: `${ui.path("~/.awesome-agents/installed.json")} or ${ui.path(".awesome-agents/installed.json")}` }
|
|
336
335
|
]
|
|
337
336
|
},
|
|
@@ -349,7 +348,7 @@ const commandHelp = {
|
|
|
349
348
|
examples: [
|
|
350
349
|
{ command: `${PACKAGE_NAME} add ${exampleSource} --list` },
|
|
351
350
|
{ command: `${PACKAGE_NAME} add ${exampleSource} --agent ${exampleProfile}` },
|
|
352
|
-
{ command: `${PACKAGE_NAME} add ${exampleSource} --agent ${exampleProfile} --harness codex
|
|
351
|
+
{ command: `${PACKAGE_NAME} add ${exampleSource} --agent ${exampleProfile} --harness codex goose` },
|
|
353
352
|
{ command: `${PACKAGE_NAME} add ${exampleSource} --all --dry-run` }
|
|
354
353
|
],
|
|
355
354
|
footer: `Generated files are marked with ${ui.profile("Generated by awesome-agents")}.`
|
|
@@ -452,7 +451,7 @@ const commandHelp = {
|
|
|
452
451
|
function installOptions({ includeHome = false } = {}) {
|
|
453
452
|
return compact([
|
|
454
453
|
{ term: ui.option("-g, --global"), description: "Install globally instead of into the current project" },
|
|
455
|
-
{ term: ui.option("-p, --project"), description: "Install into the current project; not supported for Codex
|
|
454
|
+
{ term: ui.option("-p, --project"), description: "Install into the current project; not supported for Codex profiles" },
|
|
456
455
|
{ term: ui.option("-a, --agent <profiles...>"), description: "Select agent profile slugs; harness names still work for compatibility" },
|
|
457
456
|
{ term: ui.option("--harness <harnesses...>"), description: `Select target harnesses: ${harnesses}, or *` },
|
|
458
457
|
{ term: ui.option("-s, --profile <profiles...>"), description: "Explicit profile selector; accepts *" },
|
package/src/installer.js
CHANGED
|
@@ -36,10 +36,17 @@ export async function installFromSource(sourceSpec, options = {}) {
|
|
|
36
36
|
const installedAt = new Date().toISOString();
|
|
37
37
|
|
|
38
38
|
for (const profile of profiles) {
|
|
39
|
+
const agentHome = resolveAgentHome(profile, options);
|
|
39
40
|
const supportTargets = await installProfileSupport(profile, options);
|
|
41
|
+
const supportRoots = (profile.supportDirs ?? []).map((supportDir) => ({
|
|
42
|
+
kind: supportDir.kind,
|
|
43
|
+
path: path.join(agentHome, supportDir.kind)
|
|
44
|
+
}));
|
|
40
45
|
const installedSkills = await installProfileSkills(profile, materialized.path, options);
|
|
41
46
|
const renderProfile = {
|
|
42
47
|
...profile,
|
|
48
|
+
agentHome,
|
|
49
|
+
supportRoots,
|
|
43
50
|
installedSkills
|
|
44
51
|
};
|
|
45
52
|
for (const harness of harnesses) {
|
|
@@ -63,6 +70,8 @@ export async function installFromSource(sourceSpec, options = {}) {
|
|
|
63
70
|
target,
|
|
64
71
|
installedAt,
|
|
65
72
|
contentSha256: contentHash(content),
|
|
73
|
+
agentHome,
|
|
74
|
+
supportRoots,
|
|
66
75
|
supportTargets,
|
|
67
76
|
skillTargets: installedSkills.map((skill) => skill.path),
|
|
68
77
|
installedSkills,
|
|
@@ -253,8 +262,7 @@ async function installProfileSupport(profile, options = {}) {
|
|
|
253
262
|
return [];
|
|
254
263
|
}
|
|
255
264
|
|
|
256
|
-
const
|
|
257
|
-
const agentHome = path.join(home, ".agents", "homes", profile.slug);
|
|
265
|
+
const agentHome = resolveAgentHome(profile, options);
|
|
258
266
|
const targets = [];
|
|
259
267
|
|
|
260
268
|
for (const supportDir of profile.supportDirs) {
|
|
@@ -273,6 +281,11 @@ async function installProfileSupport(profile, options = {}) {
|
|
|
273
281
|
return targets;
|
|
274
282
|
}
|
|
275
283
|
|
|
284
|
+
function resolveAgentHome(profile, options = {}) {
|
|
285
|
+
const home = path.resolve(expandHome(options.home ?? os.homedir()));
|
|
286
|
+
return path.join(home, ".agents", "homes", profile.slug);
|
|
287
|
+
}
|
|
288
|
+
|
|
276
289
|
async function listFilesRecursive(root) {
|
|
277
290
|
const entries = await fs.readdir(root, { withFileTypes: true });
|
|
278
291
|
const files = [];
|
|
@@ -369,20 +382,6 @@ function runInstructionForOperation(operation, env) {
|
|
|
369
382
|
};
|
|
370
383
|
}
|
|
371
384
|
|
|
372
|
-
if (operation.harness === "tenex-edge") {
|
|
373
|
-
if (!commandExists("tenex-edge", env)) {
|
|
374
|
-
return undefined;
|
|
375
|
-
}
|
|
376
|
-
return {
|
|
377
|
-
profile: operation.profile,
|
|
378
|
-
name: operation.name,
|
|
379
|
-
summary: operation.summary,
|
|
380
|
-
harness: operation.harness,
|
|
381
|
-
command: `tenex-edge launch ${shellWord(operation.profile)}`,
|
|
382
|
-
note: "Starts this profile as a tenex-edge-managed Claude Code agent."
|
|
383
|
-
};
|
|
384
|
-
}
|
|
385
|
-
|
|
386
385
|
return undefined;
|
|
387
386
|
}
|
|
388
387
|
|
|
@@ -513,16 +512,13 @@ function resolveScope(options = {}, harnesses = []) {
|
|
|
513
512
|
if (options.project && harnesses.includes("codex")) {
|
|
514
513
|
throw new Error("Codex profiles are loaded from $CODEX_HOME/<name>.config.toml and cannot be installed project-locally. Use --global or choose a different harness.");
|
|
515
514
|
}
|
|
516
|
-
if (options.project && harnesses.includes("tenex-edge")) {
|
|
517
|
-
throw new Error("tenex-edge agents are machine-local under $TENEX_EDGE_HOME/agents or ~/.tenex-edge/agents and cannot be installed project-locally. Use --global or choose a different harness.");
|
|
518
|
-
}
|
|
519
515
|
if (options.global) {
|
|
520
516
|
return "global";
|
|
521
517
|
}
|
|
522
518
|
if (options.project) {
|
|
523
519
|
return "project";
|
|
524
520
|
}
|
|
525
|
-
if (harnesses.includes("codex")
|
|
521
|
+
if (harnesses.includes("codex")) {
|
|
526
522
|
return "global";
|
|
527
523
|
}
|
|
528
524
|
return "project";
|
package/src/renderers.js
CHANGED
|
@@ -44,9 +44,6 @@ export function renderForAgent(profile, agent, context) {
|
|
|
44
44
|
if (normalized === "goose") {
|
|
45
45
|
return renderGoose(profile, context);
|
|
46
46
|
}
|
|
47
|
-
if (normalized === "tenex-edge") {
|
|
48
|
-
return renderTenexEdge(profile, context);
|
|
49
|
-
}
|
|
50
47
|
throw new Error(`Unsupported agent "${agent}"`);
|
|
51
48
|
}
|
|
52
49
|
|
|
@@ -104,15 +101,6 @@ export function resolveTargetPath(profile, agent, options = {}) {
|
|
|
104
101
|
return path.join(gooseHome, "agents", `${profile.slug}.md`);
|
|
105
102
|
}
|
|
106
103
|
|
|
107
|
-
if (normalized === "tenex-edge") {
|
|
108
|
-
const tenexEdgeHome = options.tenexEdgeHome
|
|
109
|
-
? path.resolve(expandHome(options.tenexEdgeHome, home))
|
|
110
|
-
: process.env.TENEX_EDGE_HOME
|
|
111
|
-
? path.resolve(expandHome(process.env.TENEX_EDGE_HOME, home))
|
|
112
|
-
: path.join(home, ".tenex-edge");
|
|
113
|
-
return path.join(tenexEdgeHome, "agents", `${profile.slug}.json`);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
104
|
throw new Error(`Unsupported agent "${agent}"`);
|
|
117
105
|
}
|
|
118
106
|
|
|
@@ -201,84 +189,6 @@ function renderGoose(profile, context) {
|
|
|
201
189
|
return stringifyFrontmatter(attributes, `${marker}\n\n${buildInstructionBody(profile, profile.adapters.goose ?? profile.adapters["claude-code"], "goose")}`);
|
|
202
190
|
}
|
|
203
191
|
|
|
204
|
-
function renderTenexEdge(profile, context) {
|
|
205
|
-
const existing = tenexEdgeKeyMaterial(context.existingContent);
|
|
206
|
-
const keyMaterial = existing ?? generateNostrKeypair();
|
|
207
|
-
const commands = tenexEdgeCommands(profile, context);
|
|
208
|
-
const agent = tenexEdgeInlineAgent(profile);
|
|
209
|
-
|
|
210
|
-
const stored = {
|
|
211
|
-
slug: profile.slug,
|
|
212
|
-
secret_key: keyMaterial.secret_key,
|
|
213
|
-
public_key: keyMaterial.public_key,
|
|
214
|
-
created_at: keyMaterial.created_at ?? Math.floor(Date.now() / 1000),
|
|
215
|
-
commands,
|
|
216
|
-
byline: profile.summary || profile.name,
|
|
217
|
-
managed_by: GENERATED_MARKER,
|
|
218
|
-
source: context.source
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
if (hasInlineClaudeCommand(commands)) {
|
|
222
|
-
stored.agent = agent;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return `${JSON.stringify(stored, null, 2)}\n`;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function tenexEdgeInlineAgent(profile) {
|
|
229
|
-
const agent = {
|
|
230
|
-
description: profile.summary || profile.name,
|
|
231
|
-
prompt: buildInstructionBody(profile, profile.adapters["tenex-edge"] ?? profile.adapters["claude-code"], "tenex-edge")
|
|
232
|
-
};
|
|
233
|
-
const model = chooseClaudeModel(profile);
|
|
234
|
-
const effort = profile.attributes.recommended_reasoning_effort;
|
|
235
|
-
|
|
236
|
-
if (model && model !== "inherit") {
|
|
237
|
-
agent.model = model;
|
|
238
|
-
}
|
|
239
|
-
if (effort && effort !== "inherit" && ["low", "medium", "high", "xhigh", "max"].includes(effort)) {
|
|
240
|
-
agent.effort = effort;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return agent;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
function tenexEdgeCommands(profile, context) {
|
|
247
|
-
const commands = [];
|
|
248
|
-
for (const harness of arrayify(context.selectedHarnesses)) {
|
|
249
|
-
if (harness === "codex") {
|
|
250
|
-
commands.push({
|
|
251
|
-
name: "codex",
|
|
252
|
-
argv: ["codex", "--profile", profile.slug]
|
|
253
|
-
});
|
|
254
|
-
} else if (harness === "claude-code") {
|
|
255
|
-
commands.push({
|
|
256
|
-
name: "claude",
|
|
257
|
-
argv: ["claude", "--agent", profile.slug]
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Keep tenex-edge-only installs self-contained. tenex-edge expands this with
|
|
263
|
-
// the inline `agent` definition as `claude --agents ... --agent <slug>`.
|
|
264
|
-
if (!commands.some((command) => command.name === "claude")) {
|
|
265
|
-
commands.push({
|
|
266
|
-
name: "claude",
|
|
267
|
-
argv: ["claude"]
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
return uniqueBy(commands, (command) => command.name);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function hasInlineClaudeCommand(commands) {
|
|
275
|
-
return commands.some((command) => (
|
|
276
|
-
command.name === "claude" &&
|
|
277
|
-
command.argv.length === 1 &&
|
|
278
|
-
command.argv[0] === "claude"
|
|
279
|
-
));
|
|
280
|
-
}
|
|
281
|
-
|
|
282
192
|
function buildInstructionBody(profile, adapter, harness) {
|
|
283
193
|
const parts = [
|
|
284
194
|
profile.body.trimEnd(),
|
|
@@ -290,9 +200,24 @@ function buildInstructionBody(profile, adapter, harness) {
|
|
|
290
200
|
`- Installed for: \`${harness}\``,
|
|
291
201
|
"- When asked who you are, what agent is running, or what role you are acting as, answer with this identity and role.",
|
|
292
202
|
"- This profile is a reusable operational agent profile, not a skill or local machine setup.",
|
|
293
|
-
|
|
203
|
+
profile.agentHome
|
|
204
|
+
? `- Agent home: \`${profile.agentHome}\``
|
|
205
|
+
: "- This render-only output does not install an agent home or support material."
|
|
294
206
|
];
|
|
295
207
|
|
|
208
|
+
if (profile.supportRoots?.length) {
|
|
209
|
+
parts.push(
|
|
210
|
+
"",
|
|
211
|
+
"## Agent-Owned Support",
|
|
212
|
+
"",
|
|
213
|
+
"Use these installed resources when the operating procedure calls for them. Resolve relative support paths against these roots.",
|
|
214
|
+
""
|
|
215
|
+
);
|
|
216
|
+
for (const support of profile.supportRoots) {
|
|
217
|
+
parts.push(`- \`${support.kind}\`: \`${support.path}\``);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
296
221
|
if (profile.installedSkills?.length) {
|
|
297
222
|
const skillBase = path.join(path.dirname(profile.installedSkills[0].path), "<skill>");
|
|
298
223
|
parts.push(
|
|
@@ -374,57 +299,6 @@ function chooseGooseModel(profile) {
|
|
|
374
299
|
return undefined;
|
|
375
300
|
}
|
|
376
301
|
|
|
377
|
-
function tenexEdgeKeyMaterial(content) {
|
|
378
|
-
if (!content) {
|
|
379
|
-
return undefined;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
let parsed;
|
|
383
|
-
try {
|
|
384
|
-
parsed = JSON.parse(content);
|
|
385
|
-
} catch {
|
|
386
|
-
return undefined;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
if (!isHex64(parsed.secret_key)) {
|
|
390
|
-
return undefined;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
const derived = derivePublicKey(parsed.secret_key);
|
|
394
|
-
if (!derived) {
|
|
395
|
-
return undefined;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return {
|
|
399
|
-
secret_key: parsed.secret_key,
|
|
400
|
-
public_key: isHex64(parsed.public_key) ? parsed.public_key : derived,
|
|
401
|
-
created_at: Number.isInteger(parsed.created_at) ? parsed.created_at : undefined
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
function generateNostrKeypair() {
|
|
406
|
-
const ecdh = crypto.createECDH("secp256k1");
|
|
407
|
-
const publicKey = ecdh.generateKeys(undefined, "uncompressed");
|
|
408
|
-
return {
|
|
409
|
-
secret_key: ecdh.getPrivateKey("hex"),
|
|
410
|
-
public_key: publicKey.subarray(1, 33).toString("hex")
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
function derivePublicKey(secretKey) {
|
|
415
|
-
try {
|
|
416
|
-
const ecdh = crypto.createECDH("secp256k1");
|
|
417
|
-
ecdh.setPrivateKey(Buffer.from(secretKey, "hex"));
|
|
418
|
-
return ecdh.getPublicKey(undefined, "uncompressed").subarray(1, 33).toString("hex");
|
|
419
|
-
} catch {
|
|
420
|
-
return undefined;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
function isHex64(value) {
|
|
425
|
-
return typeof value === "string" && /^[0-9a-fA-F]{64}$/.test(value);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
302
|
function tomlString(value) {
|
|
429
303
|
return JSON.stringify(String(value));
|
|
430
304
|
}
|
|
@@ -455,20 +329,6 @@ function arrayify(value) {
|
|
|
455
329
|
return [value];
|
|
456
330
|
}
|
|
457
331
|
|
|
458
|
-
function uniqueBy(values, keyForValue) {
|
|
459
|
-
const seen = new Set();
|
|
460
|
-
const out = [];
|
|
461
|
-
for (const value of values) {
|
|
462
|
-
const key = keyForValue(value);
|
|
463
|
-
if (seen.has(key)) {
|
|
464
|
-
continue;
|
|
465
|
-
}
|
|
466
|
-
seen.add(key);
|
|
467
|
-
out.push(value);
|
|
468
|
-
}
|
|
469
|
-
return out;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
332
|
function flattenValues(values) {
|
|
473
333
|
return arrayify(values)
|
|
474
334
|
.flatMap((value) => String(value).split(","))
|
package/src/skills.js
CHANGED
|
@@ -27,26 +27,38 @@ export async function installProfileSkills(profile, sourceRoot, options = {}) {
|
|
|
27
27
|
const installed = [];
|
|
28
28
|
|
|
29
29
|
for (const dependency of dependencies) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
await fs.cp(skill.path, target, {
|
|
37
|
-
recursive: true,
|
|
38
|
-
dereference: true,
|
|
39
|
-
preserveTimestamps: true
|
|
40
|
-
});
|
|
30
|
+
let resolved;
|
|
31
|
+
try {
|
|
32
|
+
resolved = await resolveSkillDependency(profile, dependency, sourceRoot, home, options);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.warn(`Skipping skill "${dependency.selector ?? dependency.source}" for profile "${profile.slug}": ${error.message}`);
|
|
35
|
+
continue;
|
|
41
36
|
}
|
|
42
37
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
const { skill, cleanup } = resolved;
|
|
39
|
+
try {
|
|
40
|
+
const target = path.join(home, ".agents", "homes", profile.slug, "skills", skill.installName);
|
|
41
|
+
|
|
42
|
+
if (!options.dryRun) {
|
|
43
|
+
await fs.rm(target, { recursive: true, force: true });
|
|
44
|
+
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
45
|
+
await fs.cp(skill.path, target, {
|
|
46
|
+
recursive: true,
|
|
47
|
+
dereference: true,
|
|
48
|
+
preserveTimestamps: true
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
installed.push({
|
|
53
|
+
name: skill.installName,
|
|
54
|
+
declaredName: dependency.selector ?? dependency.source ?? skill.name,
|
|
55
|
+
source: skill.source,
|
|
56
|
+
sourceKind: skill.sourceKind,
|
|
57
|
+
path: target
|
|
58
|
+
});
|
|
59
|
+
} finally {
|
|
60
|
+
await cleanup();
|
|
61
|
+
}
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
return installed;
|
|
@@ -115,6 +127,8 @@ function looksLikeRemoteSource(value) {
|
|
|
115
127
|
return value.includes("/") || value.includes(":") || value.startsWith("~") || value.startsWith(".");
|
|
116
128
|
}
|
|
117
129
|
|
|
130
|
+
const NOOP_CLEANUP = async () => {};
|
|
131
|
+
|
|
118
132
|
async function resolveSkillDependency(profile, dependency, sourceRoot, home, options) {
|
|
119
133
|
if (dependency.source) {
|
|
120
134
|
const materialized = await materializeSource(dependency.source, {
|
|
@@ -122,13 +136,15 @@ async function resolveSkillDependency(profile, dependency, sourceRoot, home, opt
|
|
|
122
136
|
requireAgentProfileLayout: false
|
|
123
137
|
});
|
|
124
138
|
try {
|
|
125
|
-
|
|
139
|
+
const skill = await selectSkillFromRoot(materialized.path, dependency.selector, {
|
|
126
140
|
dependency,
|
|
127
141
|
source: materialized.source,
|
|
128
142
|
sourceKind: materialized.kind
|
|
129
143
|
});
|
|
130
|
-
|
|
144
|
+
return { skill, cleanup: materialized.cleanup };
|
|
145
|
+
} catch (error) {
|
|
131
146
|
await materialized.cleanup();
|
|
147
|
+
throw error;
|
|
132
148
|
}
|
|
133
149
|
}
|
|
134
150
|
|
|
@@ -138,7 +154,7 @@ async function resolveSkillDependency(profile, dependency, sourceRoot, home, opt
|
|
|
138
154
|
sourceKind: "profile-local"
|
|
139
155
|
});
|
|
140
156
|
if (profileSkill) {
|
|
141
|
-
return profileSkill;
|
|
157
|
+
return { skill: profileSkill, cleanup: NOOP_CLEANUP };
|
|
142
158
|
}
|
|
143
159
|
|
|
144
160
|
const sourceSkill = await findSkillInRoot(sourceRoot, dependency.selector, {
|
|
@@ -147,7 +163,7 @@ async function resolveSkillDependency(profile, dependency, sourceRoot, home, opt
|
|
|
147
163
|
sourceKind: "local-source"
|
|
148
164
|
});
|
|
149
165
|
if (sourceSkill) {
|
|
150
|
-
return sourceSkill;
|
|
166
|
+
return { skill: sourceSkill, cleanup: NOOP_CLEANUP };
|
|
151
167
|
}
|
|
152
168
|
|
|
153
169
|
const userSkillRoot = path.join(home, ".agents", "skills");
|
|
@@ -157,7 +173,7 @@ async function resolveSkillDependency(profile, dependency, sourceRoot, home, opt
|
|
|
157
173
|
sourceKind: "user-skills"
|
|
158
174
|
});
|
|
159
175
|
if (userSkill) {
|
|
160
|
-
return userSkill;
|
|
176
|
+
return { skill: userSkill, cleanup: NOOP_CLEANUP };
|
|
161
177
|
}
|
|
162
178
|
|
|
163
179
|
throw new Error(`Skill "${dependency.selector}" was not found in the profile source or ${userSkillRoot}.`);
|
|
@@ -246,7 +262,13 @@ async function discoverSkills(root) {
|
|
|
246
262
|
return true;
|
|
247
263
|
}
|
|
248
264
|
|
|
249
|
-
|
|
265
|
+
let skill;
|
|
266
|
+
try {
|
|
267
|
+
skill = await readSkill(skillDir, root);
|
|
268
|
+
} catch (error) {
|
|
269
|
+
console.warn(`Skipping unreadable skill at ${skillDir}: ${error.message}`);
|
|
270
|
+
return true;
|
|
271
|
+
}
|
|
250
272
|
if (seenNames.has(skill.installName)) {
|
|
251
273
|
return true;
|
|
252
274
|
}
|