awesome-agents 0.1.6 → 0.1.9
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 +52 -0
- package/README.md +11 -4
- package/docs/cli.md +8 -3
- package/docs/plans/public-builder-profiles-agent-model-cards/plan.md +105 -0
- package/docs/product/README.md +2 -1
- package/docs/product/command-model.md +4 -4
- package/docs/product/harness-targets.md +30 -3
- package/docs/product/open-questions.md +6 -0
- package/docs/product/product-scope.md +1 -1
- package/docs/product/profile-source-format.md +15 -0
- package/docs/product/site-profiles-and-model-cards.md +135 -0
- package/package.json +3 -2
- package/scripts/release.js +0 -4
- package/src/cli.js +1 -1
- package/src/constants.js +4 -2
- package/src/help.js +4 -3
- package/src/installer.js +31 -3
- package/src/renderers.js +139 -13
- package/src/skills.js +46 -24
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,58 @@
|
|
|
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.9 - 2026-07-16
|
|
6
|
+
|
|
7
|
+
Changes since `v0.1.8`.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Add create-agent-profile skill (f5dcfe0)
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Expose agent-owned support to installed profiles (#12) (832094e)
|
|
16
|
+
- Name awesome-agents profiles directly (9640910)
|
|
17
|
+
- Remove agents nav link (3ad6bb3)
|
|
18
|
+
- Restore coral site accent (ba2ec5c)
|
|
19
|
+
- Refresh site agent directory (2268134)
|
|
20
|
+
- Make skill dependency resolution fault-tolerant instead of fatal (78aea64)
|
|
21
|
+
|
|
22
|
+
## 0.1.8 - 2026-07-08
|
|
23
|
+
|
|
24
|
+
Changes since `v0.1.6`.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- Add "What is an agent?" marketing page and link it site-wide (fa8255e)
|
|
29
|
+
- Add Goose to site harness surfaces (7a444cf)
|
|
30
|
+
- Add Goose harness support (#9) (c4049f2)
|
|
31
|
+
- Add public builder profile prototype (e78202e)
|
|
32
|
+
- Add plan for public-builder-profiles-agent-model-cards (64e254a)
|
|
33
|
+
- Add generated docs site (8eb21ba)
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Prepare 0.1.7 release (342e93d)
|
|
38
|
+
- Link hosted artifacts for public-builder-profiles-agent-model-cards (0f76238)
|
|
39
|
+
- Update tenex-edge launch commands (cc304e2)
|
|
40
|
+
|
|
41
|
+
### Documentation
|
|
42
|
+
|
|
43
|
+
- rebuild /docs in the shadcn-docs layout (878803c)
|
|
44
|
+
|
|
45
|
+
## 0.1.7 - 2026-07-07
|
|
46
|
+
|
|
47
|
+
Changes since `v0.1.6`.
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
|
|
51
|
+
- Add generated docs site (8eb21ba)
|
|
52
|
+
|
|
53
|
+
### Changed
|
|
54
|
+
|
|
55
|
+
- Update tenex-edge launch commands (cc304e2)
|
|
56
|
+
|
|
5
57
|
## 0.1.6 - 2026-07-06
|
|
6
58
|
|
|
7
59
|
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, or tenex-edge.
|
|
10
|
+
right place for Codex, Claude Code, OpenCode, Goose, or tenex-edge.
|
|
11
11
|
|
|
12
12
|
## Install And Run
|
|
13
13
|
|
|
@@ -46,7 +46,7 @@ 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|tenex-edge|*` to select target harnesses;
|
|
49
|
+
- `--harness codex|claude-code|opencode|goose|tenex-edge|*` 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
|
|
@@ -60,8 +60,8 @@ Useful install options:
|
|
|
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
|
-
`tenex-edge launch <profile>`.
|
|
63
|
+
`codex --profile <profile>`, `claude --agent <profile>`,
|
|
64
|
+
`tenex-edge launch <profile>`, or `goose session` then `@<profile>`.
|
|
65
65
|
|
|
66
66
|
## Harness Targets
|
|
67
67
|
|
|
@@ -70,6 +70,7 @@ Project installs write to:
|
|
|
70
70
|
- Codex: not supported; Codex profiles load from user config
|
|
71
71
|
- Claude Code: `.claude/agents/<profile>.md`
|
|
72
72
|
- OpenCode: `.opencode/agents/<profile>.md`
|
|
73
|
+
- Goose: `.agents/agents/<profile>.md`
|
|
73
74
|
- tenex-edge: not supported; tenex-edge agents are machine-local
|
|
74
75
|
|
|
75
76
|
Global installs write to:
|
|
@@ -77,6 +78,7 @@ Global installs write to:
|
|
|
77
78
|
- Codex: `$CODEX_HOME/<profile>.config.toml`, or `~/.codex/<profile>.config.toml`
|
|
78
79
|
- Claude Code: `$CLAUDE_HOME/agents/<profile>.md`, or `~/.claude/agents/<profile>.md`
|
|
79
80
|
- OpenCode: `$OPENCODE_CONFIG_DIR/agents/<profile>.md`, or `~/.config/opencode/agents/<profile>.md`
|
|
81
|
+
- Goose: `$GOOSE_HOME/agents/<profile>.md`, or `~/.agents/agents/<profile>.md`
|
|
80
82
|
- tenex-edge: `$TENEX_EDGE_HOME/agents/<profile>.json`, or `~/.tenex-edge/agents/<profile>.json`
|
|
81
83
|
|
|
82
84
|
The CLI keeps its own registry at `.awesome-agents/installed.json` for project
|
|
@@ -84,6 +86,11 @@ installs or `~/.awesome-agents/installed.json` for global installs. `list`,
|
|
|
84
86
|
`remove`, and `update` use this registry and refuse to overwrite or delete files
|
|
85
87
|
that do not contain the generated marker unless `--force` is passed.
|
|
86
88
|
|
|
89
|
+
Agent-owned references and scripts are installed under
|
|
90
|
+
`~/.agents/homes/<profile>/`. Every installed harness profile receives the exact
|
|
91
|
+
agent-home and support-root paths in its operating context, so profile instructions
|
|
92
|
+
can refer to bundled resources by relative path without becoming harness-specific.
|
|
93
|
+
|
|
87
94
|
Run Codex profiles with:
|
|
88
95
|
|
|
89
96
|
```bash
|
package/docs/cli.md
CHANGED
|
@@ -19,7 +19,9 @@ all detected selections without prompting. Installs default to project scope
|
|
|
19
19
|
where the selected harness supports project-local profiles. Codex and tenex-edge
|
|
20
20
|
are exceptions: Codex `--profile` loads named config layers from `CODEX_HOME`,
|
|
21
21
|
while tenex-edge agents live in its machine keystore under
|
|
22
|
-
`$TENEX_EDGE_HOME/agents/` or `~/.tenex-edge/agents/`.
|
|
22
|
+
`$TENEX_EDGE_HOME/agents/` or `~/.tenex-edge/agents/`. Goose uses
|
|
23
|
+
`~/.agents/agents/<profile>.md` (global) or `.agents/agents/<profile>.md`
|
|
24
|
+
(project).
|
|
23
25
|
|
|
24
26
|
## Source Resolution
|
|
25
27
|
|
|
@@ -57,11 +59,11 @@ npx awesome-agents add owner/repo --agent triage-agent --harness opencode
|
|
|
57
59
|
```
|
|
58
60
|
|
|
59
61
|
For backward compatibility, `--agent codex`, `--agent claude-code`,
|
|
60
|
-
`--agent opencode`, and `--agent tenex-edge` are still accepted as harness
|
|
62
|
+
`--agent opencode`, `--agent goose`, and `--agent tenex-edge` are still accepted as harness
|
|
61
63
|
selectors.
|
|
62
64
|
|
|
63
65
|
When no harness selector is provided, `add` detects `codex`, `claude`,
|
|
64
|
-
`opencode`, and `tenex-edge` on `PATH`. If none are found, the command fails and
|
|
66
|
+
`opencode`, `goose`, and `tenex-edge` on `PATH`. If none are found, the command fails and
|
|
65
67
|
asks for `--harness`.
|
|
66
68
|
|
|
67
69
|
When no profile selector is provided in an interactive terminal, `add` prompts
|
|
@@ -83,9 +85,12 @@ installed profile through any matching harness CLI found on `PATH`. Examples:
|
|
|
83
85
|
```bash
|
|
84
86
|
codex --profile triage-agent
|
|
85
87
|
claude --agent triage-agent
|
|
88
|
+
goose session
|
|
86
89
|
tenex-edge launch triage-agent
|
|
87
90
|
```
|
|
88
91
|
|
|
92
|
+
For Goose, start `goose session` and invoke the agent by name with `@<profile>`.
|
|
93
|
+
|
|
89
94
|
## Install Safety
|
|
90
95
|
|
|
91
96
|
Generated files contain the marker `Generated by awesome-agents`. The CLI refuses
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Public Builder Profiles And Agent Model Cards
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
Add the first public site slice for builder profiles and repository-scoped agent model cards, using GitHub identity assumptions and README-backed content where available while keeping the CLI source format repo-neutral.
|
|
6
|
+
|
|
7
|
+
## Boundaries
|
|
8
|
+
|
|
9
|
+
```mermaid
|
|
10
|
+
flowchart LR
|
|
11
|
+
GitHub[GitHub identity] --> Builder[Builder profile /handle]
|
|
12
|
+
Repo[Agent source repo] --> AgentYaml[agents/slug/agent.yaml]
|
|
13
|
+
Repo --> Readme[optional agents/slug/README.md]
|
|
14
|
+
AgentYaml --> Card[Model card route]
|
|
15
|
+
Readme --> Card
|
|
16
|
+
Builder --> Card
|
|
17
|
+
Card --> Install[npx awesome-agents add owner/repo --agent slug]
|
|
18
|
+
User[Logged-in user] --> Reviews[Reviews later persisted by backend]
|
|
19
|
+
Reviews --> Card
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Detailed Plan
|
|
23
|
+
|
|
24
|
+
## Summary
|
|
25
|
+
|
|
26
|
+
Implement the first public social-profile slice for `awesome-agents.com`: a builder profile route and repository-scoped agent model-card route. Keep it frontend-first and static-data-backed in this repo, while documenting the future backend contract for GitHub login, handle claiming, ownership verification, and reviews.
|
|
27
|
+
|
|
28
|
+
## Implementation Scope
|
|
29
|
+
|
|
30
|
+
1. Add site data structures for builders, repos, and agent cards.
|
|
31
|
+
2. Add `/pablof7z` style builder route support through `site/vercel.json` rewrites and a static page/controller.
|
|
32
|
+
3. Add `/pablof7z/touch-grass/chief-of-staff` style model-card route support.
|
|
33
|
+
4. Preserve the existing `/agents/:slug` page as compatibility or redirect-like behavior where practical.
|
|
34
|
+
5. Render optional README-backed model-card content when available in seeded data; render generated fallback sections when absent.
|
|
35
|
+
6. Add visible login/claim/review affordances as nonfunctional or mocked states only if clearly labeled by behavior, not by insecure fake auth.
|
|
36
|
+
7. Use the requested high-design frontend direction for the profile/model-card surfaces while keeping controls usable and text readable.
|
|
37
|
+
|
|
38
|
+
## Backend Boundary
|
|
39
|
+
|
|
40
|
+
Future GitHub auth should request basic profile and email access only, such as `read:user` plus `user:email`. The persisted user identity should include GitHub id, login, display name, avatar URL, and verified email where available. Handle claims are first-come-first-served. Repo ownership verification should be done through GitHub identity or GitHub App installation, not through user-entered claims alone. Reviews should require login; MVP has no spam filtering.
|
|
41
|
+
|
|
42
|
+
## Rollout
|
|
43
|
+
|
|
44
|
+
Ship the static route/content slice first. Keep existing directory links working. Once the UX holds up, add backend endpoints for auth callback, session, handle claims, repo imports, and review creation.
|
|
45
|
+
|
|
46
|
+
## Validation
|
|
47
|
+
|
|
48
|
+
Run `npm run lint` and `npm test` for the Node package. For site work, serve `site/` locally and inspect desktop and mobile routes with Playwright or a browser. Verify no horizontal overflow, route rewrites resolve, copy buttons still work, and old `/agents/:slug` pages are not broken.
|
|
49
|
+
|
|
50
|
+
## Rollback
|
|
51
|
+
|
|
52
|
+
Because the first slice is static, rollback is removing the new site page/controller/data entries and rewrites. CLI behavior should remain unaffected.
|
|
53
|
+
|
|
54
|
+
## Observability
|
|
55
|
+
|
|
56
|
+
No runtime observability is needed for the static slice. Future backend work should log OAuth callback failures, handle-claim conflicts, repo import failures, and review creation outcomes without logging tokens or private email values unnecessarily.
|
|
57
|
+
|
|
58
|
+
## Migration
|
|
59
|
+
|
|
60
|
+
No data migration is required for the first slice. Future migration should reserve existing GitHub usernames as default handles only when a user signs in or claims them, because handle policy is first-come-first-served.
|
|
61
|
+
|
|
62
|
+
## Risks
|
|
63
|
+
|
|
64
|
+
The main risk is making the prototype look like real auth or real persisted reviews. Keep those boundaries visually clear. The second risk is route collision between docs, assets, agent compatibility routes, and builder handles; rewrites should reserve known top-level paths before treating a path as a handle.
|
|
65
|
+
|
|
66
|
+
## Open Questions
|
|
67
|
+
|
|
68
|
+
Should launch support custom handles beyond GitHub usernames? Which metrics are platform-verified versus self-reported? What review moderation controls should be added once real volume exists?
|
|
69
|
+
|
|
70
|
+
## Rule And ADR Check
|
|
71
|
+
|
|
72
|
+
- Respects AGENTS.md by keeping runtime CLI behavior in `src/` untouched for the first site slice.
|
|
73
|
+
- Preserves source independence: no runtime CLI behavior, tests, or examples should hard-code one source repository.
|
|
74
|
+
- Matches product docs: README model-card content is optional, GitHub login requests basic profile plus email, reviews have no MVP spam filtering, and handles are first-come-first-served.
|
|
75
|
+
- Keeps examples that can write user directories behind dry-run or outside CLI examples.
|
|
76
|
+
|
|
77
|
+
## Possible Rule Or ADR Loosening
|
|
78
|
+
|
|
79
|
+
- No existing rule needs loosening for the frontend prototype.
|
|
80
|
+
- A future backend may need a new repository rule separating public site source fixtures from runtime CLI source fixtures so real showcased builders do not leak into CLI tests.
|
|
81
|
+
|
|
82
|
+
## Possible Rule Tightening
|
|
83
|
+
|
|
84
|
+
- Consider adding a rule that public site routes must prefer repo-neutral fixtures unless a page intentionally demonstrates a real claimed profile.
|
|
85
|
+
- Consider requiring auth-related docs to name requested OAuth scopes and stored identity fields before any backend implementation lands.
|
|
86
|
+
|
|
87
|
+
## Alternatives Considered
|
|
88
|
+
|
|
89
|
+
- Full backend now: enables real login and reviews, but expands scope into persistence, secrets, deployment, and security before route/content UX is validated.
|
|
90
|
+
- Only update product docs: too slow for the user's request to start building and does not test whether the social profile concept works on the site.
|
|
91
|
+
- Replace the existing directory with social profiles immediately: cleaner long-term shape, but risks breaking current static pages and install-directory behavior.
|
|
92
|
+
|
|
93
|
+
## Certainty
|
|
94
|
+
|
|
95
|
+
86 percent.
|
|
96
|
+
|
|
97
|
+
## Decision
|
|
98
|
+
|
|
99
|
+
ready
|
|
100
|
+
|
|
101
|
+
## Hosted Artifacts
|
|
102
|
+
|
|
103
|
+
- Plan page: https://pablof7z.github.io/awesome-agents/plans/public-builder-profiles-agent-model-cards/
|
|
104
|
+
|
|
105
|
+
- TTS audio: https://blossom.primal.net/2faa2fde8c6b962e1b629f2fb2e212aa6fd5e2e61b07e89e43c63475e0d8c195.mp3
|
package/docs/product/README.md
CHANGED
|
@@ -11,7 +11,8 @@ unless the user confirms them.
|
|
|
11
11
|
- `product-scope.md`: What `awesome-agents` is for and how it differs from skills.
|
|
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, Goose, and tenex-edge rendering/target behavior.
|
|
15
16
|
- `safety-and-publishing.md`: Install safety, registry behavior, verification, and npm/GitHub publish state.
|
|
16
17
|
- `open-questions.md`: Unresolved product questions.
|
|
17
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|tenex-edge|*>` to select target harnesses.
|
|
28
|
-
- `--agent <codex|claude-code|opencode|tenex-edge|*>` remains accepted as a
|
|
27
|
+
- `--harness <codex|claude-code|opencode|goose|tenex-edge|*>` to select target harnesses.
|
|
28
|
+
- `--agent <codex|claude-code|opencode|goose|tenex-edge|*>` 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.
|
|
@@ -39,8 +39,8 @@ Accepted implementation decision:
|
|
|
39
39
|
`$CODEX_HOME/<name>.config.toml`. tenex-edge is also global because invitable
|
|
40
40
|
local agents live under `$TENEX_EDGE_HOME/agents/` or `~/.tenex-edge/agents/`.
|
|
41
41
|
- When no `--harness` or legacy harness-valued `--agent` is provided, the CLI
|
|
42
|
-
detects supported harness CLIs on `PATH` (`codex`, `claude`, `opencode`,
|
|
43
|
-
`tenex-edge`).
|
|
42
|
+
detects supported harness CLIs on `PATH` (`codex`, `claude`, `opencode`,
|
|
43
|
+
`goose`, and `tenex-edge`).
|
|
44
44
|
- If one harness is detected, install to it. If multiple harnesses are detected,
|
|
45
45
|
interactive installs open a checkbox selector with every detected harness
|
|
46
46
|
selected by default; noninteractive, `--json`, and `--yes` installs use every
|
|
@@ -9,6 +9,7 @@ Initial harness targets:
|
|
|
9
9
|
- Codex
|
|
10
10
|
- Claude Code
|
|
11
11
|
- OpenCode
|
|
12
|
+
- Goose
|
|
12
13
|
- tenex-edge
|
|
13
14
|
|
|
14
15
|
## Codex
|
|
@@ -54,6 +55,29 @@ Generated OpenCode agents install to:
|
|
|
54
55
|
|
|
55
56
|
OpenCode output is Markdown with frontmatter and a generated marker.
|
|
56
57
|
|
|
58
|
+
## Goose
|
|
59
|
+
|
|
60
|
+
Generated Goose custom agents install to:
|
|
61
|
+
|
|
62
|
+
- Project: `.agents/agents/<profile>.md`
|
|
63
|
+
- Global: `$GOOSE_HOME/agents/<profile>.md`, or `~/.agents/agents/<profile>.md`
|
|
64
|
+
|
|
65
|
+
Run with:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
goose session
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Then invoke the agent by name in the chat session:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
@<profile>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Goose output is Markdown with YAML frontmatter (`name`, `description`, optional
|
|
78
|
+
`model`) and a generated marker. The agent body reuses the Claude Code adapter
|
|
79
|
+
when a Goose-specific adapter is not present.
|
|
80
|
+
|
|
57
81
|
## tenex-edge
|
|
58
82
|
|
|
59
83
|
Generated tenex-edge agents install to:
|
|
@@ -70,13 +94,16 @@ tenex-edge launch <profile>
|
|
|
70
94
|
The generated JSON is a tenex-edge local agent keystore entry with:
|
|
71
95
|
|
|
72
96
|
- a generated Nostr keypair, preserved across reinstalls
|
|
73
|
-
- `
|
|
74
|
-
|
|
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
|
|
75
101
|
- a byline derived from the profile summary
|
|
76
102
|
|
|
77
103
|
## Adapter Gaps
|
|
78
104
|
|
|
79
105
|
Some source repositories may provide Codex adapters first. Claude Code and
|
|
80
106
|
OpenCode use generated defaults unless a source repository adds native adapters
|
|
81
|
-
for those harnesses.
|
|
107
|
+
for those harnesses. Goose reuses the Claude Code adapter when no Goose-specific
|
|
108
|
+
adapter is present. tenex-edge uses a native adapter when present, otherwise it
|
|
82
109
|
reuses the Claude Code adapter before falling back to the base profile.
|
|
@@ -14,6 +14,12 @@ These are unresolved product questions for `awesome-agents`.
|
|
|
14
14
|
- Should remote installs record commit pins or lockfiles for reproducible updates?
|
|
15
15
|
- Should there eventually be a registry or curated index of profile sources?
|
|
16
16
|
|
|
17
|
+
## Site And Identity
|
|
18
|
+
|
|
19
|
+
- Should public builder handles always begin as GitHub usernames, or should
|
|
20
|
+
custom handles be supported from the start?
|
|
21
|
+
- What moderation or spam controls should be added after real review volume?
|
|
22
|
+
|
|
17
23
|
## Harness Support
|
|
18
24
|
|
|
19
25
|
- Should future versions also support Codex custom-agent files in addition to
|
|
@@ -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, and tenex-edge.
|
|
12
|
+
- Harness targets are Codex, Claude Code, OpenCode, Goose, and tenex-edge.
|
|
13
13
|
- The package should be published after the scaffold works.
|
|
14
14
|
|
|
15
15
|
## Product Boundary
|
|
@@ -10,6 +10,7 @@ The source format is intentionally repo-neutral:
|
|
|
10
10
|
agents/
|
|
11
11
|
<profile>/
|
|
12
12
|
agent.yaml
|
|
13
|
+
README.md # optional site model-card body
|
|
13
14
|
skills/
|
|
14
15
|
scripts/
|
|
15
16
|
references/
|
|
@@ -28,6 +29,17 @@ agents/<profile>/scripts/*
|
|
|
28
29
|
agents/<profile>/references/*
|
|
29
30
|
```
|
|
30
31
|
|
|
32
|
+
Optional site-facing documentation lives at:
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
agents/<profile>/README.md
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This README is intended for the public model-card page on
|
|
39
|
+
`awesome-agents.com/<handle>/<repo>/<profile>`. It complements the runtime
|
|
40
|
+
profile definition; it should not be treated as the installable prompt. It is
|
|
41
|
+
not required for a valid source profile.
|
|
42
|
+
|
|
31
43
|
Immediately relevant skills can be declared in the profile definition:
|
|
32
44
|
|
|
33
45
|
```yaml
|
|
@@ -60,6 +72,9 @@ Agent-owned scripts and references should be installed into
|
|
|
60
72
|
`~/.agents/homes/<profile>/references`.
|
|
61
73
|
Declared skills should be installed into
|
|
62
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.
|
|
63
78
|
|
|
64
79
|
Profile source files are intentionally under `agents/`, not `skills/`, because
|
|
65
80
|
the source format models agent profiles separately from loadable skills.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Site Profiles And Model Cards
|
|
2
|
+
|
|
3
|
+
These notes capture the requested direction for the public
|
|
4
|
+
`awesome-agents.com` experience.
|
|
5
|
+
|
|
6
|
+
## Core Direction
|
|
7
|
+
|
|
8
|
+
The site should become a social profile and discovery index for people who
|
|
9
|
+
build with agent fleets, not only a static CLI directory.
|
|
10
|
+
|
|
11
|
+
Primary route shape:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
awesome-agents.com/<handle>
|
|
15
|
+
awesome-agents.com/<handle>/<repo>/<agent-slug>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`/<handle>` is a builder profile: a public place to show the operator behind the
|
|
19
|
+
agents. It should include owned profiles, agent fleets, source repos, installs,
|
|
20
|
+
shipped examples, reviews, and activity.
|
|
21
|
+
|
|
22
|
+
This page should feel closer to a GitHub profile than a landing page. The core
|
|
23
|
+
content is profile information: about details, connected repos, agent templates,
|
|
24
|
+
recent activity, artifacts created with specific fleets, reviews,
|
|
25
|
+
discussion/forum participation, and cross-references between builders, agents,
|
|
26
|
+
and artifacts.
|
|
27
|
+
|
|
28
|
+
`/<handle>/<repo>/<agent-slug>` is an agent template page, comparable to a
|
|
29
|
+
Hugging Face model card. It should show what the agent is, why it exists, how to
|
|
30
|
+
install it, where its source lives, and what other users say about it.
|
|
31
|
+
|
|
32
|
+
This page should feel closer to a repository page than a marketing page. Users
|
|
33
|
+
should be able to inspect the template, install or download it, eventually fork
|
|
34
|
+
it, comment on it, review it, and see artifacts shared by other builders who
|
|
35
|
+
used or adapted the agent.
|
|
36
|
+
|
|
37
|
+
Profile and model-card navigation should be route-backed subpages, not in-page
|
|
38
|
+
anchor tabs. For example:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
awesome-agents.com/<handle>/agents
|
|
42
|
+
awesome-agents.com/<handle>/artifacts
|
|
43
|
+
awesome-agents.com/<handle>/activity
|
|
44
|
+
awesome-agents.com/<handle>/<repo>/<agent-slug>/reviews
|
|
45
|
+
awesome-agents.com/<handle>/<repo>/<agent-slug>/forks
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Agent Model Card Source
|
|
49
|
+
|
|
50
|
+
Agent source repositories should support optional site-facing README content
|
|
51
|
+
next to the runtime profile definition:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
agents/
|
|
55
|
+
<agent-slug>/
|
|
56
|
+
agent.yaml
|
|
57
|
+
README.md # optional site model-card body
|
|
58
|
+
scripts/
|
|
59
|
+
references/
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`agents/<agent-slug>/README.md` is not required. When present, it is the
|
|
63
|
+
canonical source for the public model-card body on the site. It complements
|
|
64
|
+
`agent.yaml`; it is not the runtime prompt. The YAML profile remains the
|
|
65
|
+
installable agent definition, while the README can explain intended use,
|
|
66
|
+
operating model, examples, limitations, changelog notes, and other human-facing
|
|
67
|
+
documentation.
|
|
68
|
+
|
|
69
|
+
The site should render this README on the model-card route when it exists:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
awesome-agents.com/<handle>/<repo>/<agent-slug>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
When no README exists, the site should still allow the agent page and generate a
|
|
76
|
+
fallback model card from `agent.yaml` metadata and profile content.
|
|
77
|
+
|
|
78
|
+
## Identity And Login
|
|
79
|
+
|
|
80
|
+
GitHub login is the preferred starting point.
|
|
81
|
+
|
|
82
|
+
Initial identity assumptions:
|
|
83
|
+
|
|
84
|
+
- The public handle can default to the GitHub username.
|
|
85
|
+
- Requested GitHub OAuth access should be limited to basic user profile and
|
|
86
|
+
email address information, such as `read:user` plus `user:email`.
|
|
87
|
+
- GitHub auth can verify repo ownership and let builders claim/import agent
|
|
88
|
+
source repositories.
|
|
89
|
+
- Repo and agent routes should be derived from GitHub ownership plus the
|
|
90
|
+
`agents/<agent-slug>/` layout.
|
|
91
|
+
- Reviews should require a logged-in identity.
|
|
92
|
+
- Public handle claims are first-come-first-served.
|
|
93
|
+
|
|
94
|
+
## Social Surface
|
|
95
|
+
|
|
96
|
+
Builder profiles should make agent operation legible and impressive without
|
|
97
|
+
turning into a conventional resume page.
|
|
98
|
+
|
|
99
|
+
Useful signals:
|
|
100
|
+
|
|
101
|
+
- published agent templates;
|
|
102
|
+
- repos connected to the builder;
|
|
103
|
+
- recent activity related to agent work;
|
|
104
|
+
- artifacts the builder publishes, including which fleet produced them;
|
|
105
|
+
- fleet or team size where the builder chooses to disclose it;
|
|
106
|
+
- installs, stars, reviews, and shipped samples;
|
|
107
|
+
- badges for verified GitHub ownership or claimed source repos;
|
|
108
|
+
- featured agents and examples of work produced with them;
|
|
109
|
+
- discussion/forum participation that can reference builders, repos, agents,
|
|
110
|
+
and artifacts.
|
|
111
|
+
|
|
112
|
+
Useful profile metrics:
|
|
113
|
+
|
|
114
|
+
- agent templates published or maintained;
|
|
115
|
+
- installs across templates and source repos;
|
|
116
|
+
- forks, remixes, and adaptations by other builders;
|
|
117
|
+
- artifacts shipped with explicit fleet tags;
|
|
118
|
+
- average review score from logged-in users;
|
|
119
|
+
- discussion karma or useful answers;
|
|
120
|
+
- verified source ownership and verified artifact links.
|
|
121
|
+
|
|
122
|
+
Agent model cards should support reviews and reputation signals so users can
|
|
123
|
+
judge an agent before installing it.
|
|
124
|
+
|
|
125
|
+
The first release should not include spam filtering for reviews. Reviews can
|
|
126
|
+
ship with logged-in identity as the baseline constraint, then add moderation
|
|
127
|
+
controls only after there is real usage pressure.
|
|
128
|
+
|
|
129
|
+
## Open Questions
|
|
130
|
+
|
|
131
|
+
- Which metrics are verified by the platform versus self-reported by builders?
|
|
132
|
+
- Should custom handles be supported at launch, or should the first version use
|
|
133
|
+
GitHub usernames only?
|
|
134
|
+
- What later moderation or spam controls are needed once real review volume
|
|
135
|
+
exists?
|
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, and tenex-edge.",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"description": "Install reusable agent profiles into Codex, Claude Code, OpenCode, Goose, and tenex-edge.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"awesome-agents": "bin/awesome-agents.js"
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"codex",
|
|
29
29
|
"claude-code",
|
|
30
30
|
"opencode",
|
|
31
|
+
"goose",
|
|
31
32
|
"cli"
|
|
32
33
|
],
|
|
33
34
|
"author": "Pablo Fernandez",
|
package/scripts/release.js
CHANGED
|
@@ -28,10 +28,6 @@ async function main() {
|
|
|
28
28
|
const nextVersion = resolveNextVersion(currentVersion, options.bump);
|
|
29
29
|
const tag = `v${nextVersion}`;
|
|
30
30
|
|
|
31
|
-
if (!options.dryRun) {
|
|
32
|
-
assertCleanWorktree();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
31
|
console.log(`Release plan: ${currentVersion} -> ${nextVersion}`);
|
|
36
32
|
|
|
37
33
|
if (options.dryRun) {
|
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, and tenex-edge.")
|
|
20
|
+
.description("Install reusable agent profiles into Codex, Claude Code, OpenCode, Goose, and tenex-edge.")
|
|
21
21
|
.version(PACKAGE_VERSION, "-v, --version")
|
|
22
22
|
.helpOption("-h, --help", "Show this help message")
|
|
23
23
|
.showHelpAfterError();
|
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.9";
|
|
3
3
|
export const DEFAULT_AGENT = "codex";
|
|
4
|
-
export const SUPPORTED_AGENTS = ["codex", "claude-code", "opencode", "tenex-edge"];
|
|
4
|
+
export const SUPPORTED_AGENTS = ["codex", "claude-code", "opencode", "goose", "tenex-edge"];
|
|
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,6 +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"],
|
|
18
19
|
["tenex", "tenex-edge"],
|
|
19
20
|
["tenex-edge", "tenex-edge"],
|
|
20
21
|
["tenexedge", "tenex-edge"]
|
|
@@ -25,5 +26,6 @@ export const HARNESS_COMMANDS = new Map([
|
|
|
25
26
|
["codex", "codex"],
|
|
26
27
|
["claude-code", "claude"],
|
|
27
28
|
["opencode", "opencode"],
|
|
29
|
+
["goose", "goose"],
|
|
28
30
|
["tenex-edge", "tenex-edge"]
|
|
29
31
|
]);
|
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, and tenex-edge")}`
|
|
191
|
+
` ${ui.dim("Operational profiles for Codex, Claude Code, OpenCode, Goose, and tenex-edge")}`
|
|
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, and tenex-edge.",
|
|
197
|
+
description: "Install reusable operational agent profiles into Codex, Claude Code, OpenCode, Goose, and tenex-edge.",
|
|
198
198
|
sections: [
|
|
199
199
|
{
|
|
200
200
|
title: "Manage Profiles:",
|
|
@@ -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, or tenex-edge files and record them in the registry."
|
|
293
|
+
"3. Render Codex, Claude Code, OpenCode, Goose, or tenex-edge files and record them in the registry."
|
|
294
294
|
]
|
|
295
295
|
},
|
|
296
296
|
{
|
|
@@ -330,6 +330,7 @@ const commandHelp = {
|
|
|
330
330
|
{ term: ui.command("codex"), description: `${ui.path("~/.codex/<profile>.config.toml")} (project-local Codex profiles are not supported)` },
|
|
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
|
+
{ term: ui.command("goose"), description: `${ui.path("~/.agents/agents/<profile>.md")} or ${ui.path(".agents/agents/<profile>.md")}` },
|
|
333
334
|
{ term: ui.command("tenex-edge"), description: `${ui.path("~/.tenex-edge/agents/<profile>.json")} (project-local tenex-edge agents are not supported)` },
|
|
334
335
|
{ term: ui.command("registry"), description: `${ui.path("~/.awesome-agents/installed.json")} or ${ui.path(".awesome-agents/installed.json")}` }
|
|
335
336
|
]
|
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) {
|
|
@@ -47,7 +54,8 @@ export async function installFromSource(sourceSpec, options = {}) {
|
|
|
47
54
|
const existingContent = await readExistingContent(target);
|
|
48
55
|
const content = renderForAgent(renderProfile, harness, {
|
|
49
56
|
source: materialized.source,
|
|
50
|
-
existingContent
|
|
57
|
+
existingContent,
|
|
58
|
+
selectedHarnesses: harnesses
|
|
51
59
|
});
|
|
52
60
|
await writeManagedFile(target, content, options);
|
|
53
61
|
|
|
@@ -62,6 +70,8 @@ export async function installFromSource(sourceSpec, options = {}) {
|
|
|
62
70
|
target,
|
|
63
71
|
installedAt,
|
|
64
72
|
contentSha256: contentHash(content),
|
|
73
|
+
agentHome,
|
|
74
|
+
supportRoots,
|
|
65
75
|
supportTargets,
|
|
66
76
|
skillTargets: installedSkills.map((skill) => skill.path),
|
|
67
77
|
installedSkills,
|
|
@@ -252,8 +262,7 @@ async function installProfileSupport(profile, options = {}) {
|
|
|
252
262
|
return [];
|
|
253
263
|
}
|
|
254
264
|
|
|
255
|
-
const
|
|
256
|
-
const agentHome = path.join(home, ".agents", "homes", profile.slug);
|
|
265
|
+
const agentHome = resolveAgentHome(profile, options);
|
|
257
266
|
const targets = [];
|
|
258
267
|
|
|
259
268
|
for (const supportDir of profile.supportDirs) {
|
|
@@ -272,6 +281,11 @@ async function installProfileSupport(profile, options = {}) {
|
|
|
272
281
|
return targets;
|
|
273
282
|
}
|
|
274
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
|
+
|
|
275
289
|
async function listFilesRecursive(root) {
|
|
276
290
|
const entries = await fs.readdir(root, { withFileTypes: true });
|
|
277
291
|
const files = [];
|
|
@@ -354,6 +368,20 @@ function runInstructionForOperation(operation, env) {
|
|
|
354
368
|
};
|
|
355
369
|
}
|
|
356
370
|
|
|
371
|
+
if (operation.harness === "goose") {
|
|
372
|
+
if (!commandExists("goose", env)) {
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
return {
|
|
376
|
+
profile: operation.profile,
|
|
377
|
+
name: operation.name,
|
|
378
|
+
summary: operation.summary,
|
|
379
|
+
harness: operation.harness,
|
|
380
|
+
command: "goose session",
|
|
381
|
+
note: `Start goose, then invoke @${operation.profile} in the session.`
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
357
385
|
if (operation.harness === "tenex-edge") {
|
|
358
386
|
if (!commandExists("tenex-edge", env)) {
|
|
359
387
|
return undefined;
|
package/src/renderers.js
CHANGED
|
@@ -41,6 +41,9 @@ export function renderForAgent(profile, agent, context) {
|
|
|
41
41
|
if (normalized === "opencode") {
|
|
42
42
|
return renderOpenCode(profile, context);
|
|
43
43
|
}
|
|
44
|
+
if (normalized === "goose") {
|
|
45
|
+
return renderGoose(profile, context);
|
|
46
|
+
}
|
|
44
47
|
if (normalized === "tenex-edge") {
|
|
45
48
|
return renderTenexEdge(profile, context);
|
|
46
49
|
}
|
|
@@ -88,6 +91,19 @@ export function resolveTargetPath(profile, agent, options = {}) {
|
|
|
88
91
|
return path.join(opencodeHome, "agents", `${profile.slug}.md`);
|
|
89
92
|
}
|
|
90
93
|
|
|
94
|
+
if (normalized === "goose") {
|
|
95
|
+
if (scope === "project") {
|
|
96
|
+
return path.join(cwd, ".agents", "agents", `${profile.slug}.md`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const gooseHome = options.gooseHome
|
|
100
|
+
? path.resolve(expandHome(options.gooseHome, home))
|
|
101
|
+
: process.env.GOOSE_HOME
|
|
102
|
+
? path.resolve(expandHome(process.env.GOOSE_HOME, home))
|
|
103
|
+
: path.join(home, ".agents");
|
|
104
|
+
return path.join(gooseHome, "agents", `${profile.slug}.md`);
|
|
105
|
+
}
|
|
106
|
+
|
|
91
107
|
if (normalized === "tenex-edge") {
|
|
92
108
|
const tenexEdgeHome = options.tenexEdgeHome
|
|
93
109
|
? path.resolve(expandHome(options.tenexEdgeHome, home))
|
|
@@ -171,9 +187,45 @@ function renderOpenCode(profile, context) {
|
|
|
171
187
|
return stringifyFrontmatter(attributes, `${marker}\n\n${buildInstructionBody(profile, undefined, "opencode")}`);
|
|
172
188
|
}
|
|
173
189
|
|
|
190
|
+
function renderGoose(profile, context) {
|
|
191
|
+
const attributes = {
|
|
192
|
+
name: profile.slug,
|
|
193
|
+
description: profile.summary || profile.name
|
|
194
|
+
};
|
|
195
|
+
const model = chooseGooseModel(profile);
|
|
196
|
+
if (model && model !== "inherit") {
|
|
197
|
+
attributes.model = model;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const marker = htmlMarker(profile, "goose", context);
|
|
201
|
+
return stringifyFrontmatter(attributes, `${marker}\n\n${buildInstructionBody(profile, profile.adapters.goose ?? profile.adapters["claude-code"], "goose")}`);
|
|
202
|
+
}
|
|
203
|
+
|
|
174
204
|
function renderTenexEdge(profile, context) {
|
|
175
205
|
const existing = tenexEdgeKeyMaterial(context.existingContent);
|
|
176
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) {
|
|
177
229
|
const agent = {
|
|
178
230
|
description: profile.summary || profile.name,
|
|
179
231
|
prompt: buildInstructionBody(profile, profile.adapters["tenex-edge"] ?? profile.adapters["claude-code"], "tenex-edge")
|
|
@@ -188,19 +240,43 @@ function renderTenexEdge(profile, context) {
|
|
|
188
240
|
agent.effort = effort;
|
|
189
241
|
}
|
|
190
242
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
secret_key: keyMaterial.secret_key,
|
|
194
|
-
public_key: keyMaterial.public_key,
|
|
195
|
-
created_at: keyMaterial.created_at ?? Math.floor(Date.now() / 1000),
|
|
196
|
-
command: ["claude"],
|
|
197
|
-
agent,
|
|
198
|
-
byline: profile.summary || profile.name,
|
|
199
|
-
managed_by: GENERATED_MARKER,
|
|
200
|
-
source: context.source
|
|
201
|
-
};
|
|
243
|
+
return agent;
|
|
244
|
+
}
|
|
202
245
|
|
|
203
|
-
|
|
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
|
+
));
|
|
204
280
|
}
|
|
205
281
|
|
|
206
282
|
function buildInstructionBody(profile, adapter, harness) {
|
|
@@ -214,9 +290,24 @@ function buildInstructionBody(profile, adapter, harness) {
|
|
|
214
290
|
`- Installed for: \`${harness}\``,
|
|
215
291
|
"- When asked who you are, what agent is running, or what role you are acting as, answer with this identity and role.",
|
|
216
292
|
"- This profile is a reusable operational agent profile, not a skill or local machine setup.",
|
|
217
|
-
|
|
293
|
+
profile.agentHome
|
|
294
|
+
? `- Agent home: \`${profile.agentHome}\``
|
|
295
|
+
: "- This render-only output does not install an agent home or support material."
|
|
218
296
|
];
|
|
219
297
|
|
|
298
|
+
if (profile.supportRoots?.length) {
|
|
299
|
+
parts.push(
|
|
300
|
+
"",
|
|
301
|
+
"## Agent-Owned Support",
|
|
302
|
+
"",
|
|
303
|
+
"Use these installed resources when the operating procedure calls for them. Resolve relative support paths against these roots.",
|
|
304
|
+
""
|
|
305
|
+
);
|
|
306
|
+
for (const support of profile.supportRoots) {
|
|
307
|
+
parts.push(`- \`${support.kind}\`: \`${support.path}\``);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
220
311
|
if (profile.installedSkills?.length) {
|
|
221
312
|
const skillBase = path.join(path.dirname(profile.installedSkills[0].path), "<skill>");
|
|
222
313
|
parts.push(
|
|
@@ -277,6 +368,27 @@ function chooseOpenCodeModel(profile) {
|
|
|
277
368
|
return candidates.find((model) => model.includes("/"));
|
|
278
369
|
}
|
|
279
370
|
|
|
371
|
+
function chooseGooseModel(profile) {
|
|
372
|
+
const candidates = [
|
|
373
|
+
profile.attributes.recommended_model,
|
|
374
|
+
...arrayify(profile.attributes.recommended_models)
|
|
375
|
+
].filter(Boolean).map((value) => String(value).toLowerCase());
|
|
376
|
+
|
|
377
|
+
if (candidates.some((model) => model.includes("opus"))) {
|
|
378
|
+
return "claude-3-5-sonnet";
|
|
379
|
+
}
|
|
380
|
+
if (candidates.some((model) => model.includes("sonnet"))) {
|
|
381
|
+
return "claude-3-5-sonnet";
|
|
382
|
+
}
|
|
383
|
+
if (candidates.some((model) => model.includes("haiku"))) {
|
|
384
|
+
return "claude-3-5-haiku";
|
|
385
|
+
}
|
|
386
|
+
if (candidates.some((model) => model.includes("gpt"))) {
|
|
387
|
+
return candidates.find((model) => model.includes("gpt"));
|
|
388
|
+
}
|
|
389
|
+
return undefined;
|
|
390
|
+
}
|
|
391
|
+
|
|
280
392
|
function tenexEdgeKeyMaterial(content) {
|
|
281
393
|
if (!content) {
|
|
282
394
|
return undefined;
|
|
@@ -358,6 +470,20 @@ function arrayify(value) {
|
|
|
358
470
|
return [value];
|
|
359
471
|
}
|
|
360
472
|
|
|
473
|
+
function uniqueBy(values, keyForValue) {
|
|
474
|
+
const seen = new Set();
|
|
475
|
+
const out = [];
|
|
476
|
+
for (const value of values) {
|
|
477
|
+
const key = keyForValue(value);
|
|
478
|
+
if (seen.has(key)) {
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
seen.add(key);
|
|
482
|
+
out.push(value);
|
|
483
|
+
}
|
|
484
|
+
return out;
|
|
485
|
+
}
|
|
486
|
+
|
|
361
487
|
function flattenValues(values) {
|
|
362
488
|
return arrayify(values)
|
|
363
489
|
.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
|
}
|