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.
Files changed (216) hide show
  1. package/README.md +6 -6
  2. package/config/roles/ops/prompt.md +140 -0
  3. package/config/roles/ops/role.json +13 -0
  4. package/config/skills/agent/browse-stealth/execute.sh +84 -0
  5. package/config/skills/agent/browse-stealth/instructions.md +108 -0
  6. package/config/skills/agent/browse-stealth/launch-chrome-cdp.sh +141 -0
  7. package/config/skills/agent/browse-stealth/skill.json +20 -0
  8. package/config/skills/agent/browse-stealth/stealth-browse.py +330 -0
  9. package/config/skills/agent/competitor-content-tracker/execute.sh +232 -0
  10. package/config/skills/agent/competitor-content-tracker/instructions.md +210 -0
  11. package/config/skills/agent/competitor-content-tracker/skill.json +22 -0
  12. package/config/skills/agent/content-calendar/execute.sh +294 -0
  13. package/config/skills/agent/content-calendar/instructions.md +122 -0
  14. package/config/skills/agent/content-calendar/skill.json +22 -0
  15. package/config/skills/agent/content-repurposer/execute.sh +194 -0
  16. package/config/skills/agent/content-repurposer/instructions.md +69 -0
  17. package/config/skills/agent/content-repurposer/skill.json +22 -0
  18. package/config/skills/agent/content-writer/execute.sh +311 -0
  19. package/config/skills/agent/content-writer/instructions.md +124 -0
  20. package/config/skills/agent/content-writer/skill.json +22 -0
  21. package/config/skills/agent/core/generate-pdf/execute.sh +88 -0
  22. package/config/skills/agent/core/generate-pdf/instructions.md +46 -0
  23. package/config/skills/agent/core/generate-pdf/skill.json +20 -0
  24. package/config/skills/agent/core/report-status/execute.sh +6 -0
  25. package/config/skills/agent/trend-monitor/execute.sh +211 -0
  26. package/config/skills/agent/trend-monitor/instructions.md +207 -0
  27. package/config/skills/agent/trend-monitor/skill.json +22 -0
  28. package/config/skills/agent/vnc-browser/execute.sh +261 -0
  29. package/config/skills/agent/vnc-browser/instructions.md +102 -0
  30. package/config/skills/agent/vnc-browser/skill.json +20 -0
  31. package/config/skills/orchestrator/delegate-task/execute.sh +63 -4
  32. package/config/skills/orchestrator/delegate-task/instructions.md +60 -0
  33. package/config/skills/orchestrator/delegate-task/skill.json +4 -4
  34. package/config/skills/orchestrator/reply-slack/execute.sh +2 -0
  35. package/config/skills/orchestrator/send-key/execute.sh +19 -6
  36. package/config/skills/orchestrator/send-key/instructions.md +44 -0
  37. package/config/skills/orchestrator/send-key/skill.json +20 -0
  38. package/config/skills/orchestrator/send-message/execute.sh +9 -1
  39. package/config/skills/registry.json +256 -0
  40. package/config/templates/code-review-team/README.md +176 -0
  41. package/config/templates/code-review-team/team-config.json +16 -0
  42. package/config/templates/code-review-team.json +62 -0
  43. package/config/templates/content-generation-team/README.md +128 -0
  44. package/config/templates/content-generation-team/team-config.json +21 -0
  45. package/config/templates/content-generation-team.json +67 -0
  46. package/config/templates/demo-team.json +22 -0
  47. package/config/templates/social-media-ops-team/README.md +145 -0
  48. package/config/templates/social-media-ops-team/team-config.json +21 -0
  49. package/config/templates/social-media-ops-team.json +67 -0
  50. package/dist/backend/backend/src/constants.d.ts +69 -6
  51. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  52. package/dist/backend/backend/src/constants.js +75 -6
  53. package/dist/backend/backend/src/constants.js.map +1 -1
  54. package/dist/backend/backend/src/controllers/index.d.ts.map +1 -1
  55. package/dist/backend/backend/src/controllers/index.js +2 -0
  56. package/dist/backend/backend/src/controllers/index.js.map +1 -1
  57. package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts +8 -0
  58. package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts.map +1 -1
  59. package/dist/backend/backend/src/controllers/messaging/messenger.routes.js +110 -63
  60. package/dist/backend/backend/src/controllers/messaging/messenger.routes.js.map +1 -1
  61. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
  62. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +31 -4
  63. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
  64. package/dist/backend/backend/src/controllers/oauth/oauth.routes.d.ts +8 -0
  65. package/dist/backend/backend/src/controllers/oauth/oauth.routes.d.ts.map +1 -1
  66. package/dist/backend/backend/src/controllers/oauth/oauth.routes.js +127 -111
  67. package/dist/backend/backend/src/controllers/oauth/oauth.routes.js.map +1 -1
  68. package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +34 -0
  69. package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +1 -1
  70. package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +219 -2
  71. package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +1 -1
  72. package/dist/backend/backend/src/controllers/user/user.routes.d.ts +7 -0
  73. package/dist/backend/backend/src/controllers/user/user.routes.d.ts.map +1 -1
  74. package/dist/backend/backend/src/controllers/user/user.routes.js +45 -38
  75. package/dist/backend/backend/src/controllers/user/user.routes.js.map +1 -1
  76. package/dist/backend/backend/src/controllers/whatsapp/index.d.ts +17 -0
  77. package/dist/backend/backend/src/controllers/whatsapp/index.d.ts.map +1 -0
  78. package/dist/backend/backend/src/controllers/whatsapp/index.js +18 -0
  79. package/dist/backend/backend/src/controllers/whatsapp/index.js.map +1 -0
  80. package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.d.ts +12 -0
  81. package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.d.ts.map +1 -0
  82. package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.js +185 -0
  83. package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.js.map +1 -0
  84. package/dist/backend/backend/src/index.d.ts +5 -0
  85. package/dist/backend/backend/src/index.d.ts.map +1 -1
  86. package/dist/backend/backend/src/index.js +35 -0
  87. package/dist/backend/backend/src/index.js.map +1 -1
  88. package/dist/backend/backend/src/routes/modules/task-management.routes.d.ts.map +1 -1
  89. package/dist/backend/backend/src/routes/modules/task-management.routes.js +4 -0
  90. package/dist/backend/backend/src/routes/modules/task-management.routes.js.map +1 -1
  91. package/dist/backend/backend/src/services/agent/agent-heartbeat.service.js +1 -1
  92. package/dist/backend/backend/src/services/agent/agent-heartbeat.service.js.map +1 -1
  93. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +14 -3
  94. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  95. package/dist/backend/backend/src/services/agent/agent-registration.service.js +160 -29
  96. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  97. package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts +4 -3
  98. package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -1
  99. package/dist/backend/backend/src/services/agent/claude-runtime.service.js +29 -4
  100. package/dist/backend/backend/src/services/agent/claude-runtime.service.js.map +1 -1
  101. package/dist/backend/backend/src/services/agent/context-window-monitor.service.d.ts.map +1 -1
  102. package/dist/backend/backend/src/services/agent/context-window-monitor.service.js +11 -0
  103. package/dist/backend/backend/src/services/agent/context-window-monitor.service.js.map +1 -1
  104. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts +32 -2
  105. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
  106. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +69 -8
  107. package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
  108. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
  109. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js +14 -2
  110. package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
  111. package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.d.ts.map +1 -1
  112. package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js +11 -2
  113. package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -1
  114. package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.d.ts +18 -0
  115. package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.d.ts.map +1 -1
  116. package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.js +28 -4
  117. package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.js.map +1 -1
  118. package/dist/backend/backend/src/services/messaging/adapters/slack-messenger.adapter.js +2 -2
  119. package/dist/backend/backend/src/services/messaging/adapters/slack-messenger.adapter.js.map +1 -1
  120. package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.d.ts +18 -0
  121. package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.d.ts.map +1 -1
  122. package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.js +26 -4
  123. package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.js.map +1 -1
  124. package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts +28 -2
  125. package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts.map +1 -1
  126. package/dist/backend/backend/src/services/messaging/messenger-registry.service.d.ts +33 -2
  127. package/dist/backend/backend/src/services/messaging/messenger-registry.service.d.ts.map +1 -1
  128. package/dist/backend/backend/src/services/messaging/messenger-registry.service.js +33 -0
  129. package/dist/backend/backend/src/services/messaging/messenger-registry.service.js.map +1 -1
  130. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
  131. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js +4 -2
  132. package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
  133. package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.d.ts.map +1 -1
  134. package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js +4 -3
  135. package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js.map +1 -1
  136. package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +27 -0
  137. package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +1 -1
  138. package/dist/backend/backend/src/services/project/task-tracking.service.js +54 -0
  139. package/dist/backend/backend/src/services/project/task-tracking.service.js.map +1 -1
  140. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +36 -6
  141. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  142. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +238 -36
  143. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  144. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
  145. package/dist/backend/backend/src/services/slack/slack.service.js +6 -4
  146. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
  147. package/dist/backend/backend/src/services/user/user-identity.service.d.ts +44 -0
  148. package/dist/backend/backend/src/services/user/user-identity.service.d.ts.map +1 -1
  149. package/dist/backend/backend/src/services/user/user-identity.service.js +75 -8
  150. package/dist/backend/backend/src/services/user/user-identity.service.js.map +1 -1
  151. package/dist/backend/backend/src/services/whatsapp/index.d.ts +11 -0
  152. package/dist/backend/backend/src/services/whatsapp/index.d.ts.map +1 -0
  153. package/dist/backend/backend/src/services/whatsapp/index.js +11 -0
  154. package/dist/backend/backend/src/services/whatsapp/index.js.map +1 -0
  155. package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.d.ts +66 -0
  156. package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.d.ts.map +1 -0
  157. package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.js +96 -0
  158. package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.js.map +1 -0
  159. package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.d.ts +109 -0
  160. package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.d.ts.map +1 -0
  161. package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.js +234 -0
  162. package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.js.map +1 -0
  163. package/dist/backend/backend/src/services/whatsapp/whatsapp.service.d.ts +127 -0
  164. package/dist/backend/backend/src/services/whatsapp/whatsapp.service.d.ts.map +1 -0
  165. package/dist/backend/backend/src/services/whatsapp/whatsapp.service.js +347 -0
  166. package/dist/backend/backend/src/services/whatsapp/whatsapp.service.js.map +1 -0
  167. package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -1
  168. package/dist/backend/backend/src/services/workflow/scheduler.service.js +4 -0
  169. package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -1
  170. package/dist/backend/backend/src/types/index.d.ts +1 -0
  171. package/dist/backend/backend/src/types/index.d.ts.map +1 -1
  172. package/dist/backend/backend/src/types/index.js.map +1 -1
  173. package/dist/backend/backend/src/types/slack.types.d.ts +24 -0
  174. package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
  175. package/dist/backend/backend/src/types/slack.types.js.map +1 -1
  176. package/dist/backend/backend/src/types/task-tracking.types.d.ts +4 -0
  177. package/dist/backend/backend/src/types/task-tracking.types.d.ts.map +1 -1
  178. package/dist/backend/backend/src/types/task-tracking.types.js.map +1 -1
  179. package/dist/backend/backend/src/types/whatsapp.types.d.ts +84 -0
  180. package/dist/backend/backend/src/types/whatsapp.types.d.ts.map +1 -0
  181. package/dist/backend/backend/src/types/whatsapp.types.js +33 -0
  182. package/dist/backend/backend/src/types/whatsapp.types.js.map +1 -0
  183. package/dist/backend/backend/src/websocket/terminal.gateway.d.ts +11 -0
  184. package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
  185. package/dist/backend/backend/src/websocket/terminal.gateway.js +35 -1
  186. package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
  187. package/dist/cli/backend/src/constants.d.ts +69 -6
  188. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  189. package/dist/cli/backend/src/constants.js +75 -6
  190. package/dist/cli/backend/src/constants.js.map +1 -1
  191. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
  192. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js +14 -2
  193. package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
  194. package/dist/cli/backend/src/types/index.d.ts +1 -0
  195. package/dist/cli/backend/src/types/index.d.ts.map +1 -1
  196. package/dist/cli/backend/src/types/index.js.map +1 -1
  197. package/dist/cli/cli/src/commands/publish.d.ts.map +1 -1
  198. package/dist/cli/cli/src/commands/publish.js +17 -15
  199. package/dist/cli/cli/src/commands/publish.js.map +1 -1
  200. package/dist/cli/cli/src/index.js +2 -2
  201. package/dist/cli/cli/src/index.js.map +1 -1
  202. package/dist/cli/cli/src/utils/gh-submit.d.ts +46 -0
  203. package/dist/cli/cli/src/utils/gh-submit.d.ts.map +1 -0
  204. package/dist/cli/cli/src/utils/gh-submit.js +167 -0
  205. package/dist/cli/cli/src/utils/gh-submit.js.map +1 -0
  206. package/dist/cli/cli/src/utils/marketplace.d.ts.map +1 -1
  207. package/dist/cli/cli/src/utils/marketplace.js +13 -5
  208. package/dist/cli/cli/src/utils/marketplace.js.map +1 -1
  209. package/dist/cli/cli/src/utils/templates.d.ts +3 -2
  210. package/dist/cli/cli/src/utils/templates.d.ts.map +1 -1
  211. package/dist/cli/cli/src/utils/templates.js +5 -4
  212. package/dist/cli/cli/src/utils/templates.js.map +1 -1
  213. package/frontend/dist/assets/{index-45eeea99.js → index-a23214ae.js} +241 -241
  214. package/frontend/dist/assets/{index-6972eeee.css → index-c407fe13.css} +1 -1
  215. package/frontend/dist/index.html +2 -2
  216. package/package.json +3 -1
@@ -0,0 +1,210 @@
1
+ # Competitor Content Tracker
2
+
3
+ Track and compare competitor content activity using browser automation and web search. Store structured data for trend analysis and content strategy.
4
+
5
+ ## Architecture
6
+
7
+ 1. **Browser scanning** (agent-driven) — Visit competitor pages, extract content data
8
+ 2. **Data management** (execute.sh) — Save, query, and compare stored data
9
+
10
+ ## Data Actions (execute.sh)
11
+
12
+ ### `save` — Store content items from a competitor scan
13
+
14
+ | Parameter | Required | Description |
15
+ |-----------|----------|-------------|
16
+ | `action` | Yes | `"save"` |
17
+ | `competitor` | Yes | `crewai`, `n8n`, `relevance-ai`, `autogen`, `langchain`, `langraph`, `openai`, `other` |
18
+ | `sourceType` | Yes | `blog`, `twitter`, `linkedin`, `github-release`, `changelog`, `youtube`, `community`, `press`, `other` |
19
+ | `items` | Yes | JSON array of content items (see schema below) |
20
+
21
+ **Content item schema:**
22
+ ```json
23
+ {
24
+ "title": "Blog post or content title",
25
+ "url": "https://...",
26
+ "publishedDate": "2026-02-27",
27
+ "description": "Brief summary",
28
+ "engagement": "45 likes, 12 comments",
29
+ "contentType": "blog post / tweet / video",
30
+ "tags": ["mcp", "agents", "enterprise"]
31
+ }
32
+ ```
33
+
34
+ ### `list` — List tracked content files
35
+
36
+ | Parameter | Required | Description |
37
+ |-----------|----------|-------------|
38
+ | `action` | Yes | `"list"` |
39
+ | `competitor` | No | Filter by competitor |
40
+ | `limit` | No | Max results (default: 20) |
41
+
42
+ ### `latest` — Get latest content from a competitor
43
+
44
+ | Parameter | Required | Description |
45
+ |-----------|----------|-------------|
46
+ | `action` | Yes | `"latest"` |
47
+ | `competitor` | Yes | Which competitor |
48
+ | `sourceType` | No | Filter by source type |
49
+ | `limit` | No | Max items (default: 15) |
50
+
51
+ ### `compare` — Compare content activity across competitors
52
+
53
+ | Parameter | Required | Description |
54
+ |-----------|----------|-------------|
55
+ | `action` | Yes | `"compare"` |
56
+ | `competitors` | No | Comma-separated list (default: `crewai,n8n,relevance-ai`) |
57
+ | `days` | No | Lookback period in days (default: 7) |
58
+
59
+ ## Browser Scanning Guide
60
+
61
+ ### Competitor: CrewAI
62
+
63
+ **Blog:**
64
+ - URL: `https://www.crewai.com/blog`
65
+ - Extract: title, date, summary, URL for each post
66
+ - Focus on: product announcements, enterprise features, case studies
67
+
68
+ **GitHub:**
69
+ - URL: `https://github.com/crewAIInc/crewAI/releases`
70
+ - Extract: version, release date, key changes
71
+ - Also check: `https://docs.crewai.com/en/changelog`
72
+
73
+ **Twitter/X:**
74
+ - URL: `https://x.com/craborai` (CrewAI official)
75
+ - Extract: recent tweets, engagement (likes, retweets, replies)
76
+ - Focus on: product announcements, partnership news
77
+
78
+ **PyPI (version tracking):**
79
+ - URL: `https://pypi.org/project/crewai/#history`
80
+ - Extract: version numbers, release dates
81
+
82
+ **Example save:**
83
+ ```bash
84
+ bash execute.sh '{"action":"save","competitor":"crewai","sourceType":"blog","projectPath":"/path","items":[
85
+ {"title":"The State of Agentic AI in 2026","url":"https://www.crewai.com/blog/state-of-agentic-ai","publishedDate":"2026-02-25","description":"Survey of 500 enterprises on AI agent adoption","engagement":"high - featured on front page","tags":["enterprise","survey","market-data"]},
86
+ {"title":"CrewAI v1.10.0 Release","url":"https://github.com/crewAIInc/crewAI/releases/tag/v1.10.0","publishedDate":"2026-02-27","description":"MCP enhancements, HITL improvements","engagement":"64 open issues","tags":["release","mcp","hitl"]}
87
+ ]}'
88
+ ```
89
+
90
+ ---
91
+
92
+ ### Competitor: n8n
93
+
94
+ **Blog / Community:**
95
+ - URL: `https://community.n8n.io/c/announcements/`
96
+ - URL: `https://blog.n8n.io/`
97
+ - Extract: announcements, feature updates, security bulletins
98
+
99
+ **GitHub:**
100
+ - URL: `https://github.com/n8n-io/n8n/releases`
101
+ - Extract: version, date, key changes
102
+ - Also: `https://docs.n8n.io/release-notes/`
103
+
104
+ **Twitter/X:**
105
+ - URL: `https://x.com/n8n_io`
106
+ - Extract: recent tweets, engagement
107
+
108
+ **Security (critical to track):**
109
+ - URL: `https://community.n8n.io/tag/security`
110
+ - Extract: CVE disclosures, patch versions
111
+
112
+ **Example save:**
113
+ ```bash
114
+ bash execute.sh '{"action":"save","competitor":"n8n","sourceType":"community","projectPath":"/path","items":[
115
+ {"title":"Security Bulletin February 25, 2026","url":"https://community.n8n.io/t/security-bulletin-february-25-2026/270324","publishedDate":"2026-02-25","description":"8 critical/high CVEs disclosed","engagement":"community discussion active","tags":["security","cve","critical"]}
116
+ ]}'
117
+ ```
118
+
119
+ ---
120
+
121
+ ### Competitor: Relevance AI
122
+
123
+ **Changelog:**
124
+ - URL: `https://relevanceai.com/changelog`
125
+ - Extract: feature name, date, description
126
+
127
+ **Blog:**
128
+ - URL: `https://relevanceai.com/blog`
129
+ - Extract: posts, topics, publication dates
130
+
131
+ **Twitter/X:**
132
+ - URL: `https://x.com/RelevanceAI_`
133
+ - Extract: tweets, engagement
134
+
135
+ ---
136
+
137
+ ### Competitor: AutoGen (Microsoft)
138
+
139
+ **GitHub:**
140
+ - URL: `https://github.com/microsoft/autogen/releases`
141
+ - Extract: version, changes, community engagement
142
+
143
+ **Blog:**
144
+ - URL: `https://microsoft.github.io/autogen/blog/`
145
+ - Extract: posts, research papers
146
+
147
+ ---
148
+
149
+ ### Competitor: LangChain / LangGraph
150
+
151
+ **Blog:**
152
+ - URL: `https://blog.langchain.dev/`
153
+ - Extract: posts, product announcements
154
+
155
+ **GitHub:**
156
+ - URL: `https://github.com/langchain-ai/langgraph/releases`
157
+ - Extract: releases, features
158
+
159
+ **Twitter/X:**
160
+ - URL: `https://x.com/LangChainAI`
161
+
162
+ ---
163
+
164
+ ## Recommended Scan Schedule
165
+
166
+ | Frequency | What to Scan |
167
+ |-----------|-------------|
168
+ | **Daily** | CrewAI Twitter, n8n Twitter — quick check for announcements |
169
+ | **Twice/week** | CrewAI blog, n8n community, Relevance AI changelog |
170
+ | **Weekly** | GitHub releases (all competitors), full comparison report |
171
+ | **Ad-hoc** | When WebSearch reveals breaking news (acquisitions, security events, major launches) |
172
+
173
+ ## Workflow Integration
174
+
175
+ ```
176
+ 1. Agent scans competitor pages via browser/WebSearch
177
+ 2. Agent saves structured data via execute.sh save
178
+ 3. Agent runs compare to see cross-competitor activity
179
+ 4. Agent identifies content opportunities (reactive or counter-narrative)
180
+ 5. Agent feeds opportunities to trend-monitor suggest or content-writer draft
181
+ ```
182
+
183
+ ## Content Strategy Angles by Competitor
184
+
185
+ ### vs CrewAI
186
+ - **Their strength:** Enterprise narrative, large community, Python ecosystem
187
+ - **Our angle:** TypeScript/runtime-agnostic, live terminal, simpler setup for SMBs
188
+ - **Content trigger:** When they release enterprise features, we publish "here's how SMBs get the same power without the complexity"
189
+
190
+ ### vs n8n
191
+ - **Their strength:** Massive community (177K stars), mature integrations, visual workflow builder
192
+ - **Our angle:** Security (PTY isolation vs their CVE history), AI-native (they added AI), full autonomy vs workflow steps
193
+ - **Content trigger:** Security events, workflow builder limitations for AI tasks
194
+
195
+ ### vs Relevance AI
196
+ - **Their strength:** No-code agents, marketplace scale (215+ agents)
197
+ - **Our angle:** Developer control, open source, custom skills, not locked into their platform
198
+ - **Content trigger:** When they push no-code, we publish "why developers need code-level control for AI agents"
199
+
200
+ ## Compare Report Example
201
+
202
+ ```bash
203
+ # Weekly comparison across top 3 competitors
204
+ bash execute.sh '{"action":"compare","competitors":"crewai,n8n,relevance-ai","days":"7","projectPath":"/path"}'
205
+ ```
206
+
207
+ This outputs total items tracked, breakdown by source type, and recent titles for each competitor. Use this to identify:
208
+ - Who is publishing most actively?
209
+ - What topics are they focusing on?
210
+ - Where are there gaps we can fill?
@@ -0,0 +1,22 @@
1
+ {
2
+ "id": "competitor-content-tracker",
3
+ "name": "Competitor Content Tracker",
4
+ "description": "Track and compare competitor content activity across blogs, social media, GitHub releases, and community channels. Supports CrewAI, n8n, Relevance AI, AutoGen, LangChain, and others.",
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": ["competitor content", "track competitor", "competitor analysis", "what are competitors posting", "competitive content"],
18
+ "tags": ["competitors", "content", "tracking", "analysis", "crewai", "n8n", "relevance-ai", "marketing", "competitive-intelligence"],
19
+ "version": "1.0.0",
20
+ "author": "Luna (Content Strategist)",
21
+ "license": "MIT"
22
+ }
@@ -0,0 +1,294 @@
1
+ #!/bin/bash
2
+ # Content Calendar Manager — CRUD operations for content scheduling
3
+ set -euo pipefail
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ source "${SCRIPT_DIR}/../_common/lib.sh"
6
+
7
+ INPUT="${1:-}"
8
+ [ -z "$INPUT" ] && error_exit "Usage: execute.sh '{\"action\":\"add|list|update|next|stats\",\"calendarPath\":\"/path/to/calendar.json\",...}'"
9
+
10
+ # Parse common parameters
11
+ ACTION=$(echo "$INPUT" | jq -r '.action // empty')
12
+ CALENDAR_PATH=$(echo "$INPUT" | jq -r '.calendarPath // empty')
13
+
14
+ require_param "action" "$ACTION"
15
+
16
+ # Default calendar path
17
+ if [ -z "$CALENDAR_PATH" ]; then
18
+ # Try to find project .crewly directory
19
+ PROJECT_PATH=$(echo "$INPUT" | jq -r '.projectPath // empty')
20
+ if [ -n "$PROJECT_PATH" ]; then
21
+ CALENDAR_PATH="${PROJECT_PATH}/.crewly/content/calendar.json"
22
+ else
23
+ CALENDAR_PATH="${HOME}/.crewly/content/calendar.json"
24
+ fi
25
+ fi
26
+
27
+ # Ensure calendar directory and file exist
28
+ CALENDAR_DIR=$(dirname "$CALENDAR_PATH")
29
+ mkdir -p "$CALENDAR_DIR"
30
+ if [ ! -f "$CALENDAR_PATH" ]; then
31
+ echo '{"entries":[],"metadata":{"createdAt":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'","version":"1.0"}}' > "$CALENDAR_PATH"
32
+ fi
33
+
34
+ # Validate calendar JSON
35
+ if ! jq empty "$CALENDAR_PATH" 2>/dev/null; then
36
+ error_exit "Calendar file is not valid JSON: $CALENDAR_PATH"
37
+ fi
38
+
39
+ case "$ACTION" in
40
+
41
+ # ─────────────────────────────────────────────
42
+ # ADD: Add a new content entry
43
+ # ─────────────────────────────────────────────
44
+ add)
45
+ TITLE=$(echo "$INPUT" | jq -r '.title // empty')
46
+ PLATFORM=$(echo "$INPUT" | jq -r '.platform // empty')
47
+ CONTENT_TYPE=$(echo "$INPUT" | jq -r '.type // "post"')
48
+ SCHEDULED_DATE=$(echo "$INPUT" | jq -r '.scheduledDate // empty')
49
+ STATUS=$(echo "$INPUT" | jq -r '.status // "draft"')
50
+ CONTENT_PATH=$(echo "$INPUT" | jq -r '.contentPath // empty')
51
+ LINE=$(echo "$INPUT" | jq -r '.line // "crewly"')
52
+ TOPIC=$(echo "$INPUT" | jq -r '.topic // empty')
53
+ NOTES=$(echo "$INPUT" | jq -r '.notes // empty')
54
+ TAGS=$(echo "$INPUT" | jq -r '.tags // "[]"')
55
+
56
+ require_param "title" "$TITLE"
57
+ require_param "platform" "$PLATFORM"
58
+ require_param "scheduledDate" "$SCHEDULED_DATE"
59
+
60
+ # Validate platform
61
+ VALID_PLATFORMS="x|linkedin|xiaohongshu|substack|youtube|github|reddit"
62
+ if ! echo "$PLATFORM" | grep -qE "^(${VALID_PLATFORMS})$"; then
63
+ error_exit "Invalid platform: $PLATFORM. Valid: x, linkedin, xiaohongshu, substack, youtube, github, reddit"
64
+ fi
65
+
66
+ # Validate status
67
+ VALID_STATUSES="idea|draft|ready|in-review|approved|published|archived"
68
+ if ! echo "$STATUS" | grep -qE "^(${VALID_STATUSES})$"; then
69
+ error_exit "Invalid status: $STATUS. Valid: idea, draft, ready, in-review, approved, published, archived"
70
+ fi
71
+
72
+ # Validate content type
73
+ VALID_TYPES="post|thread|article|video|image-text|newsletter|showcase|tutorial"
74
+ if ! echo "$CONTENT_TYPE" | grep -qE "^(${VALID_TYPES})$"; then
75
+ error_exit "Invalid type: $CONTENT_TYPE. Valid: post, thread, article, video, image-text, newsletter, showcase, tutorial"
76
+ fi
77
+
78
+ # Generate entry ID (timestamp-based)
79
+ ENTRY_ID="cc-$(date +%s)-$((RANDOM % 1000))"
80
+ NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
81
+
82
+ # Ensure tags is valid JSON array
83
+ if ! echo "$TAGS" | jq empty 2>/dev/null; then
84
+ TAGS="[]"
85
+ fi
86
+
87
+ # Build new entry
88
+ NEW_ENTRY=$(jq -n \
89
+ --arg id "$ENTRY_ID" \
90
+ --arg title "$TITLE" \
91
+ --arg platform "$PLATFORM" \
92
+ --arg type "$CONTENT_TYPE" \
93
+ --arg scheduledDate "$SCHEDULED_DATE" \
94
+ --arg status "$STATUS" \
95
+ --arg contentPath "$CONTENT_PATH" \
96
+ --arg line "$LINE" \
97
+ --arg topic "$TOPIC" \
98
+ --arg notes "$NOTES" \
99
+ --argjson tags "$TAGS" \
100
+ --arg createdAt "$NOW" \
101
+ --arg updatedAt "$NOW" \
102
+ '{
103
+ id: $id,
104
+ title: $title,
105
+ platform: $platform,
106
+ type: $type,
107
+ scheduledDate: $scheduledDate,
108
+ status: $status,
109
+ contentPath: $contentPath,
110
+ line: $line,
111
+ topic: $topic,
112
+ notes: $notes,
113
+ tags: $tags,
114
+ createdAt: $createdAt,
115
+ updatedAt: $updatedAt
116
+ }')
117
+
118
+ # Append to calendar
119
+ jq --argjson entry "$NEW_ENTRY" '.entries += [$entry]' "$CALENDAR_PATH" > "${CALENDAR_PATH}.tmp" \
120
+ && mv "${CALENDAR_PATH}.tmp" "$CALENDAR_PATH"
121
+
122
+ jq -n --argjson entry "$NEW_ENTRY" '{"success":true,"action":"add","entry":$entry}'
123
+ ;;
124
+
125
+ # ─────────────────────────────────────────────
126
+ # LIST: List calendar entries with filters
127
+ # ─────────────────────────────────────────────
128
+ list)
129
+ FILTER_PLATFORM=$(echo "$INPUT" | jq -r '.platform // empty')
130
+ FILTER_STATUS=$(echo "$INPUT" | jq -r '.status // empty')
131
+ FILTER_DATE=$(echo "$INPUT" | jq -r '.date // empty')
132
+ FILTER_DATE_FROM=$(echo "$INPUT" | jq -r '.dateFrom // empty')
133
+ FILTER_DATE_TO=$(echo "$INPUT" | jq -r '.dateTo // empty')
134
+ FILTER_LINE=$(echo "$INPUT" | jq -r '.line // empty')
135
+ LIMIT=$(echo "$INPUT" | jq -r '.limit // "50"')
136
+
137
+ # Build jq filter
138
+ JQ_FILTER=".entries"
139
+
140
+ if [ -n "$FILTER_PLATFORM" ]; then
141
+ JQ_FILTER="${JQ_FILTER} | map(select(.platform == \"${FILTER_PLATFORM}\"))"
142
+ fi
143
+ if [ -n "$FILTER_STATUS" ]; then
144
+ JQ_FILTER="${JQ_FILTER} | map(select(.status == \"${FILTER_STATUS}\"))"
145
+ fi
146
+ if [ -n "$FILTER_DATE" ]; then
147
+ JQ_FILTER="${JQ_FILTER} | map(select(.scheduledDate == \"${FILTER_DATE}\"))"
148
+ fi
149
+ if [ -n "$FILTER_DATE_FROM" ]; then
150
+ JQ_FILTER="${JQ_FILTER} | map(select(.scheduledDate >= \"${FILTER_DATE_FROM}\"))"
151
+ fi
152
+ if [ -n "$FILTER_DATE_TO" ]; then
153
+ JQ_FILTER="${JQ_FILTER} | map(select(.scheduledDate <= \"${FILTER_DATE_TO}\"))"
154
+ fi
155
+ if [ -n "$FILTER_LINE" ]; then
156
+ JQ_FILTER="${JQ_FILTER} | map(select(.line == \"${FILTER_LINE}\"))"
157
+ fi
158
+
159
+ # Sort by scheduled date and limit
160
+ JQ_FILTER="${JQ_FILTER} | sort_by(.scheduledDate) | .[:${LIMIT}]"
161
+
162
+ ENTRIES=$(jq "$JQ_FILTER" "$CALENDAR_PATH")
163
+ COUNT=$(echo "$ENTRIES" | jq 'length')
164
+
165
+ jq -n \
166
+ --argjson entries "$ENTRIES" \
167
+ --argjson count "$COUNT" \
168
+ --arg calendarPath "$CALENDAR_PATH" \
169
+ '{"success":true,"action":"list","count":$count,"entries":$entries,"calendarPath":$calendarPath}'
170
+ ;;
171
+
172
+ # ─────────────────────────────────────────────
173
+ # UPDATE: Update an existing entry
174
+ # ─────────────────────────────────────────────
175
+ update)
176
+ ENTRY_ID=$(echo "$INPUT" | jq -r '.id // empty')
177
+ require_param "id" "$ENTRY_ID"
178
+
179
+ # Check if entry exists
180
+ EXISTS=$(jq --arg id "$ENTRY_ID" '[.entries[] | select(.id == $id)] | length' "$CALENDAR_PATH")
181
+ if [ "$EXISTS" -eq 0 ]; then
182
+ error_exit "Entry not found: $ENTRY_ID"
183
+ fi
184
+
185
+ NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
186
+
187
+ # Build update fields dynamically
188
+ UPDATE_FIELDS=".updatedAt = \"${NOW}\""
189
+
190
+ NEW_STATUS=$(echo "$INPUT" | jq -r '.status // empty')
191
+ NEW_TITLE=$(echo "$INPUT" | jq -r '.title // empty')
192
+ NEW_DATE=$(echo "$INPUT" | jq -r '.scheduledDate // empty')
193
+ NEW_CONTENT_PATH=$(echo "$INPUT" | jq -r '.contentPath // empty')
194
+ NEW_NOTES=$(echo "$INPUT" | jq -r '.notes // empty')
195
+ NEW_TOPIC=$(echo "$INPUT" | jq -r '.topic // empty')
196
+
197
+ [ -n "$NEW_STATUS" ] && UPDATE_FIELDS="${UPDATE_FIELDS} | .status = \"${NEW_STATUS}\""
198
+ [ -n "$NEW_TITLE" ] && UPDATE_FIELDS="${UPDATE_FIELDS} | .title = \"${NEW_TITLE}\""
199
+ [ -n "$NEW_DATE" ] && UPDATE_FIELDS="${UPDATE_FIELDS} | .scheduledDate = \"${NEW_DATE}\""
200
+ [ -n "$NEW_CONTENT_PATH" ] && UPDATE_FIELDS="${UPDATE_FIELDS} | .contentPath = \"${NEW_CONTENT_PATH}\""
201
+ [ -n "$NEW_NOTES" ] && UPDATE_FIELDS="${UPDATE_FIELDS} | .notes = \"${NEW_NOTES}\""
202
+ [ -n "$NEW_TOPIC" ] && UPDATE_FIELDS="${UPDATE_FIELDS} | .topic = \"${NEW_TOPIC}\""
203
+
204
+ # If marking as published, record publishedAt
205
+ if [ "$NEW_STATUS" = "published" ]; then
206
+ UPDATE_FIELDS="${UPDATE_FIELDS} | .publishedAt = \"${NOW}\""
207
+ fi
208
+
209
+ # Apply update
210
+ jq --arg id "$ENTRY_ID" \
211
+ "(.entries[] | select(.id == \$id)) |= (${UPDATE_FIELDS})" \
212
+ "$CALENDAR_PATH" > "${CALENDAR_PATH}.tmp" \
213
+ && mv "${CALENDAR_PATH}.tmp" "$CALENDAR_PATH"
214
+
215
+ # Return updated entry
216
+ UPDATED=$(jq --arg id "$ENTRY_ID" '.entries[] | select(.id == $id)' "$CALENDAR_PATH")
217
+ jq -n --argjson entry "$UPDATED" '{"success":true,"action":"update","entry":$entry}'
218
+ ;;
219
+
220
+ # ─────────────────────────────────────────────
221
+ # NEXT: Get the next content to publish
222
+ # ─────────────────────────────────────────────
223
+ next)
224
+ FILTER_PLATFORM=$(echo "$INPUT" | jq -r '.platform // empty')
225
+ TODAY=$(date -u +%Y-%m-%d)
226
+
227
+ # Find entries that are ready/approved and scheduled for today or earlier
228
+ JQ_FILTER='.entries | map(select(.status == "ready" or .status == "approved"))'
229
+ JQ_FILTER="${JQ_FILTER} | map(select(.scheduledDate <= \"${TODAY}\"))"
230
+
231
+ if [ -n "$FILTER_PLATFORM" ]; then
232
+ JQ_FILTER="${JQ_FILTER} | map(select(.platform == \"${FILTER_PLATFORM}\"))"
233
+ fi
234
+
235
+ JQ_FILTER="${JQ_FILTER} | sort_by(.scheduledDate) | .[0] // null"
236
+
237
+ NEXT_ENTRY=$(jq "$JQ_FILTER" "$CALENDAR_PATH")
238
+
239
+ if [ "$NEXT_ENTRY" = "null" ]; then
240
+ # Also show upcoming entries
241
+ UPCOMING=$(jq --arg today "$TODAY" \
242
+ '[.entries[] | select(.status == "draft" or .status == "ready" or .status == "approved") | select(.scheduledDate > $today)] | sort_by(.scheduledDate) | .[:3]' \
243
+ "$CALENDAR_PATH")
244
+ jq -n --argjson upcoming "$UPCOMING" \
245
+ '{"success":true,"action":"next","next":null,"message":"No content ready to publish right now.","upcoming":$upcoming}'
246
+ else
247
+ jq -n --argjson entry "$NEXT_ENTRY" \
248
+ '{"success":true,"action":"next","next":$entry}'
249
+ fi
250
+ ;;
251
+
252
+ # ─────────────────────────────────────────────
253
+ # STATS: Calendar statistics
254
+ # ─────────────────────────────────────────────
255
+ stats)
256
+ TOTAL=$(jq '.entries | length' "$CALENDAR_PATH")
257
+ BY_STATUS=$(jq '[.entries[] | .status] | group_by(.) | map({(.[0]): length}) | add // {}' "$CALENDAR_PATH")
258
+ BY_PLATFORM=$(jq '[.entries[] | .platform] | group_by(.) | map({(.[0]): length}) | add // {}' "$CALENDAR_PATH")
259
+ BY_LINE=$(jq '[.entries[] | .line] | group_by(.) | map({(.[0]): length}) | add // {}' "$CALENDAR_PATH")
260
+
261
+ TODAY=$(date -u +%Y-%m-%d)
262
+ OVERDUE=$(jq --arg today "$TODAY" \
263
+ '[.entries[] | select(.scheduledDate < $today and (.status == "draft" or .status == "ready" or .status == "approved"))] | length' \
264
+ "$CALENDAR_PATH")
265
+ THIS_WEEK_END=$(date -u -v+7d +%Y-%m-%d 2>/dev/null || date -u -d "+7 days" +%Y-%m-%d 2>/dev/null || echo "$TODAY")
266
+ THIS_WEEK=$(jq --arg from "$TODAY" --arg to "$THIS_WEEK_END" \
267
+ '[.entries[] | select(.scheduledDate >= $from and .scheduledDate <= $to)] | length' \
268
+ "$CALENDAR_PATH")
269
+
270
+ jq -n \
271
+ --argjson total "$TOTAL" \
272
+ --argjson byStatus "$BY_STATUS" \
273
+ --argjson byPlatform "$BY_PLATFORM" \
274
+ --argjson byLine "$BY_LINE" \
275
+ --argjson overdue "$OVERDUE" \
276
+ --argjson thisWeek "$THIS_WEEK" \
277
+ --arg calendarPath "$CALENDAR_PATH" \
278
+ '{
279
+ "success": true,
280
+ "action": "stats",
281
+ "total": $total,
282
+ "byStatus": $byStatus,
283
+ "byPlatform": $byPlatform,
284
+ "byLine": $byLine,
285
+ "overdue": $overdue,
286
+ "thisWeek": $thisWeek,
287
+ "calendarPath": $calendarPath
288
+ }'
289
+ ;;
290
+
291
+ *)
292
+ error_exit "Unknown action: $ACTION. Valid actions: add, list, update, next, stats"
293
+ ;;
294
+ esac
@@ -0,0 +1,122 @@
1
+ # Content Calendar Manager
2
+
3
+ Manage a content calendar with CRUD operations. Track planned content across platforms, schedule dates, and publication status.
4
+
5
+ ## Storage
6
+
7
+ Calendar data is stored as a JSON file. Default location: `{projectPath}/.crewly/content/calendar.json`
8
+
9
+ ## Actions
10
+
11
+ ### `add` — Add a new content entry
12
+
13
+ | Parameter | Required | Description |
14
+ |-----------|----------|-------------|
15
+ | `action` | Yes | `"add"` |
16
+ | `title` | Yes | Content title or headline |
17
+ | `platform` | Yes | `x`, `linkedin`, `xiaohongshu`, `substack`, `youtube`, `github`, `reddit` |
18
+ | `type` | No | `post`, `thread`, `article`, `video`, `image-text`, `newsletter`, `showcase`, `tutorial` (default: `post`) |
19
+ | `scheduledDate` | Yes | Target publish date in `YYYY-MM-DD` format |
20
+ | `status` | No | `idea`, `draft`, `ready`, `in-review`, `approved`, `published`, `archived` (default: `draft`) |
21
+ | `contentPath` | No | Path to the content file (markdown) |
22
+ | `line` | No | Content line: `crewly` (brand) or `personal` (Steve). Default: `crewly` |
23
+ | `topic` | No | Topic or brief description |
24
+ | `notes` | No | Internal notes |
25
+ | `tags` | No | JSON array of tags, e.g. `["ai-agent","security"]` |
26
+ | `projectPath` | No | Project path to determine calendar location |
27
+ | `calendarPath` | No | Custom calendar file path (overrides default) |
28
+
29
+ ### `list` — List entries with filters
30
+
31
+ | Parameter | Required | Description |
32
+ |-----------|----------|-------------|
33
+ | `action` | Yes | `"list"` |
34
+ | `platform` | No | Filter by platform |
35
+ | `status` | No | Filter by status |
36
+ | `date` | No | Filter by exact date (`YYYY-MM-DD`) |
37
+ | `dateFrom` | No | Filter entries from this date |
38
+ | `dateTo` | No | Filter entries up to this date |
39
+ | `line` | No | Filter by content line (`crewly` or `personal`) |
40
+ | `limit` | No | Max entries to return (default: 50) |
41
+
42
+ ### `update` — Update an entry
43
+
44
+ | Parameter | Required | Description |
45
+ |-----------|----------|-------------|
46
+ | `action` | Yes | `"update"` |
47
+ | `id` | Yes | Entry ID to update |
48
+ | `status` | No | New status |
49
+ | `title` | No | New title |
50
+ | `scheduledDate` | No | New date |
51
+ | `contentPath` | No | New content file path |
52
+ | `notes` | No | New notes |
53
+ | `topic` | No | New topic |
54
+
55
+ ### `next` — Get next content to publish
56
+
57
+ Returns the next entry with status `ready` or `approved` that is scheduled for today or earlier.
58
+
59
+ | Parameter | Required | Description |
60
+ |-----------|----------|-------------|
61
+ | `action` | Yes | `"next"` |
62
+ | `platform` | No | Filter by platform |
63
+
64
+ ### `stats` — Calendar statistics
65
+
66
+ Returns counts by status, platform, and content line. Also shows overdue and this-week counts.
67
+
68
+ | Parameter | Required | Description |
69
+ |-----------|----------|-------------|
70
+ | `action` | Yes | `"stats"` |
71
+
72
+ ## Examples
73
+
74
+ ### Add a new X thread for Monday
75
+ ```bash
76
+ bash execute.sh '{"action":"add","title":"AI Agent security - lessons from n8n CVEs","platform":"x","type":"thread","scheduledDate":"2026-03-03","status":"draft","line":"crewly","topic":"AI agent security","tags":["ai-agent","security","n8n"],"projectPath":"/path/to/project"}'
77
+ ```
78
+
79
+ ### List all content for next week
80
+ ```bash
81
+ bash execute.sh '{"action":"list","dateFrom":"2026-03-03","dateTo":"2026-03-07","projectPath":"/path/to/project"}'
82
+ ```
83
+
84
+ ### List only draft X content
85
+ ```bash
86
+ bash execute.sh '{"action":"list","platform":"x","status":"draft","projectPath":"/path/to/project"}'
87
+ ```
88
+
89
+ ### Mark content as published
90
+ ```bash
91
+ bash execute.sh '{"action":"update","id":"cc-1709012345-42","status":"published","projectPath":"/path/to/project"}'
92
+ ```
93
+
94
+ ### Get next content to publish
95
+ ```bash
96
+ bash execute.sh '{"action":"next","projectPath":"/path/to/project"}'
97
+ ```
98
+
99
+ ### Get calendar stats
100
+ ```bash
101
+ bash execute.sh '{"action":"stats","projectPath":"/path/to/project"}'
102
+ ```
103
+
104
+ ## Status Workflow
105
+
106
+ ```
107
+ idea → draft → ready → in-review → approved → published
108
+
109
+ archived
110
+ ```
111
+
112
+ - **idea**: Just a topic/concept, no content written
113
+ - **draft**: Content being written
114
+ - **ready**: Content complete, pending review
115
+ - **in-review**: Sent to Steve for review
116
+ - **approved**: Steve approved, ready to publish
117
+ - **published**: Live on the platform
118
+ - **archived**: Removed from active calendar
119
+
120
+ ## Output
121
+
122
+ All actions return JSON with `success: true` and the relevant data. Errors return JSON to stderr with `error` field.
@@ -0,0 +1,22 @@
1
+ {
2
+ "id": "content-calendar",
3
+ "name": "Content Calendar Manager",
4
+ "description": "CRUD operations for content scheduling. Add, list, update, and query content calendar entries. Supports filtering by platform, status, date range, and content line (brand vs personal).",
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": 10000
14
+ }
15
+ },
16
+ "assignableRoles": ["content-strategist", "product-manager", "generalist"],
17
+ "triggers": ["content calendar", "schedule content", "content plan", "what to publish", "next post", "content schedule"],
18
+ "tags": ["content", "calendar", "scheduling", "planning", "marketing", "editorial"],
19
+ "version": "1.0.0",
20
+ "author": "Luna (Content Strategist)",
21
+ "license": "MIT"
22
+ }