@devxiyang/agent-skill 0.0.8 → 0.1.1
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/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/node/SKILL.md +173 -0
- package/skills/node/references/install.md +63 -0
- package/skills/python/SKILL.md +14 -0
- package/skills/shell/SKILL.md +93 -2
- package/skills/vcs/SKILL.md +207 -0
- package/dist/copy.test.d.ts +0 -2
- package/dist/copy.test.d.ts.map +0 -1
- package/dist/copy.test.js +0 -66
- package/dist/copy.test.js.map +0 -1
- package/dist/discovery/discovery.test.d.ts +0 -2
- package/dist/discovery/discovery.test.d.ts.map +0 -1
- package/dist/discovery/discovery.test.js +0 -128
- package/dist/discovery/discovery.test.js.map +0 -1
- package/dist/discovery/frontmatter.test.d.ts +0 -2
- package/dist/discovery/frontmatter.test.d.ts.map +0 -1
- package/dist/discovery/frontmatter.test.js +0 -39
- package/dist/discovery/frontmatter.test.js.map +0 -1
- package/skills/git/SKILL.md +0 -166
- package/skills/github/SKILL.md +0 -112
- package/skills/jq/SKILL.md +0 -109
- package/skills/jq/references/install.md +0 -38
- package/skills/weather/SKILL.md +0 -50
- package/skills/web/SKILL.md +0 -139
- package/skills/web/references/install.md +0 -51
- /package/skills/{weather/references/install.md → shell/references/install-curl.md} +0 -0
- /package/skills/{github/references/install.md → vcs/references/install-gh.md} +0 -0
- /package/skills/{git/references/install.md → vcs/references/install-git.md} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.test.d.ts","sourceRoot":"","sources":["../../src/discovery/discovery.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
2
|
-
import fs from 'node:fs/promises';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import os from 'node:os';
|
|
5
|
-
import { SkillDiscovery } from './discovery.js';
|
|
6
|
-
// ---------------------------------------------------------------------------
|
|
7
|
-
// Fixture helpers
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
async function makeSkillDir(root, name, frontmatter, body = '') {
|
|
10
|
-
const dir = path.join(root, name);
|
|
11
|
-
await fs.mkdir(dir, { recursive: true });
|
|
12
|
-
await fs.writeFile(path.join(dir, 'SKILL.md'), `---\n${frontmatter}\n---\n${body}`);
|
|
13
|
-
return dir;
|
|
14
|
-
}
|
|
15
|
-
let tmpDir;
|
|
16
|
-
beforeAll(async () => {
|
|
17
|
-
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'agent-skill-test-'));
|
|
18
|
-
});
|
|
19
|
-
afterAll(async () => {
|
|
20
|
-
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
21
|
-
});
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
describe('SkillDiscovery.list()', () => {
|
|
24
|
-
it('returns empty list when root does not exist', async () => {
|
|
25
|
-
const d = new SkillDiscovery([{ path: '/nonexistent/path', scope: 'system' }]);
|
|
26
|
-
expect(await d.list()).toEqual([]);
|
|
27
|
-
});
|
|
28
|
-
it('discovers a valid skill', async () => {
|
|
29
|
-
const root = path.join(tmpDir, 'basic');
|
|
30
|
-
await makeSkillDir(root, 'git', 'name: git\ndescription: Git skill');
|
|
31
|
-
const d = new SkillDiscovery([{ path: root, scope: 'system' }]);
|
|
32
|
-
const entries = await d.list();
|
|
33
|
-
expect(entries).toHaveLength(1);
|
|
34
|
-
expect(entries[0].name).toBe('git');
|
|
35
|
-
expect(entries[0].description).toBe('Git skill');
|
|
36
|
-
expect(entries[0].scope).toBe('system');
|
|
37
|
-
});
|
|
38
|
-
it('skips directories without SKILL.md', async () => {
|
|
39
|
-
const root = path.join(tmpDir, 'skip');
|
|
40
|
-
await fs.mkdir(path.join(root, 'empty-dir'), { recursive: true });
|
|
41
|
-
await makeSkillDir(root, 'real', 'name: real');
|
|
42
|
-
const d = new SkillDiscovery([{ path: root, scope: 'system' }]);
|
|
43
|
-
const entries = await d.list();
|
|
44
|
-
expect(entries).toHaveLength(1);
|
|
45
|
-
expect(entries[0].name).toBe('real');
|
|
46
|
-
});
|
|
47
|
-
it('user scope takes priority over system scope for same name', async () => {
|
|
48
|
-
const userRoot = path.join(tmpDir, 'priority-user');
|
|
49
|
-
const sysRoot = path.join(tmpDir, 'priority-sys');
|
|
50
|
-
await makeSkillDir(userRoot, 'shared', 'name: shared\ndescription: user version');
|
|
51
|
-
await makeSkillDir(sysRoot, 'shared', 'name: shared\ndescription: system version');
|
|
52
|
-
const d = new SkillDiscovery([
|
|
53
|
-
{ path: userRoot, scope: 'user' },
|
|
54
|
-
{ path: sysRoot, scope: 'system' },
|
|
55
|
-
]);
|
|
56
|
-
const entries = await d.list();
|
|
57
|
-
expect(entries).toHaveLength(1);
|
|
58
|
-
expect(entries[0].description).toBe('user version');
|
|
59
|
-
expect(entries[0].scope).toBe('user');
|
|
60
|
-
});
|
|
61
|
-
it('returns entries sorted by name', async () => {
|
|
62
|
-
const root = path.join(tmpDir, 'sorted');
|
|
63
|
-
for (const name of ['zebra', 'alpha', 'mango']) {
|
|
64
|
-
await makeSkillDir(root, name, `name: ${name}`);
|
|
65
|
-
}
|
|
66
|
-
const d = new SkillDiscovery([{ path: root, scope: 'system' }]);
|
|
67
|
-
const names = (await d.list()).map((e) => e.name);
|
|
68
|
-
expect(names).toEqual([...names].sort());
|
|
69
|
-
});
|
|
70
|
-
it('marks skill ineligible when validator reports missing bin', async () => {
|
|
71
|
-
const root = path.join(tmpDir, 'ineligible-bin');
|
|
72
|
-
await makeSkillDir(root, 'gh', 'name: gh\nrequires: bin:definitely-not-a-real-bin-xyz');
|
|
73
|
-
const validator = {
|
|
74
|
-
checkBin: async () => false,
|
|
75
|
-
checkEnv: () => true,
|
|
76
|
-
checkOs: () => true,
|
|
77
|
-
};
|
|
78
|
-
const d = new SkillDiscovery([{ path: root, scope: 'system' }], validator);
|
|
79
|
-
const [entry] = await d.list();
|
|
80
|
-
expect(entry.eligible).toBe(false);
|
|
81
|
-
expect(entry.missing[0].kind).toBe('bin');
|
|
82
|
-
});
|
|
83
|
-
it('marks skill ineligible when validator reports missing env', async () => {
|
|
84
|
-
const root = path.join(tmpDir, 'ineligible-env');
|
|
85
|
-
await makeSkillDir(root, 'api', 'name: api\nrequires: env:MISSING_API_KEY');
|
|
86
|
-
const validator = {
|
|
87
|
-
checkBin: async () => true,
|
|
88
|
-
checkEnv: () => false,
|
|
89
|
-
checkOs: () => true,
|
|
90
|
-
};
|
|
91
|
-
const d = new SkillDiscovery([{ path: root, scope: 'system' }], validator);
|
|
92
|
-
const [entry] = await d.list();
|
|
93
|
-
expect(entry.eligible).toBe(false);
|
|
94
|
-
expect(entry.missing[0].kind).toBe('env');
|
|
95
|
-
});
|
|
96
|
-
it('marks skill ineligible when OS does not match', async () => {
|
|
97
|
-
const root = path.join(tmpDir, 'ineligible-os');
|
|
98
|
-
await makeSkillDir(root, 'platform', `name: platform\nos: unsupported-os-xyz`);
|
|
99
|
-
const validator = {
|
|
100
|
-
checkBin: async () => true,
|
|
101
|
-
checkEnv: () => true,
|
|
102
|
-
checkOs: () => false,
|
|
103
|
-
};
|
|
104
|
-
const d = new SkillDiscovery([{ path: root, scope: 'system' }], validator);
|
|
105
|
-
const [entry] = await d.list();
|
|
106
|
-
expect(entry.eligible).toBe(false);
|
|
107
|
-
expect(entry.missing[0].kind).toBe('os');
|
|
108
|
-
});
|
|
109
|
-
it('exposes always flag', async () => {
|
|
110
|
-
const root = path.join(tmpDir, 'always');
|
|
111
|
-
await makeSkillDir(root, 'memory', 'name: memory\nalways: true');
|
|
112
|
-
const d = new SkillDiscovery([{ path: root, scope: 'system' }]);
|
|
113
|
-
const [entry] = await d.list();
|
|
114
|
-
expect(entry.always).toBe(true);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
describe('SkillDiscovery.load()', () => {
|
|
118
|
-
it('returns full SKILL.md content including frontmatter', async () => {
|
|
119
|
-
const root = path.join(tmpDir, 'load');
|
|
120
|
-
const dir = await makeSkillDir(root, 'mskill', 'name: mskill', 'This is the body.');
|
|
121
|
-
const filePath = path.join(dir, 'SKILL.md');
|
|
122
|
-
const d = new SkillDiscovery([{ path: root, scope: 'system' }]);
|
|
123
|
-
const content = await d.load(filePath);
|
|
124
|
-
expect(content).toContain('name: mskill');
|
|
125
|
-
expect(content).toContain('This is the body.');
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
//# sourceMappingURL=discovery.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.test.js","sourceRoot":"","sources":["../../src/discovery/discovery.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.test.d.ts","sourceRoot":"","sources":["../../src/discovery/frontmatter.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { parseFrontmatter } from './frontmatter.js';
|
|
3
|
-
const wrap = (body, content = '') => `---\n${body}\n---\n${content}`;
|
|
4
|
-
describe('parseFrontmatter', () => {
|
|
5
|
-
it('returns defaults when no frontmatter', () => {
|
|
6
|
-
const fm = parseFrontmatter('just markdown');
|
|
7
|
-
expect(fm.name).toBeNull();
|
|
8
|
-
expect(fm.description).toBeNull();
|
|
9
|
-
expect(fm.always).toBe(false);
|
|
10
|
-
expect(fm.requiresBins).toEqual([]);
|
|
11
|
-
expect(fm.requiresEnvs).toEqual([]);
|
|
12
|
-
expect(fm.requiresOs).toEqual([]);
|
|
13
|
-
});
|
|
14
|
-
it('parses basic fields', () => {
|
|
15
|
-
const fm = parseFrontmatter(wrap('name: github\ndescription: GitHub CLI skill\nalways: true'));
|
|
16
|
-
expect(fm.name).toBe('github');
|
|
17
|
-
expect(fm.description).toBe('GitHub CLI skill');
|
|
18
|
-
expect(fm.always).toBe(true);
|
|
19
|
-
});
|
|
20
|
-
it('parses requires string', () => {
|
|
21
|
-
const fm = parseFrontmatter(wrap('name: git\nrequires: bin:git,env:GITHUB_TOKEN'));
|
|
22
|
-
expect(fm.requiresBins).toContain('git');
|
|
23
|
-
expect(fm.requiresEnvs).toContain('GITHUB_TOKEN');
|
|
24
|
-
});
|
|
25
|
-
it('handles quoted description', () => {
|
|
26
|
-
const fm = parseFrontmatter(wrap('name: x\ndescription: "hello world"'));
|
|
27
|
-
expect(fm.description).toBe('hello world');
|
|
28
|
-
});
|
|
29
|
-
it('ignores unknown boolean values and uses fallback', () => {
|
|
30
|
-
const fm = parseFrontmatter(wrap('name: x\nalways: maybe'));
|
|
31
|
-
expect(fm.always).toBe(false);
|
|
32
|
-
});
|
|
33
|
-
it('parses top-level os field', () => {
|
|
34
|
-
const fm = parseFrontmatter(wrap('name: tmux\nos: darwin,linux'));
|
|
35
|
-
expect(fm.requiresOs).toContain('darwin');
|
|
36
|
-
expect(fm.requiresOs).toContain('linux');
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
//# sourceMappingURL=frontmatter.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.test.js","sourceRoot":"","sources":["../../src/discovery/frontmatter.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE,CAC1C,QAAQ,IAAI,UAAU,OAAO,EAAE,CAAC;AAElC,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,EAAE,GAAG,gBAAgB,CAAC,eAAe,CAAC,CAAC;QAC7C,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC3B,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;QAClC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACpC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACpC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC,CAAC;QAC/F,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAChD,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAChC,MAAM,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC,CAAC;QACzE,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC;QAC5D,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACnC,MAAM,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC1C,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/skills/git/SKILL.md
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: git
|
|
3
|
-
description: Local git operations — branching, committing, merging, rebasing, history inspection, and conflict resolution.
|
|
4
|
-
requires: bin:git
|
|
5
|
-
tags: vcs,git
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Git Skill
|
|
9
|
-
|
|
10
|
-
## Preflight
|
|
11
|
-
|
|
12
|
-
Verify git is available before proceeding:
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
git --version
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
If missing, load `references/install.md` for installation instructions.
|
|
19
|
-
|
|
20
|
-
## Common workflow
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
git status
|
|
24
|
-
git diff
|
|
25
|
-
git add <files>
|
|
26
|
-
git commit -m "message"
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Branching
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
git checkout -b feature/name
|
|
33
|
-
git switch main
|
|
34
|
-
git branch -d feature/name
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Inspecting history
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
git log --oneline -20
|
|
41
|
-
git log --oneline --graph --all
|
|
42
|
-
git show <commit>
|
|
43
|
-
git diff main...HEAD
|
|
44
|
-
git blame <file>
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Cherry-pick
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
# Apply a specific commit onto the current branch
|
|
51
|
-
git cherry-pick <commit>
|
|
52
|
-
|
|
53
|
-
# Cherry-pick a range
|
|
54
|
-
git cherry-pick <from>..<to>
|
|
55
|
-
|
|
56
|
-
# Cherry-pick without committing (stage only)
|
|
57
|
-
git cherry-pick -n <commit>
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Tags
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
# Create annotated tag
|
|
64
|
-
git tag -a v1.0.0 -m "Release 1.0.0"
|
|
65
|
-
|
|
66
|
-
# List tags
|
|
67
|
-
git tag
|
|
68
|
-
|
|
69
|
-
# Push tags to remote
|
|
70
|
-
git push origin --tags
|
|
71
|
-
|
|
72
|
-
# Delete a tag
|
|
73
|
-
git tag -d v1.0.0
|
|
74
|
-
git push origin :refs/tags/v1.0.0
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Undoing changes
|
|
78
|
-
|
|
79
|
-
```bash
|
|
80
|
-
# Unstage
|
|
81
|
-
git restore --staged <file>
|
|
82
|
-
|
|
83
|
-
# Discard working tree changes
|
|
84
|
-
git restore <file>
|
|
85
|
-
|
|
86
|
-
# Undo last commit (keep changes staged)
|
|
87
|
-
git reset --soft HEAD~1
|
|
88
|
-
|
|
89
|
-
# Interactive rebase to edit recent commits
|
|
90
|
-
git rebase -i HEAD~3
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
## Stashing
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
git stash push -m "description"
|
|
97
|
-
git stash list
|
|
98
|
-
git stash pop
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
## Merging & rebasing
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
# Merge
|
|
105
|
-
git merge feature/name
|
|
106
|
-
|
|
107
|
-
# Rebase onto main
|
|
108
|
-
git rebase main
|
|
109
|
-
|
|
110
|
-
# Abort on conflict
|
|
111
|
-
git rebase --abort
|
|
112
|
-
git merge --abort
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
## Conflict resolution
|
|
116
|
-
|
|
117
|
-
1. Open conflicting files, look for `<<<<<<<` markers
|
|
118
|
-
2. Edit to desired state
|
|
119
|
-
3. `git add <resolved-file>`
|
|
120
|
-
4. `git rebase --continue` or `git merge --continue`
|
|
121
|
-
|
|
122
|
-
## Worktrees
|
|
123
|
-
|
|
124
|
-
Check out multiple branches simultaneously in separate directories — useful for working on or reviewing a branch without touching the current working tree:
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
# Add a worktree for an existing branch
|
|
128
|
-
git worktree add ../project-fix fix/some-bug
|
|
129
|
-
|
|
130
|
-
# Add a worktree and create a new branch
|
|
131
|
-
git worktree add -b feature/new ../project-feature main
|
|
132
|
-
|
|
133
|
-
# List worktrees
|
|
134
|
-
git worktree list
|
|
135
|
-
|
|
136
|
-
# Remove a worktree when done
|
|
137
|
-
git worktree remove ../project-fix
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
Each worktree shares the same repository history but has its own working directory and HEAD.
|
|
141
|
-
|
|
142
|
-
## Debugging
|
|
143
|
-
|
|
144
|
-
```bash
|
|
145
|
-
# Find which commit introduced a bug (binary search)
|
|
146
|
-
git bisect start
|
|
147
|
-
git bisect bad # current commit is broken
|
|
148
|
-
git bisect good <commit> # last known good commit
|
|
149
|
-
# git will check out commits for you to test; mark each:
|
|
150
|
-
git bisect good
|
|
151
|
-
git bisect bad
|
|
152
|
-
git bisect reset # done
|
|
153
|
-
|
|
154
|
-
# Show who last changed each line
|
|
155
|
-
git blame <file>
|
|
156
|
-
git blame -L 10,20 <file> # specific line range
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
## Remotes
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
git remote -v
|
|
163
|
-
git fetch origin
|
|
164
|
-
git pull --rebase
|
|
165
|
-
git push -u origin HEAD
|
|
166
|
-
```
|
package/skills/github/SKILL.md
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: github
|
|
3
|
-
description: Interact with GitHub using the `gh` CLI. Use for issues, pull requests, CI runs, code review, and GitHub API queries.
|
|
4
|
-
requires: bin:gh
|
|
5
|
-
tags: vcs,github
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# GitHub Skill
|
|
9
|
-
|
|
10
|
-
## Preflight
|
|
11
|
-
|
|
12
|
-
Verify gh is available before proceeding:
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
gh --version
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
If missing, load `references/install.md` for installation and authentication instructions.
|
|
19
|
-
|
|
20
|
-
Use the `gh` CLI to interact with GitHub. Always specify `--repo owner/repo` when not inside a git directory.
|
|
21
|
-
|
|
22
|
-
## Pull Requests
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
# List open PRs
|
|
26
|
-
gh pr list --repo owner/repo
|
|
27
|
-
|
|
28
|
-
# View a PR
|
|
29
|
-
gh pr view <number> --repo owner/repo
|
|
30
|
-
|
|
31
|
-
# Check CI status
|
|
32
|
-
gh pr checks <number> --repo owner/repo
|
|
33
|
-
|
|
34
|
-
# View failed CI logs
|
|
35
|
-
gh run view <run-id> --repo owner/repo --log-failed
|
|
36
|
-
|
|
37
|
-
# Merge a PR
|
|
38
|
-
gh pr merge <number> --repo owner/repo --squash
|
|
39
|
-
gh pr merge <number> --repo owner/repo --merge
|
|
40
|
-
gh pr merge <number> --repo owner/repo --rebase
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Code review
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
# Approve
|
|
47
|
-
gh pr review <number> --approve --repo owner/repo
|
|
48
|
-
|
|
49
|
-
# Request changes
|
|
50
|
-
gh pr review <number> --request-changes --body "Please fix X" --repo owner/repo
|
|
51
|
-
|
|
52
|
-
# Leave a comment
|
|
53
|
-
gh pr review <number> --comment --body "Looks good overall" --repo owner/repo
|
|
54
|
-
|
|
55
|
-
# Add inline comment via API
|
|
56
|
-
gh api repos/owner/repo/pulls/<number>/comments \
|
|
57
|
-
--method POST \
|
|
58
|
-
--field body="Comment text" \
|
|
59
|
-
--field commit_id="<sha>" \
|
|
60
|
-
--field path="src/file.ts" \
|
|
61
|
-
--field line=42
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Issues
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
# List issues
|
|
68
|
-
gh issue list --repo owner/repo --state open
|
|
69
|
-
|
|
70
|
-
# View an issue
|
|
71
|
-
gh issue view <number> --repo owner/repo
|
|
72
|
-
|
|
73
|
-
# Create issue
|
|
74
|
-
gh issue create --title "Title" --body "Body" --repo owner/repo
|
|
75
|
-
|
|
76
|
-
# Comment on an issue
|
|
77
|
-
gh issue comment <number> --body "Comment" --repo owner/repo
|
|
78
|
-
|
|
79
|
-
# Close / reopen
|
|
80
|
-
gh issue close <number> --repo owner/repo
|
|
81
|
-
gh issue reopen <number> --repo owner/repo
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Releases
|
|
85
|
-
|
|
86
|
-
```bash
|
|
87
|
-
# List releases
|
|
88
|
-
gh release list --repo owner/repo
|
|
89
|
-
|
|
90
|
-
# Create a release
|
|
91
|
-
gh release create v1.0.0 --repo owner/repo --title "v1.0.0" --notes "Release notes"
|
|
92
|
-
|
|
93
|
-
# Upload assets to a release
|
|
94
|
-
gh release upload v1.0.0 dist/app.zip --repo owner/repo
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## API
|
|
98
|
-
|
|
99
|
-
Use `gh api` for data not available via subcommands:
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
gh api repos/owner/repo/pulls/55 --jq '.title, .state, .user.login'
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## JSON Output
|
|
106
|
-
|
|
107
|
-
Most commands support `--json` + `--jq`:
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
gh issue list --repo owner/repo --json number,title --jq '.[] | "\(.number): \(.title)"'
|
|
111
|
-
gh pr list --repo owner/repo --json number,title,author --jq '.[] | "\(.number): \(.title) by \(.author.login)"'
|
|
112
|
-
```
|
package/skills/jq/SKILL.md
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: jq
|
|
3
|
-
description: Process and transform JSON data using jq. Use when filtering API responses, extracting fields, reshaping JSON, or querying structured data.
|
|
4
|
-
requires: bin:jq
|
|
5
|
-
tags: json,jq
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# jq Skill
|
|
9
|
-
|
|
10
|
-
## Preflight
|
|
11
|
-
|
|
12
|
-
Verify jq is available before proceeding:
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
jq --version
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
If missing, load `references/install.md` for installation instructions.
|
|
19
|
-
|
|
20
|
-
## Basic filtering
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
# Pretty-print JSON
|
|
24
|
-
cat data.json | jq .
|
|
25
|
-
|
|
26
|
-
# Extract a field
|
|
27
|
-
echo '{"name":"alice","age":30}' | jq '.name'
|
|
28
|
-
|
|
29
|
-
# Nested field
|
|
30
|
-
echo '{"user":{"email":"a@b.com"}}' | jq '.user.email'
|
|
31
|
-
|
|
32
|
-
# Array index
|
|
33
|
-
echo '[1,2,3]' | jq '.[0]'
|
|
34
|
-
|
|
35
|
-
# Array slice
|
|
36
|
-
echo '[1,2,3,4,5]' | jq '.[2:4]'
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Iterating arrays
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
# Iterate all elements
|
|
43
|
-
curl -s "https://api.example.com/users" | jq '.[]'
|
|
44
|
-
|
|
45
|
-
# Extract field from each element
|
|
46
|
-
curl -s "https://api.example.com/users" | jq '.[].name'
|
|
47
|
-
|
|
48
|
-
# Same with pipe
|
|
49
|
-
curl -s "https://api.example.com/users" | jq '.[] | .name'
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Selecting & filtering
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
# Filter array by condition
|
|
56
|
-
jq '[.[] | select(.age > 25)]' data.json
|
|
57
|
-
|
|
58
|
-
# Filter by string match
|
|
59
|
-
jq '[.[] | select(.status == "active")]' data.json
|
|
60
|
-
|
|
61
|
-
# Filter by field existence
|
|
62
|
-
jq '[.[] | select(.email != null)]' data.json
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Transforming
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
# Build a new object
|
|
69
|
-
jq '{id: .id, label: .name}' data.json
|
|
70
|
-
|
|
71
|
-
# Map over array
|
|
72
|
-
jq '[.[] | {id: .id, label: .name}]' data.json
|
|
73
|
-
|
|
74
|
-
# Append a field
|
|
75
|
-
jq '. + {processed: true}' data.json
|
|
76
|
-
|
|
77
|
-
# keys, values, length
|
|
78
|
-
jq 'keys' data.json
|
|
79
|
-
jq '.items | length' data.json
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## String interpolation
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
jq '.[] | "User \(.name) is \(.age) years old"' data.json
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Combining with curl
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
# Extract specific field from API response
|
|
92
|
-
curl -s "https://api.example.com/item/1" | jq '.data.title'
|
|
93
|
-
|
|
94
|
-
# Filter and format a list
|
|
95
|
-
curl -s "https://api.example.com/items" | jq '[.[] | select(.active) | {id, name}]'
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Raw output & compact
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
# Raw string output (no quotes)
|
|
102
|
-
jq -r '.name' data.json
|
|
103
|
-
|
|
104
|
-
# Compact output (no whitespace)
|
|
105
|
-
jq -c '.' data.json
|
|
106
|
-
|
|
107
|
-
# Read from file
|
|
108
|
-
jq '.items' data.json
|
|
109
|
-
```
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# Installing jq
|
|
2
|
-
|
|
3
|
-
## macOS
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
brew install jq
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
If Homebrew is not installed, download the binary from https://jqlang.github.io/jq/download/ and place it in `/usr/local/bin`.
|
|
10
|
-
|
|
11
|
-
## Windows
|
|
12
|
-
|
|
13
|
-
If winget is available:
|
|
14
|
-
|
|
15
|
-
```powershell
|
|
16
|
-
winget install jqlang.jq
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Download the binary directly from https://jqlang.github.io/jq/download/ — pick `jq-windows-amd64.exe`, rename to `jq.exe`, and add its location to PATH.
|
|
20
|
-
|
|
21
|
-
If Chocolatey is available:
|
|
22
|
-
|
|
23
|
-
```powershell
|
|
24
|
-
choco install jq
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Linux
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
# Debian/Ubuntu
|
|
31
|
-
sudo apt install jq
|
|
32
|
-
|
|
33
|
-
# Fedora
|
|
34
|
-
sudo dnf install jq
|
|
35
|
-
|
|
36
|
-
# Arch
|
|
37
|
-
sudo pacman -S jq
|
|
38
|
-
```
|
package/skills/weather/SKILL.md
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: weather
|
|
3
|
-
description: Get current weather and forecasts for any location. No API key required.
|
|
4
|
-
requires: bin:curl
|
|
5
|
-
tags: weather,web
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Weather Skill
|
|
9
|
-
|
|
10
|
-
## Preflight
|
|
11
|
-
|
|
12
|
-
Verify curl is available before proceeding:
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
curl --version
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
If missing, load `references/install.md` for installation instructions.
|
|
19
|
-
|
|
20
|
-
Two free services, no API keys needed.
|
|
21
|
-
|
|
22
|
-
## wttr.in (primary)
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
# One-liner
|
|
26
|
-
curl -s "wttr.in/London?format=3"
|
|
27
|
-
# London: ⛅️ +8°C
|
|
28
|
-
|
|
29
|
-
# Compact format
|
|
30
|
-
curl -s "wttr.in/London?format=%l:+%c+%t+%h+%w"
|
|
31
|
-
|
|
32
|
-
# Full 3-day forecast
|
|
33
|
-
curl -s "wttr.in/London?T"
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Format codes: `%c` condition · `%t` temp · `%h` humidity · `%w` wind · `%l` location
|
|
37
|
-
|
|
38
|
-
Tips:
|
|
39
|
-
- URL-encode spaces: `wttr.in/New+York`
|
|
40
|
-
- Airport codes work: `wttr.in/JFK`
|
|
41
|
-
- Units: `?m` metric · `?u` imperial
|
|
42
|
-
- Today only: `?1` · Current only: `?0`
|
|
43
|
-
|
|
44
|
-
## Open-Meteo (fallback, JSON, no key)
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
curl -s "https://api.open-meteo.com/v1/forecast?latitude=51.5&longitude=-0.12¤t_weather=true"
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Get coordinates first, then query. Returns JSON with temperature, windspeed, and weather code.
|