Skip to content

Commit 4aa226a

Browse files
authored
feat: gh to md skill (#5)
https://github.com/o-az/2md skill
1 parent 05ea320 commit 4aa226a

5 files changed

Lines changed: 451 additions & 0 deletions

File tree

.github/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Hand-crafted [skills](https://skills.sh) for agents, built from workflows I kept
99
| [upload-image](/skills/upload-image) | Uploads images to [imgbb](https://ibb.co) — local files, URLs, SVGs, base64, whatever. No more manual hosting. |
1010
| [terminal-recording](/skills/terminal-recording) | Record, upload, and GIF-convert terminal sessions with [`asciinema`](https://github.com/asciinema/asciinema) and [`agg`](https://github.com/asciinema/agg). |
1111
| [ghostty-remote-control](/skills/ghostty-remote-control) | kitty-inspired `kitten` remote control for agents to control ghostty terminal sessions, tabs, and windows. |
12+
| [github-to-markdown](/skills/github-to-markdown) | Uses [2md](https://github.com/o-az/2md) to convert a GitHub repo, directory, or file into a single markdown document for LLM or documentation workflows. |
1213

1314
> [!NOTE]
1415
> Skills are reusable capabilities for AI agents. They provide procedural knowledge that helps agents accomplish specific tasks more effectively. Skills can include code generation patterns, domain expertise, tool integrations, and more.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"skill_name": "github-to-markdown",
3+
"evals": [
4+
{
5+
"id": "whole-repo-bundle",
6+
"prompt": "Turn github.com/honojs/hono into one markdown document I can hand to an LLM, and save it locally.",
7+
"expected_output": "A 2md-based workflow that targets the full repo and saves the generated markdown to a local file.",
8+
"assertions": [
9+
"The workflow uses the 2md hosted endpoint or CLI",
10+
"The target is normalized as a GitHub repository rather than a local path",
11+
"The result includes a concrete output file path or filename"
12+
]
13+
},
14+
{
15+
"id": "directory-with-filters",
16+
"prompt": "Bundle only the TypeScript source from https://github.com/vercel-labs/json-render/tree/main/examples/dashboard and exclude tests.",
17+
"expected_output": "A filtered 2md request for the specified directory using include and exclude parameters.",
18+
"assertions": [
19+
"The workflow targets the provided directory URL",
20+
"The result uses include or exclude query parameters",
21+
"The response avoids bundling the whole repository when a directory was requested"
22+
]
23+
},
24+
{
25+
"id": "single-file-cli-command",
26+
"prompt": "Give me a rerunnable command to convert https://github.com/honojs/hono/blob/main/README.md into markdown.",
27+
"expected_output": "A concrete CLI command using github:o-az/2md that converts the given file URL and can be rerun locally, preferring bunx and falling back to npx --yes.",
28+
"assertions": [
29+
"The response provides a concrete CLI command using bunx or npx --yes",
30+
"The command uses github:o-az/2md",
31+
"The command targets the single file URL rather than the repo root"
32+
]
33+
},
34+
{
35+
"id": "nonexistent-repo-error",
36+
"prompt": "Convert github.com/nonexistent-user-xyz/fake-repo-abc into markdown.",
37+
"expected_output": "The agent attempts the 2md workflow and surfaces the resulting HTTP or 2md error instead of fabricating markdown content.",
38+
"assertions": [
39+
"The agent does not fabricate markdown content for a nonexistent repo",
40+
"The response mentions an error, failure, or inability to fetch the repo",
41+
"The workflow still uses 2md rather than inventing an alternate source"
42+
]
43+
},
44+
{
45+
"id": "preserve-non-main-ref",
46+
"prompt": "Bundle only the CLI branch source from https://github.com/o-az/2md/tree/cli/src and keep that exact ref.",
47+
"expected_output": "A directory-scoped 2md workflow that preserves the cli ref and does not rewrite it to main.",
48+
"assertions": [
49+
"The workflow preserves the provided non-main ref",
50+
"The response does not rewrite the request to main",
51+
"The response keeps the scope limited to the requested src directory"
52+
]
53+
},
54+
{
55+
"id": "local-path-non-trigger",
56+
"prompt": "Convert ./src into one markdown document for me.",
57+
"expected_output": "The agent recognizes that this skill is for GitHub-hosted input and does not incorrectly treat the local path as a valid 2md target.",
58+
"assertions": [
59+
"The response does not present ./src as a valid 2md GitHub target",
60+
"The response notes that the input is a local path or otherwise outside this skill's normal scope",
61+
"The response does not fabricate a github.com URL from the local path"
62+
]
63+
}
64+
]
65+
}

skills/github-to-markdown/SKILL.md

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
---
2+
name: github-to-markdown
3+
description: Converts a GitHub repository, directory, or file into a single markdown document using 2md. Use when asked to convert a repo to markdown, flatten GitHub code into one file, dump a repo for an LLM, bundle source for a prompt, snapshot GitHub code, or use 2md.
4+
license: MIT
5+
compatibility: Requires internet access and either curl or Bun/Node.js for the optional CLI path
6+
metadata:
7+
author: github.com/o-az
8+
version: "1.0.0"
9+
---
10+
11+
# github-to-markdown
12+
13+
Use [2md](https://github.com/o-az/2md) to turn a GitHub repository, subdirectory, or single file into one markdown document.
14+
15+
## When to auto-trigger
16+
17+
- The user wants a GitHub repo converted into one markdown file.
18+
- The user wants to feed a repo, folder, or file into an LLM or prompt as a single document.
19+
- The user asks to flatten, concatenate, dump, bundle, snapshot, or export GitHub code into markdown.
20+
- The user wants a specific GitHub repo, directory, file, or filtered subset bundled into markdown.
21+
- The user wants to include or exclude files while generating the markdown bundle.
22+
- The user asks to use 2md or wants a rerunnable 2md command.
23+
- Do not use this skill for local non-GitHub directories unless the user explicitly wants GitHub-hosted input.
24+
- Do not use this skill for generic web scraping or for converting markdown into some other format.
25+
26+
## Requirements
27+
28+
- Network access to `https://2md.sauce.wiki`
29+
- Either:
30+
- `curl`, or
31+
- Bun with `bunx`, or
32+
- Node.js with `npx --yes` as a fallback when `bunx` is unavailable
33+
34+
## Inputs
35+
36+
Accepted source forms:
37+
38+
- Full GitHub repo URL: `https://github.com/owner/repo`
39+
- Repo shorthand: `owner/repo`
40+
- Directory URL: `https://github.com/owner/repo/tree/<ref>/path/to/dir`
41+
- File URL: `https://github.com/owner/repo/blob/<ref>/README.md`
42+
- Path shorthand accepted by the CLI:
43+
- `owner/repo/path/to/dir`
44+
- `owner/repo/README.md`
45+
46+
Optional query params:
47+
48+
- `include=.ts`
49+
- `include=.tsx`
50+
- `exclude=.test.ts`
51+
- `exclude=dist/`
52+
- `submodules=true`
53+
54+
Supported filter pattern styles:
55+
56+
- suffix match like `.test.ts`
57+
- directory match like `src/`
58+
- glob match like `*.test.*`
59+
- contains match like `test`
60+
61+
## Instructions
62+
63+
### 1. Normalize the target
64+
65+
First classify the request as one of these target types:
66+
67+
- repo
68+
- directory
69+
- file
70+
- filtered subset of a repo
71+
72+
If the user gives repo shorthand or owner/repo/path shorthand, convert it into one of these 2md target path forms:
73+
74+
- repo: `github.com/owner/repo`
75+
- directory: `github.com/owner/repo/tree/<ref>/path/to/dir`
76+
- file: `github.com/owner/repo/blob/<ref>/path/to/file`
77+
78+
Rules:
79+
80+
- Preserve the branch or ref from the user input whenever it is present.
81+
- Do not invent `main` unless you have verified that it is the intended ref.
82+
- Do not widen scope. If the user asked for a file or directory, do not silently bundle the whole repo.
83+
- Treat “specific set of files” as a filtered repo or filtered directory request using `include` and `exclude` params.
84+
- If the user gives a local path like `./src` or `/tmp/project`, this skill is usually not the right tool.
85+
86+
### 2. Prefer the hosted HTTP endpoint
87+
88+
For direct retrieval, use the 2md endpoint:
89+
90+
```bash
91+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/owner/repo"
92+
```
93+
94+
Directory example:
95+
96+
```bash
97+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/owner/repo/tree/<ref>/src"
98+
```
99+
100+
File example:
101+
102+
```bash
103+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/owner/repo/blob/<ref>/README.md"
104+
```
105+
106+
With filters:
107+
108+
```bash
109+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/owner/repo?include=.ts&exclude=.test.ts"
110+
```
111+
112+
With submodules:
113+
114+
```bash
115+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/owner/repo?submodules=true"
116+
```
117+
118+
When the user wants a saved artifact, write the response to a local file:
119+
120+
```bash
121+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/owner/repo" -o repo.md
122+
```
123+
124+
If 2md returns an HTTP error, surface the status and response body instead of guessing. Prefer `--fail-with-body` so HTTP failures do not get treated as successful markdown output. Common failures include private repos, nonexistent repos, bad paths, rate limits, timeouts, and other upstream fetch failures.
125+
126+
### 3. Use the CLI when it is a better fit
127+
128+
Use the CLI when the user explicitly wants a command they can rerun locally.
129+
130+
Prefer `bunx` first. If `bunx` is unavailable, fall back to `npx --yes`.
131+
132+
Preferred examples:
133+
134+
```bash
135+
bunx github:o-az/2md o-az/2md > repo.md
136+
bunx github:o-az/2md o-az/sandbox/src > src.md
137+
bunx github:o-az/2md https://github.com/honojs/hono/blob/main/README.md > README.bundle.md
138+
```
139+
140+
Fallback examples:
141+
142+
```bash
143+
npx --yes github:o-az/2md o-az/2md > repo.md
144+
npx --yes github:o-az/2md o-az/sandbox/src > src.md
145+
npx --yes github:o-az/2md https://github.com/honojs/hono/blob/main/README.md > README.bundle.md
146+
```
147+
148+
The CLI also accepts full GitHub URLs.
149+
150+
### 4. Choose filters carefully
151+
152+
When the user wants a smaller bundle for LLM context, prefer targeted `include` and `exclude` params.
153+
154+
Use filters to narrow scope, not to broaden it.
155+
156+
Examples:
157+
158+
- TypeScript only:
159+
160+
```text
161+
?include=.ts&include=.tsx
162+
```
163+
164+
- Exclude tests:
165+
166+
```text
167+
?exclude=.test.ts&exclude=.spec.ts
168+
```
169+
170+
- Include source, exclude tests:
171+
172+
```text
173+
?include=src&exclude=*.test.ts
174+
```
175+
176+
- Filter a specific directory instead of the whole repo:
177+
178+
```text
179+
https://2md.sauce.wiki/github.com/owner/repo/tree/<ref>/src?include=.ts&exclude=.test.ts
180+
```
181+
182+
If the requested bundle could become very large, warn the user and suggest `include` and `exclude` filters before returning a huge inline response.
183+
184+
### 5. Return the right thing
185+
186+
- If the user asked you to do the conversion and save an artifact, execute it and report the exact output file path.
187+
- If the user asked for a rerunnable workflow, return the exact 2md URL, CLI command, or both.
188+
- If the user asked for the markdown content itself, return the generated markdown or the specific excerpt they asked for.
189+
- If the generated markdown is too large to return comfortably inline, say so and offer to save it to a file or narrow it with filters.
190+
191+
## Agent checklist
192+
193+
1. Classify the target as repo, directory, file, or filtered subset.
194+
2. Preserve the branch or ref from the input.
195+
3. Prefer the hosted endpoint unless the user asked for a rerunnable CLI command.
196+
4. Do not widen scope.
197+
5. Use filters only to narrow scope.
198+
6. Report the exact output file path when saving locally.
199+
7. On failure, report the HTTP status and response body instead of fabricating output.
200+
201+
## Quick reference
202+
203+
Show a whole repo as markdown:
204+
205+
```bash
206+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/o-az/2md"
207+
```
208+
209+
Show a subdirectory as markdown:
210+
211+
```bash
212+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/o-az/2md/tree/main/scripts"
213+
```
214+
215+
Show a single file as markdown:
216+
217+
```bash
218+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/o-az/2md/blob/main/bunfig.toml"
219+
```
220+
221+
Show a smaller LLM-focused bundle:
222+
223+
```bash
224+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/o-az/2md?include=.tsx&include=.mjs"
225+
```
226+
227+
Save a whole repo locally:
228+
229+
```bash
230+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/o-az/2md" -o o-az-2md.md
231+
```
232+
233+
Save a subdirectory locally:
234+
235+
```bash
236+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/o-az/2md/tree/main/scripts" -o o-az-2md-scripts.md
237+
```
238+
239+
Save a single file locally:
240+
241+
```bash
242+
curl --silent --show-error --fail-with-body --location "https://2md.sauce.wiki/github.com/o-az/2md/blob/main/bunfig.toml" -o o-az-2md-bunfig-toml.md
243+
```

skills/terminal-recording/SKILL.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,20 @@ Record terminal sessions with [asciinema](https://asciinema.org), upload them, a
3434

3535
## Available scripts
3636

37+
- `scripts/requirements.mjs` - Checks required tools and optional env vars, then prints what is missing and where to get it.
3738
- `scripts/finalize-recording.sh` - Uploads a `.cast`, renders a GIF, and prints JSON to stdout.
3839
- `scripts/headless-record.sh` - Records a non-interactive command to a `.cast` and prints JSON to stdout.
3940

4041
## Instructions
4142

4243
Choose the recording flow based on whether the environment supports a true interactive terminal.
4344

45+
Run the requirements check first when setup is unknown:
46+
47+
```bash
48+
node scripts/requirements.mjs
49+
```
50+
4451
### Preferred Flow — Non-Interactive / Agent-Driven
4552

4653
Use this flow by default when working through an agent shell, CI, automation, or any environment where you cannot reliably enter and exit an interactive recording shell.

0 commit comments

Comments
 (0)