ma-agents 1.5.0 → 1.7.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/CLAUDE.md +14 -0
- package/lib/agents.js +12 -6
- package/lib/installer.js +99 -3
- package/package.json +1 -1
- package/skills/README.md +1 -1
- package/skills/git-workflow-skill/SKILL.md +20 -7
- package/skills/git-workflow-skill/skill.json +18 -4
- package/skills/js-ts-security-skill/skill.json +13 -2
- package/skills/logging-best-practices/skill.json +5 -0
- package/skills/test-accompanied-development/skill.json +5 -0
- package/skills/test-generator/skill.json +12 -2
- package/skills/vercel-react-best-practices/skill.json +14 -2
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
<!-- MA-AGENTS-START -->
|
|
3
|
+
# AI Agent Skills - Planning Instruction
|
|
4
|
+
|
|
5
|
+
You have access to a library of skills in your skills directory. Before starting any task:
|
|
6
|
+
|
|
7
|
+
1. Read the skill manifest at skills/MANIFEST.yaml
|
|
8
|
+
2. Based on the task description, select which skills are relevant
|
|
9
|
+
3. Read only the selected skill files
|
|
10
|
+
4. Then proceed with the task
|
|
11
|
+
|
|
12
|
+
Always load skills marked with always_load: true.
|
|
13
|
+
Do not load skills that are not relevant to the current task.
|
|
14
|
+
<!-- MA-AGENTS-END -->
|
package/lib/agents.js
CHANGED
|
@@ -31,7 +31,8 @@ const agents = [
|
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
fileExtension: '.md',
|
|
34
|
-
template: 'claude-code'
|
|
34
|
+
template: 'claude-code',
|
|
35
|
+
instructionFiles: ['CLAUDE.md']
|
|
35
36
|
},
|
|
36
37
|
{
|
|
37
38
|
id: 'gemini',
|
|
@@ -50,7 +51,8 @@ const agents = [
|
|
|
50
51
|
}
|
|
51
52
|
},
|
|
52
53
|
fileExtension: '.md',
|
|
53
|
-
template: 'generic'
|
|
54
|
+
template: 'generic',
|
|
55
|
+
instructionFiles: [] // Gemini doesn't have a standard project-level instruction file yet
|
|
54
56
|
},
|
|
55
57
|
{
|
|
56
58
|
id: 'copilot',
|
|
@@ -69,7 +71,8 @@ const agents = [
|
|
|
69
71
|
}
|
|
70
72
|
},
|
|
71
73
|
fileExtension: '.md',
|
|
72
|
-
template: 'generic'
|
|
74
|
+
template: 'generic',
|
|
75
|
+
instructionFiles: [] // Copilot uses path-scoped instructions, maybe support .github/instructions/ later
|
|
73
76
|
},
|
|
74
77
|
{
|
|
75
78
|
id: 'kilocode',
|
|
@@ -88,7 +91,8 @@ const agents = [
|
|
|
88
91
|
}
|
|
89
92
|
},
|
|
90
93
|
fileExtension: '.md',
|
|
91
|
-
template: 'generic'
|
|
94
|
+
template: 'generic',
|
|
95
|
+
instructionFiles: []
|
|
92
96
|
},
|
|
93
97
|
{
|
|
94
98
|
id: 'cline',
|
|
@@ -112,7 +116,8 @@ const agents = [
|
|
|
112
116
|
resourceMap: {
|
|
113
117
|
'references': 'docs',
|
|
114
118
|
'assets': 'templates'
|
|
115
|
-
}
|
|
119
|
+
},
|
|
120
|
+
instructionFiles: ['.clinerules']
|
|
116
121
|
},
|
|
117
122
|
{
|
|
118
123
|
id: 'cursor',
|
|
@@ -131,7 +136,8 @@ const agents = [
|
|
|
131
136
|
}
|
|
132
137
|
},
|
|
133
138
|
fileExtension: '.md',
|
|
134
|
-
template: 'generic'
|
|
139
|
+
template: 'generic',
|
|
140
|
+
instructionFiles: [] // Cursor uses .cursorrules or individual .mdc files
|
|
135
141
|
}
|
|
136
142
|
];
|
|
137
143
|
|
package/lib/installer.js
CHANGED
|
@@ -52,6 +52,84 @@ function getInstalledSkillInfo(installPath, skillId) {
|
|
|
52
52
|
return manifest.skills[skillId];
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
async function generateSkillsManifest(installPath, agent) {
|
|
56
|
+
const skills = listSkills();
|
|
57
|
+
const manifest = readManifest(installPath);
|
|
58
|
+
if (!manifest || !manifest.skills) return;
|
|
59
|
+
|
|
60
|
+
const manifestYamlPath = path.join(installPath, 'MANIFEST.yaml');
|
|
61
|
+
let yamlContent = '# skills/MANIFEST.yaml\n\nskills:\n';
|
|
62
|
+
|
|
63
|
+
const skillIds = Object.keys(manifest.skills).sort();
|
|
64
|
+
for (const skillId of skillIds) {
|
|
65
|
+
const skill = skills.find(s => s.id === skillId);
|
|
66
|
+
if (!skill) continue;
|
|
67
|
+
|
|
68
|
+
yamlContent += ` - id: ${skillId}\n`;
|
|
69
|
+
yamlContent += ` file: skills/${skillId}/SKILL.md\n`;
|
|
70
|
+
yamlContent += ` description: ${skill.description}\n`;
|
|
71
|
+
|
|
72
|
+
if (skill.applies_when && Array.isArray(skill.applies_when)) {
|
|
73
|
+
yamlContent += ' applies_when:\n';
|
|
74
|
+
skill.applies_when.forEach(cond => {
|
|
75
|
+
yamlContent += ` - ${cond}\n`;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (skill.always_load) {
|
|
80
|
+
yamlContent += ' always_load: true\n';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
yamlContent += '\n';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
await fs.writeFile(manifestYamlPath, yamlContent, 'utf-8');
|
|
87
|
+
console.log(chalk.cyan(` + Generated ${manifestYamlPath}`));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function updateAgentInstructions(agent, projectRoot) {
|
|
91
|
+
if (!agent.instructionFiles || agent.instructionFiles.length === 0) return;
|
|
92
|
+
|
|
93
|
+
const planningInstruction = `
|
|
94
|
+
# AI Agent Skills - Planning Instruction
|
|
95
|
+
|
|
96
|
+
You have access to a library of skills in your skills directory. Before starting any task:
|
|
97
|
+
|
|
98
|
+
1. Read the skill manifest at skills/MANIFEST.yaml
|
|
99
|
+
2. Based on the task description, select which skills are relevant
|
|
100
|
+
3. Read only the selected skill files
|
|
101
|
+
4. Then proceed with the task
|
|
102
|
+
|
|
103
|
+
Always load skills marked with always_load: true.
|
|
104
|
+
Do not load skills that are not relevant to the current task.
|
|
105
|
+
`;
|
|
106
|
+
|
|
107
|
+
const markerStart = '<!-- MA-AGENTS-START -->';
|
|
108
|
+
const markerEnd = '<!-- MA-AGENTS-END -->';
|
|
109
|
+
const wrappedInstruction = `\n${markerStart}${planningInstruction}${markerEnd}\n`;
|
|
110
|
+
|
|
111
|
+
for (const fileName of agent.instructionFiles) {
|
|
112
|
+
const filePath = path.join(projectRoot, fileName);
|
|
113
|
+
let content = '';
|
|
114
|
+
|
|
115
|
+
if (fs.existsSync(filePath)) {
|
|
116
|
+
content = await fs.readFile(filePath, 'utf-8');
|
|
117
|
+
|
|
118
|
+
const regex = new RegExp(`${markerStart}[\\s\\S]*?${markerEnd}`, 'g');
|
|
119
|
+
if (regex.test(content)) {
|
|
120
|
+
content = content.replace(regex, wrappedInstruction.trim());
|
|
121
|
+
} else {
|
|
122
|
+
content += wrappedInstruction;
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
content = wrappedInstruction;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
129
|
+
console.log(chalk.cyan(` + Updated ${fileName}`));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
55
133
|
/**
|
|
56
134
|
* Compare two semver strings. Returns -1, 0, or 1.
|
|
57
135
|
*/
|
|
@@ -252,6 +330,12 @@ async function installSkill(skillId, agentIds, customPath = '', scope = 'project
|
|
|
252
330
|
delete manifest.skills[skillId];
|
|
253
331
|
writeManifest(installPath, manifest);
|
|
254
332
|
console.log(chalk.green(` - Removed ${skill.name} from ${agent.name}`));
|
|
333
|
+
|
|
334
|
+
// Generate MANIFEST.yaml and update agent instruction files
|
|
335
|
+
await generateSkillsManifest(installPath, agent);
|
|
336
|
+
if (scope === 'project') {
|
|
337
|
+
await updateAgentInstructions(agent, process.cwd());
|
|
338
|
+
}
|
|
255
339
|
continue;
|
|
256
340
|
}
|
|
257
341
|
|
|
@@ -281,6 +365,12 @@ async function installSkill(skillId, agentIds, customPath = '', scope = 'project
|
|
|
281
365
|
agentVersion: agent.version
|
|
282
366
|
};
|
|
283
367
|
writeManifest(installPath, manifest);
|
|
368
|
+
|
|
369
|
+
// Generate MANIFEST.yaml and update agent instruction files
|
|
370
|
+
await generateSkillsManifest(installPath, agent);
|
|
371
|
+
if (scope === 'project') {
|
|
372
|
+
await updateAgentInstructions(agent, process.cwd());
|
|
373
|
+
}
|
|
284
374
|
}
|
|
285
375
|
} catch (error) {
|
|
286
376
|
console.log(chalk.red(` x Failed: ${error.message}`));
|
|
@@ -330,6 +420,12 @@ async function uninstallSkill(skillId, agentIds, customPath = '', scope = 'proje
|
|
|
330
420
|
writeManifest(installPath, manifest);
|
|
331
421
|
|
|
332
422
|
console.log(chalk.green(` - Removed ${skillId} v${installed.version} from ${agent.name}`));
|
|
423
|
+
|
|
424
|
+
// Generate MANIFEST.yaml and update agent instruction files
|
|
425
|
+
await generateSkillsManifest(installPath, agent);
|
|
426
|
+
if (scope === 'project') {
|
|
427
|
+
await updateAgentInstructions(agent, process.cwd());
|
|
428
|
+
}
|
|
333
429
|
} catch (error) {
|
|
334
430
|
console.log(chalk.red(` x Failed: ${error.message}`));
|
|
335
431
|
}
|
|
@@ -353,9 +449,9 @@ function getStatus(agentIds, customPath = '', scope = 'project') {
|
|
|
353
449
|
const pathsToCheck = customPath
|
|
354
450
|
? [{ path: customPath, scope: 'custom' }]
|
|
355
451
|
: [
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
452
|
+
{ path: projectPath, scope: 'project' },
|
|
453
|
+
{ path: globalPath, scope: 'global' }
|
|
454
|
+
];
|
|
359
455
|
|
|
360
456
|
for (const { path: checkPath, scope: checkScope } of pathsToCheck) {
|
|
361
457
|
const manifest = readManifest(checkPath);
|
package/package.json
CHANGED
package/skills/README.md
CHANGED
|
@@ -7,7 +7,7 @@ This directory contains reusable skills for development workflows.
|
|
|
7
7
|
### 1. Git Workflow Skill
|
|
8
8
|
**Directory:** `git-workflow-skill/`
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
**MANDATORY** feature branch workflow for ALL file-changing operations. Enforces branch creation via worktrees, conventional commits, automatic PR creation, and returns to dev branch after push. Agents MUST use this skill for every activity that modifies tracked repository files.
|
|
11
11
|
|
|
12
12
|
**Usage:**
|
|
13
13
|
```bash
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# Mandatory Usage Policy (CRITICAL)
|
|
2
|
+
|
|
3
|
+
**This skill is MANDATORY for all activities that modify tracked files in this repository.**
|
|
4
|
+
|
|
5
|
+
1. **Before starting ANY work** that changes source code, config files, or documentation: You MUST run `./scripts/start-feature.sh` (or the equivalent `git worktree add`) to create an isolated feature branch and worktree.
|
|
6
|
+
2. **During development**: You MUST perform all file-writing activities inside the newly created worktree directory.
|
|
7
|
+
3. **After completing work**: You MUST run `./scripts/finish-feature.sh` (or the equivalent rebase/push/PR/cleanup sequence) to integrate your changes and clean up the worktree.
|
|
8
|
+
|
|
9
|
+
**Failure to follow this workflow is a violation of repository standards.**
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
1
13
|
# Git Workflow (Worktree-Based)
|
|
2
14
|
|
|
3
15
|
Multi-agent parallel development using git worktrees. Each agent gets an isolated working directory — no branch switching, no conflicts between agents.
|
|
@@ -168,10 +180,11 @@ git worktree prune
|
|
|
168
180
|
|
|
169
181
|
## Critical Rules
|
|
170
182
|
|
|
171
|
-
- **NEVER** modify tracked files without being in a worktree on a feature branch
|
|
172
|
-
- **NEVER** commit directly to `dev` or `main
|
|
173
|
-
- **ALWAYS** check if file is gitignored before applying this workflow
|
|
174
|
-
- **ALWAYS** create a worktree
|
|
175
|
-
- **ALWAYS** rebase on `dev` before pushing
|
|
176
|
-
- **ALWAYS** use conventional commit format
|
|
177
|
-
- **ALWAYS** add `.worktrees/` to your `.gitignore
|
|
183
|
+
- **NEVER** modify tracked files without being in a worktree on a feature branch.
|
|
184
|
+
- **NEVER** commit directly to `dev` or `main`.
|
|
185
|
+
- **ALWAYS** check if a file is gitignored before applying this workflow.
|
|
186
|
+
- **ALWAYS** create a worktree **BEFORE** calling any file-writing tools (write_to_file, replace_file_content, etc.).
|
|
187
|
+
- **ALWAYS** rebase on `dev` before pushing.
|
|
188
|
+
- **ALWAYS** use conventional commit format.
|
|
189
|
+
- **ALWAYS** add `.worktrees/` to your `.gitignore`.
|
|
190
|
+
- **ALWAYS** finish the workflow by creating a PR and removing the worktree once work is verified.
|
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "Git Workflow",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "2.
|
|
3
|
+
"description": "MANDATORY worktree-based workflow for ALL file-changing activities. Enforces isolated feature branches, conventional commits, and PR-based merging.",
|
|
4
|
+
"version": "2.1.0",
|
|
5
5
|
"author": "AI Agent Skills",
|
|
6
|
-
"tags": [
|
|
7
|
-
|
|
6
|
+
"tags": [
|
|
7
|
+
"git",
|
|
8
|
+
"worktrees",
|
|
9
|
+
"workflow",
|
|
10
|
+
"branching",
|
|
11
|
+
"conventional-commits",
|
|
12
|
+
"pull-requests",
|
|
13
|
+
"multi-agent"
|
|
14
|
+
],
|
|
15
|
+
"applies_when": [
|
|
16
|
+
"committing changes",
|
|
17
|
+
"creating branches or PRs",
|
|
18
|
+
"any code writing or modification task"
|
|
19
|
+
],
|
|
20
|
+
"always_load": true
|
|
21
|
+
}
|
|
@@ -3,5 +3,16 @@
|
|
|
3
3
|
"description": "Verify security of JavaScript and TypeScript codebases against OWASP Top 10 2025 standards",
|
|
4
4
|
"version": "1.0.0",
|
|
5
5
|
"author": "AI Agent Skills",
|
|
6
|
-
"tags": [
|
|
7
|
-
|
|
6
|
+
"tags": [
|
|
7
|
+
"javascript",
|
|
8
|
+
"typescript",
|
|
9
|
+
"security",
|
|
10
|
+
"OWASP",
|
|
11
|
+
"vulnerability-scanning"
|
|
12
|
+
],
|
|
13
|
+
"applies_when": [
|
|
14
|
+
"writing or reviewing security-critical code",
|
|
15
|
+
"analyzing third-party dependencies",
|
|
16
|
+
"performing security audits"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -3,5 +3,15 @@
|
|
|
3
3
|
"description": "Generates comprehensive unit and integration tests",
|
|
4
4
|
"version": "1.0.0",
|
|
5
5
|
"author": "AI Agent Skills",
|
|
6
|
-
"tags": [
|
|
7
|
-
|
|
6
|
+
"tags": [
|
|
7
|
+
"testing",
|
|
8
|
+
"unit-tests",
|
|
9
|
+
"integration-tests",
|
|
10
|
+
"quality"
|
|
11
|
+
],
|
|
12
|
+
"applies_when": [
|
|
13
|
+
"creating new code files",
|
|
14
|
+
"adding complex logic",
|
|
15
|
+
"refactoring existing code"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -4,5 +4,17 @@
|
|
|
4
4
|
"version": "1.0.0",
|
|
5
5
|
"author": "vercel-labs",
|
|
6
6
|
"source": "https://skills.sh/vercel-labs/agent-skills/vercel-react-best-practices",
|
|
7
|
-
"tags": [
|
|
8
|
-
|
|
7
|
+
"tags": [
|
|
8
|
+
"react",
|
|
9
|
+
"nextjs",
|
|
10
|
+
"performance",
|
|
11
|
+
"optimization",
|
|
12
|
+
"vercel",
|
|
13
|
+
"best-practices"
|
|
14
|
+
],
|
|
15
|
+
"applies_when": [
|
|
16
|
+
"working on React or Next.js components",
|
|
17
|
+
"optimizing page performance",
|
|
18
|
+
"reviewing frontend code architecture"
|
|
19
|
+
]
|
|
20
|
+
}
|