coursmith 0.0.0-stage → 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/README.md +18 -2
- package/dist/index.js +93 -0
- package/package.json +48 -4
- package/skill/coursmith-course/SKILL.md +131 -0
- package/skill/coursmith-course/examples/sample-course/assets/cover.svg +23 -0
- package/skill/coursmith-course/examples/sample-course/assets/home-panel.svg +28 -0
- package/skill/coursmith-course/examples/sample-course/course.json +813 -0
- package/skill/coursmith-course/references/animation-presets.md +143 -0
- package/skill/coursmith-course/references/block-catalog.md +277 -0
- package/skill/coursmith-course/references/content-policy.md +47 -0
- package/skill/coursmith-course/references/course.schema.json +1901 -0
- package/skill/coursmith-course/references/writing-guide.md +89 -0
package/package.json
CHANGED
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coursmith",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Publish AI-written courses to Coursmith from Claude Code, Codex, Cursor, OpenCode or any agent with a shell.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/Uranio/coursmith.git",
|
|
8
|
+
"directory": "packages/cli"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://coursmith.onrender.com/install",
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"bin": {
|
|
16
|
+
"coursmith": "dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"skill"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "node scripts/build.mjs",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"commander": "^15.0.0",
|
|
29
|
+
"open": "^11.0.4"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@coursmith/course-schema": "0.1.0",
|
|
33
|
+
"esbuild": "^0.28.2",
|
|
34
|
+
"@types/node": "^24.0.0",
|
|
35
|
+
"vitest": "^5.0.5"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=20"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"coursmith",
|
|
42
|
+
"agent-skills",
|
|
43
|
+
"claude-code",
|
|
44
|
+
"codex",
|
|
45
|
+
"cursor",
|
|
46
|
+
"opencode",
|
|
47
|
+
"courses",
|
|
48
|
+
"e-learning"
|
|
49
|
+
]
|
|
50
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: coursmith-course
|
|
3
|
+
description: Create an interactive course (steps, charts, diagrams, animations, images, a glossary per section and a final quiz) and publish it to the Coursmith catalog with the coursmith CLI. Use when the user asks to create, write, generate, update, publish or submit a course or lesson for Coursmith, or to check a Coursmith review.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Create and publish a Coursmith course
|
|
7
|
+
|
|
8
|
+
You write a course as a folder containing `course.json` and an `assets/` directory, check it with the
|
|
9
|
+
`coursmith` CLI, and submit it. A review agent on the portal then approves it, asks for a revision or
|
|
10
|
+
rejects it. Your job ends when the course is approved, or when you have explained the review outcome to the user.
|
|
11
|
+
|
|
12
|
+
Run the CLI as `coursmith <command> --json`. It is installed from the private repository (the npm package
|
|
13
|
+
`coursmith` is not published yet); if the command is missing, ask the user to follow the installation guide
|
|
14
|
+
at `/install` before continuing. With `--json` every command prints one JSON document; read it instead of guessing.
|
|
15
|
+
|
|
16
|
+
Reference files in this skill folder (read them when you reach the matching step):
|
|
17
|
+
|
|
18
|
+
| File | Use it for |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `references/course.schema.json` | The exact structure of `course.json`. Unknown keys are rejected. |
|
|
21
|
+
| `references/block-catalog.md` | Every content block and visual, with valid JSON examples and rules. |
|
|
22
|
+
| `references/animation-presets.md` | The 7 animation presets and when to use each. |
|
|
23
|
+
| `references/writing-guide.md` | How to write steps, glossaries and quizzes that pass review. |
|
|
24
|
+
| `references/content-policy.md` | What is not allowed and how to treat sensitive topics. |
|
|
25
|
+
| `examples/sample-course/` | A complete course that passes validation. Copy its shape. |
|
|
26
|
+
|
|
27
|
+
## 1. Log in
|
|
28
|
+
|
|
29
|
+
1. Run `coursmith whoami --json`. If it prints a `username`, continue to step 2.
|
|
30
|
+
2. Otherwise run `coursmith login --no-wait --json`. Show the user the `verificationUri` and the
|
|
31
|
+
`userCode` and ask them to open the link, check the code and click **Approve**.
|
|
32
|
+
3. When the user confirms, run `coursmith login --resume --json` and check that it prints `logged_in`.
|
|
33
|
+
|
|
34
|
+
## 2. Agree on the course with the user
|
|
35
|
+
|
|
36
|
+
Ask, in one message, for anything the user has not already given:
|
|
37
|
+
|
|
38
|
+
- **Topic** and, if useful, the angle or audience.
|
|
39
|
+
- **Language** of the course (any language; you will need its BCP-47 code such as `it`, `en`, `pt-BR`).
|
|
40
|
+
- **Difficulty**: `beginner`, `intermediate` or `advanced`.
|
|
41
|
+
- Optional: desired length (default about 30 minutes), prerequisites, things to include or avoid.
|
|
42
|
+
|
|
43
|
+
Check the topic against `references/content-policy.md`. If it is not allowed, say so and stop. If it is a
|
|
44
|
+
sensitive topic (health, law, finance, politics, religion…), plan a neutral treatment and a disclaimer.
|
|
45
|
+
|
|
46
|
+
## 3. Propose an outline and get it approved
|
|
47
|
+
|
|
48
|
+
Show the user:
|
|
49
|
+
|
|
50
|
+
- title, one-line subtitle, 2–6 learning objectives;
|
|
51
|
+
- 3–6 sections, each with a one-line summary and 2–5 step titles;
|
|
52
|
+
- for each step, the visual you plan (chart, diagram, animation preset, image or none);
|
|
53
|
+
- the planned number of quiz questions (at least 10, covering every section).
|
|
54
|
+
|
|
55
|
+
Revise until the user agrees. Do not write `course.json` before that.
|
|
56
|
+
|
|
57
|
+
## 4. Write the course
|
|
58
|
+
|
|
59
|
+
Create a new folder named after the course (kebab-case) with `course.json` and `assets/`. Follow
|
|
60
|
+
`references/course.schema.json` exactly and copy the structure of `examples/sample-course/course.json`.
|
|
61
|
+
|
|
62
|
+
Rules the validator enforces (details in `references/block-catalog.md`):
|
|
63
|
+
|
|
64
|
+
- `schemaVersion` is `"1.0"`. Do not write `courseId`: the CLI manages it.
|
|
65
|
+
- All ids are lowercase letters, digits and dashes, unique across the course (sections, steps, assets,
|
|
66
|
+
quiz questions).
|
|
67
|
+
- Every step has a `title` and at least one block; most steps also have a `visual`.
|
|
68
|
+
- **Glossary**: every section has a `glossary` that defines every concept it introduces and every technical or
|
|
69
|
+
domain term it uses. In the text, mark each term as `[[term]]`, or `[[term|text shown]]` when the
|
|
70
|
+
wording differs (use `aliases` for plurals and inflections). A marked term must be defined in the same
|
|
71
|
+
section or an earlier one. Definitions are self-contained and written in the course language.
|
|
72
|
+
- **Visuals**: charts are Vega-Lite specs with inline `data.values` (no URLs); diagrams are Mermaid without
|
|
73
|
+
`click` or `%%{init}%%`; animations use one of the 7 presets; images refer to an asset by id.
|
|
74
|
+
- **Markdown**: no raw HTML, no Markdown images (use an image block), links must be `https://`.
|
|
75
|
+
- **Final quiz**: at least 10 questions; every section is tested by at least one question (`sectionRef`);
|
|
76
|
+
every question has an `explanation`. Types: `single`, `multiple`, `true_false`, `ordering`
|
|
77
|
+
(ordering items are listed in the correct order; the portal shuffles them).
|
|
78
|
+
- Optional `check` questions at the end of a step give learners quick feedback and are not scored.
|
|
79
|
+
|
|
80
|
+
Write section by section and keep the language, difficulty and terminology consistent throughout
|
|
81
|
+
(see `references/writing-guide.md`).
|
|
82
|
+
|
|
83
|
+
## 5. Create the assets
|
|
84
|
+
|
|
85
|
+
- A **cover image** is required (`meta.coverImage`), ideally 1200×630.
|
|
86
|
+
- If you have an image-generation tool, produce PNG, JPEG or WebP files. Otherwise write clean SVG by hand:
|
|
87
|
+
simple shapes, a clear palette, `viewBox` set, no scripts, no external links or fonts, no embedded images.
|
|
88
|
+
- For a `highlight-svg` animation, give the elements to highlight an `id` attribute.
|
|
89
|
+
- Put every file directly in `assets/` and declare it in `assets[]` with `kind` (`image` or `svg`), `file`
|
|
90
|
+
(`assets/<name>`) and a meaningful `alt` text. Fill `generatedBy` for AI-generated images.
|
|
91
|
+
- Each file must be under 3 MB; the whole bundle under 25 MB.
|
|
92
|
+
|
|
93
|
+
## 6. Validate until clean
|
|
94
|
+
|
|
95
|
+
Run `coursmith validate <folder> --json`. It prints `{ "ok": ..., "issues": [...] }`; each issue has
|
|
96
|
+
`severity`, `code`, `path` (for example `sections[1].steps[0].blocks[2]`) and `message`.
|
|
97
|
+
|
|
98
|
+
Fix every `error`, then run it again. Repeat until `ok` is `true`. Fix warnings too when they are cheap
|
|
99
|
+
(for example `glossary.unreferenced`: mark the term with `[[...]]` where it is used).
|
|
100
|
+
|
|
101
|
+
## 7. Submit and follow the review
|
|
102
|
+
|
|
103
|
+
1. Run `coursmith submit <folder> --json`. It uploads the course and prints `status: "in_review"`
|
|
104
|
+
with a `submissionId`. The CLI writes `.coursmith.json` in the folder; keep it, because it links later
|
|
105
|
+
submissions to the same course.
|
|
106
|
+
2. Run `coursmith status --dir <folder> --wait --json` (it waits up to 10 minutes; run it again if
|
|
107
|
+
the status is still `in_review`).
|
|
108
|
+
3. Act on the `status`:
|
|
109
|
+
- `approved`: give the user the `courseUrl`. Mention any optional suggestions in `review.issues`.
|
|
110
|
+
- `needs_revision`: for each issue in `review.issues`, open the element at `path`, apply the
|
|
111
|
+
`suggestion` (or fix what `message` describes), then validate and submit again. Tell the user what you
|
|
112
|
+
changed. Issues with `severity: "warning"` are optional.
|
|
113
|
+
- `rejected`: explain `review.summary` to the user. Do not resubmit the same content.
|
|
114
|
+
|
|
115
|
+
If `submit` reports `review_in_progress`, wait for the current review with `status --wait` first.
|
|
116
|
+
|
|
117
|
+
## Updating a published course
|
|
118
|
+
|
|
119
|
+
Edit the same folder (keep `.coursmith.json`) and submit again. The new version goes through review while
|
|
120
|
+
the current one stays online; keep step ids stable so learners keep their progress.
|
|
121
|
+
|
|
122
|
+
## Troubleshooting
|
|
123
|
+
|
|
124
|
+
| CLI output | What to do |
|
|
125
|
+
|---|---|
|
|
126
|
+
| `not_logged_in` / exit code 3 | Go back to step 1. |
|
|
127
|
+
| `client_outdated` | Ask the user to update the CLI from the repository (`git pull`, rebuild, `npm install -g ./packages/cli`), then retry. |
|
|
128
|
+
| `validation_failed` from `submit` | Run `validate` and fix the issues it lists. |
|
|
129
|
+
| `rate_limited` | The user reached the daily submission limit; try again tomorrow. |
|
|
130
|
+
| `assets.content_type` / `assets.invalid` | The file content does not match its extension, or it is corrupt. Re-export it. |
|
|
131
|
+
| `animation.unknown_element` | The SVG lacks an element with that `id` (ids are kept, scripts and external links are removed). |
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 630" role="img" aria-labelledby="t">
|
|
2
|
+
<title id="t">Power line crossing hills toward a house</title>
|
|
3
|
+
<defs>
|
|
4
|
+
<linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
|
|
5
|
+
<stop offset="0" stop-color="#1e3a8a"/>
|
|
6
|
+
<stop offset="1" stop-color="#3b82f6"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
</defs>
|
|
9
|
+
<rect width="1200" height="630" fill="url(#sky)"/>
|
|
10
|
+
<circle cx="980" cy="140" r="60" fill="#fde68a"/>
|
|
11
|
+
<path d="M0 470 Q300 380 600 450 T1200 430 V630 H0Z" fill="#1e40af"/>
|
|
12
|
+
<path d="M0 520 Q350 450 700 520 T1200 500 V630 H0Z" fill="#172554"/>
|
|
13
|
+
<g stroke="#e0e7ff" stroke-width="6" fill="none" stroke-linecap="round">
|
|
14
|
+
<path d="M140 470 L180 250 L220 470 M150 320 H210 M160 280 H200"/>
|
|
15
|
+
<path d="M520 470 L560 250 L600 470 M530 320 H590 M540 280 H580"/>
|
|
16
|
+
<path d="M180 260 Q370 330 560 260" stroke-width="3"/>
|
|
17
|
+
<path d="M560 260 Q760 330 880 400" stroke-width="3"/>
|
|
18
|
+
</g>
|
|
19
|
+
<g transform="translate(860 400)">
|
|
20
|
+
<path d="M0 60 L60 10 L120 60 V140 H0Z" fill="#f8fafc"/>
|
|
21
|
+
<rect x="45" y="80" width="30" height="30" fill="#facc15"/>
|
|
22
|
+
</g>
|
|
23
|
+
</svg>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 520" role="img" aria-labelledby="t">
|
|
2
|
+
<title id="t">Home electrical panel</title>
|
|
3
|
+
<rect x="10" y="10" width="380" height="500" rx="16" fill="#f1f5f9" stroke="#334155" stroke-width="4"/>
|
|
4
|
+
<g id="meter">
|
|
5
|
+
<rect x="130" y="40" width="140" height="90" rx="8" fill="#e2e8f0" stroke="#334155" stroke-width="3"/>
|
|
6
|
+
<rect x="150" y="60" width="100" height="30" rx="4" fill="#0f172a"/>
|
|
7
|
+
<text x="200" y="82" font-family="monospace" font-size="18" fill="#4ade80" text-anchor="middle">01234</text>
|
|
8
|
+
<text x="200" y="118" font-family="sans-serif" font-size="14" fill="#334155" text-anchor="middle">kWh</text>
|
|
9
|
+
</g>
|
|
10
|
+
<path d="M200 130 V170" stroke="#334155" stroke-width="4"/>
|
|
11
|
+
<g id="main-switch">
|
|
12
|
+
<rect x="160" y="170" width="80" height="70" rx="6" fill="#fecaca" stroke="#b91c1c" stroke-width="3"/>
|
|
13
|
+
<rect x="190" y="185" width="20" height="40" rx="3" fill="#b91c1c"/>
|
|
14
|
+
</g>
|
|
15
|
+
<path d="M200 240 V280" stroke="#334155" stroke-width="4"/>
|
|
16
|
+
<g id="rcd">
|
|
17
|
+
<rect x="140" y="280" width="120" height="70" rx="6" fill="#bfdbfe" stroke="#1d4ed8" stroke-width="3"/>
|
|
18
|
+
<circle cx="230" cy="315" r="10" fill="#1d4ed8"/>
|
|
19
|
+
<rect x="160" y="295" width="20" height="40" rx="3" fill="#1d4ed8"/>
|
|
20
|
+
</g>
|
|
21
|
+
<path d="M200 350 V380 M80 380 H320 M80 380 V400 M160 380 V400 M240 380 V400 M320 380 V400" stroke="#334155" stroke-width="4" fill="none"/>
|
|
22
|
+
<g id="breakers">
|
|
23
|
+
<rect x="55" y="400" width="50" height="80" rx="5" fill="#e2e8f0" stroke="#334155" stroke-width="3"/>
|
|
24
|
+
<rect x="135" y="400" width="50" height="80" rx="5" fill="#e2e8f0" stroke="#334155" stroke-width="3"/>
|
|
25
|
+
<rect x="215" y="400" width="50" height="80" rx="5" fill="#e2e8f0" stroke="#334155" stroke-width="3"/>
|
|
26
|
+
<rect x="295" y="400" width="50" height="80" rx="5" fill="#e2e8f0" stroke="#334155" stroke-width="3"/>
|
|
27
|
+
</g>
|
|
28
|
+
</svg>
|