@acmecloud/core 1.0.5 → 1.0.7
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/dist/skills/builtin/code-concise.md +84 -0
- package/dist/skills/builtin/frontend-design.md +137 -0
- package/dist/skills/builtin/systematic-debugging.md +156 -0
- package/dist/skills/builtin/tdd.md +157 -0
- package/dist/skills/builtin/windows-shell-guide.md +119 -0
- package/dist/skills/index.js +56 -11
- package/package.json +5 -3
- package/src/skills/builtin/code-concise.md +84 -0
- package/src/skills/builtin/frontend-design.md +137 -0
- package/src/skills/builtin/systematic-debugging.md +156 -0
- package/src/skills/builtin/tdd.md +157 -0
- package/src/skills/builtin/windows-shell-guide.md +119 -0
- package/src/skills/index.ts +141 -86
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: windows-shell-guide
|
|
3
|
+
description: Windows PowerShell command reference - use on Windows instead of Unix commands
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Windows Shell Guide
|
|
7
|
+
|
|
8
|
+
**Use when OS is Windows (win32)**
|
|
9
|
+
|
|
10
|
+
## Forbidden Commands on Windows
|
|
11
|
+
|
|
12
|
+
**DO NOT use:**
|
|
13
|
+
`head`, `tail`, `grep`, `sed`, `awk`, `xargs`, `wc`, `ls`, `cp`, `mv`, `rm`, `ps`, `kill`, `chmod`, `chown`
|
|
14
|
+
|
|
15
|
+
## Quick Reference
|
|
16
|
+
|
|
17
|
+
| Need | PowerShell Command |
|
|
18
|
+
| -------------- | ------------------------------------ |
|
|
19
|
+
| View file | `Get-Content file` |
|
|
20
|
+
| First N lines | `Get-Content file -Head N` |
|
|
21
|
+
| Last N lines | `Get-Content file -Tail N` |
|
|
22
|
+
| Search text | `Select-String "pattern" file` |
|
|
23
|
+
| Count lines | `(Get-Content file).Count` |
|
|
24
|
+
| List files | `Get-ChildItem` |
|
|
25
|
+
| Copy file | `Copy-Item src dest` |
|
|
26
|
+
| Move file | `Move-Item src dest` |
|
|
27
|
+
| Delete file | `Remove-Item file -Force` |
|
|
28
|
+
| Delete folder | `Remove-Item folder -Recurse -Force` |
|
|
29
|
+
| List processes | `Get-Process` |
|
|
30
|
+
| Kill process | `Stop-Process -Id PID -Force` |
|
|
31
|
+
|
|
32
|
+
## Common Patterns
|
|
33
|
+
|
|
34
|
+
### File Operations
|
|
35
|
+
|
|
36
|
+
```powershell
|
|
37
|
+
# Read file
|
|
38
|
+
Get-Content file.txt
|
|
39
|
+
|
|
40
|
+
# Search in file
|
|
41
|
+
Select-String "error" file.txt
|
|
42
|
+
|
|
43
|
+
# Count lines
|
|
44
|
+
(Get-Content file.txt).Count
|
|
45
|
+
|
|
46
|
+
# Find files
|
|
47
|
+
Get-ChildItem -Filter "*.py" -Recurse
|
|
48
|
+
|
|
49
|
+
# Delete with force
|
|
50
|
+
Remove-Item file.txt -Force
|
|
51
|
+
Remove-Item folder -Recurse -Force
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Process Management
|
|
55
|
+
|
|
56
|
+
```powershell
|
|
57
|
+
# List processes
|
|
58
|
+
Get-Process python
|
|
59
|
+
|
|
60
|
+
# Kill process
|
|
61
|
+
Stop-Process -Id 1234 -Force
|
|
62
|
+
|
|
63
|
+
# Filter processes
|
|
64
|
+
Get-Process | Where-Object {$_.Name -like "python"}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Pipes and Filtering
|
|
68
|
+
|
|
69
|
+
```powershell
|
|
70
|
+
# Find files > 1MB
|
|
71
|
+
Get-ChildItem -Recurse | Where-Object {$_.Length -gt 1MB}
|
|
72
|
+
|
|
73
|
+
# Search in multiple files
|
|
74
|
+
Get-ChildItem -Filter "*.log" | Select-String "ERROR"
|
|
75
|
+
|
|
76
|
+
# Get top 5 by CPU
|
|
77
|
+
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Common Mistakes
|
|
81
|
+
|
|
82
|
+
| Unix (DON'T) | PowerShell (DO) |
|
|
83
|
+
| ------------------- | ------------------------------------ |
|
|
84
|
+
| `head file.txt` | `Get-Content file.txt -Head 10` |
|
|
85
|
+
| `grep "pattern"` | `Select-String "pattern"` |
|
|
86
|
+
| `cat file \| wc -l` | `(Get-Content file).Count` |
|
|
87
|
+
| `rm -rf folder` | `Remove-Item folder -Recurse -Force` |
|
|
88
|
+
| `ls -la` | `Get-ChildItem` |
|
|
89
|
+
|
|
90
|
+
## Safe Execution
|
|
91
|
+
|
|
92
|
+
```powershell
|
|
93
|
+
# Dry run (preview changes)
|
|
94
|
+
Get-ChildItem folder -Recurse -WhatIf
|
|
95
|
+
|
|
96
|
+
# Check before delete
|
|
97
|
+
if (Test-Path file.txt) { Remove-Item file.txt }
|
|
98
|
+
|
|
99
|
+
# Suppress errors
|
|
100
|
+
Get-Content file.txt -ErrorAction SilentlyContinue
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Common Parameters
|
|
104
|
+
|
|
105
|
+
- `-WhatIf` - Preview changes
|
|
106
|
+
- `-Confirm` - Prompt before execution
|
|
107
|
+
- `-ErrorAction` - Stop, SilentlyContinue, Continue
|
|
108
|
+
- `-Verbose` - Detailed output
|
|
109
|
+
- `-Recurse` - Include subdirectories
|
|
110
|
+
- `-Force` - Override restrictions
|
|
111
|
+
|
|
112
|
+
## Key Principles
|
|
113
|
+
|
|
114
|
+
1. Always check OS first
|
|
115
|
+
2. Use PowerShell Verb-Noun syntax
|
|
116
|
+
3. Reference this guide before guessing
|
|
117
|
+
4. Test dangerous operations with `-WhatIf`
|
|
118
|
+
|
|
119
|
+
**Stop errors before they happen:** Check OS, read guide, execute correctly.
|
package/src/skills/index.ts
CHANGED
|
@@ -1,86 +1,141 @@
|
|
|
1
|
-
import * as fs from
|
|
2
|
-
import path from
|
|
3
|
-
import os from
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import { dirname } from "path";
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
|
|
10
|
+
export interface Skill {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
content: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Load built-in skills from the builtin directory
|
|
18
|
+
*/
|
|
19
|
+
async function loadBuiltinSkills(): Promise<Skill[]> {
|
|
20
|
+
const builtinSkillsDir = path.join(__dirname, "builtin");
|
|
21
|
+
const skills: Skill[] = [];
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const files = await fs.readdir(builtinSkillsDir);
|
|
25
|
+
for (const file of files) {
|
|
26
|
+
if (file.endsWith(".md")) {
|
|
27
|
+
const filePath = path.join(builtinSkillsDir, file);
|
|
28
|
+
const content = await fs.readFile(filePath, "utf8");
|
|
29
|
+
let name = file.replace(".md", "");
|
|
30
|
+
let description = `Skill ${name}`;
|
|
31
|
+
|
|
32
|
+
// Extract name from frontmatter
|
|
33
|
+
const nameMatch = content.match(/^---[\r\n]+name:\s*(.*)/m);
|
|
34
|
+
if (nameMatch) {
|
|
35
|
+
name = nameMatch[1].trim();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Extract description from frontmatter
|
|
39
|
+
const descriptionMatch = content.match(/^description:\s*(.*)/m);
|
|
40
|
+
if (descriptionMatch) {
|
|
41
|
+
description = descriptionMatch[1].trim();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
skills.push({ name, description, content });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} catch (err: any) {
|
|
48
|
+
if (err.code !== "ENOENT") {
|
|
49
|
+
console.warn(`Could not read builtin skills: ${err.message}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return skills;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Searches upward from startDir for the given targets.
|
|
58
|
+
*/
|
|
59
|
+
async function findUpDirectories(
|
|
60
|
+
startDir: string,
|
|
61
|
+
targets: string[],
|
|
62
|
+
): Promise<string[]> {
|
|
63
|
+
const results: string[] = [];
|
|
64
|
+
let current = path.resolve(startDir);
|
|
65
|
+
const root = path.parse(current).root;
|
|
66
|
+
|
|
67
|
+
while (true) {
|
|
68
|
+
for (const target of targets) {
|
|
69
|
+
const fullPath = path.join(current, target);
|
|
70
|
+
try {
|
|
71
|
+
const stat = await fs.stat(fullPath);
|
|
72
|
+
if (stat.isDirectory()) {
|
|
73
|
+
results.push(fullPath);
|
|
74
|
+
}
|
|
75
|
+
} catch {
|
|
76
|
+
// Ignore
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (current === root) break;
|
|
80
|
+
current = path.dirname(current);
|
|
81
|
+
}
|
|
82
|
+
return results;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function loadSkills(): Promise<Skill[]> {
|
|
86
|
+
const globalSkillsPath = path.join(os.homedir(), ".acmecode", "skills");
|
|
87
|
+
|
|
88
|
+
// OpenCode patterns: .agents/skills, .claude/skills, .acmecode/skills
|
|
89
|
+
const searchTargets = [
|
|
90
|
+
".acmecode/skills",
|
|
91
|
+
".agents/skills",
|
|
92
|
+
".claude/skills",
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
const localSkillDirs = await findUpDirectories(process.cwd(), searchTargets);
|
|
96
|
+
|
|
97
|
+
// Priority: Lower directories in the tree (closer to project root) are processed first,
|
|
98
|
+
// and higher directories (closer to CWD) are processed last to overwrite.
|
|
99
|
+
// Global is processed first of all.
|
|
100
|
+
const allDirs = [globalSkillsPath, ...localSkillDirs.reverse()];
|
|
101
|
+
const skillsMap = new Map<string, Skill>();
|
|
102
|
+
|
|
103
|
+
// First, load built-in skills
|
|
104
|
+
const builtinSkills = await loadBuiltinSkills();
|
|
105
|
+
for (const skill of builtinSkills) {
|
|
106
|
+
skillsMap.set(skill.name, skill);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Then load user skills (can override built-ins)
|
|
110
|
+
for (const dir of allDirs) {
|
|
111
|
+
try {
|
|
112
|
+
const files = await fs.readdir(dir);
|
|
113
|
+
for (const file of files) {
|
|
114
|
+
if (file.endsWith(".md")) {
|
|
115
|
+
const content = await fs.readFile(path.join(dir, file), "utf8");
|
|
116
|
+
let name = file.replace(".md", "");
|
|
117
|
+
|
|
118
|
+
// Improved parsing: Look for name and description in YAML frontmatter or content
|
|
119
|
+
let description = `Skill ${name}`;
|
|
120
|
+
|
|
121
|
+
// Try to extract name from frontmatter
|
|
122
|
+
const nameMatch = content.match(/^name:\s*(.*)/m);
|
|
123
|
+
if (nameMatch) name = nameMatch[1].trim();
|
|
124
|
+
|
|
125
|
+
const descriptionMatch = content.match(/^description:\s*(.*)/m);
|
|
126
|
+
if (descriptionMatch) {
|
|
127
|
+
description = descriptionMatch[1].trim();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
skillsMap.set(name, { name, description, content });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
} catch (err: any) {
|
|
134
|
+
if (err.code !== "ENOENT") {
|
|
135
|
+
console.warn(`Could not read skills directory ${dir}: ${err.message}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return Array.from(skillsMap.values());
|
|
141
|
+
}
|