@crowdlisten/harness 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +167 -0
- package/LICENSE +21 -0
- package/README.md +153 -0
- package/dist/agent-proxy.d.ts +24 -0
- package/dist/agent-proxy.js +140 -0
- package/dist/agent-tools.d.ts +736 -0
- package/dist/agent-tools.js +409 -0
- package/dist/context/api.d.ts +5 -0
- package/dist/context/api.js +164 -0
- package/dist/context/cli.d.ts +19 -0
- package/dist/context/cli.js +108 -0
- package/dist/context/extractor.d.ts +12 -0
- package/dist/context/extractor.js +43 -0
- package/dist/context/index.d.ts +12 -0
- package/dist/context/index.js +11 -0
- package/dist/context/matcher.d.ts +39 -0
- package/dist/context/matcher.js +246 -0
- package/dist/context/parser.d.ts +28 -0
- package/dist/context/parser.js +157 -0
- package/dist/context/pipeline.d.ts +26 -0
- package/dist/context/pipeline.js +56 -0
- package/dist/context/prompts.d.ts +6 -0
- package/dist/context/prompts.js +60 -0
- package/dist/context/providers.d.ts +6 -0
- package/dist/context/providers.js +106 -0
- package/dist/context/redactor.d.ts +10 -0
- package/dist/context/redactor.js +68 -0
- package/dist/context/server.d.ts +5 -0
- package/dist/context/server.js +134 -0
- package/dist/context/store.d.ts +12 -0
- package/dist/context/store.js +82 -0
- package/dist/context/types.d.ts +79 -0
- package/dist/context/types.js +4 -0
- package/dist/context/user-state.d.ts +40 -0
- package/dist/context/user-state.js +144 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +385 -0
- package/dist/insights/browser/BrowserPool.d.ts +87 -0
- package/dist/insights/browser/BrowserPool.js +266 -0
- package/dist/insights/browser/RequestInterceptor.d.ts +46 -0
- package/dist/insights/browser/RequestInterceptor.js +115 -0
- package/dist/insights/cli.d.ts +8 -0
- package/dist/insights/cli.js +206 -0
- package/dist/insights/core/base/BaseAdapter.d.ts +37 -0
- package/dist/insights/core/base/BaseAdapter.js +123 -0
- package/dist/insights/core/health/HealthMonitor.d.ts +75 -0
- package/dist/insights/core/health/HealthMonitor.js +171 -0
- package/dist/insights/core/interfaces/SocialMediaPlatform.d.ts +125 -0
- package/dist/insights/core/interfaces/SocialMediaPlatform.js +42 -0
- package/dist/insights/core/utils/DataNormalizer.d.ts +53 -0
- package/dist/insights/core/utils/DataNormalizer.js +349 -0
- package/dist/insights/core/utils/InstagramUrlUtils.d.ts +11 -0
- package/dist/insights/core/utils/InstagramUrlUtils.js +60 -0
- package/dist/insights/core/utils/TikTokUrlUtils.d.ts +10 -0
- package/dist/insights/core/utils/TikTokUrlUtils.js +57 -0
- package/dist/insights/handlers.d.ts +157 -0
- package/dist/insights/handlers.js +246 -0
- package/dist/insights/index.d.ts +437 -0
- package/dist/insights/index.js +426 -0
- package/dist/insights/platforms/instagram/InstagramAdapter.d.ts +34 -0
- package/dist/insights/platforms/instagram/InstagramAdapter.js +342 -0
- package/dist/insights/platforms/moltbook/MoltbookAdapter.d.ts +31 -0
- package/dist/insights/platforms/moltbook/MoltbookAdapter.js +227 -0
- package/dist/insights/platforms/reddit/RedditAdapter.d.ts +21 -0
- package/dist/insights/platforms/reddit/RedditAdapter.js +212 -0
- package/dist/insights/platforms/tiktok/TikTokAdapter.d.ts +34 -0
- package/dist/insights/platforms/tiktok/TikTokAdapter.js +269 -0
- package/dist/insights/platforms/twitter/TwitterAdapter.d.ts +23 -0
- package/dist/insights/platforms/twitter/TwitterAdapter.js +211 -0
- package/dist/insights/platforms/xiaohongshu/XiaohongshuAdapter.d.ts +35 -0
- package/dist/insights/platforms/xiaohongshu/XiaohongshuAdapter.js +258 -0
- package/dist/insights/platforms/youtube/YouTubeAdapter.d.ts +22 -0
- package/dist/insights/platforms/youtube/YouTubeAdapter.js +254 -0
- package/dist/insights/service-config.d.ts +7 -0
- package/dist/insights/service-config.js +60 -0
- package/dist/insights/services/UnifiedSocialMediaService.d.ts +94 -0
- package/dist/insights/services/UnifiedSocialMediaService.js +259 -0
- package/dist/insights/vision/VisionExtractor.d.ts +46 -0
- package/dist/insights/vision/VisionExtractor.js +236 -0
- package/dist/learnings.d.ts +50 -0
- package/dist/learnings.js +130 -0
- package/dist/openapi.d.ts +29 -0
- package/dist/openapi.js +169 -0
- package/dist/server-factory.d.ts +20 -0
- package/dist/server-factory.js +41 -0
- package/dist/suggestions.d.ts +16 -0
- package/dist/suggestions.js +72 -0
- package/dist/telemetry.d.ts +44 -0
- package/dist/telemetry.js +93 -0
- package/dist/tools/registry.d.ts +65 -0
- package/dist/tools/registry.js +256 -0
- package/dist/tools.d.ts +2433 -0
- package/dist/tools.js +2294 -0
- package/dist/transport/http.d.ts +15 -0
- package/dist/transport/http.js +154 -0
- package/package.json +76 -0
- package/skills/catalog.json +272 -0
- package/skills/community-catalog.json +4202 -0
- package/skills/competitive-analysis/SKILL.md +174 -0
- package/skills/content-creator/SKILL.md +256 -0
- package/skills/content-strategy/SKILL.md +222 -0
- package/skills/data-storytelling/SKILL.md +248 -0
- package/skills/heuristic-evaluation/SKILL.md +201 -0
- package/skills/market-research-reports/SKILL.md +184 -0
- package/skills/user-stories/SKILL.md +178 -0
- package/skills/ux-researcher/SKILL.md +239 -0
- package/web-dist/assets/index-B1b25lNd.css +1 -0
- package/web-dist/assets/index-CDWHwHbl.js +64 -0
- package/web-dist/index.html +16 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# CrowdListen — Agent Reference
|
|
2
|
+
|
|
3
|
+
Unified MCP server for AI agents. Planning, social listening, skill packs, and knowledge management with progressive disclosure.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @crowdlisten/harness login
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Auto-configures MCP for Claude Code, Cursor, Gemini CLI, Codex, OpenClaw, Amp.
|
|
12
|
+
|
|
13
|
+
### Manual MCP config (stdio)
|
|
14
|
+
```json
|
|
15
|
+
{ "crowdlisten": { "command": "npx", "args": ["-y", "@crowdlisten/harness"] } }
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Remote MCP config (Streamable HTTP)
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"crowdlisten": {
|
|
22
|
+
"url": "https://mcp.crowdlisten.com/mcp",
|
|
23
|
+
"headers": {
|
|
24
|
+
"Authorization": "Bearer YOUR_API_KEY"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Interfaces
|
|
31
|
+
|
|
32
|
+
| Interface | Access | Best for |
|
|
33
|
+
|-----------|--------|----------|
|
|
34
|
+
| MCP stdio | `npx @crowdlisten/harness` — ~41 tools | Local agents |
|
|
35
|
+
| MCP HTTP | `POST https://mcp.crowdlisten.com/mcp` | Remote agents, cloud |
|
|
36
|
+
| REST | `POST https://mcp.crowdlisten.com/tools/{name}` | Non-MCP integrations |
|
|
37
|
+
| OpenAPI | `GET https://mcp.crowdlisten.com/openapi.json` | Docs, code gen |
|
|
38
|
+
| CLI | `npx @crowdlisten/harness login/setup/serve/openapi` | Auth, config, hosting |
|
|
39
|
+
| Web UI | `npx @crowdlisten/harness context` → localhost:3847 | Visual context extraction |
|
|
40
|
+
|
|
41
|
+
## Progressive Disclosure
|
|
42
|
+
|
|
43
|
+
You start with **4 tools**. Activate skill packs to unlock more:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
list_skill_packs() → see available packs
|
|
47
|
+
activate_skill_pack({ pack_id: "planning" }) → unlocks 11 task tools
|
|
48
|
+
activate_skill_pack({ pack_id: "social-listening" }) → unlocks 7 social tools
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
After activation, new tools appear automatically via `tools/list_changed`.
|
|
52
|
+
|
|
53
|
+
## Always-On Tools (4)
|
|
54
|
+
|
|
55
|
+
- **list_skill_packs**(include_virtual?) — List all packs with status (active/available), tool counts
|
|
56
|
+
- **activate_skill_pack**(pack_id) — Activate a pack to unlock its tools. For SKILL.md packs, returns workflow instructions.
|
|
57
|
+
- **remember**(type, title, content) — Save context across sessions. Types: preference, decision, pattern, insight, style
|
|
58
|
+
- **recall**(type?, search?, limit?) — Retrieve saved context blocks
|
|
59
|
+
|
|
60
|
+
## Skill Packs
|
|
61
|
+
|
|
62
|
+
| Pack | Tools | Description |
|
|
63
|
+
|------|-------|-------------|
|
|
64
|
+
| **core** (always on) | 4 | Discovery + memory |
|
|
65
|
+
| **planning** | 11 | Tasks, plans, progress tracking |
|
|
66
|
+
| **knowledge** | 3 | Project knowledge base |
|
|
67
|
+
| **social-listening** | 7 | Search social platforms (free) |
|
|
68
|
+
| **audience-analysis** | 6 | AI analysis (CROWDLISTEN_API_KEY) |
|
|
69
|
+
| **sessions** | 3 | Multi-agent coordination |
|
|
70
|
+
| **setup** | 5 | Board management |
|
|
71
|
+
| **legacy** | 6 | Previous-gen context extraction |
|
|
72
|
+
|
|
73
|
+
Plus: 8 native SKILL.md workflow packs (competitive-analysis, content-creator, etc.)
|
|
74
|
+
|
|
75
|
+
## Planning Pack (11 tools)
|
|
76
|
+
|
|
77
|
+
- **list_tasks**(board_id?, status?, limit?) — List board tasks
|
|
78
|
+
- **get_task**(task_id) — Full task details
|
|
79
|
+
- **create_task**(title, description?, priority?) — Create task
|
|
80
|
+
- **update_task**(task_id, ...) — Update task fields
|
|
81
|
+
- **claim_task**(task_id, executor?, branch?) — Start work, get context
|
|
82
|
+
- **complete_task**(task_id, summary?) — Mark done
|
|
83
|
+
- **delete_task**(task_id) — Remove task
|
|
84
|
+
- **log_progress**(task_id, message) — Track execution
|
|
85
|
+
- **create_plan**(task_id, approach, ...) — Draft execution plan
|
|
86
|
+
- **get_plan**(task_id) — View plan with history
|
|
87
|
+
- **update_plan**(plan_id, ...) — Iterate, submit for review
|
|
88
|
+
|
|
89
|
+
## Knowledge Pack (3 tools)
|
|
90
|
+
|
|
91
|
+
- **query_context**(search?, type?, tags?) — Search decisions, patterns, learnings
|
|
92
|
+
- **add_context**(type, title, body, ...) — Write to knowledge base
|
|
93
|
+
- **record_learning**(task_id, title, body, promote?) — Capture learning
|
|
94
|
+
|
|
95
|
+
## Social Listening Pack (7 tools, free)
|
|
96
|
+
|
|
97
|
+
- **search_content**(platform, query, limit?) — Search posts across platforms
|
|
98
|
+
- **get_content_comments**(platform, contentId, limit?) — Get comments/replies
|
|
99
|
+
- **get_trending_content**(platform, limit?) — Trending posts
|
|
100
|
+
- **get_user_content**(platform, userId, limit?) — User's recent posts
|
|
101
|
+
- **get_platform_status**() — Available platforms + capabilities
|
|
102
|
+
- **health_check**() — Platform connectivity status
|
|
103
|
+
- **extract_url**(url, mode?, limit?) — Vision extraction from any URL
|
|
104
|
+
|
|
105
|
+
Platforms: reddit, twitter, tiktok, instagram, youtube, moltbook
|
|
106
|
+
|
|
107
|
+
## Audience Analysis Pack (6 tools, CROWDLISTEN_API_KEY)
|
|
108
|
+
|
|
109
|
+
- **analyze_content**(platform, contentId, analysisDepth?) — Sentiment, themes, tensions
|
|
110
|
+
- **cluster_opinions**(platform, contentId, clusterCount?) — Opinion clustering
|
|
111
|
+
- **enrich_content**(platform, contentId, question?) — Intent/stance analysis
|
|
112
|
+
- **deep_analyze**(platform, contentId, analysisDepth?) — Full audience intelligence
|
|
113
|
+
- **extract_insights**(platform, contentId, categories?) — Pain points, feature requests
|
|
114
|
+
- **research_synthesis**(query, platforms?, depth?) — Cross-platform research
|
|
115
|
+
|
|
116
|
+
## Analysis (5 tools) — requires CROWDLISTEN_API_KEY
|
|
117
|
+
|
|
118
|
+
- **run_analysis**(project_id, question, platforms?, max_results?) — Run audience analysis across Reddit, YouTube, TikTok, Twitter, Instagram, Xiaohongshu. Streams results.
|
|
119
|
+
- **continue_analysis**(analysis_id, question) — Follow-up question on existing analysis.
|
|
120
|
+
- **get_analysis**(analysis_id) — Get full analysis results with themes, sentiment, quotes.
|
|
121
|
+
- **list_analyses**(project_id, limit?) — List analyses for a project.
|
|
122
|
+
- **generate_specs**(project_id, analysis_id?, spec_type?) — Generate feature requests, user stories, acceptance criteria from analysis.
|
|
123
|
+
|
|
124
|
+
## Content & Vectors (4 tools) — requires CROWDLISTEN_API_KEY
|
|
125
|
+
|
|
126
|
+
- **ingest_content**(project_id, content, source_url?, title?, metadata?) — Ingest content into vector store.
|
|
127
|
+
- **search_vectors**(project_id, query, limit?, threshold?) — Semantic search across ingested content.
|
|
128
|
+
- **get_content_stats**(project_id) — Document count, chunks, storage usage.
|
|
129
|
+
- **delete_content**(content_id) — Delete content document and embeddings.
|
|
130
|
+
|
|
131
|
+
## Document Generation (2 tools) — requires CROWDLISTEN_API_KEY
|
|
132
|
+
|
|
133
|
+
- **generate_prd**(project_id, analysis_ids?, template?, sections?) — Generate PRD from analysis. Templates: standard, lean, technical, marketing.
|
|
134
|
+
- **update_prd_section**(document_id, section, instructions?, content?) — Update a specific PRD section.
|
|
135
|
+
|
|
136
|
+
## Sessions (3 tools) — Parallel Agents
|
|
137
|
+
|
|
138
|
+
- **start_session**(task_id, executor?, focus) — Start additional parallel session.
|
|
139
|
+
- **list_sessions**(task_id, status?) — List sessions showing status and focus.
|
|
140
|
+
- **update_session**(session_id, status?, focus?) — Update session: idle, running, completed, failed, stopped.
|
|
141
|
+
|
|
142
|
+
## LLM Proxy (2 tools) — free, no API key
|
|
143
|
+
|
|
144
|
+
- **llm_complete**(prompt, model?, max_tokens?, temperature?, system?) — LLM completion through CrowdListen. Default: gpt-4o-mini.
|
|
145
|
+
- **list_llm_models**() — List available models and capabilities.
|
|
146
|
+
|
|
147
|
+
## Agent Network (3 tools) — mixed auth
|
|
148
|
+
|
|
149
|
+
- **register_agent**(name, capabilities?, executor?) — Register in agent network. Free.
|
|
150
|
+
- **get_capabilities**() — List network capabilities. Free.
|
|
151
|
+
- **submit_analysis**(agent_id, analysis_id, summary) — Share analysis results. Requires API key.
|
|
152
|
+
|
|
153
|
+
## Core Workflow
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
list_skill_packs → activate_skill_pack("planning")
|
|
157
|
+
→ list_tasks → claim_task → query_context → create_plan
|
|
158
|
+
→ [human review] → execute → record_learning → complete_task
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Privacy
|
|
162
|
+
|
|
163
|
+
- PII redacted locally before LLM calls
|
|
164
|
+
- Context stored locally (~/.crowdlisten/)
|
|
165
|
+
- User's own API keys for extraction
|
|
166
|
+
- No data syncs without explicit user action
|
|
167
|
+
- Agent-proxied tools go through `agent.crowdlisten.com` with your API key
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CrowdListen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# CrowdListen
|
|
2
|
+
|
|
3
|
+
> Give your AI agent crowd context — analyzed intelligence from what real users say, what markets think, and what communities want.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
[English](README.md) | [中文文档](README-CN.md) | [한국어](README-KO.md) | [Español](README-ES.md)
|
|
8
|
+
|
|
9
|
+
## The Problem
|
|
10
|
+
|
|
11
|
+
AI agents don't know what your users think. Every session starts from scratch — no awareness of what people say on Reddit, no signal from TikTok comments, no synthesis of forum discussions. You end up copy-pasting feedback manually and watching your agent make decisions without the one input that matters most: what real people think.
|
|
12
|
+
|
|
13
|
+
CrowdListen fixes this with a four-step loop:
|
|
14
|
+
|
|
15
|
+
1. **Listen** — search Reddit, YouTube, TikTok, Twitter/X, Instagram, Xiaohongshu, and forums
|
|
16
|
+
2. **Analyze** — cluster opinions by theme, extract pain points, synthesize cross-platform reports
|
|
17
|
+
3. **Remember** — save analyzed insights with semantic embeddings, not raw posts
|
|
18
|
+
4. **Recall** — any agent retrieves crowd context via natural language, across sessions and devices
|
|
19
|
+
|
|
20
|
+
Any agent — Claude Code, Cursor, Gemini CLI, Codex — can recall this later. The intelligence compounds across sessions and across agents. That's crowd context.
|
|
21
|
+
|
|
22
|
+
## Get Started
|
|
23
|
+
|
|
24
|
+
One command. Your browser opens, you sign in, and your agents are configured automatically:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx @crowdlisten/harness login
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Auto-configures MCP for **Claude Code, Cursor, Gemini CLI, Codex, Amp, and OpenClaw**. No env vars, no JSON editing, no API keys to manage. Restart your agent after login.
|
|
31
|
+
|
|
32
|
+
### Manual Setup
|
|
33
|
+
|
|
34
|
+
Add to your agent's MCP config:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"mcpServers": {
|
|
39
|
+
"crowdlisten": {
|
|
40
|
+
"command": "npx",
|
|
41
|
+
"args": ["-y", "@crowdlisten/harness"]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For remote access, use the HTTP transport:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"mcpServers": {
|
|
52
|
+
"crowdlisten": {
|
|
53
|
+
"url": "https://mcp.crowdlisten.com/mcp",
|
|
54
|
+
"headers": {
|
|
55
|
+
"Authorization": "Bearer YOUR_API_KEY"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## What You Can Do
|
|
63
|
+
|
|
64
|
+
| Capability | What it does | How it works |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| **Search social platforms** | Search Reddit, YouTube, TikTok, Twitter/X, Instagram, Xiaohongshu from one tool | Returns structured posts with engagement metrics, timestamps, and author info — same format regardless of platform |
|
|
67
|
+
| **Analyze audience signal** | Cluster opinions, extract pain points, generate cross-platform reports | AI groups comments by theme, scores sentiment, identifies competitive signals |
|
|
68
|
+
| **Save and recall across sessions** | Semantic memory that follows you across agents and devices | Your agent saves with `save`, retrieves with `recall` using meaning-based search — not keyword matching |
|
|
69
|
+
| **Plan and track work** | Tasks, execution plans, progress tracking | Your agent claims tasks, drafts plans with assumptions and risks, logs progress |
|
|
70
|
+
| **Get specs from crowd feedback** | Turn crowd intelligence into implementation-ready specs | Specs include evidence citations, acceptance criteria, and confidence scores |
|
|
71
|
+
| **Extract from any website** | Screenshot any URL and get structured data back | Vision mode sends screenshots to an LLM — works on forums, paywalled sites, anything with a URL |
|
|
72
|
+
|
|
73
|
+
## How It Works
|
|
74
|
+
|
|
75
|
+

|
|
76
|
+
|
|
77
|
+
Your agent starts with **5 core tools** and activates skill packs on demand. No restart required — new tools appear instantly.
|
|
78
|
+
|
|
79
|
+
### Skill Packs
|
|
80
|
+
|
|
81
|
+
| Pack | Tools | What it does | Free? |
|
|
82
|
+
|------|:-----:|---|:---:|
|
|
83
|
+
| **core** (always on) | 5 | Semantic memory, discovery, preferences | Yes |
|
|
84
|
+
| **social-listening** | 7 | Search Reddit, TikTok, YouTube, Twitter, Instagram, Xiaohongshu | Yes |
|
|
85
|
+
| **audience-analysis** | 6 | Opinion clustering, deep analysis, insight extraction, research synthesis | API key |
|
|
86
|
+
| **planning** | 11 | Tasks, execution plans, progress tracking | Yes |
|
|
87
|
+
| **spec-delivery** | 3 | Browse and claim actionable specs from crowd feedback | Yes |
|
|
88
|
+
| **sessions** | 3 | Multi-agent coordination | Yes |
|
|
89
|
+
| **analysis** | 5 | Run full analyses, generate specs from results | API key |
|
|
90
|
+
| **content** | 4 | Ingest content, vector search | API key |
|
|
91
|
+
| **generation** | 2 | PRD generation | API key |
|
|
92
|
+
| **llm** | 2 | Free LLM completion proxy | Yes |
|
|
93
|
+
| **agent-network** | 3 | Register agents, discover capabilities | Mixed |
|
|
94
|
+
|
|
95
|
+
Plus 8 **workflow packs** (competitive-analysis, content-strategy, market-research, ux-research, and more) that deliver expert methodology when activated.
|
|
96
|
+
|
|
97
|
+
Full tool reference: **[docs/TOOLS.md](docs/TOOLS.md)**
|
|
98
|
+
|
|
99
|
+
### Platforms
|
|
100
|
+
|
|
101
|
+
| Platform | Setup | Notes |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| Reddit | None | Works immediately |
|
|
104
|
+
| TikTok, Instagram, Xiaohongshu | `npx playwright install chromium` | Browser-based extraction |
|
|
105
|
+
| Twitter/X | `TWITTER_USERNAME` + `TWITTER_PASSWORD` in `.env` | Credential-based |
|
|
106
|
+
| YouTube | `YOUTUBE_API_KEY` in `.env` | API key required |
|
|
107
|
+
| Vision mode (any URL) | Any one of: `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, or `OPENAI_API_KEY` | Screenshots + LLM extraction |
|
|
108
|
+
|
|
109
|
+
### Supported Agents
|
|
110
|
+
|
|
111
|
+
**Auto-configured on login:** Claude Code, Cursor, Gemini CLI, Codex, Amp, OpenClaw
|
|
112
|
+
|
|
113
|
+
**Also works with (manual config):** Copilot, Droid, Qwen Code, OpenCode
|
|
114
|
+
|
|
115
|
+
## CLI
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npx @crowdlisten/harness login # Sign in + auto-configure agents
|
|
119
|
+
npx @crowdlisten/harness setup # Re-run auto-configure
|
|
120
|
+
npx @crowdlisten/harness serve # Start HTTP server on :3848
|
|
121
|
+
|
|
122
|
+
npx crowdlisten search reddit "AI agents" --limit 20
|
|
123
|
+
npx crowdlisten vision https://news.ycombinator.com --limit 10
|
|
124
|
+
npx crowdlisten trending reddit --limit 10
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Privacy
|
|
128
|
+
|
|
129
|
+
- PII redacted locally before LLM calls
|
|
130
|
+
- Memories stored with row-level security — users can only access their own data
|
|
131
|
+
- Local fallback when cloud is unavailable
|
|
132
|
+
- Your own API keys for LLM extraction
|
|
133
|
+
- No data syncs without explicit action
|
|
134
|
+
- MIT open-source and inspectable
|
|
135
|
+
|
|
136
|
+
## Development
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
git clone https://github.com/Crowdlisten/crowdlisten_harness.git
|
|
140
|
+
cd crowdlisten_harness
|
|
141
|
+
npm install && npm run build
|
|
142
|
+
npm test # 210+ tests via Vitest
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
For agent-readable capability descriptions and example workflows, see [AGENTS.md](AGENTS.md).
|
|
146
|
+
|
|
147
|
+
## Contributing
|
|
148
|
+
|
|
149
|
+
Highest-value contributions: new platform adapters (Threads, Bluesky, Hacker News, Product Hunt, Mastodon) and extraction fixes.
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
MIT — [crowdlisten.com](https://crowdlisten.com)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Proxy — Shared HTTP client for agent.crowdlisten.com
|
|
3
|
+
*
|
|
4
|
+
* All agent-proxied tools route through these helpers.
|
|
5
|
+
* Supports POST, GET, and SSE streaming endpoints.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Returns the CROWDLISTEN_API_KEY or throws.
|
|
9
|
+
* Tools that require auth call this; free tools skip it.
|
|
10
|
+
*/
|
|
11
|
+
export declare function requireApiKey(): string;
|
|
12
|
+
export declare function agentPost(path: string, body: Record<string, unknown>, apiKey?: string): Promise<unknown>;
|
|
13
|
+
export declare function agentGet(path: string, apiKey?: string): Promise<unknown>;
|
|
14
|
+
export declare function agentDelete(path: string, apiKey?: string): Promise<unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* Connects to an SSE endpoint, collects all events, and returns
|
|
17
|
+
* the aggregated result. Used for long-running operations like
|
|
18
|
+
* analysis/run and PRD generation.
|
|
19
|
+
*
|
|
20
|
+
* Collects `data:` lines until the stream closes or times out.
|
|
21
|
+
* If the last event contains a JSON object with a "status" field,
|
|
22
|
+
* that's treated as the final result. Otherwise returns all events.
|
|
23
|
+
*/
|
|
24
|
+
export declare function agentStream(path: string, body: Record<string, unknown>, apiKey?: string, timeoutMs?: number): Promise<unknown>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Proxy — Shared HTTP client for agent.crowdlisten.com
|
|
3
|
+
*
|
|
4
|
+
* All agent-proxied tools route through these helpers.
|
|
5
|
+
* Supports POST, GET, and SSE streaming endpoints.
|
|
6
|
+
*/
|
|
7
|
+
const AGENT_BASE = process.env.CROWDLISTEN_AGENT_URL || "https://agent.crowdlisten.com";
|
|
8
|
+
// ─── Auth ──────────────────────────────────────────────────────────────────
|
|
9
|
+
/**
|
|
10
|
+
* Returns the CROWDLISTEN_API_KEY or throws.
|
|
11
|
+
* Tools that require auth call this; free tools skip it.
|
|
12
|
+
*/
|
|
13
|
+
export function requireApiKey() {
|
|
14
|
+
const key = process.env.CROWDLISTEN_API_KEY;
|
|
15
|
+
if (!key) {
|
|
16
|
+
throw new Error("CROWDLISTEN_API_KEY is required for this tool. " +
|
|
17
|
+
"Get one at https://crowdlisten.com/settings/api-keys");
|
|
18
|
+
}
|
|
19
|
+
return key;
|
|
20
|
+
}
|
|
21
|
+
function headers(apiKey) {
|
|
22
|
+
const h = {
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
Accept: "application/json",
|
|
25
|
+
};
|
|
26
|
+
if (apiKey)
|
|
27
|
+
h["Authorization"] = `Bearer ${apiKey}`;
|
|
28
|
+
return h;
|
|
29
|
+
}
|
|
30
|
+
// ─── POST ──────────────────────────────────────────────────────────────────
|
|
31
|
+
export async function agentPost(path, body, apiKey) {
|
|
32
|
+
const url = `${AGENT_BASE}${path}`;
|
|
33
|
+
const res = await fetch(url, {
|
|
34
|
+
method: "POST",
|
|
35
|
+
headers: headers(apiKey),
|
|
36
|
+
body: JSON.stringify(body),
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
const text = await res.text().catch(() => "");
|
|
40
|
+
throw new Error(`Agent API error ${res.status} on POST ${path}: ${text || res.statusText}`);
|
|
41
|
+
}
|
|
42
|
+
return res.json();
|
|
43
|
+
}
|
|
44
|
+
// ─── GET ───────────────────────────────────────────────────────────────────
|
|
45
|
+
export async function agentGet(path, apiKey) {
|
|
46
|
+
const url = `${AGENT_BASE}${path}`;
|
|
47
|
+
const res = await fetch(url, {
|
|
48
|
+
method: "GET",
|
|
49
|
+
headers: headers(apiKey),
|
|
50
|
+
});
|
|
51
|
+
if (!res.ok) {
|
|
52
|
+
const text = await res.text().catch(() => "");
|
|
53
|
+
throw new Error(`Agent API error ${res.status} on GET ${path}: ${text || res.statusText}`);
|
|
54
|
+
}
|
|
55
|
+
return res.json();
|
|
56
|
+
}
|
|
57
|
+
// ─── DELETE ────────────────────────────────────────────────────────────────
|
|
58
|
+
export async function agentDelete(path, apiKey) {
|
|
59
|
+
const url = `${AGENT_BASE}${path}`;
|
|
60
|
+
const res = await fetch(url, {
|
|
61
|
+
method: "DELETE",
|
|
62
|
+
headers: headers(apiKey),
|
|
63
|
+
});
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
const text = await res.text().catch(() => "");
|
|
66
|
+
throw new Error(`Agent API error ${res.status} on DELETE ${path}: ${text || res.statusText}`);
|
|
67
|
+
}
|
|
68
|
+
return res.json();
|
|
69
|
+
}
|
|
70
|
+
// ─── SSE Stream → Aggregated Result ────────────────────────────────────────
|
|
71
|
+
/**
|
|
72
|
+
* Connects to an SSE endpoint, collects all events, and returns
|
|
73
|
+
* the aggregated result. Used for long-running operations like
|
|
74
|
+
* analysis/run and PRD generation.
|
|
75
|
+
*
|
|
76
|
+
* Collects `data:` lines until the stream closes or times out.
|
|
77
|
+
* If the last event contains a JSON object with a "status" field,
|
|
78
|
+
* that's treated as the final result. Otherwise returns all events.
|
|
79
|
+
*/
|
|
80
|
+
export async function agentStream(path, body, apiKey, timeoutMs = 120_000) {
|
|
81
|
+
const url = `${AGENT_BASE}${path}`;
|
|
82
|
+
const controller = new AbortController();
|
|
83
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
84
|
+
try {
|
|
85
|
+
const res = await fetch(url, {
|
|
86
|
+
method: "POST",
|
|
87
|
+
headers: {
|
|
88
|
+
...headers(apiKey),
|
|
89
|
+
Accept: "text/event-stream",
|
|
90
|
+
},
|
|
91
|
+
body: JSON.stringify(body),
|
|
92
|
+
signal: controller.signal,
|
|
93
|
+
});
|
|
94
|
+
if (!res.ok) {
|
|
95
|
+
const text = await res.text().catch(() => "");
|
|
96
|
+
throw new Error(`Agent API error ${res.status} on SSE ${path}: ${text || res.statusText}`);
|
|
97
|
+
}
|
|
98
|
+
// Read SSE stream
|
|
99
|
+
const reader = res.body?.getReader();
|
|
100
|
+
if (!reader)
|
|
101
|
+
throw new Error("No response body from SSE endpoint");
|
|
102
|
+
const decoder = new TextDecoder();
|
|
103
|
+
const events = [];
|
|
104
|
+
let buffer = "";
|
|
105
|
+
while (true) {
|
|
106
|
+
const { done, value } = await reader.read();
|
|
107
|
+
if (done)
|
|
108
|
+
break;
|
|
109
|
+
buffer += decoder.decode(value, { stream: true });
|
|
110
|
+
const lines = buffer.split("\n");
|
|
111
|
+
buffer = lines.pop() || "";
|
|
112
|
+
for (const line of lines) {
|
|
113
|
+
if (line.startsWith("data: ")) {
|
|
114
|
+
const data = line.slice(6).trim();
|
|
115
|
+
if (data === "[DONE]")
|
|
116
|
+
continue;
|
|
117
|
+
try {
|
|
118
|
+
events.push(JSON.parse(data));
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
events.push(data);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Return the last event if it looks like a final result, otherwise all events
|
|
127
|
+
if (events.length === 0)
|
|
128
|
+
return { status: "completed", events: [] };
|
|
129
|
+
const last = events[events.length - 1];
|
|
130
|
+
if (typeof last === "object" &&
|
|
131
|
+
last !== null &&
|
|
132
|
+
"status" in last) {
|
|
133
|
+
return last;
|
|
134
|
+
}
|
|
135
|
+
return { status: "completed", events };
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
clearTimeout(timer);
|
|
139
|
+
}
|
|
140
|
+
}
|