skool-cli 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.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +179 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +33 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/create-folder.d.ts +3 -0
  8. package/dist/commands/create-folder.d.ts.map +1 -0
  9. package/dist/commands/create-folder.js +24 -0
  10. package/dist/commands/create-folder.js.map +1 -0
  11. package/dist/commands/create-lesson.d.ts +3 -0
  12. package/dist/commands/create-lesson.d.ts.map +1 -0
  13. package/dist/commands/create-lesson.js +35 -0
  14. package/dist/commands/create-lesson.js.map +1 -0
  15. package/dist/commands/create-post.d.ts +3 -0
  16. package/dist/commands/create-post.d.ts.map +1 -0
  17. package/dist/commands/create-post.js +36 -0
  18. package/dist/commands/create-post.js.map +1 -0
  19. package/dist/commands/debug-api.d.ts +3 -0
  20. package/dist/commands/debug-api.d.ts.map +1 -0
  21. package/dist/commands/debug-api.js +112 -0
  22. package/dist/commands/debug-api.js.map +1 -0
  23. package/dist/commands/debug-manual.d.ts +3 -0
  24. package/dist/commands/debug-manual.d.ts.map +1 -0
  25. package/dist/commands/debug-manual.js +66 -0
  26. package/dist/commands/debug-manual.js.map +1 -0
  27. package/dist/commands/debug.d.ts +3 -0
  28. package/dist/commands/debug.d.ts.map +1 -0
  29. package/dist/commands/debug.js +114 -0
  30. package/dist/commands/debug.js.map +1 -0
  31. package/dist/commands/delete-lesson.d.ts +3 -0
  32. package/dist/commands/delete-lesson.d.ts.map +1 -0
  33. package/dist/commands/delete-lesson.js +17 -0
  34. package/dist/commands/delete-lesson.js.map +1 -0
  35. package/dist/commands/get-categories.d.ts +3 -0
  36. package/dist/commands/get-categories.d.ts.map +1 -0
  37. package/dist/commands/get-categories.js +34 -0
  38. package/dist/commands/get-categories.js.map +1 -0
  39. package/dist/commands/get-members.d.ts +3 -0
  40. package/dist/commands/get-members.d.ts.map +1 -0
  41. package/dist/commands/get-members.js +35 -0
  42. package/dist/commands/get-members.js.map +1 -0
  43. package/dist/commands/get-posts.d.ts +3 -0
  44. package/dist/commands/get-posts.d.ts.map +1 -0
  45. package/dist/commands/get-posts.js +41 -0
  46. package/dist/commands/get-posts.js.map +1 -0
  47. package/dist/commands/list-lessons.d.ts +3 -0
  48. package/dist/commands/list-lessons.d.ts.map +1 -0
  49. package/dist/commands/list-lessons.js +45 -0
  50. package/dist/commands/list-lessons.js.map +1 -0
  51. package/dist/commands/login.d.ts +3 -0
  52. package/dist/commands/login.d.ts.map +1 -0
  53. package/dist/commands/login.js +30 -0
  54. package/dist/commands/login.js.map +1 -0
  55. package/dist/commands/test-api.d.ts +3 -0
  56. package/dist/commands/test-api.d.ts.map +1 -0
  57. package/dist/commands/test-api.js +143 -0
  58. package/dist/commands/test-api.js.map +1 -0
  59. package/dist/commands/whoami.d.ts +3 -0
  60. package/dist/commands/whoami.d.ts.map +1 -0
  61. package/dist/commands/whoami.js +17 -0
  62. package/dist/commands/whoami.js.map +1 -0
  63. package/dist/core/browser-manager.d.ts +25 -0
  64. package/dist/core/browser-manager.d.ts.map +1 -0
  65. package/dist/core/browser-manager.js +104 -0
  66. package/dist/core/browser-manager.js.map +1 -0
  67. package/dist/core/config.d.ts +15 -0
  68. package/dist/core/config.d.ts.map +1 -0
  69. package/dist/core/config.js +17 -0
  70. package/dist/core/config.js.map +1 -0
  71. package/dist/core/html-generator.d.ts +15 -0
  72. package/dist/core/html-generator.d.ts.map +1 -0
  73. package/dist/core/html-generator.js +254 -0
  74. package/dist/core/html-generator.js.map +1 -0
  75. package/dist/core/page-ops.d.ts +69 -0
  76. package/dist/core/page-ops.d.ts.map +1 -0
  77. package/dist/core/page-ops.js +511 -0
  78. package/dist/core/page-ops.js.map +1 -0
  79. package/dist/core/skool-api.d.ts +74 -0
  80. package/dist/core/skool-api.d.ts.map +1 -0
  81. package/dist/core/skool-api.js +389 -0
  82. package/dist/core/skool-api.js.map +1 -0
  83. package/dist/core/skool-client.d.ts +63 -0
  84. package/dist/core/skool-client.d.ts.map +1 -0
  85. package/dist/core/skool-client.js +501 -0
  86. package/dist/core/skool-client.js.map +1 -0
  87. package/dist/core/types.d.ts +58 -0
  88. package/dist/core/types.d.ts.map +1 -0
  89. package/dist/core/types.js +2 -0
  90. package/dist/core/types.js.map +1 -0
  91. package/package.json +51 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 UNIKPROMPT Technologies LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,179 @@
1
+ # skool-cli
2
+
3
+ CLI and programmatic API for [Skool.com](https://www.skool.com) automation. Create classroom lessons, community posts, and manage your Skool groups from the terminal.
4
+
5
+ **Skool has no public API.** This tool uses browser automation (Playwright) to give you full programmatic access to Skool's features.
6
+
7
+ ## Killer Feature: Classroom Lessons
8
+
9
+ Create rich HTML lessons in Skool's classroom with a single command. Supports headers, lists, code blocks, bold, italic, links, and images via TipTap editor injection.
10
+
11
+ ```bash
12
+ skool create-lesson \
13
+ --group my-community \
14
+ --module "Getting Started" \
15
+ --title "Your First Lesson" \
16
+ --file lesson.md
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```bash
22
+ # Install globally
23
+ npm install -g skool-cli
24
+
25
+ # Or run directly with npx
26
+ npx skool-cli login --email you@email.com --password yourpass
27
+
28
+ # Install browser (first time only)
29
+ npx playwright install chromium
30
+ ```
31
+
32
+ ## Commands
33
+
34
+ ### Authentication
35
+
36
+ ```bash
37
+ # Login (saves session for future use)
38
+ skool login --email you@email.com --password yourpass
39
+
40
+ # Check session status
41
+ skool whoami --group my-community
42
+ ```
43
+
44
+ ### Classroom (Lessons)
45
+
46
+ ```bash
47
+ # Create lesson from markdown file
48
+ skool create-lesson -g my-community -m "Module Name" -t "Lesson Title" -f lesson.md
49
+
50
+ # Create lesson from HTML
51
+ skool create-lesson -g my-community -m "Module Name" -t "Lesson Title" --html lesson.html
52
+
53
+ # Create lesson from content JSON (with skool_class structure)
54
+ skool create-lesson -g my-community -m "Module Name" -t "Lesson Title" -f content.json
55
+
56
+ # Inline markdown
57
+ skool create-lesson -g my-community -m "Module Name" -t "Quick Tip" --markdown "## Hello\n\nThis is a lesson."
58
+ ```
59
+
60
+ ### Community (Posts)
61
+
62
+ ```bash
63
+ # Create a post
64
+ skool create-post -g my-community -t "Welcome!" -b "Hello everyone..."
65
+
66
+ # Create a post from file
67
+ skool create-post -g my-community -t "Weekly Update" -f post.txt -c "General"
68
+
69
+ # List posts
70
+ skool get-posts -g my-community
71
+ skool get-posts -g my-community --json
72
+
73
+ # List categories
74
+ skool get-categories -g my-community
75
+ ```
76
+
77
+ ### Members
78
+
79
+ ```bash
80
+ # List members
81
+ skool get-members -g my-community
82
+
83
+ # Search members
84
+ skool get-members -g my-community --search "mario"
85
+
86
+ # JSON output
87
+ skool get-members -g my-community --json
88
+ ```
89
+
90
+ ## Programmatic API
91
+
92
+ Use `skool-cli` as a library in your Node.js projects:
93
+
94
+ ```typescript
95
+ import { SkoolClient } from 'skool-cli';
96
+
97
+ const client = new SkoolClient();
98
+
99
+ // Login
100
+ await client.login('you@email.com', 'yourpass');
101
+
102
+ // Create a lesson
103
+ await client.createLesson({
104
+ group: 'my-community',
105
+ module: 'Getting Started',
106
+ title: 'Lesson 1',
107
+ markdownContent: '## Hello\n\nThis is a lesson.',
108
+ });
109
+
110
+ // Create a post
111
+ await client.createPost({
112
+ group: 'my-community',
113
+ title: 'Welcome!',
114
+ body: 'Hello everyone...',
115
+ category: 'General',
116
+ });
117
+
118
+ // Read data
119
+ const { posts } = await client.getPosts('my-community');
120
+ const { categories } = await client.getCategories('my-community');
121
+ const { members } = await client.getMembers('my-community');
122
+
123
+ // Cleanup
124
+ await client.close();
125
+ ```
126
+
127
+ ## Environment Variables
128
+
129
+ | Variable | Description |
130
+ |----------|-------------|
131
+ | `SKOOL_EMAIL` | Default email for login |
132
+ | `SKOOL_PASSWORD` | Default password for login |
133
+ | `SKOOL_GROUP` | Default group slug (avoids passing `--group` every time) |
134
+ | `SKOOL_CLI_HEADLESS` | Set to `false` for visible browser (debugging) |
135
+ | `SKOOL_CLI_DATA_DIR` | Custom data directory (default: `~/.skool-cli/`) |
136
+ | `SKOOL_CLI_TIMEOUT` | Operation timeout in ms (default: 30000) |
137
+
138
+ ## How It Works
139
+
140
+ 1. **Login**: Playwright opens a headless Chromium browser and logs into Skool
141
+ 2. **Session persistence**: Browser profile is saved to `~/.skool-cli/browser-data/`, so subsequent runs reuse the session without re-logging in
142
+ 3. **Operations**: Each command navigates to the appropriate Skool page and interacts with it programmatically
143
+ 4. **TipTap injection**: For classroom lessons, HTML is injected directly into Skool's TipTap editor via `editor.commands.setContent()`
144
+
145
+ ## Supported Content Formats
146
+
147
+ The `create-lesson` command accepts:
148
+
149
+ - **Markdown** (`.md`): Converted to TipTap-compatible HTML automatically
150
+ - **HTML** (`.html`): Injected directly into the editor
151
+ - **JSON** (`.json`): Extracts `skool_class` structure and converts to HTML (compatible with content pipeline JSONs)
152
+
153
+ ### Supported HTML Elements
154
+
155
+ Headers (h1-h4), paragraphs, bold, italic, strikethrough, inline code, code blocks, ordered/unordered lists, blockquotes, horizontal rules, links, images.
156
+
157
+ **Not supported by Skool's editor**: Tables, iframes (except video embeds), forms.
158
+
159
+ ## Troubleshooting
160
+
161
+ | Issue | Solution |
162
+ |-------|----------|
163
+ | "Browser not found" | Run `npx playwright install chromium` |
164
+ | Login fails | Check email/password. Try `SKOOL_CLI_HEADLESS=false` to see the browser |
165
+ | Session expired | Run `skool login` again |
166
+ | SAVE button not working | Known Skool quirk. The CLI handles this automatically with a dirty-state trigger |
167
+ | Title too long | Automatically truncated to 50 characters |
168
+ | Community posts look plain | Skool community posts only support plain text (no HTML) |
169
+
170
+ ## Learn More
171
+
172
+ - [TikTok @unikprompt](https://tiktok.com/@unikprompt) - Automation tutorials
173
+ - [Facebook: Claude Code en Espanol](https://facebook.com/groups/claudecodeenespanol) - Free community
174
+ - [Skool: Operadores Aumentados](https://skool.com/operadores-aumentados) - Premium community
175
+ - [UNIKPROMPT](https://unikprompt.com) - More tools and resources
176
+
177
+ ## License
178
+
179
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { loginCommand } from "./commands/login.js";
4
+ import { whoamiCommand } from "./commands/whoami.js";
5
+ import { createLessonCommand } from "./commands/create-lesson.js";
6
+ import { createFolderCommand } from "./commands/create-folder.js";
7
+ import { createPostCommand } from "./commands/create-post.js";
8
+ import { getPostsCommand } from "./commands/get-posts.js";
9
+ import { getCategoriesCommand } from "./commands/get-categories.js";
10
+ import { getMembersCommand } from "./commands/get-members.js";
11
+ import { deleteLessonCommand } from "./commands/delete-lesson.js";
12
+ import { listLessonsCommand } from "./commands/list-lessons.js";
13
+ const program = new Command();
14
+ program
15
+ .name("skool")
16
+ .description("CLI for Skool.com automation — create lessons, posts, and manage communities")
17
+ .version("1.0.0");
18
+ // Auth
19
+ program.addCommand(loginCommand);
20
+ program.addCommand(whoamiCommand);
21
+ // Classroom
22
+ program.addCommand(createLessonCommand);
23
+ program.addCommand(createFolderCommand);
24
+ program.addCommand(deleteLessonCommand);
25
+ program.addCommand(listLessonsCommand);
26
+ // Community
27
+ program.addCommand(createPostCommand);
28
+ program.addCommand(getPostsCommand);
29
+ program.addCommand(getCategoriesCommand);
30
+ // Members
31
+ program.addCommand(getMembersCommand);
32
+ program.parse();
33
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CACV,8EAA8E,CAC/E;KACA,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;AACP,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAElC,YAAY;AACZ,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;AAEvC,YAAY;AACZ,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;AACtC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;AAEzC,UAAU;AACV,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;AAEtC,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const createFolderCommand: Command;
3
+ //# sourceMappingURL=create-folder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-folder.d.ts","sourceRoot":"","sources":["../../src/commands/create-folder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,eAAO,MAAM,mBAAmB,SAmB5B,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { Command } from "commander";
2
+ import { SkoolClient } from "../core/skool-client.js";
3
+ export const createFolderCommand = new Command("create-folder")
4
+ .description("Create a new folder (module) in a Skool classroom course")
5
+ .requiredOption("-g, --group <slug>", "Skool group slug", process.env.SKOOL_GROUP)
6
+ .requiredOption("-t, --title <title>", "Folder name (max 50 chars)")
7
+ .option("--course <name>", "Course name (if multiple courses exist)")
8
+ .action(async (opts) => {
9
+ const client = new SkoolClient();
10
+ try {
11
+ console.log(`Creating folder "${opts.title}"...`);
12
+ const result = await client.createFolder({
13
+ group: opts.group,
14
+ title: opts.title,
15
+ course: opts.course,
16
+ });
17
+ console.log(result.success ? `OK: ${result.message}` : `FAIL: ${result.message}`);
18
+ process.exit(result.success ? 0 : 1);
19
+ }
20
+ finally {
21
+ await client.close();
22
+ }
23
+ });
24
+ //# sourceMappingURL=create-folder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-folder.js","sourceRoot":"","sources":["../../src/commands/create-folder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,OAAO,CAAC,eAAe,CAAC;KAC5D,WAAW,CAAC,0DAA0D,CAAC;KACvE,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;KACjF,cAAc,CAAC,qBAAqB,EAAE,4BAA4B,CAAC;KACnE,MAAM,CAAC,iBAAiB,EAAE,yCAAyC,CAAC;KACpE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YACvC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const createLessonCommand: Command;
3
+ //# sourceMappingURL=create-lesson.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-lesson.d.ts","sourceRoot":"","sources":["../../src/commands/create-lesson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,eAAO,MAAM,mBAAmB,SA8B5B,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { Command } from "commander";
2
+ import { SkoolClient } from "../core/skool-client.js";
3
+ export const createLessonCommand = new Command("create-lesson")
4
+ .description("Create a new lesson in a Skool classroom module")
5
+ .requiredOption("-g, --group <slug>", "Skool group slug", process.env.SKOOL_GROUP)
6
+ .requiredOption("-m, --module <name>", "Module name (exact match)")
7
+ .requiredOption("-t, --title <title>", "Lesson title (max 50 chars)")
8
+ .option("--course <name>", "Course name (if multiple courses exist)")
9
+ .option("--folder <name>", "Folder/module name to create the lesson in")
10
+ .option("--folder-id <id>", "Folder ID directly (from create-folder output)")
11
+ .option("-f, --file <path>", "Content file (.md, .html, or .json with skool_class)")
12
+ .option("--html <path>", "HTML file to inject directly")
13
+ .option("--markdown <text>", "Inline markdown content")
14
+ .action(async (opts) => {
15
+ const client = new SkoolClient();
16
+ try {
17
+ console.log(`Creating lesson "${opts.title}" in module "${opts.module}"...`);
18
+ const result = await client.createLesson({
19
+ group: opts.group,
20
+ module: opts.module,
21
+ title: opts.title,
22
+ course: opts.course,
23
+ folder: opts.folder,
24
+ folderId: opts.folderId,
25
+ filePath: opts.file || opts.html,
26
+ markdownContent: opts.markdown,
27
+ });
28
+ console.log(result.success ? `OK: ${result.message}` : `FAIL: ${result.message}`);
29
+ process.exit(result.success ? 0 : 1);
30
+ }
31
+ finally {
32
+ await client.close();
33
+ }
34
+ });
35
+ //# sourceMappingURL=create-lesson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-lesson.js","sourceRoot":"","sources":["../../src/commands/create-lesson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,OAAO,CAAC,eAAe,CAAC;KAC5D,WAAW,CAAC,iDAAiD,CAAC;KAC9D,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;KACjF,cAAc,CAAC,qBAAqB,EAAE,2BAA2B,CAAC;KAClE,cAAc,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;KACpE,MAAM,CAAC,iBAAiB,EAAE,yCAAyC,CAAC;KACpE,MAAM,CAAC,iBAAiB,EAAE,4CAA4C,CAAC;KACvE,MAAM,CAAC,kBAAkB,EAAE,gDAAgD,CAAC;KAC5E,MAAM,CAAC,mBAAmB,EAAE,sDAAsD,CAAC;KACnF,MAAM,CAAC,eAAe,EAAE,8BAA8B,CAAC;KACvD,MAAM,CAAC,mBAAmB,EAAE,yBAAyB,CAAC;KACtD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,KAAK,gBAAgB,IAAI,CAAC,MAAM,MAAM,CAAC,CAAC;QAC7E,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC;YACvC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI;YAChC,eAAe,EAAE,IAAI,CAAC,QAAQ;SAC/B,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const createPostCommand: Command;
3
+ //# sourceMappingURL=create-post.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-post.d.ts","sourceRoot":"","sources":["../../src/commands/create-post.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,iBAAiB,SA+B1B,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { Command } from "commander";
2
+ import { readFileSync } from "node:fs";
3
+ import { SkoolClient } from "../core/skool-client.js";
4
+ export const createPostCommand = new Command("create-post")
5
+ .description("Create a new community post in Skool")
6
+ .requiredOption("-g, --group <slug>", "Skool group slug", process.env.SKOOL_GROUP)
7
+ .requiredOption("-t, --title <title>", "Post title")
8
+ .option("-b, --body <text>", "Post body text")
9
+ .option("-f, --file <path>", "Read post body from file")
10
+ .option("-c, --category <name>", "Post category")
11
+ .action(async (opts) => {
12
+ let body = opts.body;
13
+ if (!body && opts.file) {
14
+ body = readFileSync(opts.file, "utf-8");
15
+ }
16
+ if (!body) {
17
+ console.error("Error: Post body required. Use --body or --file.");
18
+ process.exit(1);
19
+ }
20
+ const client = new SkoolClient();
21
+ try {
22
+ console.log(`Creating post "${opts.title}"...`);
23
+ const result = await client.createPost({
24
+ group: opts.group,
25
+ title: opts.title,
26
+ body,
27
+ category: opts.category,
28
+ });
29
+ console.log(result.success ? `OK: ${result.message}` : `FAIL: ${result.message}`);
30
+ process.exit(result.success ? 0 : 1);
31
+ }
32
+ finally {
33
+ await client.close();
34
+ }
35
+ });
36
+ //# sourceMappingURL=create-post.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-post.js","sourceRoot":"","sources":["../../src/commands/create-post.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC;KACxD,WAAW,CAAC,sCAAsC,CAAC;KACnD,cAAc,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;KACjF,cAAc,CAAC,qBAAqB,EAAE,YAAY,CAAC;KACnD,MAAM,CAAC,mBAAmB,EAAE,gBAAgB,CAAC;KAC7C,MAAM,CAAC,mBAAmB,EAAE,0BAA0B,CAAC;KACvD,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,IAAI,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACrB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC;YACrC,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI;YACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const debugApiCommand: Command;
3
+ //# sourceMappingURL=debug-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-api.d.ts","sourceRoot":"","sources":["../../src/commands/debug-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,eAAe,SAsHxB,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { Command } from "commander";
2
+ import { BrowserManager } from "../core/browser-manager.js";
3
+ import { PageOps } from "../core/page-ops.js";
4
+ import { writeFileSync } from "node:fs";
5
+ export const debugApiCommand = new Command("debug-api")
6
+ .description("Intercept Skool API calls during classroom operations")
7
+ .requiredOption("-g, --group <slug>", "Skool group slug", process.env.SKOOL_GROUP)
8
+ .option("--course <name>", "Course name", "Fundamentos de IA y Claude")
9
+ .action(async (opts) => {
10
+ const browser = new BrowserManager();
11
+ const ops = new PageOps(browser);
12
+ const apiLog = [];
13
+ try {
14
+ const page = await browser.getPage();
15
+ // Intercept ALL requests and responses
16
+ page.on("request", (req) => {
17
+ const url = req.url();
18
+ const method = req.method();
19
+ // Only log non-static requests (API calls, not images/css/js)
20
+ if (url.includes("/api/") ||
21
+ url.includes("graphql") ||
22
+ (method !== "GET" && !url.includes(".js") && !url.includes(".css") && !url.includes(".png") && !url.includes(".woff"))) {
23
+ const postData = req.postData();
24
+ const line = `>>> ${method} ${url}${postData ? `\n BODY: ${postData.slice(0, 500)}` : ""}`;
25
+ apiLog.push(line);
26
+ console.log(line);
27
+ }
28
+ });
29
+ page.on("response", async (res) => {
30
+ const url = res.url();
31
+ const status = res.status();
32
+ if (url.includes("/api/") ||
33
+ url.includes("graphql") ||
34
+ (status >= 200 && status < 400 && !url.includes(".js") && !url.includes(".css") && !url.includes(".png") && !url.includes(".woff") && res.request().method() !== "GET")) {
35
+ let body = "";
36
+ try {
37
+ body = await res.text();
38
+ if (body.length > 1000)
39
+ body = body.slice(0, 1000) + "...";
40
+ }
41
+ catch {
42
+ body = "(could not read body)";
43
+ }
44
+ const line = `<<< ${status} ${url}\n RESPONSE: ${body}`;
45
+ apiLog.push(line);
46
+ console.log(line);
47
+ }
48
+ });
49
+ // Also capture ALL fetch/XHR by intercepting at the page level
50
+ await page.addInitScript(() => {
51
+ const origFetch = window.fetch;
52
+ window.fetch = async (...args) => {
53
+ const url = typeof args[0] === "string" ? args[0] : args[0].url;
54
+ const opts = args[1];
55
+ console.log(`[FETCH] ${opts?.method || "GET"} ${url}`);
56
+ if (opts?.body) {
57
+ console.log(`[FETCH BODY] ${String(opts.body).slice(0, 500)}`);
58
+ }
59
+ return origFetch.apply(window, args);
60
+ };
61
+ });
62
+ console.log("\n=== Step 1: Navigate to classroom ===\n");
63
+ await ops.gotoClassroom(opts.group);
64
+ console.log("\n=== Step 2: Enter course ===\n");
65
+ await page.getByText(opts.course, { exact: false }).first().click();
66
+ await page.waitForTimeout(3000);
67
+ console.log("\n=== Step 3: Click '...' menu ===\n");
68
+ const courseTopArea = page.locator('div[class*="CourseMenuTop"]').first();
69
+ await courseTopArea.hover();
70
+ await page.waitForTimeout(500);
71
+ // Click "..." via JS
72
+ await page.evaluate(() => {
73
+ const topArea = document.querySelector('div[class*="CourseMenuTop"]');
74
+ if (!topArea)
75
+ return;
76
+ topArea.querySelectorAll("div, button, span, svg").forEach((el) => {
77
+ const rect = el.getBoundingClientRect();
78
+ const text = el.textContent?.trim() || "";
79
+ if (rect.width > 10 && rect.width < 50 && rect.height > 10 && rect.height < 50 && text.length < 4) {
80
+ el.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
81
+ }
82
+ });
83
+ });
84
+ await page.waitForTimeout(800);
85
+ console.log("\n=== Step 4: Click 'Add page' ===\n");
86
+ try {
87
+ await page.getByText("Add page", { exact: true }).click({ timeout: 5000 });
88
+ }
89
+ catch {
90
+ await page.getByText("Add page", { exact: true }).click({ force: true, timeout: 5000 });
91
+ }
92
+ await page.waitForTimeout(5000);
93
+ console.log("\n=== Step 5: Capture current URL and page state ===\n");
94
+ console.log(`Current URL: ${page.url()}`);
95
+ // Also capture all cookies for reference
96
+ const context = page.context();
97
+ const cookies = await context.cookies();
98
+ const skoolCookies = cookies
99
+ .filter((c) => c.domain.includes("skool"))
100
+ .map((c) => `${c.name}=${c.value.slice(0, 20)}...`)
101
+ .join("; ");
102
+ console.log(`Skool cookies: ${skoolCookies}`);
103
+ // Save log
104
+ const logPath = "/tmp/skool-api-log.txt";
105
+ writeFileSync(logPath, apiLog.join("\n\n"));
106
+ console.log(`\nAPI log saved to: ${logPath} (${apiLog.length} entries)`);
107
+ }
108
+ finally {
109
+ await browser.close();
110
+ }
111
+ });
112
+ //# sourceMappingURL=debug-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-api.js","sourceRoot":"","sources":["../../src/commands/debug-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const debugManualCommand: Command;
3
+ //# sourceMappingURL=debug-manual.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-manual.d.ts","sourceRoot":"","sources":["../../src/commands/debug-manual.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,kBAAkB,SA8D3B,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { Command } from "commander";
2
+ import { BrowserManager } from "../core/browser-manager.js";
3
+ import { PageOps } from "../core/page-ops.js";
4
+ import { writeFileSync } from "node:fs";
5
+ import { createInterface } from "node:readline";
6
+ export const debugManualCommand = new Command("debug-manual")
7
+ .description("Open browser with API interception — waits for you to interact manually")
8
+ .requiredOption("-g, --group <slug>", "Skool group slug", process.env.SKOOL_GROUP)
9
+ .action(async (opts) => {
10
+ const browser = new BrowserManager();
11
+ const ops = new PageOps(browser);
12
+ const apiLog = [];
13
+ try {
14
+ const page = await browser.getPage();
15
+ // Intercept API calls
16
+ page.on("request", (req) => {
17
+ const url = req.url();
18
+ const method = req.method();
19
+ if (url.includes("api2.skool.com")) {
20
+ const body = req.postData();
21
+ const line = `>>> ${method} ${url}\n BODY: ${body || "(none)"}`;
22
+ apiLog.push(line);
23
+ console.log(line);
24
+ }
25
+ });
26
+ page.on("response", async (res) => {
27
+ const url = res.url();
28
+ if (url.includes("api2.skool.com")) {
29
+ let body = "";
30
+ try {
31
+ body = await res.text();
32
+ if (body.length > 2000)
33
+ body = body.slice(0, 2000) + "...";
34
+ }
35
+ catch {
36
+ body = "(unreadable)";
37
+ }
38
+ const line = `<<< ${res.status()} ${url}\n RESPONSE: ${body}`;
39
+ apiLog.push(line);
40
+ console.log(line);
41
+ }
42
+ });
43
+ // Navigate to classroom
44
+ console.log("Opening classroom...\n");
45
+ await ops.gotoClassroom(opts.group);
46
+ // Wait for user to interact
47
+ console.log("=======================================================");
48
+ console.log("Browser is open with API interception active.");
49
+ console.log("Go to a lesson, click the pencil, edit, and click SAVE.");
50
+ console.log("All api2.skool.com calls will be logged here.");
51
+ console.log("Press ENTER when done to close the browser.");
52
+ console.log("=======================================================\n");
53
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
54
+ await new Promise((resolve) => {
55
+ rl.question("", () => { rl.close(); resolve(); });
56
+ });
57
+ // Save log
58
+ const logPath = "/tmp/skool-api-manual-log.txt";
59
+ writeFileSync(logPath, apiLog.join("\n\n"));
60
+ console.log(`\nAPI log saved to: ${logPath} (${apiLog.length} entries)`);
61
+ }
62
+ finally {
63
+ await browser.close();
64
+ }
65
+ });
66
+ //# sourceMappingURL=debug-manual.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-manual.js","sourceRoot":"","sources":["../../src/commands/debug-manual.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare const debugCommand: Command;
3
+ //# sourceMappingURL=debug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/commands/debug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,YAAY,SA0GrB,CAAC"}