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.
@@ -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.
@@ -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
+ [![Python 3.7+](https://img.shields.io/badge/python-3.7+-blue.svg)](https://python.org)
72
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
73
+ [![GitHub Stars](https://img.shields.io/github/stars/VinuBalagopalAP/claudforge?style=social)](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
+ [![Python 3.7+](https://img.shields.io/badge/python-3.7+-blue.svg)](https://python.org)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
12
+ [![GitHub Stars](https://img.shields.io/github/stars/VinuBalagopalAP/claudforge?style=social)](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 []