emberflow-skills 1.0.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 +46 -0
- package/bin/install.js +70 -0
- package/package.json +15 -0
- package/skills/ember-publish/SKILL.md +194 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Emberflow Skills
|
|
2
|
+
|
|
3
|
+
Agent skills for publishing beautiful docs from your AI coding tools to [Emberflow](https://supportive-forgiveness-production.up.railway.app).
|
|
4
|
+
|
|
5
|
+
## Quick Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx emberflow-skills
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Auto-detects Claude Code and Cursor projects and installs the skill to the right place.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Install globally for Claude Code (available in all projects)
|
|
15
|
+
npx emberflow-skills --global
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Available Skills
|
|
19
|
+
|
|
20
|
+
### `ember-publish`
|
|
21
|
+
|
|
22
|
+
Publish markdown documents with Mermaid diagrams, syntax highlighting, tables, and inline comments.
|
|
23
|
+
|
|
24
|
+
**Usage:** `/ember-publish architecture overview for the payments service`
|
|
25
|
+
|
|
26
|
+
Your AI writes the doc, generates diagrams, and publishes it — you get back a shareable URL.
|
|
27
|
+
|
|
28
|
+
**Works with:** Claude Code, Cursor, Codex CLI, and any tool that supports the SKILL.md format.
|
|
29
|
+
|
|
30
|
+
## What Emberflow renders
|
|
31
|
+
|
|
32
|
+
- Live Mermaid diagrams with zoom, pan, and fullscreen
|
|
33
|
+
- Syntax-highlighted code blocks (190+ languages)
|
|
34
|
+
- Auto-generated table of contents
|
|
35
|
+
- Per-block inline comments and discussions
|
|
36
|
+
- Dark mode with font selection
|
|
37
|
+
|
|
38
|
+
## Manual Installation
|
|
39
|
+
|
|
40
|
+
If you prefer not to use npx:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Clone and copy
|
|
44
|
+
git clone https://github.com/toptalPatrick/emberflow-skills.git
|
|
45
|
+
cp -r emberflow-skills/skills/ember-publish .claude/skills/
|
|
46
|
+
```
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const SKILL_NAME = 'ember-publish';
|
|
7
|
+
const SKILL_SRC = path.join(__dirname, '..', 'skills', SKILL_NAME, 'SKILL.md');
|
|
8
|
+
|
|
9
|
+
const targets = [
|
|
10
|
+
{ dir: '.claude/skills', label: 'Claude Code (project)' },
|
|
11
|
+
{ dir: '.cursor/skills', label: 'Cursor (project)' },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const globalTargets = [
|
|
15
|
+
{ dir: path.join(require('os').homedir(), '.claude', 'skills'), label: 'Claude Code (global)' },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const args = process.argv.slice(2);
|
|
19
|
+
const isGlobal = args.includes('--global') || args.includes('-g');
|
|
20
|
+
|
|
21
|
+
function install(destDir, label) {
|
|
22
|
+
const skillDir = path.join(destDir, SKILL_NAME);
|
|
23
|
+
const destFile = path.join(skillDir, 'SKILL.md');
|
|
24
|
+
|
|
25
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
26
|
+
fs.copyFileSync(SKILL_SRC, destFile);
|
|
27
|
+
console.log(` \x1b[32m✓\x1b[0m Installed to ${path.relative(process.cwd(), skillDir) || skillDir} \x1b[2m(${label})\x1b[0m`);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log();
|
|
32
|
+
console.log(' \x1b[1mEmberflow Skills Installer\x1b[0m');
|
|
33
|
+
console.log();
|
|
34
|
+
|
|
35
|
+
let installed = 0;
|
|
36
|
+
|
|
37
|
+
if (isGlobal) {
|
|
38
|
+
for (const t of globalTargets) {
|
|
39
|
+
install(t.dir, t.label);
|
|
40
|
+
installed++;
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
// Auto-detect which tool directories exist or can be created
|
|
44
|
+
const cwd = process.cwd();
|
|
45
|
+
const detected = [];
|
|
46
|
+
|
|
47
|
+
for (const t of targets) {
|
|
48
|
+
const parent = path.dirname(path.join(cwd, t.dir));
|
|
49
|
+
// Install if parent config dir exists (e.g. .claude/ or .cursor/) or if neither exists (default to .claude)
|
|
50
|
+
if (fs.existsSync(path.join(cwd, t.dir)) || fs.existsSync(parent)) {
|
|
51
|
+
detected.push(t);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Default to Claude Code if nothing detected
|
|
56
|
+
if (detected.length === 0) {
|
|
57
|
+
detected.push(targets[0]);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
for (const t of detected) {
|
|
61
|
+
install(path.join(cwd, t.dir), t.label);
|
|
62
|
+
installed++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (installed > 0) {
|
|
67
|
+
console.log();
|
|
68
|
+
console.log(` Use: \x1b[36m/ember-publish\x1b[0m \x1b[2m[topic]\x1b[0m`);
|
|
69
|
+
console.log();
|
|
70
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "emberflow-skills",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Install Emberflow skills for AI coding tools",
|
|
5
|
+
"bin": {
|
|
6
|
+
"emberflow-skills": "./bin/install.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": ["emberflow", "claude-code", "cursor", "skill", "mcp", "ai", "documentation", "mermaid"],
|
|
9
|
+
"author": "Patrick",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/toptalPatrick/emberflow-skills"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ember-publish
|
|
3
|
+
description: Create a markdown document with Mermaid diagrams and publish it to Emberflow for hosted viewing with comments
|
|
4
|
+
argument-hint: [topic or description of what to document]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Emberflow Document Publisher
|
|
8
|
+
|
|
9
|
+
Create a polished markdown document and publish it to Emberflow — a hosted viewer at **https://supportive-forgiveness-production.up.railway.app** with Mermaid diagram rendering (zoom/pan/fullscreen), dark mode, font selection, and per-block commenting.
|
|
10
|
+
|
|
11
|
+
## Step 1: Create the Markdown File
|
|
12
|
+
|
|
13
|
+
Write a `.md` file in the current project. The document should follow these conventions:
|
|
14
|
+
|
|
15
|
+
### Structure
|
|
16
|
+
- Start with a single `# Title` as the first line (this becomes the document title and slug)
|
|
17
|
+
- Use `##` and `###` for sections — these become commentable blocks in the viewer
|
|
18
|
+
- Keep paragraphs concise — each paragraph, list, table, blockquote, and heading is independently commentable by readers
|
|
19
|
+
|
|
20
|
+
### Mermaid Diagrams
|
|
21
|
+
|
|
22
|
+
Use fenced code blocks with the `mermaid` language tag. The viewer renders them with zoom, pan, and fullscreen controls.
|
|
23
|
+
|
|
24
|
+
````markdown
|
|
25
|
+
```mermaid
|
|
26
|
+
graph LR
|
|
27
|
+
A[Start] --> B{Decision}
|
|
28
|
+
B -->|Yes| C[Action]
|
|
29
|
+
B -->|No| D[Other Action]
|
|
30
|
+
```
|
|
31
|
+
````
|
|
32
|
+
|
|
33
|
+
Supported diagram types:
|
|
34
|
+
- `graph` / `flowchart` — flow diagrams (LR, TD, etc.)
|
|
35
|
+
- `sequenceDiagram` — interaction sequences
|
|
36
|
+
- `classDiagram` — class relationships
|
|
37
|
+
- `stateDiagram-v2` — state machines
|
|
38
|
+
- `erDiagram` — entity relationships
|
|
39
|
+
- `gantt` — project timelines
|
|
40
|
+
- `pie` — pie charts
|
|
41
|
+
- `gitgraph` — git branch visualizations
|
|
42
|
+
- `mindmap` — mind maps
|
|
43
|
+
- `timeline` — chronological events
|
|
44
|
+
|
|
45
|
+
#### Dark Mode Color Palette
|
|
46
|
+
|
|
47
|
+
The viewer auto-remaps these light colors to dark equivalents. Use them for best cross-theme rendering:
|
|
48
|
+
|
|
49
|
+
| Color | Use For |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `#e1f5fe` | Blue backgrounds |
|
|
52
|
+
| `#e8f5e9` | Green backgrounds |
|
|
53
|
+
| `#fff3e0` | Orange backgrounds |
|
|
54
|
+
| `#fce4ec` | Red backgrounds |
|
|
55
|
+
| `#f3e5f5` | Purple backgrounds |
|
|
56
|
+
| `#fff9c4` | Yellow backgrounds |
|
|
57
|
+
|
|
58
|
+
### Tables, Code, Blockquotes
|
|
59
|
+
|
|
60
|
+
Standard GFM (GitHub Flavored Markdown) is fully supported:
|
|
61
|
+
|
|
62
|
+
```markdown
|
|
63
|
+
| Column A | Column B |
|
|
64
|
+
|----------|----------|
|
|
65
|
+
| value | value |
|
|
66
|
+
|
|
67
|
+
> Blockquotes render with a blue left border
|
|
68
|
+
|
|
69
|
+
`inline code` and fenced code blocks with syntax highlighting
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Example Document
|
|
73
|
+
|
|
74
|
+
````markdown
|
|
75
|
+
# API Architecture Overview
|
|
76
|
+
|
|
77
|
+
Brief introduction to the system.
|
|
78
|
+
|
|
79
|
+
## Components
|
|
80
|
+
|
|
81
|
+
```mermaid
|
|
82
|
+
graph TD
|
|
83
|
+
Client[Web Client] --> API[API Gateway]
|
|
84
|
+
API --> Auth[Auth Service]
|
|
85
|
+
API --> Docs[Doc Service]
|
|
86
|
+
Docs --> DB[(PostgreSQL)]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Request Flow
|
|
90
|
+
|
|
91
|
+
```mermaid
|
|
92
|
+
sequenceDiagram
|
|
93
|
+
participant C as Client
|
|
94
|
+
participant G as Gateway
|
|
95
|
+
participant S as Service
|
|
96
|
+
C->>G: Request
|
|
97
|
+
G->>S: Forward
|
|
98
|
+
S->>G: Response
|
|
99
|
+
G->>C: Response
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Data Model
|
|
103
|
+
|
|
104
|
+
| Entity | Purpose |
|
|
105
|
+
|--------|---------|
|
|
106
|
+
| Users | Account management |
|
|
107
|
+
| Documents | Published content |
|
|
108
|
+
| Comments | Discussion threads |
|
|
109
|
+
|
|
110
|
+
## Design Notes
|
|
111
|
+
|
|
112
|
+
> We chose event sourcing to maintain a complete audit trail of all state changes.
|
|
113
|
+
````
|
|
114
|
+
|
|
115
|
+
## Step 2: Authenticate (if needed)
|
|
116
|
+
|
|
117
|
+
Session tokens are stored at `~/.emberflow/token.json`. Check if a valid session exists:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
cat ~/.emberflow/token.json 2>/dev/null
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
If the file exists, verify the token still works:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
curl -s -H "Authorization: Bearer $(jq -r .token ~/.emberflow/token.json)" \
|
|
127
|
+
https://supportive-forgiveness-production.up.railway.app/api/docs
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
If no session exists, it's expired, or the verify call returns 401, authenticate using the device flow:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
EMBERFLOW_URL="https://supportive-forgiveness-production.up.railway.app"
|
|
134
|
+
|
|
135
|
+
# Step 1: Request a device code
|
|
136
|
+
RESP=$(curl -s -X POST "$EMBERFLOW_URL/api/device-code")
|
|
137
|
+
CODE=$(echo "$RESP" | jq -r .code)
|
|
138
|
+
URL=$(echo "$RESP" | jq -r .verification_url)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Tell the user to open the URL in their browser to sign in and approve the device. Then poll until approved:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Step 2: Poll until approved (every 3s)
|
|
145
|
+
while true; do
|
|
146
|
+
STATUS=$(curl -s "$EMBERFLOW_URL/api/device-code/$CODE")
|
|
147
|
+
S=$(echo "$STATUS" | jq -r .status)
|
|
148
|
+
if [ "$S" = "approved" ]; then
|
|
149
|
+
TOKEN=$(echo "$STATUS" | jq -r .session_token)
|
|
150
|
+
mkdir -p ~/.emberflow
|
|
151
|
+
echo "{\"token\":\"$TOKEN\"}" > ~/.emberflow/token.json
|
|
152
|
+
break
|
|
153
|
+
fi
|
|
154
|
+
if [ "$S" = "expired" ]; then
|
|
155
|
+
echo "Code expired. Please try again."
|
|
156
|
+
break
|
|
157
|
+
fi
|
|
158
|
+
sleep 3
|
|
159
|
+
done
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Step 3: Publish
|
|
163
|
+
|
|
164
|
+
Generate a slug from the document title and publish using the API:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
# Read the file, extract title, generate slug, and publish
|
|
168
|
+
EMBERFLOW_URL="https://supportive-forgiveness-production.up.railway.app"
|
|
169
|
+
FILE_PATH="/absolute/path/to/document.md"
|
|
170
|
+
TITLE=$(head -1 "$FILE_PATH" | sed 's/^#\s*//')
|
|
171
|
+
SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | sed 's/^-//;s/-$//')
|
|
172
|
+
TOKEN=$(jq -r .token ~/.emberflow/token.json)
|
|
173
|
+
|
|
174
|
+
curl -s -X POST "$EMBERFLOW_URL/api/docs" \
|
|
175
|
+
-H 'Content-Type: application/json' \
|
|
176
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
177
|
+
-d "$(jq -n --arg slug "$SLUG" --arg title "$TITLE" --rawfile content "$FILE_PATH" \
|
|
178
|
+
'{slug: $slug, title: $title, content: $content, visibility: "public"}')"
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The response JSON includes the URL. Documents are viewable at:
|
|
182
|
+
- Public: `https://supportive-forgiveness-production.up.railway.app/d/<shortId>/<slug>`
|
|
183
|
+
|
|
184
|
+
To **update** an existing document, publish again with the same slug — the API upserts for the same author.
|
|
185
|
+
|
|
186
|
+
### Other Operations
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# List all your documents
|
|
190
|
+
curl -s -H "Authorization: Bearer $TOKEN" "$EMBERFLOW_URL/api/docs"
|
|
191
|
+
|
|
192
|
+
# Delete a document
|
|
193
|
+
curl -s -X DELETE -H "Authorization: Bearer $TOKEN" "$EMBERFLOW_URL/api/docs/<shortId>/<slug>"
|
|
194
|
+
```
|