awesome-agents 0.1.0
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/AGENTS.md +60 -0
- package/LICENSE +21 -0
- package/README.md +96 -0
- package/bin/awesome-agents.js +9 -0
- package/docs/cli.md +34 -0
- package/docs/product/README.md +12 -0
- package/docs/product/awesome-agents-flow-notes.md +45 -0
- package/package.json +44 -0
- package/src/cli.js +208 -0
- package/src/constants.js +19 -0
- package/src/frontmatter.js +33 -0
- package/src/installer.js +315 -0
- package/src/registry.js +58 -0
- package/src/renderers.js +256 -0
- package/src/source.js +179 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
`awesome-agents` is a Node.js CLI package for installing reusable operational
|
|
6
|
+
agent profiles into agent harnesses. It intentionally mirrors the command shape
|
|
7
|
+
of `npx skills`, but installs profile artifacts for Codex, Claude Code, and
|
|
8
|
+
OpenCode.
|
|
9
|
+
|
|
10
|
+
The canonical source format is the `touch-grass` layout:
|
|
11
|
+
|
|
12
|
+
- `agents/profiles/*.md`: Markdown profile with YAML frontmatter.
|
|
13
|
+
- `agents/adapters/<harness>/*.md`: optional harness-specific metadata and notes.
|
|
14
|
+
|
|
15
|
+
## Setup Commands
|
|
16
|
+
|
|
17
|
+
- Install dependencies: `npm install`
|
|
18
|
+
- Run tests: `npm test`
|
|
19
|
+
- Check syntax: `npm run lint`
|
|
20
|
+
- Try the CLI locally: `node ./bin/awesome-agents.js --help`
|
|
21
|
+
|
|
22
|
+
## Development Workflow
|
|
23
|
+
|
|
24
|
+
- Keep runtime code in `src/` and the executable shim in `bin/`.
|
|
25
|
+
- Use `node --test` for tests under `test/`.
|
|
26
|
+
- Use `--dry-run` in examples that would otherwise write to real user agent
|
|
27
|
+
directories.
|
|
28
|
+
- Do not publish the npm package from this repository unless explicitly asked.
|
|
29
|
+
|
|
30
|
+
## Testing Instructions
|
|
31
|
+
|
|
32
|
+
- Run the full suite with `npm test`.
|
|
33
|
+
- Add or update tests when changing command behavior, path resolution,
|
|
34
|
+
frontmatter parsing, renderer output, registry writes, or safety checks.
|
|
35
|
+
- Tests should use temporary HOME directories and fixtures, not the user's real
|
|
36
|
+
`~/.codex`, `~/.claude`, or `~/.config/opencode` directories.
|
|
37
|
+
|
|
38
|
+
## Code Style
|
|
39
|
+
|
|
40
|
+
- Use ESM modules.
|
|
41
|
+
- Prefer Node standard library APIs unless a focused dependency is already in
|
|
42
|
+
`package.json`.
|
|
43
|
+
- Keep generated files marked with `Generated by awesome-agents` so remove and
|
|
44
|
+
overwrite safety checks remain reliable.
|
|
45
|
+
- Keep command output stable enough for humans and use `--json` for scripts.
|
|
46
|
+
|
|
47
|
+
## Safety
|
|
48
|
+
|
|
49
|
+
- Never overwrite or delete unmanaged harness files by default.
|
|
50
|
+
- Keep install behavior deterministic and noninteractive. `--yes` exists for
|
|
51
|
+
parity with `npx skills`, but the CLI should not require prompts to complete.
|
|
52
|
+
- Do not mutate harness configuration beyond writing the selected generated
|
|
53
|
+
profile files and the `awesome-agents` registry.
|
|
54
|
+
|
|
55
|
+
## Pull Request Guidelines
|
|
56
|
+
|
|
57
|
+
- Keep changes scoped to one command, renderer, or source-format behavior at a
|
|
58
|
+
time when practical.
|
|
59
|
+
- Run `npm run lint` and `npm test` before handing off changes.
|
|
60
|
+
- Document user-visible CLI behavior in `README.md` when it changes.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pablo Fernandez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# awesome-agents
|
|
2
|
+
|
|
3
|
+
`awesome-agents` is an `npx`-compatible installer for reusable agent profiles.
|
|
4
|
+
It mirrors the useful parts of `npx skills`, but the unit is an operational
|
|
5
|
+
agent profile instead of a skill.
|
|
6
|
+
|
|
7
|
+
The first supported source is `touch-grass`: local at `/Users/customer/touch-grass`
|
|
8
|
+
or remote as `pablof7z/touch-grass`. Profiles are read from
|
|
9
|
+
`agents/profiles/*.md`, adapted for the selected harness, and installed into the
|
|
10
|
+
right place for Codex, Claude Code, or OpenCode.
|
|
11
|
+
|
|
12
|
+
## Install And Run
|
|
13
|
+
|
|
14
|
+
From this repo:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install
|
|
18
|
+
npm test
|
|
19
|
+
node ./bin/awesome-agents.js add /Users/customer/touch-grass --agent codex --profile ios-tester --dry-run
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Once published, the intended entrypoint is:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx awesome-agents add pablof7z/touch-grass --agent codex --profile ios-tester
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Commands
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
awesome-agents add [source] [options]
|
|
32
|
+
awesome-agents install [source] [options] # alias for add
|
|
33
|
+
awesome-agents use <source@profile> [options]
|
|
34
|
+
awesome-agents list [options]
|
|
35
|
+
awesome-agents remove <profile...> [options]
|
|
36
|
+
awesome-agents update [profile...] [options]
|
|
37
|
+
awesome-agents init [name]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Useful install options:
|
|
41
|
+
|
|
42
|
+
- `--agent codex|claude-code|opencode|*`
|
|
43
|
+
- `--profile <slug>` or `--profile '*'`
|
|
44
|
+
- `--all` to install all profiles to all supported harnesses
|
|
45
|
+
- `--dry-run` to preview writes
|
|
46
|
+
- `--project` for project-level install, the default
|
|
47
|
+
- `--global` for user-level install
|
|
48
|
+
- `--list` to inspect available source profiles without installing
|
|
49
|
+
|
|
50
|
+
## Harness Targets
|
|
51
|
+
|
|
52
|
+
Project installs write to:
|
|
53
|
+
|
|
54
|
+
- Codex: `.codex/agents/<profile>.toml`
|
|
55
|
+
- Claude Code: `.claude/agents/<profile>.md`
|
|
56
|
+
- OpenCode: `.opencode/agents/<profile>.md`
|
|
57
|
+
|
|
58
|
+
Global installs write to:
|
|
59
|
+
|
|
60
|
+
- Codex: `$CODEX_HOME/agents/<profile>.toml`, or `~/.codex/agents/<profile>.toml`
|
|
61
|
+
- Claude Code: `$CLAUDE_HOME/agents/<profile>.md`, or `~/.claude/agents/<profile>.md`
|
|
62
|
+
- OpenCode: `$OPENCODE_CONFIG_DIR/agents/<profile>.md`, or `~/.config/opencode/agents/<profile>.md`
|
|
63
|
+
|
|
64
|
+
The CLI keeps its own registry at `.awesome-agents/installed.json` for project
|
|
65
|
+
installs or `~/.awesome-agents/installed.json` for global installs. `list`,
|
|
66
|
+
`remove`, and `update` use this registry and refuse to overwrite or delete files
|
|
67
|
+
that do not contain the generated marker unless `--force` is passed.
|
|
68
|
+
|
|
69
|
+
## Source Format
|
|
70
|
+
|
|
71
|
+
An agent-profile source should look like:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
agents/
|
|
75
|
+
profiles/
|
|
76
|
+
ios-tester.md
|
|
77
|
+
adapters/
|
|
78
|
+
codex/
|
|
79
|
+
ios-tester.md
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Profile files are Markdown with YAML frontmatter. Adapters are optional and can
|
|
83
|
+
provide harness-specific metadata such as model and reasoning effort.
|
|
84
|
+
|
|
85
|
+
## Examples
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
awesome-agents add /Users/customer/touch-grass --list
|
|
89
|
+
awesome-agents add /Users/customer/touch-grass --agent codex --profile ios-tester
|
|
90
|
+
awesome-agents add /Users/customer/touch-grass --agent codex --profile ios-tester --global
|
|
91
|
+
awesome-agents add pablof7z/touch-grass --all --dry-run
|
|
92
|
+
awesome-agents use pablof7z/touch-grass@ios-ux-ui-critic --agent claude-code
|
|
93
|
+
awesome-agents list --json
|
|
94
|
+
awesome-agents remove ios-tester --agent codex
|
|
95
|
+
awesome-agents update ios-tester --agent codex --dry-run
|
|
96
|
+
```
|
package/docs/cli.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# CLI Design
|
|
2
|
+
|
|
3
|
+
`awesome-agents` uses `npx skills` as the command-shape reference:
|
|
4
|
+
|
|
5
|
+
- `add` installs a source package.
|
|
6
|
+
- `install` is an alias for `add`.
|
|
7
|
+
- `use` renders a single profile without installing.
|
|
8
|
+
- `list` / `ls` shows installed profiles.
|
|
9
|
+
- `remove` / `rm` removes installed profiles.
|
|
10
|
+
- `update` / `upgrade` reinstalls from the recorded source.
|
|
11
|
+
- `init` creates a profile source skeleton.
|
|
12
|
+
|
|
13
|
+
The CLI is noninteractive for the initial scaffold. Options such as `--yes` are
|
|
14
|
+
accepted for parity, but command behavior should be fully scriptable. Installs
|
|
15
|
+
default to project scope; pass `--global` for user-level installs.
|
|
16
|
+
|
|
17
|
+
## Source Resolution
|
|
18
|
+
|
|
19
|
+
Supported source values:
|
|
20
|
+
|
|
21
|
+
- Local path: `/Users/customer/touch-grass`, `~/touch-grass`, `.`
|
|
22
|
+
- GitHub shorthand: `pablof7z/touch-grass`
|
|
23
|
+
- GitHub URL: `https://github.com/pablof7z/touch-grass`
|
|
24
|
+
|
|
25
|
+
For GitHub sources, the CLI clones a shallow temporary copy and reads
|
|
26
|
+
`agents/profiles`.
|
|
27
|
+
|
|
28
|
+
## Install Safety
|
|
29
|
+
|
|
30
|
+
Generated files contain the marker `Generated by awesome-agents`. The CLI refuses
|
|
31
|
+
to overwrite or delete unmarked target files unless `--force` is passed.
|
|
32
|
+
|
|
33
|
+
The registry records only what this CLI installed. It is not intended to discover
|
|
34
|
+
or manage hand-written harness profiles.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Product Notes
|
|
2
|
+
|
|
3
|
+
This folder captures product thinking for `awesome-agents`.
|
|
4
|
+
|
|
5
|
+
Keep these notes grounded in explicit user requests and accepted implementation
|
|
6
|
+
direction. Do not turn incidental implementation choices into product strategy
|
|
7
|
+
unless the user confirms them.
|
|
8
|
+
|
|
9
|
+
## Files
|
|
10
|
+
|
|
11
|
+
- `awesome-agents-flow-notes.md`: living notes about command shape, source
|
|
12
|
+
format, harness targets, and open questions.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Awesome Agents Flow Notes
|
|
2
|
+
|
|
3
|
+
These are factual notes from the implementation request and current scaffold.
|
|
4
|
+
|
|
5
|
+
## Core Direction
|
|
6
|
+
|
|
7
|
+
- The package is named `awesome-agents`.
|
|
8
|
+
- It should be installable with `npx`.
|
|
9
|
+
- Its command structure should mirror `npx skills`, but for agent profiles.
|
|
10
|
+
- It should install profiles from `touch-grass`, both local
|
|
11
|
+
`/Users/customer/touch-grass` and GitHub `pablof7z/touch-grass`.
|
|
12
|
+
- Initial harness targets are Codex, Claude Code, and OpenCode.
|
|
13
|
+
- The package should be published after the scaffold works.
|
|
14
|
+
|
|
15
|
+
## Source Model
|
|
16
|
+
|
|
17
|
+
- Canonical profiles live at `agents/profiles/*.md`.
|
|
18
|
+
- Harness adapters live at `agents/adapters/<harness>/*.md`.
|
|
19
|
+
- Current touch-grass profiles include `ios-tester` and `ios-ux-ui-critic`.
|
|
20
|
+
- The CLI should preserve canonical profile content and generate harness-specific
|
|
21
|
+
install files.
|
|
22
|
+
|
|
23
|
+
## Command Model
|
|
24
|
+
|
|
25
|
+
- `add` is the primary install command because `npx skills` uses `add`.
|
|
26
|
+
- `install` is an alias because the user explicitly requested an install command.
|
|
27
|
+
- `use` renders one profile without installing it.
|
|
28
|
+
- `list`, `remove`, and `update` operate from an `awesome-agents` registry so
|
|
29
|
+
the CLI manages only its own generated files.
|
|
30
|
+
- `init` creates a starter profile source layout.
|
|
31
|
+
- Install scope defaults to project to match the `npx skills` mental model.
|
|
32
|
+
|
|
33
|
+
## Safety Constraints
|
|
34
|
+
|
|
35
|
+
- Default behavior should not overwrite or delete unmanaged harness files.
|
|
36
|
+
- `--dry-run` should be available for install, remove, update, and init flows.
|
|
37
|
+
- Tests should exercise fake homes and fixture sources instead of writing to real
|
|
38
|
+
user harness directories.
|
|
39
|
+
|
|
40
|
+
## Open Questions
|
|
41
|
+
|
|
42
|
+
- Whether future versions should also generate Codex `--profile` config layers in addition to Codex custom agents.
|
|
43
|
+
- Whether touch-grass should add native Claude Code and OpenCode adapters instead
|
|
44
|
+
of relying on generated defaults.
|
|
45
|
+
- Whether future versions should include interactive prompts like `npx skills`.
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "awesome-agents",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Install reusable agent profiles into Codex, Claude Code, and OpenCode.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"awesome-agents": "bin/awesome-agents.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"src",
|
|
12
|
+
"docs",
|
|
13
|
+
"README.md",
|
|
14
|
+
"AGENTS.md"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"lint": "node --check bin/awesome-agents.js && node --check src/*.js && node --check test/*.test.js",
|
|
18
|
+
"test": "node --test"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"agents",
|
|
22
|
+
"agent-profiles",
|
|
23
|
+
"codex",
|
|
24
|
+
"claude-code",
|
|
25
|
+
"opencode",
|
|
26
|
+
"cli"
|
|
27
|
+
],
|
|
28
|
+
"author": "Pablo Fernandez",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/pablof7z/awesome-agents.git"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=22.12.0"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"commander": "^15.0.0",
|
|
42
|
+
"yaml": "^2.9.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/cli.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { PACKAGE_NAME, PACKAGE_VERSION, SUPPORTED_AGENTS } from "./constants.js";
|
|
3
|
+
import {
|
|
4
|
+
initProfile,
|
|
5
|
+
installFromSource,
|
|
6
|
+
listAvailable,
|
|
7
|
+
listInstalled,
|
|
8
|
+
removeInstalled,
|
|
9
|
+
updateInstalled,
|
|
10
|
+
useFromSource
|
|
11
|
+
} from "./installer.js";
|
|
12
|
+
|
|
13
|
+
export async function run(argv = process.argv) {
|
|
14
|
+
const program = new Command();
|
|
15
|
+
program
|
|
16
|
+
.name(PACKAGE_NAME)
|
|
17
|
+
.description("Install reusable agent profiles into Codex, Claude Code, and OpenCode.")
|
|
18
|
+
.version(PACKAGE_VERSION, "-v, --version")
|
|
19
|
+
.helpOption("-h, --help", "Show this help message")
|
|
20
|
+
.showHelpAfterError();
|
|
21
|
+
|
|
22
|
+
addInstallCommand(program, "add");
|
|
23
|
+
addInstallCommand(program, "install");
|
|
24
|
+
|
|
25
|
+
program
|
|
26
|
+
.command("use")
|
|
27
|
+
.argument("[source]", "Source plus profile, for example pablof7z/touch-grass@ios-tester")
|
|
28
|
+
.description("Print one rendered agent profile without installing it")
|
|
29
|
+
.option("-s, --profile <profile>", "Profile slug to use")
|
|
30
|
+
.option("--skill <profile>", "Compatibility alias for --profile")
|
|
31
|
+
.option("-a, --agent <agent>", `Target agent harness (${SUPPORTED_AGENTS.join(", ")})`)
|
|
32
|
+
.option("--json", "Output JSON")
|
|
33
|
+
.option("--home <dir>", "Override HOME for path expansion")
|
|
34
|
+
.action(async (source = undefined, options) => {
|
|
35
|
+
const result = await useFromSource(source, options);
|
|
36
|
+
if (options.json) {
|
|
37
|
+
printJson(result);
|
|
38
|
+
} else {
|
|
39
|
+
process.stdout.write(result.content);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
program
|
|
44
|
+
.command("list")
|
|
45
|
+
.alias("ls")
|
|
46
|
+
.description("List installed agent profiles")
|
|
47
|
+
.option("-g, --global", "List global installs")
|
|
48
|
+
.option("-p, --project", "List project installs")
|
|
49
|
+
.option("-a, --agent <agents...>", "Filter by agent harness")
|
|
50
|
+
.option("--json", "Output JSON")
|
|
51
|
+
.option("--home <dir>", "Override HOME for path expansion")
|
|
52
|
+
.action(async (options) => {
|
|
53
|
+
const result = await listInstalled(options);
|
|
54
|
+
if (options.json) {
|
|
55
|
+
printJson(result);
|
|
56
|
+
} else {
|
|
57
|
+
printInstalled(result);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
program
|
|
62
|
+
.command("remove")
|
|
63
|
+
.alias("rm")
|
|
64
|
+
.argument("[profiles...]", "Installed profile slugs to remove")
|
|
65
|
+
.description("Remove installed agent profiles")
|
|
66
|
+
.option("-g, --global", "Remove global installs")
|
|
67
|
+
.option("-p, --project", "Remove project installs")
|
|
68
|
+
.option("-a, --agent <agents...>", "Filter by agent harness")
|
|
69
|
+
.option("-y, --yes", "Accepted for npx skills parity; prompts are not used")
|
|
70
|
+
.option("--all", "Remove all matching installed profiles")
|
|
71
|
+
.option("--dry-run", "Print planned removals without deleting files")
|
|
72
|
+
.option("--force", "Allow removing files without the generated marker")
|
|
73
|
+
.option("--json", "Output JSON")
|
|
74
|
+
.option("--home <dir>", "Override HOME for path expansion")
|
|
75
|
+
.action(async (profiles, options) => {
|
|
76
|
+
const result = await removeInstalled(profiles, options);
|
|
77
|
+
if (options.json) {
|
|
78
|
+
printJson(result);
|
|
79
|
+
} else {
|
|
80
|
+
printOperations(result.operations, result.registryPath);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
program
|
|
85
|
+
.command("update")
|
|
86
|
+
.alias("upgrade")
|
|
87
|
+
.argument("[profiles...]", "Installed profile slugs to update")
|
|
88
|
+
.description("Update installed agent profiles from their original source")
|
|
89
|
+
.option("-g, --global", "Update global installs")
|
|
90
|
+
.option("-p, --project", "Update project installs")
|
|
91
|
+
.option("-a, --agent <agents...>", "Filter by agent harness")
|
|
92
|
+
.option("-y, --yes", "Accepted for npx skills parity; prompts are not used")
|
|
93
|
+
.option("--dry-run", "Print planned updates without writing files")
|
|
94
|
+
.option("--json", "Output JSON")
|
|
95
|
+
.option("--home <dir>", "Override HOME for path expansion")
|
|
96
|
+
.action(async (profiles, options) => {
|
|
97
|
+
const result = await updateInstalled(profiles, options);
|
|
98
|
+
if (options.json) {
|
|
99
|
+
printJson(result);
|
|
100
|
+
} else {
|
|
101
|
+
printOperations(result.operations, result.registryPath);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
program
|
|
106
|
+
.command("init")
|
|
107
|
+
.argument("[name]", "New profile slug")
|
|
108
|
+
.description("Initialize a profile source layout in the current directory")
|
|
109
|
+
.option("--dry-run", "Print planned files without writing")
|
|
110
|
+
.option("--force", "Overwrite existing initialized files")
|
|
111
|
+
.option("--json", "Output JSON")
|
|
112
|
+
.action(async (name, options) => {
|
|
113
|
+
const result = await initProfile(name, { ...options, cwd: process.cwd() });
|
|
114
|
+
if (options.json) {
|
|
115
|
+
printJson(result);
|
|
116
|
+
} else {
|
|
117
|
+
console.log(`${result.action}:`);
|
|
118
|
+
for (const file of result.files) {
|
|
119
|
+
console.log(` ${file}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
if (argv.length <= 2) {
|
|
125
|
+
program.help();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
await program.parseAsync(argv);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function addInstallCommand(program, commandName) {
|
|
133
|
+
program
|
|
134
|
+
.command(commandName)
|
|
135
|
+
.argument("[source]", "Local path, GitHub owner/repo, or GitHub URL")
|
|
136
|
+
.description(commandName === "install" ? "Alias for add" : "Install agent profiles from a source")
|
|
137
|
+
.option("-g, --global", "Install globally")
|
|
138
|
+
.option("-p, --project", "Install into the current project (default)")
|
|
139
|
+
.option("-a, --agent <agents...>", `Target agent harnesses (${SUPPORTED_AGENTS.join(", ")}, or *)`)
|
|
140
|
+
.option("-s, --profile <profiles...>", "Profile slugs to install (or *)")
|
|
141
|
+
.option("--skill <profiles...>", "Compatibility alias for --profile")
|
|
142
|
+
.option("-l, --list", "List available profiles in the source without installing")
|
|
143
|
+
.option("-y, --yes", "Accepted for npx skills parity; prompts are not used")
|
|
144
|
+
.option("--all", "Install all profiles to all supported agents")
|
|
145
|
+
.option("--dry-run", "Print planned installs without writing files")
|
|
146
|
+
.option("--force", "Allow overwriting files without the generated marker")
|
|
147
|
+
.option("--json", "Output JSON")
|
|
148
|
+
.option("--home <dir>", "Override HOME for path expansion")
|
|
149
|
+
.action(async (source = undefined, options) => {
|
|
150
|
+
if (options.list) {
|
|
151
|
+
const profiles = await listAvailable(source, options);
|
|
152
|
+
if (options.json) {
|
|
153
|
+
printJson({ profiles });
|
|
154
|
+
} else {
|
|
155
|
+
printAvailable(profiles);
|
|
156
|
+
}
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const result = await installFromSource(source, options);
|
|
161
|
+
if (options.json) {
|
|
162
|
+
printJson(result);
|
|
163
|
+
} else {
|
|
164
|
+
printOperations(result.operations, result.registryPath);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function printAvailable(profiles) {
|
|
170
|
+
if (profiles.length === 0) {
|
|
171
|
+
console.log("No profiles found.");
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
for (const profile of profiles) {
|
|
175
|
+
console.log(`${profile.slug} ${profile.summary || profile.name}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function printInstalled(result) {
|
|
180
|
+
if (result.installs.length === 0) {
|
|
181
|
+
console.log(`No ${result.scope} profiles installed.`);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
for (const install of result.installs) {
|
|
186
|
+
const missing = install.exists ? "" : " (missing target)";
|
|
187
|
+
console.log(`${install.profile} ${install.harness} ${install.target}${missing}`);
|
|
188
|
+
}
|
|
189
|
+
console.log(`Registry: ${result.registryPath}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function printOperations(operations, registryPath) {
|
|
193
|
+
if (operations.length === 0) {
|
|
194
|
+
console.log("No matching profiles.");
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
for (const operation of operations) {
|
|
199
|
+
console.log(`${operation.action}: ${operation.profile} -> ${operation.harness} at ${operation.target}`);
|
|
200
|
+
}
|
|
201
|
+
if (registryPath) {
|
|
202
|
+
console.log(`Registry: ${registryPath}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function printJson(value) {
|
|
207
|
+
console.log(JSON.stringify(value, null, 2));
|
|
208
|
+
}
|
package/src/constants.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const PACKAGE_NAME = "awesome-agents";
|
|
2
|
+
export const PACKAGE_VERSION = "0.1.0";
|
|
3
|
+
export const DEFAULT_SOURCE = "pablof7z/touch-grass";
|
|
4
|
+
export const DEFAULT_AGENT = "codex";
|
|
5
|
+
export const SUPPORTED_AGENTS = ["codex", "claude-code", "opencode"];
|
|
6
|
+
export const REGISTRY_DIRNAME = ".awesome-agents";
|
|
7
|
+
export const REGISTRY_FILENAME = "installed.json";
|
|
8
|
+
export const GENERATED_MARKER = "Generated by awesome-agents";
|
|
9
|
+
|
|
10
|
+
export const AGENT_ALIASES = new Map([
|
|
11
|
+
["codex", "codex"],
|
|
12
|
+
["openai", "codex"],
|
|
13
|
+
["openai-codex", "codex"],
|
|
14
|
+
["claude", "claude-code"],
|
|
15
|
+
["claude-code", "claude-code"],
|
|
16
|
+
["claudecode", "claude-code"],
|
|
17
|
+
["opencode", "opencode"],
|
|
18
|
+
["open-code", "opencode"]
|
|
19
|
+
]);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import YAML from "yaml";
|
|
2
|
+
|
|
3
|
+
export function parseFrontmatter(text, filePath = "document") {
|
|
4
|
+
if (!text.startsWith("---")) {
|
|
5
|
+
return { attributes: {}, body: text };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---[ \t]*\r?\n?/);
|
|
9
|
+
if (!match) {
|
|
10
|
+
throw new Error(`Invalid YAML frontmatter in ${filePath}`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let attributes;
|
|
14
|
+
try {
|
|
15
|
+
attributes = YAML.parse(match[1]) ?? {};
|
|
16
|
+
} catch (error) {
|
|
17
|
+
throw new Error(`Could not parse YAML frontmatter in ${filePath}: ${error.message}`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
attributes,
|
|
22
|
+
body: text.slice(match[0].length).trimStart()
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function stringifyFrontmatter(attributes, body) {
|
|
27
|
+
const yaml = YAML.stringify(attributes, {
|
|
28
|
+
collectionStyle: "block",
|
|
29
|
+
lineWidth: 0
|
|
30
|
+
}).trimEnd();
|
|
31
|
+
|
|
32
|
+
return `---\n${yaml}\n---\n\n${body.trimStart()}`;
|
|
33
|
+
}
|