claudforge 2.0.0__tar.gz
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.
- claudforge-2.0.0/.gitignore +27 -0
- claudforge-2.0.0/CHANGELOG.md +45 -0
- claudforge-2.0.0/LICENSE +21 -0
- claudforge-2.0.0/PKG-INFO +214 -0
- claudforge-2.0.0/README.md +153 -0
- claudforge-2.0.0/claudforge/__init__.py +1 -0
- claudforge-2.0.0/claudforge/browser/__init__.py +0 -0
- claudforge-2.0.0/claudforge/browser/launcher.py +131 -0
- claudforge-2.0.0/claudforge/cli.py +257 -0
- claudforge-2.0.0/claudforge/dashboard/app.py +135 -0
- claudforge-2.0.0/claudforge/uploader/__init__.py +0 -0
- claudforge-2.0.0/claudforge/uploader/batch.py +324 -0
- claudforge-2.0.0/claudforge/uploader/single.py +133 -0
- claudforge-2.0.0/claudforge/utils/__init__.py +0 -0
- claudforge-2.0.0/claudforge/utils/archive.py +41 -0
- claudforge-2.0.0/claudforge/utils/history.py +32 -0
- claudforge-2.0.0/claudforge/utils/yaml_parser.py +70 -0
- claudforge-2.0.0/claudforge/utils/zipper.py +36 -0
- claudforge-2.0.0/pyproject.toml +76 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
venv/
|
|
6
|
+
.venv/
|
|
7
|
+
.env
|
|
8
|
+
|
|
9
|
+
# Project specific
|
|
10
|
+
_zips/
|
|
11
|
+
*.zip
|
|
12
|
+
.claudforge_history*
|
|
13
|
+
.claudforge_session*
|
|
14
|
+
.claudforge_debug/
|
|
15
|
+
website/claudforge_data.json
|
|
16
|
+
|
|
17
|
+
# OS
|
|
18
|
+
.DS_Store
|
|
19
|
+
Thumbs.db
|
|
20
|
+
|
|
21
|
+
# Browser / IDE
|
|
22
|
+
.vscode/
|
|
23
|
+
.idea/
|
|
24
|
+
node_modules/
|
|
25
|
+
dist/
|
|
26
|
+
build/
|
|
27
|
+
.playwright/
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [v2.0.0] - 2026-04-11
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Real-time Web Dashboard**: Streamlit-powered monitor (`claudforge dashboard`) with progress gauges, ETR calculations, and live activity logs.
|
|
9
|
+
- **Rollback System**: **NEW**: Automatic timestamped snapshots for every successful upload; revert any skill to a prior version via `claudforge rollback`.
|
|
10
|
+
- **Professional Packaging**: Full `pyproject.toml` support for `pip install` and global `claudforge` command access.
|
|
11
|
+
- **Self-Healing Automation**: Hardened "Flicker-Proof" browser logic that handles DOM re-renders and Cloudflare delays in real-time.
|
|
12
|
+
- **Predictive Batching**: Intelligent `--limit` fulfillment that refills the queue from pending skills automatically.
|
|
13
|
+
- **Cloud Inventory Sync**: Instant account scraping to detect existing skills and prevent redundant uploads.
|
|
14
|
+
- **Auto-Sanitization**: Automatic detection and correction of reserved words (e.g., 'anthropic' -> 'assistant').
|
|
15
|
+
- **Groomed Repository**: Optimized project structure with dedicated `/website` assets and enhanced ignores.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- **Packaging**: Refactored project into a structured Python package ready for PyPI.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## [1.2.0] - 2026-04-10
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- **Unified CLI**: New `claudforge` command-line interface using Typer and Rich.
|
|
26
|
+
- **Smart Validation**: `claudforge validate` command for offline SKILL.md linting.
|
|
27
|
+
- **Scaffolding**: `claudforge init` command to quickly create new skill templates.
|
|
28
|
+
- **Health Check**: `claudforge doctor` command to verify environment setup.
|
|
29
|
+
- **Batch Processing**: Stabilized batch upload logic with progress tracking.
|
|
30
|
+
- **Professional Docs**: Added `CONTRIBUTING.md`, `LICENSE`, and revamped `README.md`.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- **UX**: Switched to Rich-formatted terminal output for better readability.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
- Fixed case-sensitivity issues with `SKILL.md` zipping.
|
|
37
|
+
- Improved Cloudflare challenge detection and manual bypass prompts.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## [1.1.0] - 2026-04-09
|
|
42
|
+
- Initial release with standalone batch upload scripts.
|
|
43
|
+
|
|
44
|
+
## [1.0.0] - 2026-04-08
|
|
45
|
+
- First functional prototype for single skill uploads.
|
claudforge-2.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vinu Balagopal A P
|
|
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.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: claudforge
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: The high-performance CLI suite for Claude.ai Skills automation.
|
|
5
|
+
Project-URL: Homepage, https://claudforge.vercel.app
|
|
6
|
+
Project-URL: Repository, https://github.com/VinuBalagopalAP/claudforge
|
|
7
|
+
Project-URL: Issues, https://github.com/VinuBalagopalAP/claudforge/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/VinuBalagopalAP/claudforge/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Vinu Balagopal A P <vinubalagopalap@gmail.com>
|
|
10
|
+
License: MIT License
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2026 Vinu Balagopal A P
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
SOFTWARE.
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Keywords: ai,automation,browser-automation,claude,claude-ai,cli,mcp,playwright,skills
|
|
33
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
34
|
+
Classifier: Environment :: Console
|
|
35
|
+
Classifier: Intended Audience :: Developers
|
|
36
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Operating System :: OS Independent
|
|
39
|
+
Classifier: Programming Language :: Python :: 3
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
44
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
45
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
46
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
|
|
47
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
48
|
+
Classifier: Topic :: Utilities
|
|
49
|
+
Requires-Python: >=3.8
|
|
50
|
+
Requires-Dist: pandas>=2.0.0
|
|
51
|
+
Requires-Dist: playwright>=1.41.0
|
|
52
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
53
|
+
Requires-Dist: rich>=13.0.0
|
|
54
|
+
Requires-Dist: streamlit>=1.30.0
|
|
55
|
+
Requires-Dist: typer[all]>=0.9.0
|
|
56
|
+
Provides-Extra: dev
|
|
57
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
58
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
59
|
+
Requires-Dist: twine>=5.0.0; extra == 'dev'
|
|
60
|
+
Description-Content-Type: text/markdown
|
|
61
|
+
|
|
62
|
+
<div align="center">
|
|
63
|
+
|
|
64
|
+
<img src="https://claudforge.vercel.app/assets/favicon/logo.svg" alt="ClaudForge" width="100" />
|
|
65
|
+
|
|
66
|
+
# ClaudForge โ๏ธ
|
|
67
|
+
|
|
68
|
+
### The high-performance CLI suite for Claude.ai Skills.
|
|
69
|
+
**Package. Validate. Deploy. Any scale. From your terminal.**
|
|
70
|
+
|
|
71
|
+
[](https://python.org)
|
|
72
|
+
[](LICENSE)
|
|
73
|
+
[](https://github.com/VinuBalagopalAP/claudforge)
|
|
74
|
+
|
|
75
|
+
[**Quick Start**](#-quick-start) ยท [**Features**](#-features) ยท [**CLI Reference**](#-cli-reference) ยท [**Roadmap**](#-roadmap) ยท [**Website**](https://claudforge.vercel.app)
|
|
76
|
+
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## The Problem
|
|
82
|
+
|
|
83
|
+
Every Claude.ai power user knows this pain:
|
|
84
|
+
1. Zip the skill folder manually
|
|
85
|
+
2. Open browser
|
|
86
|
+
3. Navigate to settings -> skills
|
|
87
|
+
4. Bypass Cloudflare
|
|
88
|
+
5. Upload
|
|
89
|
+
6. Repeat for every. single. skill.
|
|
90
|
+
|
|
91
|
+
**ClaudForge fixes this.** One command. Any scale. Whether you have 10 skills or 832, it handles the logic, the auth, and the persistence so you don't have to.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## โจ Features
|
|
96
|
+
|
|
97
|
+
| Feature | What it does |
|
|
98
|
+
|---------|-------------|
|
|
99
|
+
| ๐ต๏ธ **Stealth Automation** | Human-mimicry delays, randomized viewports, and physical click simulation. |
|
|
100
|
+
| ๐ก๏ธ **Self-Healing** | "Flicker-Proof" logic with auto-retries and smart success polling. |
|
|
101
|
+
| ๐ **Rollback System** | **NEW**: Automatically backup skills on every upload; revert versions with one command. |
|
|
102
|
+
| ๐ฆ **Predictive Batching** | `--limit` fulfillment that refills the queue from pending items automatically. |
|
|
103
|
+
| ๐ **Cloud Inventory** | Scans your Claude.ai account instantly to prevent redundant uploads. |
|
|
104
|
+
| ๐ ๏ธ **Auto-Sanitize** | Scans for reserved words (like `anthropic`) and fixes them automatically. |
|
|
105
|
+
| ๐ **Progress Dashboard** | `status`, `list`, and `dashboard` commands for real-time visibility. |
|
|
106
|
+
| ๐ฅ๏ธ **Live Monitor** | A dedicated Streamlit Web UI to track long-running batches with ETR gauges. |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## ๐ Quick Start
|
|
111
|
+
|
|
112
|
+
**Requirements:** Python 3.7+, Chrome browser
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# 1. Setup
|
|
116
|
+
git clone https://github.com/VinuBalagopalAP/claudforge.git
|
|
117
|
+
cd claudforge
|
|
118
|
+
pip install . # This installs 'claudforge' globally
|
|
119
|
+
playwright install chrome
|
|
120
|
+
|
|
121
|
+
# 2. Launch the Live Monitor (optional)
|
|
122
|
+
claudforge dashboard ./my_skills
|
|
123
|
+
|
|
124
|
+
# 3. Deploy (Smart detection: folder or batch)
|
|
125
|
+
claudforge upload ./my_skills --limit 30 --profile "claude_user"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## ๐ CLI Reference
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
Usage: claudforge [command] [PATH] [options]
|
|
134
|
+
|
|
135
|
+
Commands:
|
|
136
|
+
upload [PATH] Deploy a skill or batch (auto-detects mode)
|
|
137
|
+
rollback [PATH] Revert a skill to a previous version from the archive
|
|
138
|
+
dashboard [PATH] Launch the real-time web monitor (Streamlit)
|
|
139
|
+
status [PATH] Fast summary of batch progress (Local History vs Total)
|
|
140
|
+
list [PATH] List every skill name recorded in the local history
|
|
141
|
+
validate [PATH] Check SKILL.md structure and reserved word compliance
|
|
142
|
+
init Scaffold a new Claude skill folder
|
|
143
|
+
doctor Check environment health (Chrome, Playwright, Python)
|
|
144
|
+
|
|
145
|
+
Options:
|
|
146
|
+
--limit N Strictly attempt N brand-new uploads
|
|
147
|
+
--force, -f Ignore local history; re-verify everything on Cloud
|
|
148
|
+
--profile NAME Use a persistent Chrome profile (keeps you logged in)
|
|
149
|
+
--headless Run in headless mode
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## ๐ฏ Use Cases
|
|
155
|
+
|
|
156
|
+
**The "Mass Collection" Publisher**
|
|
157
|
+
> You have 800+ skills (like the Composio collection). You run `claudforge upload` in chunks of 50. The tool remembers what you've done, handles Cloudflare blocks, and skips duplicates automatically.
|
|
158
|
+
|
|
159
|
+
**Team Skill Library**
|
|
160
|
+
> Your team shares a private `/skills` directory. You add ClaudForge to your CI pipeline and every merged PR auto-deploys the updated skill library.
|
|
161
|
+
|
|
162
|
+
**Solo Power User**
|
|
163
|
+
> You maintain 15 custom skills. Instead of zipping and clicking for 20 minutes, you run `claudforge upload ./my-skills` and it finishes in seconds.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## ๐ Architecture
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
claudforge/
|
|
171
|
+
โโโ uploader/
|
|
172
|
+
โ โโโ single.py # Flicker-proof upload logic & success polling
|
|
173
|
+
โ โโโ batch.py # Predictive queueing & pre-batch sanitization
|
|
174
|
+
โโโ browser/
|
|
175
|
+
โ โโโ launcher.py # Stealth Chrome launcher & Inventory scraping
|
|
176
|
+
โโโ utils/
|
|
177
|
+
โ โโโ history.py # Persistent .claudforge_history management
|
|
178
|
+
โ โโโ archive.py # Rollback snapshots & versioning logic
|
|
179
|
+
โ โโโ yaml_parser.py # SKILL.md parsing & Auto-Sanitization
|
|
180
|
+
โ โโโ zipper.py # High-speed skill packaging
|
|
181
|
+
โโโ cli.py # Typer CLI (Dashboards & Commands)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## ๐บ Roadmap
|
|
187
|
+
|
|
188
|
+
| Status | Feature |
|
|
189
|
+
|--------|---------|
|
|
190
|
+
| โ
Done | Single & Batch Smart Upload |
|
|
191
|
+
| โ
Done | Self-Healing (Flicker-Resistance) |
|
|
192
|
+
| โ
Done | Cloud Inventory Scraping |
|
|
193
|
+
| โ
Done | Predictive `--limit` Logic |
|
|
194
|
+
| โ
Done | `claudforge status` & `list` Dashboards |
|
|
195
|
+
| โ
Done | Auto-Sanitization (Anthropic -> Assistant) |
|
|
196
|
+
| โ
Done | Professional PyPI Packaging |
|
|
197
|
+
| โ
Done | Real-time Web Monitor (Streamlit) |
|
|
198
|
+
| โ
Done | `claudforge rollback` System |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## โ ๏ธ Disclaimer
|
|
203
|
+
|
|
204
|
+
ClaudForge uses browser automation to interact with Claude.ai's UI. This is not an officially supported API. Use at your own discretion.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## ๐ License
|
|
209
|
+
|
|
210
|
+
MIT โ Copyright (c) 2026 Vinu Balagopal AP
|
|
211
|
+
|
|
212
|
+
<div align="center">
|
|
213
|
+
Made with โ๏ธ by <a href="https://github.com/VinuBalagopalAP">Vinu Balagopal A P</a> ยท <a href="https://claudforge.vercel.app">Website</a>
|
|
214
|
+
</div>
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="https://claudforge.vercel.app/assets/favicon/logo.svg" alt="ClaudForge" width="100" />
|
|
4
|
+
|
|
5
|
+
# ClaudForge โ๏ธ
|
|
6
|
+
|
|
7
|
+
### The high-performance CLI suite for Claude.ai Skills.
|
|
8
|
+
**Package. Validate. Deploy. Any scale. From your terminal.**
|
|
9
|
+
|
|
10
|
+
[](https://python.org)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
[](https://github.com/VinuBalagopalAP/claudforge)
|
|
13
|
+
|
|
14
|
+
[**Quick Start**](#-quick-start) ยท [**Features**](#-features) ยท [**CLI Reference**](#-cli-reference) ยท [**Roadmap**](#-roadmap) ยท [**Website**](https://claudforge.vercel.app)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## The Problem
|
|
21
|
+
|
|
22
|
+
Every Claude.ai power user knows this pain:
|
|
23
|
+
1. Zip the skill folder manually
|
|
24
|
+
2. Open browser
|
|
25
|
+
3. Navigate to settings -> skills
|
|
26
|
+
4. Bypass Cloudflare
|
|
27
|
+
5. Upload
|
|
28
|
+
6. Repeat for every. single. skill.
|
|
29
|
+
|
|
30
|
+
**ClaudForge fixes this.** One command. Any scale. Whether you have 10 skills or 832, it handles the logic, the auth, and the persistence so you don't have to.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## โจ Features
|
|
35
|
+
|
|
36
|
+
| Feature | What it does |
|
|
37
|
+
|---------|-------------|
|
|
38
|
+
| ๐ต๏ธ **Stealth Automation** | Human-mimicry delays, randomized viewports, and physical click simulation. |
|
|
39
|
+
| ๐ก๏ธ **Self-Healing** | "Flicker-Proof" logic with auto-retries and smart success polling. |
|
|
40
|
+
| ๐ **Rollback System** | **NEW**: Automatically backup skills on every upload; revert versions with one command. |
|
|
41
|
+
| ๐ฆ **Predictive Batching** | `--limit` fulfillment that refills the queue from pending items automatically. |
|
|
42
|
+
| ๐ **Cloud Inventory** | Scans your Claude.ai account instantly to prevent redundant uploads. |
|
|
43
|
+
| ๐ ๏ธ **Auto-Sanitize** | Scans for reserved words (like `anthropic`) and fixes them automatically. |
|
|
44
|
+
| ๐ **Progress Dashboard** | `status`, `list`, and `dashboard` commands for real-time visibility. |
|
|
45
|
+
| ๐ฅ๏ธ **Live Monitor** | A dedicated Streamlit Web UI to track long-running batches with ETR gauges. |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## ๐ Quick Start
|
|
50
|
+
|
|
51
|
+
**Requirements:** Python 3.7+, Chrome browser
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# 1. Setup
|
|
55
|
+
git clone https://github.com/VinuBalagopalAP/claudforge.git
|
|
56
|
+
cd claudforge
|
|
57
|
+
pip install . # This installs 'claudforge' globally
|
|
58
|
+
playwright install chrome
|
|
59
|
+
|
|
60
|
+
# 2. Launch the Live Monitor (optional)
|
|
61
|
+
claudforge dashboard ./my_skills
|
|
62
|
+
|
|
63
|
+
# 3. Deploy (Smart detection: folder or batch)
|
|
64
|
+
claudforge upload ./my_skills --limit 30 --profile "claude_user"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## ๐ CLI Reference
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
Usage: claudforge [command] [PATH] [options]
|
|
73
|
+
|
|
74
|
+
Commands:
|
|
75
|
+
upload [PATH] Deploy a skill or batch (auto-detects mode)
|
|
76
|
+
rollback [PATH] Revert a skill to a previous version from the archive
|
|
77
|
+
dashboard [PATH] Launch the real-time web monitor (Streamlit)
|
|
78
|
+
status [PATH] Fast summary of batch progress (Local History vs Total)
|
|
79
|
+
list [PATH] List every skill name recorded in the local history
|
|
80
|
+
validate [PATH] Check SKILL.md structure and reserved word compliance
|
|
81
|
+
init Scaffold a new Claude skill folder
|
|
82
|
+
doctor Check environment health (Chrome, Playwright, Python)
|
|
83
|
+
|
|
84
|
+
Options:
|
|
85
|
+
--limit N Strictly attempt N brand-new uploads
|
|
86
|
+
--force, -f Ignore local history; re-verify everything on Cloud
|
|
87
|
+
--profile NAME Use a persistent Chrome profile (keeps you logged in)
|
|
88
|
+
--headless Run in headless mode
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## ๐ฏ Use Cases
|
|
94
|
+
|
|
95
|
+
**The "Mass Collection" Publisher**
|
|
96
|
+
> You have 800+ skills (like the Composio collection). You run `claudforge upload` in chunks of 50. The tool remembers what you've done, handles Cloudflare blocks, and skips duplicates automatically.
|
|
97
|
+
|
|
98
|
+
**Team Skill Library**
|
|
99
|
+
> Your team shares a private `/skills` directory. You add ClaudForge to your CI pipeline and every merged PR auto-deploys the updated skill library.
|
|
100
|
+
|
|
101
|
+
**Solo Power User**
|
|
102
|
+
> You maintain 15 custom skills. Instead of zipping and clicking for 20 minutes, you run `claudforge upload ./my-skills` and it finishes in seconds.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## ๐ Architecture
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
claudforge/
|
|
110
|
+
โโโ uploader/
|
|
111
|
+
โ โโโ single.py # Flicker-proof upload logic & success polling
|
|
112
|
+
โ โโโ batch.py # Predictive queueing & pre-batch sanitization
|
|
113
|
+
โโโ browser/
|
|
114
|
+
โ โโโ launcher.py # Stealth Chrome launcher & Inventory scraping
|
|
115
|
+
โโโ utils/
|
|
116
|
+
โ โโโ history.py # Persistent .claudforge_history management
|
|
117
|
+
โ โโโ archive.py # Rollback snapshots & versioning logic
|
|
118
|
+
โ โโโ yaml_parser.py # SKILL.md parsing & Auto-Sanitization
|
|
119
|
+
โ โโโ zipper.py # High-speed skill packaging
|
|
120
|
+
โโโ cli.py # Typer CLI (Dashboards & Commands)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## ๐บ Roadmap
|
|
126
|
+
|
|
127
|
+
| Status | Feature |
|
|
128
|
+
|--------|---------|
|
|
129
|
+
| โ
Done | Single & Batch Smart Upload |
|
|
130
|
+
| โ
Done | Self-Healing (Flicker-Resistance) |
|
|
131
|
+
| โ
Done | Cloud Inventory Scraping |
|
|
132
|
+
| โ
Done | Predictive `--limit` Logic |
|
|
133
|
+
| โ
Done | `claudforge status` & `list` Dashboards |
|
|
134
|
+
| โ
Done | Auto-Sanitization (Anthropic -> Assistant) |
|
|
135
|
+
| โ
Done | Professional PyPI Packaging |
|
|
136
|
+
| โ
Done | Real-time Web Monitor (Streamlit) |
|
|
137
|
+
| โ
Done | `claudforge rollback` System |
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## โ ๏ธ Disclaimer
|
|
142
|
+
|
|
143
|
+
ClaudForge uses browser automation to interact with Claude.ai's UI. This is not an officially supported API. Use at your own discretion.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## ๐ License
|
|
148
|
+
|
|
149
|
+
MIT โ Copyright (c) 2026 Vinu Balagopal AP
|
|
150
|
+
|
|
151
|
+
<div align="center">
|
|
152
|
+
Made with โ๏ธ by <a href="https://github.com/VinuBalagopalAP">Vinu Balagopal A P</a> ยท <a href="https://claudforge.vercel.app">Website</a>
|
|
153
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.0.0"
|
|
File without changes
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
from playwright.sync_api import sync_playwright, Browser, Page
|
|
2
|
+
from rich.console import Console
|
|
3
|
+
|
|
4
|
+
console = Console()
|
|
5
|
+
|
|
6
|
+
def launch_browser(p, headless: bool = False, connect_port: int = None, profile_path: str = None) -> tuple[any, Page]:
|
|
7
|
+
"""Launch a fresh browser, a persistent session, or connect to an existing one."""
|
|
8
|
+
import random
|
|
9
|
+
|
|
10
|
+
# Randomize viewport slightly to avoid "bot signatures"
|
|
11
|
+
width = random.randint(1280, 1920)
|
|
12
|
+
height = random.randint(720, 1080)
|
|
13
|
+
|
|
14
|
+
stealth_args = [
|
|
15
|
+
"--disable-blink-features=AutomationControlled",
|
|
16
|
+
"--no-sandbox",
|
|
17
|
+
"--disable-infobars",
|
|
18
|
+
f"--window-size={width},{height}",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
if connect_port:
|
|
22
|
+
console.print(f"[bold cyan]๐ Connecting to existing Chrome on port {connect_port}...[/bold cyan]")
|
|
23
|
+
try:
|
|
24
|
+
browser = p.chromium.connect_over_cdp(f"http://127.0.0.1:{connect_port}")
|
|
25
|
+
# Existing sessions are already "stealthy" because they are real processes
|
|
26
|
+
page = None
|
|
27
|
+
for context in browser.contexts:
|
|
28
|
+
for p_ in context.pages:
|
|
29
|
+
if "claude.ai" in p_.url:
|
|
30
|
+
page = p_
|
|
31
|
+
console.print(f"[bold green]โ
Found existing Claude tab: '{page.title()}'[/bold green]")
|
|
32
|
+
break
|
|
33
|
+
if page: break
|
|
34
|
+
|
|
35
|
+
if not page:
|
|
36
|
+
page = browser.contexts[0].new_page()
|
|
37
|
+
return browser, page
|
|
38
|
+
except Exception as e:
|
|
39
|
+
if "Browser.setDownloadBehavior" in str(e) or "context management" in str(e):
|
|
40
|
+
raise RuntimeError(
|
|
41
|
+
"Protocol Error: Your Chrome version is incompatible with direct CDP connection.\n"
|
|
42
|
+
"FIX: Close Chrome and run with the --profile flag instead:\n"
|
|
43
|
+
"claudforge upload --batch ... --profile \"/tmp/claudforge_debug\""
|
|
44
|
+
)
|
|
45
|
+
raise RuntimeError(f"Failed to connect to Chrome: {e}")
|
|
46
|
+
elif profile_path:
|
|
47
|
+
console.print(f"[bold cyan]๐ Launching persistent Chrome session: {profile_path}[/bold cyan]")
|
|
48
|
+
context = p.chromium.launch_persistent_context(
|
|
49
|
+
profile_path,
|
|
50
|
+
headless=headless,
|
|
51
|
+
channel="chrome",
|
|
52
|
+
args=stealth_args,
|
|
53
|
+
no_viewport=True,
|
|
54
|
+
viewport={"width": width, "height": height}
|
|
55
|
+
)
|
|
56
|
+
page = context.pages[0] if context.pages else context.new_page()
|
|
57
|
+
return context, page
|
|
58
|
+
else:
|
|
59
|
+
console.print("[bold cyan]๐ Launching fresh Chrome...[/bold cyan]")
|
|
60
|
+
browser = p.chromium.launch(headless=headless, channel="chrome", args=stealth_args)
|
|
61
|
+
context = browser.new_context(viewport={"width": width, "height": height})
|
|
62
|
+
page = context.new_page()
|
|
63
|
+
return browser, page
|
|
64
|
+
|
|
65
|
+
def navigate_to_skills(page, console: Console):
|
|
66
|
+
"""Navigate to the skills page and handle auth/Cloudflare."""
|
|
67
|
+
TARGET = "https://claude.ai/customize/skills"
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
page.goto(TARGET, wait_until="domcontentloaded", timeout=30000)
|
|
71
|
+
except Exception:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
# Handle Login
|
|
75
|
+
if "login" in page.url or "signin" in page.url:
|
|
76
|
+
console.print("\n[bold yellow]โ ๏ธ Please log in manually in the browser window, then press Enter.[/bold yellow]")
|
|
77
|
+
input(" [Press Enter once logged in] ")
|
|
78
|
+
if TARGET not in page.url:
|
|
79
|
+
page.goto(TARGET, wait_until="networkidle")
|
|
80
|
+
|
|
81
|
+
# Handle Cloudflare
|
|
82
|
+
while "api/challenge_redirect" in page.url or "cloudflare" in page.content().lower() or "Just a moment" in page.title():
|
|
83
|
+
console.print("\n[bold red]๐ก๏ธ Cloudflare challenge detected![/bold red]")
|
|
84
|
+
console.print(" Please solve the challenge in the browser window.")
|
|
85
|
+
console.print(" The script will detect when you are through. (Or press Enter if page is ready)")
|
|
86
|
+
try:
|
|
87
|
+
# Wait for content or user to press enter
|
|
88
|
+
page.wait_for_selector("button:has-text('Add skill')", timeout=15000)
|
|
89
|
+
break
|
|
90
|
+
except Exception:
|
|
91
|
+
input(" [Press Enter once the Skills page has fully loaded] ")
|
|
92
|
+
if TARGET not in page.url:
|
|
93
|
+
page.goto(TARGET, wait_until="domcontentloaded")
|
|
94
|
+
break
|
|
95
|
+
|
|
96
|
+
def get_existing_skills(page: Page) -> list[str]:
|
|
97
|
+
"""Extract names of already uploaded skills from the settings page."""
|
|
98
|
+
try:
|
|
99
|
+
# Claude lists skills in a list-like structure.
|
|
100
|
+
skills = []
|
|
101
|
+
# Wait a bit for the list to render
|
|
102
|
+
page.wait_for_timeout(2000)
|
|
103
|
+
|
|
104
|
+
# 1. Primary: Look for elements in the flex list
|
|
105
|
+
elements = page.query_selector_all("div.flex.flex-col > div.flex.items-center.justify-between")
|
|
106
|
+
for el in elements:
|
|
107
|
+
text = el.inner_text().split('\n')[0]
|
|
108
|
+
if text and text not in ["Add skill", "Settings", "Skills"]:
|
|
109
|
+
skills.append(text.strip())
|
|
110
|
+
|
|
111
|
+
# 2. Fallback: Search all H3s (often used for skill titles)
|
|
112
|
+
if not skills:
|
|
113
|
+
elements = page.query_selector_all("h3")
|
|
114
|
+
for el in elements:
|
|
115
|
+
t = el.inner_text().strip()
|
|
116
|
+
if t and t not in ["Add skill", "Settings", "Skills", "Customize Clause"]:
|
|
117
|
+
skills.append(t)
|
|
118
|
+
|
|
119
|
+
# 3. Last Resort: Any text near an 'Edit' button
|
|
120
|
+
if not skills:
|
|
121
|
+
elements = page.query_selector_all("button:has-text('Edit')")
|
|
122
|
+
for el in elements:
|
|
123
|
+
# Find the text in the same row/container
|
|
124
|
+
parent = el.evaluate_handle("node => node.closest('div.flex')")
|
|
125
|
+
if parent:
|
|
126
|
+
t = parent.as_element().inner_text().split('\n')[0]
|
|
127
|
+
if t: skills.append(t.strip())
|
|
128
|
+
|
|
129
|
+
return list(set([s for s in skills if s])) # Cleanup and deduplicate
|
|
130
|
+
except Exception:
|
|
131
|
+
return []
|