crewly 1.1.2 → 1.2.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 +6 -6
- package/config/roles/ops/prompt.md +140 -0
- package/config/roles/ops/role.json +13 -0
- package/config/skills/agent/browse-stealth/execute.sh +84 -0
- package/config/skills/agent/browse-stealth/instructions.md +108 -0
- package/config/skills/agent/browse-stealth/launch-chrome-cdp.sh +141 -0
- package/config/skills/agent/browse-stealth/skill.json +20 -0
- package/config/skills/agent/browse-stealth/stealth-browse.py +330 -0
- package/config/skills/agent/competitor-content-tracker/execute.sh +232 -0
- package/config/skills/agent/competitor-content-tracker/instructions.md +210 -0
- package/config/skills/agent/competitor-content-tracker/skill.json +22 -0
- package/config/skills/agent/content-calendar/execute.sh +294 -0
- package/config/skills/agent/content-calendar/instructions.md +122 -0
- package/config/skills/agent/content-calendar/skill.json +22 -0
- package/config/skills/agent/content-repurposer/execute.sh +194 -0
- package/config/skills/agent/content-repurposer/instructions.md +69 -0
- package/config/skills/agent/content-repurposer/skill.json +22 -0
- package/config/skills/agent/content-writer/execute.sh +311 -0
- package/config/skills/agent/content-writer/instructions.md +124 -0
- package/config/skills/agent/content-writer/skill.json +22 -0
- package/config/skills/agent/core/generate-pdf/execute.sh +88 -0
- package/config/skills/agent/core/generate-pdf/instructions.md +46 -0
- package/config/skills/agent/core/generate-pdf/skill.json +20 -0
- package/config/skills/agent/core/report-status/execute.sh +6 -0
- package/config/skills/agent/trend-monitor/execute.sh +211 -0
- package/config/skills/agent/trend-monitor/instructions.md +207 -0
- package/config/skills/agent/trend-monitor/skill.json +22 -0
- package/config/skills/agent/vnc-browser/execute.sh +261 -0
- package/config/skills/agent/vnc-browser/instructions.md +102 -0
- package/config/skills/agent/vnc-browser/skill.json +20 -0
- package/config/skills/orchestrator/delegate-task/execute.sh +63 -4
- package/config/skills/orchestrator/delegate-task/instructions.md +60 -0
- package/config/skills/orchestrator/delegate-task/skill.json +4 -4
- package/config/skills/orchestrator/reply-slack/execute.sh +2 -0
- package/config/skills/orchestrator/send-key/execute.sh +19 -6
- package/config/skills/orchestrator/send-key/instructions.md +44 -0
- package/config/skills/orchestrator/send-key/skill.json +20 -0
- package/config/skills/orchestrator/send-message/execute.sh +9 -1
- package/config/skills/registry.json +256 -0
- package/config/templates/code-review-team/README.md +176 -0
- package/config/templates/code-review-team/team-config.json +16 -0
- package/config/templates/code-review-team.json +62 -0
- package/config/templates/content-generation-team/README.md +128 -0
- package/config/templates/content-generation-team/team-config.json +21 -0
- package/config/templates/content-generation-team.json +67 -0
- package/config/templates/demo-team.json +22 -0
- package/config/templates/social-media-ops-team/README.md +145 -0
- package/config/templates/social-media-ops-team/team-config.json +21 -0
- package/config/templates/social-media-ops-team.json +67 -0
- package/dist/backend/backend/src/constants.d.ts +69 -6
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +75 -6
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/index.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/index.js +2 -0
- package/dist/backend/backend/src/controllers/index.js.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts +8 -0
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js +110 -63
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +31 -4
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.d.ts +8 -0
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.js +127 -111
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +34 -0
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +219 -2
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/user/user.routes.d.ts +7 -0
- package/dist/backend/backend/src/controllers/user/user.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/user/user.routes.js +45 -38
- package/dist/backend/backend/src/controllers/user/user.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/whatsapp/index.d.ts +17 -0
- package/dist/backend/backend/src/controllers/whatsapp/index.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/whatsapp/index.js +18 -0
- package/dist/backend/backend/src/controllers/whatsapp/index.js.map +1 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.d.ts +12 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.js +185 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts +5 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +35 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/task-management.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/modules/task-management.routes.js +4 -0
- package/dist/backend/backend/src/routes/modules/task-management.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-heartbeat.service.js +1 -1
- package/dist/backend/backend/src/services/agent/agent-heartbeat.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +14 -3
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +160 -29
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts +4 -3
- package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.js +29 -4
- package/dist/backend/backend/src/services/agent/claude-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.js +11 -0
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts +32 -2
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +69 -8
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js +14 -2
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js +11 -2
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.d.ts +18 -0
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.js +28 -4
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/slack-messenger.adapter.js +2 -2
- package/dist/backend/backend/src/services/messaging/adapters/slack-messenger.adapter.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.d.ts +18 -0
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.js +26 -4
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts +28 -2
- package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.d.ts +33 -2
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.js +33 -0
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js +4 -2
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js +4 -3
- package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js.map +1 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +27 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.js +54 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +36 -6
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +238 -36
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.js +6 -4
- package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/backend/backend/src/services/user/user-identity.service.d.ts +44 -0
- package/dist/backend/backend/src/services/user/user-identity.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/user/user-identity.service.js +75 -8
- package/dist/backend/backend/src/services/user/user-identity.service.js.map +1 -1
- package/dist/backend/backend/src/services/whatsapp/index.d.ts +11 -0
- package/dist/backend/backend/src/services/whatsapp/index.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/index.js +11 -0
- package/dist/backend/backend/src/services/whatsapp/index.js.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.d.ts +66 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.js +96 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.js.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.d.ts +109 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.js +234 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.js.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.d.ts +127 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.js +347 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.js.map +1 -0
- package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.js +4 -0
- package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +1 -0
- package/dist/backend/backend/src/types/index.d.ts.map +1 -1
- package/dist/backend/backend/src/types/index.js.map +1 -1
- package/dist/backend/backend/src/types/slack.types.d.ts +24 -0
- package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/slack.types.js.map +1 -1
- package/dist/backend/backend/src/types/task-tracking.types.d.ts +4 -0
- package/dist/backend/backend/src/types/task-tracking.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/task-tracking.types.js.map +1 -1
- package/dist/backend/backend/src/types/whatsapp.types.d.ts +84 -0
- package/dist/backend/backend/src/types/whatsapp.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/whatsapp.types.js +33 -0
- package/dist/backend/backend/src/types/whatsapp.types.js.map +1 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts +11 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js +35 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +69 -6
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +75 -6
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js +14 -2
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/cli/backend/src/types/index.d.ts +1 -0
- package/dist/cli/backend/src/types/index.d.ts.map +1 -1
- package/dist/cli/backend/src/types/index.js.map +1 -1
- package/dist/cli/cli/src/commands/publish.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/publish.js +17 -15
- package/dist/cli/cli/src/commands/publish.js.map +1 -1
- package/dist/cli/cli/src/index.js +2 -2
- package/dist/cli/cli/src/index.js.map +1 -1
- package/dist/cli/cli/src/utils/gh-submit.d.ts +46 -0
- package/dist/cli/cli/src/utils/gh-submit.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/gh-submit.js +167 -0
- package/dist/cli/cli/src/utils/gh-submit.js.map +1 -0
- package/dist/cli/cli/src/utils/marketplace.d.ts.map +1 -1
- package/dist/cli/cli/src/utils/marketplace.js +13 -5
- package/dist/cli/cli/src/utils/marketplace.js.map +1 -1
- package/dist/cli/cli/src/utils/templates.d.ts +3 -2
- package/dist/cli/cli/src/utils/templates.d.ts.map +1 -1
- package/dist/cli/cli/src/utils/templates.js +5 -4
- package/dist/cli/cli/src/utils/templates.js.map +1 -1
- package/frontend/dist/assets/{index-45eeea99.js → index-a23214ae.js} +241 -241
- package/frontend/dist/assets/{index-6972eeee.css → index-c407fe13.css} +1 -1
- package/frontend/dist/index.html +2 -2
- package/package.json +3 -1
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Trend Monitor
|
|
2
|
+
|
|
3
|
+
Monitor trending topics across platforms using browser automation, then store and query them for content planning.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
This skill has two parts:
|
|
8
|
+
1. **Browser scanning** (agent-driven) — You use Playwright MCP or Chrome browser tools to visit pages and extract trends
|
|
9
|
+
2. **Data management** (execute.sh) — Save, query, and get suggestions from stored trend data
|
|
10
|
+
|
|
11
|
+
## Data Actions (execute.sh)
|
|
12
|
+
|
|
13
|
+
### `save` — Store trends from a browser scan
|
|
14
|
+
|
|
15
|
+
| Parameter | Required | Description |
|
|
16
|
+
|-----------|----------|-------------|
|
|
17
|
+
| `action` | Yes | `"save"` |
|
|
18
|
+
| `source` | Yes | `x-trending`, `google-trends`, `hackernews`, `producthunt`, `reddit`, `github-trending`, `custom` |
|
|
19
|
+
| `trends` | Yes | JSON array of trend objects (see schema below) |
|
|
20
|
+
| `projectPath` | No | Project path for storage location |
|
|
21
|
+
|
|
22
|
+
**Trend object schema:**
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"title": "Topic or headline",
|
|
26
|
+
"url": "https://source-url",
|
|
27
|
+
"description": "Brief description",
|
|
28
|
+
"engagement": "500 points / 200 comments",
|
|
29
|
+
"relevanceScore": 8,
|
|
30
|
+
"tags": ["ai", "agents", "automation"]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`relevanceScore` (1-10): How relevant to AI Agent / Crewly content. Score guide:
|
|
35
|
+
- 9-10: Directly about AI agents, orchestration, multi-agent systems
|
|
36
|
+
- 7-8: About AI tools, LLMs, automation, developer tooling
|
|
37
|
+
- 5-6: About SaaS, startups, productivity, SMB
|
|
38
|
+
- 3-4: General tech, not directly relevant
|
|
39
|
+
- 1-2: Not relevant
|
|
40
|
+
|
|
41
|
+
### `list` — List available trend scan files
|
|
42
|
+
|
|
43
|
+
| Parameter | Required | Description |
|
|
44
|
+
|-----------|----------|-------------|
|
|
45
|
+
| `action` | Yes | `"list"` |
|
|
46
|
+
| `source` | No | Filter by source |
|
|
47
|
+
| `date` | No | Filter by date (YYYY-MM-DD) |
|
|
48
|
+
| `limit` | No | Max files to return (default: 10) |
|
|
49
|
+
|
|
50
|
+
### `latest` — Get the most recent trends
|
|
51
|
+
|
|
52
|
+
| Parameter | Required | Description |
|
|
53
|
+
|-----------|----------|-------------|
|
|
54
|
+
| `action` | Yes | `"latest"` |
|
|
55
|
+
| `source` | No | Filter by source |
|
|
56
|
+
| `limit` | No | Max items (default: 20) |
|
|
57
|
+
|
|
58
|
+
### `suggest` — Get AI-filtered topic suggestions
|
|
59
|
+
|
|
60
|
+
| Parameter | Required | Description |
|
|
61
|
+
|-----------|----------|-------------|
|
|
62
|
+
| `action` | Yes | `"suggest"` |
|
|
63
|
+
| `line` | No | Content line: `crewly` or `personal` (default: crewly) |
|
|
64
|
+
| `limit` | No | Max suggestions (default: 5) |
|
|
65
|
+
|
|
66
|
+
## Browser Scanning Guide
|
|
67
|
+
|
|
68
|
+
### Step-by-step: How to scan each source
|
|
69
|
+
|
|
70
|
+
The agent should perform these browser operations, then pass the extracted data to `execute.sh save`.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### Source 1: Hacker News (hackernews)
|
|
75
|
+
|
|
76
|
+
**URL:** `https://news.ycombinator.com`
|
|
77
|
+
|
|
78
|
+
**Steps:**
|
|
79
|
+
1. Navigate to `https://news.ycombinator.com`
|
|
80
|
+
2. Take a snapshot of the page
|
|
81
|
+
3. Extract from each story row:
|
|
82
|
+
- Title text
|
|
83
|
+
- URL (href from titleline link)
|
|
84
|
+
- Points and comment count (from subline)
|
|
85
|
+
4. Score relevance (AI/agent/automation related = high score)
|
|
86
|
+
5. Save top 20 stories
|
|
87
|
+
|
|
88
|
+
**Alternative (faster):** Use WebSearch with query `site:news.ycombinator.com AI agents` for targeted results.
|
|
89
|
+
|
|
90
|
+
**Example save:**
|
|
91
|
+
```bash
|
|
92
|
+
bash execute.sh '{"action":"save","source":"hackernews","projectPath":"/path/to/project","trends":[
|
|
93
|
+
{"title":"Show HN: Open-source AI agent framework","url":"https://news.ycombinator.com/item?id=123","engagement":"342 points, 89 comments","relevanceScore":9,"tags":["ai","agents","open-source"]},
|
|
94
|
+
{"title":"Why we moved from n8n to custom orchestration","url":"https://example.com/post","engagement":"156 points, 43 comments","relevanceScore":8,"tags":["automation","n8n","orchestration"]}
|
|
95
|
+
]}'
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### Source 2: X/Twitter Trending (x-trending)
|
|
101
|
+
|
|
102
|
+
**URL:** `https://x.com/explore/tabs/trending`
|
|
103
|
+
|
|
104
|
+
**Steps:**
|
|
105
|
+
1. Navigate to `https://x.com/explore/tabs/trending` (or `https://x.com/explore`)
|
|
106
|
+
2. Take a snapshot
|
|
107
|
+
3. Extract trending topics and hashtags
|
|
108
|
+
4. For each trend, note:
|
|
109
|
+
- Topic name / hashtag
|
|
110
|
+
- Tweet count or category if shown
|
|
111
|
+
- Brief context if available
|
|
112
|
+
5. Score relevance to AI/tech/startup
|
|
113
|
+
|
|
114
|
+
**Alternative:** Use WebSearch with `site:x.com trending AI agents` or check `https://trends24.in/united-states/`
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### Source 3: Product Hunt (producthunt)
|
|
119
|
+
|
|
120
|
+
**URL:** `https://www.producthunt.com`
|
|
121
|
+
|
|
122
|
+
**Steps:**
|
|
123
|
+
1. Navigate to `https://www.producthunt.com`
|
|
124
|
+
2. Take a snapshot of today's launches
|
|
125
|
+
3. Extract from each product:
|
|
126
|
+
- Product name and tagline
|
|
127
|
+
- Upvote count
|
|
128
|
+
- URL
|
|
129
|
+
- Category/tags
|
|
130
|
+
4. Filter for AI/automation/developer tools
|
|
131
|
+
5. Score relevance
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### Source 4: Google Trends (google-trends)
|
|
136
|
+
|
|
137
|
+
**URL:** `https://trends.google.com/trending?geo=US`
|
|
138
|
+
|
|
139
|
+
**Steps:**
|
|
140
|
+
1. Navigate to `https://trends.google.com/trending?geo=US`
|
|
141
|
+
2. Take a snapshot
|
|
142
|
+
3. Extract daily trending searches
|
|
143
|
+
4. Filter for tech/AI related terms
|
|
144
|
+
5. Score relevance
|
|
145
|
+
|
|
146
|
+
**Alternative:** Use WebSearch with `Google Trends AI agents 2026` for curated results.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
### Source 5: Reddit (reddit)
|
|
151
|
+
|
|
152
|
+
**URLs:**
|
|
153
|
+
- `https://www.reddit.com/r/artificial/hot/`
|
|
154
|
+
- `https://www.reddit.com/r/LocalLLaMA/hot/`
|
|
155
|
+
- `https://www.reddit.com/r/SideProject/hot/`
|
|
156
|
+
|
|
157
|
+
**Steps:**
|
|
158
|
+
1. Navigate to each subreddit
|
|
159
|
+
2. Extract top 10 posts: title, score, comment count, URL
|
|
160
|
+
3. Score relevance
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### Source 6: GitHub Trending (github-trending)
|
|
165
|
+
|
|
166
|
+
**URL:** `https://github.com/trending`
|
|
167
|
+
|
|
168
|
+
**Steps:**
|
|
169
|
+
1. Navigate to `https://github.com/trending`
|
|
170
|
+
2. Extract: repo name, description, stars today, language
|
|
171
|
+
3. Filter for AI/agent/automation repos
|
|
172
|
+
4. Score relevance
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Recommended Scan Schedule
|
|
177
|
+
|
|
178
|
+
| Time | Source | Frequency |
|
|
179
|
+
|------|--------|-----------|
|
|
180
|
+
| Morning | Hacker News + Product Hunt | Daily |
|
|
181
|
+
| Afternoon | X Trending + Reddit | Daily |
|
|
182
|
+
| Weekly | Google Trends + GitHub Trending | Monday |
|
|
183
|
+
|
|
184
|
+
## Workflow Integration
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
1. Agent runs browser scans → saves via execute.sh save
|
|
188
|
+
2. Agent calls execute.sh suggest → gets AI-filtered topics
|
|
189
|
+
3. Agent feeds suggestions to content-writer skill
|
|
190
|
+
4. Agent adds chosen topics to content-calendar
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Example: Full Daily Scan
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
# After scanning HN via browser and extracting data:
|
|
197
|
+
bash execute.sh '{"action":"save","source":"hackernews","projectPath":"/path","trends":[...]}'
|
|
198
|
+
|
|
199
|
+
# After scanning PH via browser:
|
|
200
|
+
bash execute.sh '{"action":"save","source":"producthunt","projectPath":"/path","trends":[...]}'
|
|
201
|
+
|
|
202
|
+
# Get suggestions for content:
|
|
203
|
+
bash execute.sh '{"action":"suggest","line":"crewly","projectPath":"/path"}'
|
|
204
|
+
|
|
205
|
+
# Check latest across all sources:
|
|
206
|
+
bash execute.sh '{"action":"latest","limit":"10","projectPath":"/path"}'
|
|
207
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "trend-monitor",
|
|
3
|
+
"name": "Trend Monitor",
|
|
4
|
+
"description": "Monitor and store trending topics from X, Google Trends, Hacker News, Product Hunt, Reddit, and GitHub. Save browser-extracted trends, query latest data, and get AI-filtered topic suggestions for content planning.",
|
|
5
|
+
"category": "content",
|
|
6
|
+
"skillType": "claude-skill",
|
|
7
|
+
"promptFile": "instructions.md",
|
|
8
|
+
"execution": {
|
|
9
|
+
"type": "script",
|
|
10
|
+
"script": {
|
|
11
|
+
"file": "execute.sh",
|
|
12
|
+
"interpreter": "bash",
|
|
13
|
+
"timeoutMs": 15000
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"assignableRoles": ["content-strategist", "product-manager", "generalist"],
|
|
17
|
+
"triggers": ["trending topics", "what is trending", "trend monitor", "hot topics", "content ideas", "topic suggestions"],
|
|
18
|
+
"tags": ["trends", "monitoring", "content", "social-media", "hackernews", "producthunt", "x-twitter", "marketing"],
|
|
19
|
+
"version": "1.0.0",
|
|
20
|
+
"author": "Luna (Content Strategist)",
|
|
21
|
+
"license": "MIT"
|
|
22
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# VNC Remote Browser Access — bridge macOS Screen Sharing to a public URL via noVNC
|
|
3
|
+
# Allows remote viewing/control of the Mac desktop (and any browser on it) via a web URL.
|
|
4
|
+
#
|
|
5
|
+
# Architecture:
|
|
6
|
+
# macOS Screen Sharing (built-in VNC server on port 5900)
|
|
7
|
+
# → websockify (WebSocket bridge + noVNC web server, port 6080)
|
|
8
|
+
# → cloudflared (Quick Tunnel → public HTTPS URL)
|
|
9
|
+
#
|
|
10
|
+
# Prerequisites: macOS Screen Sharing must be enabled manually in System Settings.
|
|
11
|
+
#
|
|
12
|
+
# Usage: execute.sh '{"action":"start|stop|status|get-url"}'
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
source "${SCRIPT_DIR}/../../_common/lib.sh"
|
|
16
|
+
|
|
17
|
+
# ---------------------------------------------------------------------------
|
|
18
|
+
# Configuration
|
|
19
|
+
# ---------------------------------------------------------------------------
|
|
20
|
+
VNC_PORT=5900
|
|
21
|
+
NOVNC_PORT=6080
|
|
22
|
+
PID_DIR="${HOME}/.crewly/vnc"
|
|
23
|
+
NOVNC_DIR="${HOME}/.crewly/novnc"
|
|
24
|
+
CLOUDFLARED_LOG="${PID_DIR}/cloudflared.log"
|
|
25
|
+
|
|
26
|
+
INPUT="${1:-}"
|
|
27
|
+
[ -z "$INPUT" ] && error_exit "Usage: execute.sh '{\"action\":\"start|stop|status|get-url\"}'"
|
|
28
|
+
|
|
29
|
+
ACTION=$(echo "$INPUT" | jq -r '.action // empty')
|
|
30
|
+
require_param "action" "$ACTION"
|
|
31
|
+
|
|
32
|
+
mkdir -p "$PID_DIR"
|
|
33
|
+
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
# Dependency installation (macOS / Homebrew)
|
|
36
|
+
# ---------------------------------------------------------------------------
|
|
37
|
+
install_deps() {
|
|
38
|
+
local missing=()
|
|
39
|
+
|
|
40
|
+
# websockify — WebSocket-to-TCP bridge (Python)
|
|
41
|
+
if ! command -v websockify &>/dev/null; then
|
|
42
|
+
missing+=("websockify")
|
|
43
|
+
echo '{"status":"installing","dep":"websockify"}' >&2
|
|
44
|
+
pip3 install websockify 2>/dev/null \
|
|
45
|
+
|| error_exit "Failed to install websockify. Run: pip3 install websockify"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# noVNC — HTML5 VNC client
|
|
49
|
+
if ! [ -d "$NOVNC_DIR" ] || ! [ -f "$NOVNC_DIR/vnc.html" ]; then
|
|
50
|
+
missing+=("novnc")
|
|
51
|
+
echo '{"status":"installing","dep":"novnc"}' >&2
|
|
52
|
+
local novnc_version="1.5.0"
|
|
53
|
+
local novnc_url="https://github.com/novnc/noVNC/archive/refs/tags/v${novnc_version}.tar.gz"
|
|
54
|
+
mkdir -p "$NOVNC_DIR"
|
|
55
|
+
curl -sL "$novnc_url" | tar -xz -C "$NOVNC_DIR" --strip-components=1
|
|
56
|
+
if ! [ -f "$NOVNC_DIR/vnc.html" ]; then
|
|
57
|
+
rm -rf "$NOVNC_DIR"
|
|
58
|
+
error_exit "Failed to download noVNC web client"
|
|
59
|
+
fi
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# cloudflared — Cloudflare Tunnel for public HTTPS URL
|
|
63
|
+
if ! command -v cloudflared &>/dev/null; then
|
|
64
|
+
missing+=("cloudflared")
|
|
65
|
+
echo '{"status":"installing","dep":"cloudflared"}' >&2
|
|
66
|
+
brew install cloudflare/cloudflare/cloudflared 2>/dev/null \
|
|
67
|
+
|| error_exit "Failed to install cloudflared. Run: brew install cloudflare/cloudflare/cloudflared"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
if [ ${#missing[@]} -gt 0 ]; then
|
|
71
|
+
echo '{"status":"deps_installed","installed":"'"$(IFS=,; echo "${missing[*]}")"'"}' >&2
|
|
72
|
+
fi
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
# ---------------------------------------------------------------------------
|
|
76
|
+
# Helper: check if a service is running via its PID file
|
|
77
|
+
# ---------------------------------------------------------------------------
|
|
78
|
+
is_running() {
|
|
79
|
+
local pid_file="$PID_DIR/${1}.pid"
|
|
80
|
+
[ -f "$pid_file" ] && kill -0 "$(cat "$pid_file")" 2>/dev/null
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# ---------------------------------------------------------------------------
|
|
84
|
+
# Helper: check if macOS Screen Sharing VNC is listening on port 5900
|
|
85
|
+
# ---------------------------------------------------------------------------
|
|
86
|
+
check_screen_sharing() {
|
|
87
|
+
nc -z localhost "$VNC_PORT" 2>/dev/null
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# ---------------------------------------------------------------------------
|
|
91
|
+
# start — Launch websockify + cloudflared (requires Screen Sharing on)
|
|
92
|
+
# ---------------------------------------------------------------------------
|
|
93
|
+
start_vnc() {
|
|
94
|
+
# Already running?
|
|
95
|
+
if is_running websockify && is_running cloudflared; then
|
|
96
|
+
local url=""
|
|
97
|
+
[ -f "$PID_DIR/tunnel_url.txt" ] && url=$(cat "$PID_DIR/tunnel_url.txt")
|
|
98
|
+
jq -n --arg url "$url" \
|
|
99
|
+
'{success: true, status: "already_running", publicUrl: (if $url != "" then ($url + "/vnc.html?autoconnect=true") else null end), localUrl: ("http://localhost:'"$NOVNC_PORT"'/vnc.html?autoconnect=true")}'
|
|
100
|
+
return 0
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
# Check macOS Screen Sharing is enabled
|
|
104
|
+
if ! check_screen_sharing; then
|
|
105
|
+
error_exit "macOS Screen Sharing is not running (port $VNC_PORT not listening). Enable it: System Settings → General → Sharing → Screen Sharing → ON"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# Install missing dependencies
|
|
109
|
+
install_deps
|
|
110
|
+
|
|
111
|
+
# 1. Start websockify (WebSocket bridge + noVNC web server)
|
|
112
|
+
# Bridges noVNC web client (port 6080) to macOS VNC (port 5900)
|
|
113
|
+
websockify --web "$NOVNC_DIR" "$NOVNC_PORT" "localhost:$VNC_PORT" \
|
|
114
|
+
> "$PID_DIR/websockify.log" 2>&1 &
|
|
115
|
+
echo $! > "$PID_DIR/websockify.pid"
|
|
116
|
+
sleep 1
|
|
117
|
+
|
|
118
|
+
if ! is_running websockify; then
|
|
119
|
+
error_exit "websockify failed to start. Check $PID_DIR/websockify.log"
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# 2. Start cloudflared Quick Tunnel (zero-config public URL)
|
|
123
|
+
cloudflared tunnel --url "http://localhost:$NOVNC_PORT" \
|
|
124
|
+
> "$CLOUDFLARED_LOG" 2>&1 &
|
|
125
|
+
echo $! > "$PID_DIR/cloudflared.pid"
|
|
126
|
+
|
|
127
|
+
# Wait for cloudflared to print the tunnel URL (up to 30s)
|
|
128
|
+
local url=""
|
|
129
|
+
for _ in $(seq 1 30); do
|
|
130
|
+
url=$(grep -oE 'https://[a-z0-9-]+\.trycloudflare\.com' "$CLOUDFLARED_LOG" 2>/dev/null | head -1 || true)
|
|
131
|
+
[ -n "$url" ] && break
|
|
132
|
+
sleep 1
|
|
133
|
+
done
|
|
134
|
+
|
|
135
|
+
if [ -n "$url" ]; then
|
|
136
|
+
echo "$url" > "$PID_DIR/tunnel_url.txt"
|
|
137
|
+
jq -n --arg url "$url" \
|
|
138
|
+
'{success: true, status: "started", publicUrl: ($url + "/vnc.html?autoconnect=true"), localUrl: ("http://localhost:'"$NOVNC_PORT"'/vnc.html?autoconnect=true"), hint: "Share the publicUrl with the user. They will see the Mac desktop and can interact with the browser."}'
|
|
139
|
+
else
|
|
140
|
+
jq -n \
|
|
141
|
+
'{success: true, status: "started_no_tunnel", publicUrl: null, localUrl: ("http://localhost:'"$NOVNC_PORT"'/vnc.html?autoconnect=true"), hint: "Cloudflared URL not ready yet. Use get-url action to retrieve it later."}'
|
|
142
|
+
fi
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
# ---------------------------------------------------------------------------
|
|
146
|
+
# stop — Tear down websockify + cloudflared (does NOT touch Screen Sharing)
|
|
147
|
+
# ---------------------------------------------------------------------------
|
|
148
|
+
stop_vnc() {
|
|
149
|
+
local stopped=0
|
|
150
|
+
|
|
151
|
+
for service in cloudflared websockify; do
|
|
152
|
+
local pid_file="$PID_DIR/${service}.pid"
|
|
153
|
+
if [ -f "$pid_file" ]; then
|
|
154
|
+
local pid
|
|
155
|
+
pid=$(cat "$pid_file")
|
|
156
|
+
if kill -0 "$pid" 2>/dev/null; then
|
|
157
|
+
kill "$pid" 2>/dev/null || true
|
|
158
|
+
stopped=$((stopped + 1))
|
|
159
|
+
fi
|
|
160
|
+
rm -f "$pid_file"
|
|
161
|
+
fi
|
|
162
|
+
done
|
|
163
|
+
|
|
164
|
+
rm -f "$PID_DIR/tunnel_url.txt"
|
|
165
|
+
|
|
166
|
+
jq -n --argjson stopped "$stopped" \
|
|
167
|
+
'{success: true, status: "stopped", stoppedServices: $stopped, note: "macOS Screen Sharing was not touched"}'
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# ---------------------------------------------------------------------------
|
|
171
|
+
# status — Check which services are running
|
|
172
|
+
# ---------------------------------------------------------------------------
|
|
173
|
+
status_vnc() {
|
|
174
|
+
local services='[]'
|
|
175
|
+
local all_running=true
|
|
176
|
+
|
|
177
|
+
# Check macOS Screen Sharing (port 5900)
|
|
178
|
+
local screen_sharing=false
|
|
179
|
+
if check_screen_sharing; then
|
|
180
|
+
screen_sharing=true
|
|
181
|
+
else
|
|
182
|
+
all_running=false
|
|
183
|
+
fi
|
|
184
|
+
services=$(echo "$services" | jq \
|
|
185
|
+
--arg name "screen-sharing" \
|
|
186
|
+
--argjson running "$screen_sharing" \
|
|
187
|
+
--arg pid "system" \
|
|
188
|
+
'. + [{name: $name, running: $running, pid: $pid}]')
|
|
189
|
+
|
|
190
|
+
# Check managed services
|
|
191
|
+
for service in websockify cloudflared; do
|
|
192
|
+
local pid_file="$PID_DIR/${service}.pid"
|
|
193
|
+
local running=false
|
|
194
|
+
local pid=""
|
|
195
|
+
|
|
196
|
+
if [ -f "$pid_file" ]; then
|
|
197
|
+
pid=$(cat "$pid_file")
|
|
198
|
+
if kill -0 "$pid" 2>/dev/null; then
|
|
199
|
+
running=true
|
|
200
|
+
fi
|
|
201
|
+
fi
|
|
202
|
+
|
|
203
|
+
[ "$running" = false ] && all_running=false
|
|
204
|
+
|
|
205
|
+
services=$(echo "$services" | jq \
|
|
206
|
+
--arg name "$service" \
|
|
207
|
+
--argjson running "$running" \
|
|
208
|
+
--arg pid "$pid" \
|
|
209
|
+
'. + [{name: $name, running: $running, pid: $pid}]')
|
|
210
|
+
done
|
|
211
|
+
|
|
212
|
+
local url=""
|
|
213
|
+
[ -f "$PID_DIR/tunnel_url.txt" ] && url=$(cat "$PID_DIR/tunnel_url.txt")
|
|
214
|
+
|
|
215
|
+
jq -n \
|
|
216
|
+
--argjson allRunning "$all_running" \
|
|
217
|
+
--argjson services "$services" \
|
|
218
|
+
--arg publicUrl "${url:-}" \
|
|
219
|
+
'{success: true, allRunning: $allRunning, publicUrl: (if $publicUrl != "" then ($publicUrl + "/vnc.html?autoconnect=true") else null end), services: $services}'
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
# ---------------------------------------------------------------------------
|
|
223
|
+
# get-url — Retrieve the public tunnel URL
|
|
224
|
+
# ---------------------------------------------------------------------------
|
|
225
|
+
get_url() {
|
|
226
|
+
# Try saved URL
|
|
227
|
+
if [ -f "$PID_DIR/tunnel_url.txt" ]; then
|
|
228
|
+
local url
|
|
229
|
+
url=$(cat "$PID_DIR/tunnel_url.txt")
|
|
230
|
+
if [ -n "$url" ]; then
|
|
231
|
+
jq -n --arg url "$url" \
|
|
232
|
+
'{success: true, publicUrl: ($url + "/vnc.html?autoconnect=true"), localUrl: ("http://localhost:'"$NOVNC_PORT"'/vnc.html?autoconnect=true")}'
|
|
233
|
+
return 0
|
|
234
|
+
fi
|
|
235
|
+
fi
|
|
236
|
+
|
|
237
|
+
# Try parsing from cloudflared log
|
|
238
|
+
if [ -f "$CLOUDFLARED_LOG" ]; then
|
|
239
|
+
local url
|
|
240
|
+
url=$(grep -oE 'https://[a-z0-9-]+\.trycloudflare\.com' "$CLOUDFLARED_LOG" 2>/dev/null | head -1 || true)
|
|
241
|
+
if [ -n "$url" ]; then
|
|
242
|
+
echo "$url" > "$PID_DIR/tunnel_url.txt"
|
|
243
|
+
jq -n --arg url "$url" \
|
|
244
|
+
'{success: true, publicUrl: ($url + "/vnc.html?autoconnect=true"), localUrl: ("http://localhost:'"$NOVNC_PORT"'/vnc.html?autoconnect=true")}'
|
|
245
|
+
return 0
|
|
246
|
+
fi
|
|
247
|
+
fi
|
|
248
|
+
|
|
249
|
+
error_exit "No tunnel URL available. Is VNC started? Try: execute.sh '{\"action\":\"start\"}'"
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
# ---------------------------------------------------------------------------
|
|
253
|
+
# Dispatch
|
|
254
|
+
# ---------------------------------------------------------------------------
|
|
255
|
+
case "$ACTION" in
|
|
256
|
+
start) start_vnc ;;
|
|
257
|
+
stop) stop_vnc ;;
|
|
258
|
+
status) status_vnc ;;
|
|
259
|
+
get-url) get_url ;;
|
|
260
|
+
*) error_exit "Unknown action: $ACTION. Valid actions: start, stop, status, get-url" ;;
|
|
261
|
+
esac
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# VNC Remote Browser Access
|
|
2
|
+
|
|
3
|
+
Bridge macOS Screen Sharing to a public HTTPS URL via noVNC + cloudflared. This lets humans remotely view and control the Mac desktop (and any browser on it) from anywhere — essential when Playwright hits a login page, CAPTCHA, or 2FA prompt.
|
|
4
|
+
|
|
5
|
+
The stack: **macOS Screen Sharing** (built-in VNC, port 5900) → **websockify + noVNC** (web client, port 6080) → **cloudflared** (public HTTPS tunnel).
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
**macOS Screen Sharing must be enabled manually** before using this skill:
|
|
10
|
+
|
|
11
|
+
1. Open **System Settings** → **General** → **Sharing**
|
|
12
|
+
2. Turn on **Screen Sharing**
|
|
13
|
+
3. (Optional) Set a VNC password under Screen Sharing options
|
|
14
|
+
|
|
15
|
+
This only needs to be done once. Screen Sharing runs as a system service and persists across reboots.
|
|
16
|
+
|
|
17
|
+
## When to Use
|
|
18
|
+
|
|
19
|
+
- Playwright hits a login page that requires human credentials
|
|
20
|
+
- A website shows a CAPTCHA or anti-bot challenge
|
|
21
|
+
- Two-factor authentication (2FA/MFA) requires a code from the user
|
|
22
|
+
- You need the user to visually verify something in the browser
|
|
23
|
+
- Any browser automation step that needs human-in-the-loop interaction
|
|
24
|
+
|
|
25
|
+
## Parameters
|
|
26
|
+
|
|
27
|
+
| Parameter | Required | Description |
|
|
28
|
+
|-----------|----------|-------------|
|
|
29
|
+
| `action` | Yes | One of: `start`, `stop`, `status`, `get-url` |
|
|
30
|
+
|
|
31
|
+
### Actions
|
|
32
|
+
|
|
33
|
+
- **start** — Check Screen Sharing is on, install deps if needed, launch websockify + noVNC + cloudflared. Returns the public URL.
|
|
34
|
+
- **stop** — Shut down websockify + cloudflared. Does NOT touch Screen Sharing.
|
|
35
|
+
- **status** — Check Screen Sharing (port 5900), websockify, and cloudflared status.
|
|
36
|
+
- **get-url** — Retrieve the cloudflared public URL.
|
|
37
|
+
|
|
38
|
+
## Examples
|
|
39
|
+
|
|
40
|
+
### Start and get the public URL
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
bash config/skills/agent/vnc-browser/execute.sh '{"action":"start"}'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Output:
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"success": true,
|
|
50
|
+
"status": "started",
|
|
51
|
+
"publicUrl": "https://abc-xyz.trycloudflare.com/vnc.html?autoconnect=true",
|
|
52
|
+
"localUrl": "http://localhost:6080/vnc.html?autoconnect=true",
|
|
53
|
+
"hint": "Share the publicUrl with the user..."
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Send the URL to the user via Slack
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
URL=$(bash config/skills/agent/vnc-browser/execute.sh '{"action":"get-url"}' | jq -r '.publicUrl')
|
|
61
|
+
# Then send via reply-slack or report-status
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Check status
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
bash config/skills/agent/vnc-browser/execute.sh '{"action":"status"}'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Stop when done
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
bash config/skills/agent/vnc-browser/execute.sh '{"action":"stop"}'
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Workflow
|
|
77
|
+
|
|
78
|
+
1. **Ensure Screen Sharing is on** (one-time setup)
|
|
79
|
+
2. **Start VNC bridge** → get the public URL
|
|
80
|
+
3. **Launch Playwright** in headful mode (the browser appears on the Mac desktop)
|
|
81
|
+
4. **Navigate** to the page requiring human interaction
|
|
82
|
+
5. **Send the public URL** to the user via Slack
|
|
83
|
+
6. **Wait** for the user to complete the manual step (login, CAPTCHA, etc.)
|
|
84
|
+
7. **Continue automation** once the browser is past the manual step
|
|
85
|
+
8. **Stop VNC bridge** when no longer needed
|
|
86
|
+
|
|
87
|
+
## Technical Details
|
|
88
|
+
|
|
89
|
+
- **VNC source**: macOS Screen Sharing on port 5900 (system-managed)
|
|
90
|
+
- **Web client**: noVNC on port 6080 via websockify
|
|
91
|
+
- **Public tunnel**: cloudflared Quick Tunnel (random `*.trycloudflare.com` subdomain)
|
|
92
|
+
- **Security**: Screen Sharing requires macOS user credentials; cloudflared provides HTTPS
|
|
93
|
+
- **Dependencies**: websockify (pip), noVNC (GitHub release), cloudflared (Homebrew) — auto-installed on first run
|
|
94
|
+
- **PID files**: `~/.crewly/vnc/` for websockify and cloudflared lifecycle
|
|
95
|
+
- **Note**: This skill does NOT start or stop macOS Screen Sharing — that is user-managed
|
|
96
|
+
|
|
97
|
+
## Requirements
|
|
98
|
+
|
|
99
|
+
- macOS with Screen Sharing enabled
|
|
100
|
+
- Homebrew installed
|
|
101
|
+
- Python 3 with pip (for websockify)
|
|
102
|
+
- Internet access (for cloudflared tunnel and dependency installation)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "agent-vnc-browser",
|
|
3
|
+
"name": "VNC Remote Browser Access",
|
|
4
|
+
"description": "Launch a virtual display with VNC + noVNC + cloudflared for remote browser viewing and control. Enables human-in-the-loop login/verification when Playwright needs manual interaction.",
|
|
5
|
+
"category": "browser",
|
|
6
|
+
"skillType": "claude-skill",
|
|
7
|
+
"promptFile": "instructions.md",
|
|
8
|
+
"execution": {
|
|
9
|
+
"type": "script",
|
|
10
|
+
"script": {
|
|
11
|
+
"file": "execute.sh",
|
|
12
|
+
"interpreter": "bash",
|
|
13
|
+
"timeoutMs": 60000
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"assignableRoles": ["developer", "qa", "qa-engineer", "fullstack-dev", "backend-developer", "frontend-developer", "generalist"],
|
|
17
|
+
"triggers": ["vnc", "remote browser", "browser login", "manual login", "human verification", "captcha", "2fa", "playwright headful"],
|
|
18
|
+
"tags": ["vnc", "browser", "remote-access", "playwright", "noVNC", "cloudflared"],
|
|
19
|
+
"version": "1.0.0"
|
|
20
|
+
}
|