crewly 1.4.61 → 1.4.63

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 (105) hide show
  1. package/config/skills/agent/content-calendar/execute.sh +2 -2
  2. package/config/skills/agent/marketing/brand-onboarding/SKILL.md +76 -0
  3. package/config/skills/agent/marketing/brand-onboarding/execute.sh +312 -0
  4. package/config/skills/agent/marketing/submit-for-approval/SKILL.md +73 -0
  5. package/config/skills/agent/marketing/submit-for-approval/execute.sh +138 -0
  6. package/config/skills/agent/marketing/weekly-content-planning/SKILL.md +52 -0
  7. package/config/skills/agent/marketing/weekly-content-planning/execute.sh +202 -0
  8. package/config/skills/agent/marketing/weekly-content-planning/execute.test.sh +151 -0
  9. package/config/skills/agent/marketing/weekly-marketing-report/SKILL.md +51 -0
  10. package/config/skills/agent/marketing/weekly-marketing-report/execute.sh +190 -0
  11. package/config/skills/agent/marketing/weekly-marketing-report/execute.test.sh +241 -0
  12. package/config/skills/orchestrator/send-to-remote/SKILL.md +51 -0
  13. package/config/skills/orchestrator/send-to-remote/execute.sh +114 -0
  14. package/config/templates/marketing-team/README.md +42 -0
  15. package/config/templates/marketing-team/goals.md +21 -0
  16. package/config/templates/marketing-team/knowledge/docs/brand-voice-guide.md +61 -0
  17. package/config/templates/marketing-team/knowledge/docs/content-best-practices.md +64 -0
  18. package/config/templates/marketing-team/knowledge/index.json +24 -0
  19. package/config/templates/marketing-team/learned-patterns.json +5 -0
  20. package/config/templates/marketing-team/norms/brand-consistency.md +40 -0
  21. package/config/templates/marketing-team/norms/content-quality-checklist.md +45 -0
  22. package/config/templates/marketing-team/quality-gates.yaml +47 -0
  23. package/config/templates/marketing-team/roles/analyst.md +63 -0
  24. package/config/templates/marketing-team/roles/strategist.md +26 -0
  25. package/config/templates/marketing-team/roles/writer.md +58 -0
  26. package/config/templates/marketing-team/template.json +90 -0
  27. package/config/templates/marketing-team/workflows/weekly-content-cycle.yaml +48 -0
  28. package/dist/backend/backend/src/constants.d.ts +9 -0
  29. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  30. package/dist/backend/backend/src/constants.js +9 -0
  31. package/dist/backend/backend/src/constants.js.map +1 -1
  32. package/dist/backend/backend/src/controllers/cross-machine/cross-machine.controller.d.ts +16 -0
  33. package/dist/backend/backend/src/controllers/cross-machine/cross-machine.controller.d.ts.map +1 -0
  34. package/dist/backend/backend/src/controllers/cross-machine/cross-machine.controller.js +140 -0
  35. package/dist/backend/backend/src/controllers/cross-machine/cross-machine.controller.js.map +1 -0
  36. package/dist/backend/backend/src/controllers/cross-machine/index.d.ts +7 -0
  37. package/dist/backend/backend/src/controllers/cross-machine/index.d.ts.map +1 -0
  38. package/dist/backend/backend/src/controllers/cross-machine/index.js +7 -0
  39. package/dist/backend/backend/src/controllers/cross-machine/index.js.map +1 -0
  40. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  41. package/dist/backend/backend/src/routes/api.routes.js +3 -0
  42. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  43. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  44. package/dist/backend/backend/src/services/agent/agent-registration.service.js +46 -6
  45. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  46. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts +13 -0
  47. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
  48. package/dist/backend/backend/src/services/ai/prompt-builder.service.js +50 -5
  49. package/dist/backend/backend/src/services/ai/prompt-builder.service.js.map +1 -1
  50. package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.d.ts +8 -0
  51. package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.d.ts.map +1 -1
  52. package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.js +52 -3
  53. package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.js.map +1 -1
  54. package/dist/backend/backend/src/services/cloud/relay-client.service.d.ts +5 -1
  55. package/dist/backend/backend/src/services/cloud/relay-client.service.d.ts.map +1 -1
  56. package/dist/backend/backend/src/services/cloud/relay-client.service.js +14 -2
  57. package/dist/backend/backend/src/services/cloud/relay-client.service.js.map +1 -1
  58. package/dist/backend/backend/src/services/index.d.ts +2 -0
  59. package/dist/backend/backend/src/services/index.d.ts.map +1 -1
  60. package/dist/backend/backend/src/services/index.js +2 -0
  61. package/dist/backend/backend/src/services/index.js.map +1 -1
  62. package/dist/backend/backend/src/services/onboarding/brand-onboarding.service.d.ts +155 -0
  63. package/dist/backend/backend/src/services/onboarding/brand-onboarding.service.d.ts.map +1 -0
  64. package/dist/backend/backend/src/services/onboarding/brand-onboarding.service.js +469 -0
  65. package/dist/backend/backend/src/services/onboarding/brand-onboarding.service.js.map +1 -0
  66. package/dist/backend/backend/src/services/onboarding/brand-onboarding.types.d.ts +107 -0
  67. package/dist/backend/backend/src/services/onboarding/brand-onboarding.types.d.ts.map +1 -0
  68. package/dist/backend/backend/src/services/onboarding/brand-onboarding.types.js +104 -0
  69. package/dist/backend/backend/src/services/onboarding/brand-onboarding.types.js.map +1 -0
  70. package/dist/backend/backend/src/services/onboarding/content-approval.service.d.ts +124 -0
  71. package/dist/backend/backend/src/services/onboarding/content-approval.service.d.ts.map +1 -0
  72. package/dist/backend/backend/src/services/onboarding/content-approval.service.js +256 -0
  73. package/dist/backend/backend/src/services/onboarding/content-approval.service.js.map +1 -0
  74. package/dist/backend/backend/src/services/onboarding/content-approval.types.d.ts +80 -0
  75. package/dist/backend/backend/src/services/onboarding/content-approval.types.d.ts.map +1 -0
  76. package/dist/backend/backend/src/services/onboarding/content-approval.types.js +16 -0
  77. package/dist/backend/backend/src/services/onboarding/content-approval.types.js.map +1 -0
  78. package/dist/backend/backend/src/services/onboarding/index.d.ts +12 -0
  79. package/dist/backend/backend/src/services/onboarding/index.d.ts.map +1 -0
  80. package/dist/backend/backend/src/services/onboarding/index.js +10 -0
  81. package/dist/backend/backend/src/services/onboarding/index.js.map +1 -0
  82. package/dist/backend/backend/src/services/slack/cross-machine-message.service.d.ts +147 -0
  83. package/dist/backend/backend/src/services/slack/cross-machine-message.service.d.ts.map +1 -0
  84. package/dist/backend/backend/src/services/slack/cross-machine-message.service.js +306 -0
  85. package/dist/backend/backend/src/services/slack/cross-machine-message.service.js.map +1 -0
  86. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +7 -0
  87. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  88. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +76 -0
  89. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  90. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
  91. package/dist/backend/backend/src/services/slack/slack.service.js +8 -2
  92. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
  93. package/dist/backend/backend/src/types/cross-machine.types.d.ts +103 -0
  94. package/dist/backend/backend/src/types/cross-machine.types.d.ts.map +1 -0
  95. package/dist/backend/backend/src/types/cross-machine.types.js +47 -0
  96. package/dist/backend/backend/src/types/cross-machine.types.js.map +1 -0
  97. package/dist/cli/backend/src/constants.d.ts +9 -0
  98. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  99. package/dist/cli/backend/src/constants.js +9 -0
  100. package/dist/cli/backend/src/constants.js.map +1 -1
  101. package/dist/cli/cli/src/commands/cloud.d.ts +18 -2
  102. package/dist/cli/cli/src/commands/cloud.d.ts.map +1 -1
  103. package/dist/cli/cli/src/commands/cloud.js +72 -16
  104. package/dist/cli/cli/src/commands/cloud.js.map +1 -1
  105. package/package.json +1 -1
@@ -0,0 +1,241 @@
1
+ #!/bin/bash
2
+ # Tests for weekly-marketing-report skill
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ EXECUTE="${SCRIPT_DIR}/execute.sh"
7
+ TEST_PROJECT=$(mktemp -d)
8
+ PASS=0
9
+ FAIL=0
10
+
11
+ cleanup() {
12
+ rm -rf "$TEST_PROJECT"
13
+ }
14
+ trap cleanup EXIT
15
+
16
+ assert_eq() {
17
+ local test_name="$1" expected="$2" actual="$3"
18
+ if [ "$expected" = "$actual" ]; then
19
+ echo " ✓ ${test_name}"
20
+ PASS=$((PASS + 1))
21
+ else
22
+ echo " ✗ ${test_name}: expected '${expected}', got '${actual}'"
23
+ FAIL=$((FAIL + 1))
24
+ fi
25
+ }
26
+
27
+ assert_true() {
28
+ local test_name="$1" value="$2"
29
+ if [ "$value" = "true" ]; then
30
+ echo " ✓ ${test_name}"
31
+ PASS=$((PASS + 1))
32
+ else
33
+ echo " ✗ ${test_name}: expected true, got '${value}'"
34
+ FAIL=$((FAIL + 1))
35
+ fi
36
+ }
37
+
38
+ echo "=== Weekly Marketing Report Skill Tests ==="
39
+ echo ""
40
+
41
+ # ─────────────────────────────────────────────
42
+ # Test 1: Missing required parameters
43
+ # ─────────────────────────────────────────────
44
+ echo "Test 1: Missing required parameters"
45
+ RESULT=$(bash "$EXECUTE" '{}' 2>&1 || true)
46
+ HAS_ERROR=$(echo "$RESULT" | jq -r '.error // empty' 2>/dev/null || echo "")
47
+ assert_true "exits with error on missing params" "$([ -n "$HAS_ERROR" ] && echo true || echo false)"
48
+
49
+ # ─────────────────────────────────────────────
50
+ # Test 2: Empty calendar (no file)
51
+ # ─────────────────────────────────────────────
52
+ echo "Test 2: No calendar file"
53
+ EMPTY_PROJECT=$(mktemp -d)
54
+ RESULT=$(bash "$EXECUTE" "{
55
+ \"projectPath\": \"${EMPTY_PROJECT}\",
56
+ \"weekEndDate\": \"2026-03-29\",
57
+ \"businessName\": \"EmptyBiz\"
58
+ }")
59
+
60
+ assert_true "returns success" "$(echo "$RESULT" | jq -r '.success')"
61
+ assert_eq "totalPosts is 0" "0" "$(echo "$RESULT" | jq -r '.report.totalPosts')"
62
+ assert_true "has recommendations" "$(echo "$RESULT" | jq -r '.report.recommendations | length > 0')"
63
+ assert_true "has markdown" "$(echo "$RESULT" | jq -r '.markdown' | grep -q 'Weekly Marketing Report' && echo true || echo false)"
64
+ rm -rf "$EMPTY_PROJECT"
65
+
66
+ # ─────────────────────────────────────────────
67
+ # Test 3: Calendar with sample data
68
+ # ─────────────────────────────────────────────
69
+ echo "Test 3: Calendar with sample data"
70
+ CALENDAR_DIR="${TEST_PROJECT}/.crewly/content"
71
+ mkdir -p "$CALENDAR_DIR"
72
+ cat > "${CALENDAR_DIR}/calendar.json" << 'CALEOF'
73
+ {
74
+ "entries": [
75
+ {
76
+ "id": "cc-test-001",
77
+ "title": "AI Trends Thread",
78
+ "platform": "x",
79
+ "type": "thread",
80
+ "scheduledDate": "2026-03-23",
81
+ "status": "published",
82
+ "publishedAt": "2026-03-23T10:00:00Z",
83
+ "line": "crewly",
84
+ "topic": "AI trends",
85
+ "notes": "",
86
+ "tags": ["ai"],
87
+ "createdAt": "2026-03-22T00:00:00Z",
88
+ "updatedAt": "2026-03-23T10:00:00Z"
89
+ },
90
+ {
91
+ "id": "cc-test-002",
92
+ "title": "LinkedIn Thought Leadership",
93
+ "platform": "linkedin",
94
+ "type": "post",
95
+ "scheduledDate": "2026-03-24",
96
+ "status": "published",
97
+ "publishedAt": "2026-03-24T09:00:00Z",
98
+ "line": "crewly",
99
+ "topic": "Leadership",
100
+ "notes": "",
101
+ "tags": ["leadership"],
102
+ "createdAt": "2026-03-22T00:00:00Z",
103
+ "updatedAt": "2026-03-24T09:00:00Z"
104
+ },
105
+ {
106
+ "id": "cc-test-003",
107
+ "title": "Product Update Post",
108
+ "platform": "x",
109
+ "type": "post",
110
+ "scheduledDate": "2026-03-25",
111
+ "status": "draft",
112
+ "line": "crewly",
113
+ "topic": "Product update",
114
+ "notes": "",
115
+ "tags": ["product"],
116
+ "createdAt": "2026-03-22T00:00:00Z",
117
+ "updatedAt": "2026-03-22T00:00:00Z"
118
+ },
119
+ {
120
+ "id": "cc-test-004",
121
+ "title": "Community Question",
122
+ "platform": "linkedin",
123
+ "type": "post",
124
+ "scheduledDate": "2026-03-26",
125
+ "status": "ready",
126
+ "line": "crewly",
127
+ "topic": "Community",
128
+ "notes": "",
129
+ "tags": ["community"],
130
+ "createdAt": "2026-03-22T00:00:00Z",
131
+ "updatedAt": "2026-03-22T00:00:00Z"
132
+ },
133
+ {
134
+ "id": "cc-test-old",
135
+ "title": "Old Post (outside week)",
136
+ "platform": "x",
137
+ "type": "post",
138
+ "scheduledDate": "2026-03-10",
139
+ "status": "published",
140
+ "publishedAt": "2026-03-10T10:00:00Z",
141
+ "line": "crewly",
142
+ "topic": "Old",
143
+ "notes": "",
144
+ "tags": [],
145
+ "createdAt": "2026-03-09T00:00:00Z",
146
+ "updatedAt": "2026-03-10T10:00:00Z"
147
+ }
148
+ ],
149
+ "metadata": {
150
+ "createdAt": "2026-03-22T00:00:00Z",
151
+ "version": "1.0"
152
+ }
153
+ }
154
+ CALEOF
155
+
156
+ RESULT=$(bash "$EXECUTE" "{
157
+ \"projectPath\": \"${TEST_PROJECT}\",
158
+ \"weekEndDate\": \"2026-03-29\",
159
+ \"businessName\": \"TestBiz\"
160
+ }")
161
+
162
+ assert_true "returns success" "$(echo "$RESULT" | jq -r '.success')"
163
+ assert_eq "totalPosts is 4" "4" "$(echo "$RESULT" | jq -r '.report.totalPosts')"
164
+ assert_eq "publishedCount is 2" "2" "$(echo "$RESULT" | jq -r '.report.publishedCount')"
165
+ assert_eq "completionRate is 50" "50" "$(echo "$RESULT" | jq -r '.report.completionRate')"
166
+
167
+ # Platform breakdown
168
+ assert_eq "x platform count" "2" "$(echo "$RESULT" | jq -r '.report.platformBreakdown.x')"
169
+ assert_eq "linkedin platform count" "2" "$(echo "$RESULT" | jq -r '.report.platformBreakdown.linkedin')"
170
+
171
+ # Status breakdown
172
+ assert_eq "published status count" "2" "$(echo "$RESULT" | jq -r '.report.statusBreakdown.published')"
173
+ assert_eq "draft status count" "1" "$(echo "$RESULT" | jq -r '.report.statusBreakdown.draft')"
174
+ assert_eq "ready status count" "1" "$(echo "$RESULT" | jq -r '.report.statusBreakdown.ready')"
175
+
176
+ # Pipeline health
177
+ assert_eq "pipeline draft count" "1" "$(echo "$RESULT" | jq -r '.report.pipelineHealth.draft')"
178
+ assert_eq "pipeline ready count" "1" "$(echo "$RESULT" | jq -r '.report.pipelineHealth.ready')"
179
+ assert_eq "pipeline published count" "2" "$(echo "$RESULT" | jq -r '.report.pipelineHealth.published')"
180
+
181
+ # Recommendations
182
+ assert_true "has recommendations" "$(echo "$RESULT" | jq -r '.report.recommendations | length > 0')"
183
+
184
+ # Markdown output
185
+ assert_true "markdown contains business name" "$(echo "$RESULT" | jq -r '.markdown' | grep -q 'TestBiz' && echo true || echo false)"
186
+ assert_true "markdown contains Platform Breakdown" "$(echo "$RESULT" | jq -r '.markdown' | grep -q 'Platform Breakdown' && echo true || echo false)"
187
+
188
+ # ─────────────────────────────────────────────
189
+ # Test 4: Excludes out-of-range entries
190
+ # ─────────────────────────────────────────────
191
+ echo "Test 4: Excludes out-of-range entries"
192
+ # The old post (2026-03-10) should NOT be in the week ending 2026-03-29
193
+ assert_eq "old post excluded from count" "4" "$(echo "$RESULT" | jq -r '.report.totalPosts')"
194
+
195
+ # ─────────────────────────────────────────────
196
+ # Test 5: Report with custom calendarPath
197
+ # ─────────────────────────────────────────────
198
+ echo "Test 5: Custom calendarPath"
199
+ CUSTOM_CAL=$(mktemp)
200
+ cat > "$CUSTOM_CAL" << 'CALEOF'
201
+ {
202
+ "entries": [
203
+ {
204
+ "id": "cc-custom-001",
205
+ "title": "Custom Post",
206
+ "platform": "x",
207
+ "type": "post",
208
+ "scheduledDate": "2026-04-01",
209
+ "status": "published",
210
+ "publishedAt": "2026-04-01T10:00:00Z",
211
+ "line": "crewly",
212
+ "topic": "Custom",
213
+ "notes": "",
214
+ "tags": [],
215
+ "createdAt": "2026-04-01T00:00:00Z",
216
+ "updatedAt": "2026-04-01T10:00:00Z"
217
+ }
218
+ ],
219
+ "metadata": {"createdAt":"2026-04-01T00:00:00Z","version":"1.0"}
220
+ }
221
+ CALEOF
222
+
223
+ RESULT=$(bash "$EXECUTE" "{
224
+ \"calendarPath\": \"${CUSTOM_CAL}\",
225
+ \"weekEndDate\": \"2026-04-05\",
226
+ \"businessName\": \"CustomBiz\"
227
+ }")
228
+
229
+ assert_true "returns success with custom path" "$(echo "$RESULT" | jq -r '.success')"
230
+ assert_eq "finds 1 entry" "1" "$(echo "$RESULT" | jq -r '.report.totalPosts')"
231
+ rm -f "$CUSTOM_CAL"
232
+
233
+ # ─────────────────────────────────────────────
234
+ # Summary
235
+ # ─────────────────────────────────────────────
236
+ echo ""
237
+ echo "=== Results: ${PASS} passed, ${FAIL} failed ==="
238
+
239
+ if [ "$FAIL" -gt 0 ]; then
240
+ exit 1
241
+ fi
@@ -0,0 +1,51 @@
1
+ # send-to-remote
2
+
3
+ Send a cross-machine message to a remote Crewly instance via Slack.
4
+
5
+ ## When to use
6
+
7
+ Use this skill when you need to communicate with a Crewly orchestrator running on a different machine. Both machines must be connected to the same Slack workspace and have cross-machine messaging configured.
8
+
9
+ ## Prerequisites
10
+
11
+ 1. Both machines must have Slack connected
12
+ 2. Cross-machine messaging must be configured on both machines (via `POST /api/cross-machine/configure`)
13
+ 3. Both machines must be in the same Slack workspace
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ # Delegate a task to a remote machine
19
+ bash execute.sh '{"targetMachine":"<device-id>","type":"delegate-task","message":"Run the full test suite on branch feature/xyz"}'
20
+
21
+ # Send a message to a remote orchestrator
22
+ bash execute.sh '{"targetMachine":"<device-id>","type":"send-message","message":"Build completed successfully"}'
23
+
24
+ # Request status from a remote machine
25
+ bash execute.sh '{"targetMachine":"<device-id>","type":"status-request"}'
26
+
27
+ # Ping all machines (broadcast)
28
+ bash execute.sh '{"targetMachine":"*","type":"ping"}'
29
+ ```
30
+
31
+ ## Parameters
32
+
33
+ | Parameter | Required | Description |
34
+ |-----------|----------|-------------|
35
+ | `targetMachine` | Yes | Target device ID (UUID from `~/.crewly/device.json`) or `*` for broadcast |
36
+ | `type` | Yes | Message type: `delegate-task`, `send-message`, `status-request`, `ping` |
37
+ | `message` | No | Human-readable message text |
38
+ | `payload` | No | JSON object with additional structured data |
39
+
40
+ ## Message Types
41
+
42
+ - **delegate-task**: Ask the remote orchestrator to execute a task
43
+ - **send-message**: Send an informational message
44
+ - **status-request**: Request status from the remote machine (triggers automatic response)
45
+ - **ping**: Check if a machine is online (triggers automatic pong response)
46
+
47
+ ## Finding Device IDs
48
+
49
+ To find a remote machine's device ID:
50
+ 1. On the remote machine: `cat ~/.crewly/device.json` → `deviceId` field
51
+ 2. Or use `GET /api/cross-machine/status` on the local machine to see your own ID
@@ -0,0 +1,114 @@
1
+ #!/bin/bash
2
+ # Send a cross-machine message to a remote Crewly instance via Slack
3
+ #
4
+ # Usage:
5
+ # bash execute.sh '{"targetMachine":"device-uuid","type":"delegate-task","message":"Run tests"}'
6
+ # bash execute.sh --target device-uuid --type delegate-task --message "Run tests"
7
+ # bash execute.sh --target "*" --type ping # Broadcast ping to all machines
8
+ #
9
+ # Parameters:
10
+ # targetMachine / --target Target device ID or "*" for broadcast (required)
11
+ # type / --type Message type: delegate-task|send-message|status-request|ping (required)
12
+ # message / --message Message text (optional, included in payload)
13
+ # payload / --payload JSON payload string (optional)
14
+ #
15
+ set -euo pipefail
16
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17
+ source "${SCRIPT_DIR}/../_common/lib.sh"
18
+
19
+ print_usage() {
20
+ cat <<'EOF_USAGE'
21
+ Usage:
22
+ bash execute.sh '{"targetMachine":"device-uuid","type":"delegate-task","message":"..."}'
23
+ bash execute.sh --target <deviceId> --type <type> [--message <text>] [--payload <json>]
24
+
25
+ Options:
26
+ --target | -t Target device ID or "*" for broadcast (required)
27
+ --type | -T Message type: delegate-task, send-message, status-request, ping (required)
28
+ --message | -m Message text (optional)
29
+ --payload | -p JSON payload object (optional)
30
+ --help | -h Show this help
31
+ EOF_USAGE
32
+ }
33
+
34
+ INPUT_JSON=""
35
+ TARGET=""
36
+ TYPE=""
37
+ MESSAGE=""
38
+ PAYLOAD=""
39
+
40
+ # Detect legacy JSON argument
41
+ if [[ $# -gt 0 && ${1:0:1} == '{' ]]; then
42
+ INPUT_JSON="$1"
43
+ shift || true
44
+ fi
45
+
46
+ while [[ $# -gt 0 ]]; do
47
+ case "$1" in
48
+ --target|-t)
49
+ TARGET="$2"
50
+ shift 2
51
+ ;;
52
+ --type|-T)
53
+ TYPE="$2"
54
+ shift 2
55
+ ;;
56
+ --message|-m)
57
+ MESSAGE="$2"
58
+ shift 2
59
+ ;;
60
+ --payload|-p)
61
+ PAYLOAD="$2"
62
+ shift 2
63
+ ;;
64
+ --help|-h)
65
+ print_usage
66
+ exit 0
67
+ ;;
68
+ *)
69
+ if [[ -z "$INPUT_JSON" && ${1:0:1} == '{' ]]; then
70
+ INPUT_JSON="$1"
71
+ shift
72
+ else
73
+ echo '{"error":"Unknown argument: '"$1"'"}' >&2
74
+ exit 1
75
+ fi
76
+ ;;
77
+ esac
78
+ done
79
+
80
+ # Parse JSON input
81
+ if [ -n "$INPUT_JSON" ]; then
82
+ TARGET=${TARGET:-$(printf '%s\n' "$INPUT_JSON" | jq -r '.targetMachine // empty')}
83
+ TYPE=${TYPE:-$(printf '%s\n' "$INPUT_JSON" | jq -r '.type // empty')}
84
+ MESSAGE=${MESSAGE:-$(printf '%s\n' "$INPUT_JSON" | jq -r '.message // empty')}
85
+ PAYLOAD=${PAYLOAD:-$(printf '%s\n' "$INPUT_JSON" | jq -r '.payload // empty')}
86
+ fi
87
+
88
+ require_param "targetMachine" "$TARGET"
89
+ require_param "type" "$TYPE"
90
+
91
+ # Build the API request body
92
+ export _TARGET="$TARGET"
93
+ export _TYPE="$TYPE"
94
+ export _MESSAGE="${MESSAGE:-}"
95
+
96
+ if [ -n "$PAYLOAD" ] && [ "$PAYLOAD" != "null" ]; then
97
+ export _PAYLOAD="$PAYLOAD"
98
+ BODY=$(jq -n '{
99
+ targetMachine: env._TARGET,
100
+ type: env._TYPE,
101
+ message: (if env._MESSAGE != "" then env._MESSAGE else null end),
102
+ payload: (env._PAYLOAD | fromjson)
103
+ } | with_entries(select(.value != null))')
104
+ unset _PAYLOAD
105
+ else
106
+ BODY=$(jq -n '{
107
+ targetMachine: env._TARGET,
108
+ type: env._TYPE,
109
+ message: (if env._MESSAGE != "" then env._MESSAGE else null end)
110
+ } | with_entries(select(.value != null))')
111
+ fi
112
+ unset _TARGET _TYPE _MESSAGE
113
+
114
+ api_call POST "/cross-machine/send" "$BODY"
@@ -0,0 +1,42 @@
1
+ # AI Marketing Team Template
2
+
3
+ A 3-agent AI marketing team designed for SMBs. Automates content strategy, creation, and analytics across social media platforms.
4
+
5
+ ## Team Composition
6
+
7
+ - **Maya (Strategist)**: Plans weekly content calendars, researches trends, monitors competitors, and delegates content tasks to the Writer.
8
+ - **Alex (Writer)**: Creates platform-specific social media posts, blog articles, and email newsletters following brand guidelines.
9
+ - **Jordan (Analyst)**: Compiles weekly performance reports with platform metrics, top performers, and data-driven recommendations.
10
+
11
+ ## Workflow
12
+
13
+ The team follows a weekly content cycle:
14
+
15
+ 1. **Strategy** (Maya) — Research trends, review last week's performance, create content calendar
16
+ 2. **Creation** (Alex) — Write content pieces from the calendar, following platform and brand guidelines
17
+ 3. **Analysis** (Jordan) — Compile performance metrics, identify top content, recommend optimizations
18
+
19
+ ## Included Skills
20
+
21
+ - `content-calendar` — CRUD operations for content scheduling
22
+ - `social-media-post` — Generate platform-specific posts
23
+ - `seo-blog-writer` — Write SEO-optimized blog content
24
+ - `daily-standup-report` — Generate team activity reports
25
+
26
+ ## Quick Start
27
+
28
+ ```bash
29
+ npx crewly create team --template marketing-team
30
+ ```
31
+
32
+ ## Customization
33
+
34
+ 1. Fill in `knowledge/docs/brand-voice-guide.md` with your brand's voice and tone
35
+ 2. Update `goals.md` with your specific marketing KPIs
36
+ 3. Adjust content mix ratios in the Strategist's role prompt
37
+
38
+ ## Quality Gates
39
+
40
+ - **Strategy Quality** — Validates calendar completeness and content mix
41
+ - **Content Quality** — Checks brand voice, grammar, and platform formatting
42
+ - **Report Quality** — Ensures metrics accuracy and actionable recommendations
@@ -0,0 +1,21 @@
1
+ # Marketing Team Goals
2
+
3
+ ## Objective 1: Content Consistency and Quality
4
+ - **KR1**: Publish a minimum of 5 pieces of content per week across all platforms.
5
+ - **KR2**: Maintain 100% adherence to the weekly content calendar (no missed posts).
6
+ - **KR3**: Achieve a minimum content quality score of 80/100 across all peer reviews.
7
+
8
+ ## Objective 2: Audience Growth and Engagement
9
+ - **KR1**: Grow total audience across platforms by 10% month-over-month.
10
+ - **KR2**: Achieve an average engagement rate of 3%+ on X and LinkedIn posts.
11
+ - **KR3**: Increase content reach by 15% week-over-week through optimized posting times and formats.
12
+
13
+ ## Objective 3: Brand Voice and Strategic Alignment
14
+ - **KR1**: 100% of published content passes the brand voice consistency checklist.
15
+ - **KR2**: Maintain a content mix ratio within 5% of target (40% educational, 30% engagement, 20% promotional, 10% community).
16
+ - **KR3**: Respond to trending topics within 24 hours of identification.
17
+
18
+ ## Objective 4: Data-Driven Optimization
19
+ - **KR1**: Deliver weekly performance reports within 24 hours of the reporting period end.
20
+ - **KR2**: Implement at least 2 data-backed strategy adjustments per week based on analytics.
21
+ - **KR3**: Reduce cost-per-engagement by 10% month-over-month through content optimization.
@@ -0,0 +1,61 @@
1
+ # Brand Voice Guide
2
+
3
+ > **Note**: This is a template. Fill in the sections below during brand onboarding to customize for your business.
4
+
5
+ ## Brand Identity
6
+
7
+ - **Business Name**: [Your Business Name]
8
+ - **Industry**: [Your Industry]
9
+ - **Target Audience**: [Primary audience description]
10
+ - **Brand Mission**: [One-sentence mission statement]
11
+
12
+ ## Voice Attributes
13
+
14
+ Define 3-5 adjectives that describe your brand voice:
15
+
16
+ 1. [e.g., Professional]
17
+ 2. [e.g., Approachable]
18
+ 3. [e.g., Innovative]
19
+ 4. [e.g., Trustworthy]
20
+
21
+ ## Tone Guidelines
22
+
23
+ ### We Sound Like
24
+ - [Example: A knowledgeable friend who explains complex topics simply]
25
+ - [Example: An enthusiastic expert who genuinely cares about helping]
26
+
27
+ ### We Never Sound Like
28
+ - [Example: Condescending or overly academic]
29
+ - [Example: Pushy or sales-driven]
30
+
31
+ ## Language Rules
32
+
33
+ ### Preferred Terms
34
+ | Instead of... | Use... |
35
+ |---------------|--------|
36
+ | [e.g., Users] | [e.g., Customers] |
37
+ | [e.g., Buy] | [e.g., Get started] |
38
+
39
+ ### Words to Avoid
40
+ - [e.g., Cheap, basic, simple]
41
+
42
+ ## Platform Tone Adjustments
43
+
44
+ ### X (Twitter)
45
+ - Tone shift: [e.g., More casual, punchy]
46
+ - Emoji usage: [e.g., Moderate, 1-2 per post]
47
+
48
+ ### LinkedIn
49
+ - Tone shift: [e.g., More professional, thought-leadership]
50
+ - Emoji usage: [e.g., Minimal]
51
+
52
+ ### Instagram
53
+ - Tone shift: [e.g., More visual, story-driven]
54
+ - Emoji usage: [e.g., Liberal, use to enhance readability]
55
+
56
+ ## Content Pillars
57
+
58
+ 1. **[Pillar 1 Name]**: [Description — e.g., Industry insights and trends]
59
+ 2. **[Pillar 2 Name]**: [Description — e.g., Product tips and tutorials]
60
+ 3. **[Pillar 3 Name]**: [Description — e.g., Customer success stories]
61
+ 4. **[Pillar 4 Name]**: [Description — e.g., Behind-the-scenes and culture]
@@ -0,0 +1,64 @@
1
+ # Social Media Content Best Practices
2
+
3
+ ## General Principles
4
+
5
+ ### The 80/20 Rule
6
+ - 80% of content should inform, educate, or entertain your audience
7
+ - 20% can directly promote your product or service
8
+
9
+ ### Platform-Native Content
10
+ - Never cross-post identical content across platforms
11
+ - Adapt format, length, and tone for each platform
12
+ - Respect platform-specific conventions (e.g., threads on X, carousels on LinkedIn)
13
+
14
+ ## Content Creation Guidelines
15
+
16
+ ### Headlines and Hooks
17
+ - Lead with the most compelling insight or question
18
+ - Use numbers and specifics ("3 lessons" beats "some lessons")
19
+ - Create curiosity gaps without being clickbait
20
+ - Front-load value — readers decide in 2 seconds
21
+
22
+ ### Visual Content
23
+ - Use consistent brand colors and fonts
24
+ - Prefer data visualizations over stock photos
25
+ - Screenshots and real examples outperform generic graphics
26
+ - Always include alt text for accessibility
27
+
28
+ ### Hashtag Strategy
29
+ - Research hashtag reach before using them
30
+ - Mix high-volume and niche hashtags
31
+ - Create a branded hashtag for campaigns
32
+ - Platform limits: X (1-2), LinkedIn (3-5), Instagram (5-15)
33
+
34
+ ## Engagement Best Practices
35
+
36
+ ### Timing
37
+ - Post during peak audience activity hours
38
+ - Maintain consistent posting schedule
39
+ - Space posts at least 2 hours apart on the same platform
40
+
41
+ ### Community Building
42
+ - Respond to comments within 1 hour during business hours
43
+ - Ask questions to encourage discussion
44
+ - Share and comment on relevant community content
45
+ - Tag relevant people and companies when appropriate
46
+
47
+ ### Content Repurposing
48
+ - Turn blog posts into social media threads
49
+ - Convert data points into infographics
50
+ - Extract quotes from long-form content for standalone posts
51
+ - Compile related posts into roundup articles
52
+
53
+ ## Measuring Success
54
+
55
+ ### Key Metrics by Platform
56
+ - **X**: Impressions, engagement rate, retweets, profile clicks
57
+ - **LinkedIn**: Impressions, engagement rate, shares, profile views
58
+ - **Instagram**: Reach, saves, shares, comments
59
+ - **Facebook**: Reach, engagement, shares, click-through rate
60
+
61
+ ### Benchmarks
62
+ - Good engagement rate: 1-3% (varies by platform and audience size)
63
+ - Good click-through rate: 2-5%
64
+ - Healthy follower growth: 2-5% monthly
@@ -0,0 +1,24 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "lastUpdated": "2026-03-22T00:00:00.000Z",
4
+ "documents": [
5
+ {
6
+ "id": "content-best-practices",
7
+ "title": "Social Media Content Best Practices",
8
+ "path": "docs/content-best-practices.md",
9
+ "category": "best-practice",
10
+ "tags": ["social-media", "content", "marketing", "engagement"],
11
+ "summary": "Best practices for creating effective social media content across platforms.",
12
+ "createdAt": "2026-03-22T00:00:00.000Z"
13
+ },
14
+ {
15
+ "id": "brand-voice-guide",
16
+ "title": "Brand Voice Guide",
17
+ "path": "docs/brand-voice-guide.md",
18
+ "category": "terminology",
19
+ "tags": ["brand", "voice", "tone", "guidelines"],
20
+ "summary": "Template for defining brand voice, tone, and messaging guidelines. Filled during onboarding.",
21
+ "createdAt": "2026-03-22T00:00:00.000Z"
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "lastUpdated": "2026-03-22T00:00:00.000Z",
4
+ "patterns": []
5
+ }
@@ -0,0 +1,40 @@
1
+ # Brand Consistency Rules
2
+
3
+ ## Purpose
4
+
5
+ These rules ensure all marketing output maintains a consistent brand identity across platforms, agents, and content types.
6
+
7
+ ## Mandatory Rules
8
+
9
+ ### 1. Voice Consistency
10
+ - All content must follow the Brand Voice Guide (see `knowledge/docs/brand-voice-guide.md`)
11
+ - When in doubt about tone, err on the side of the brand's primary voice attribute
12
+ - Platform-specific tone adjustments are allowed, but core voice must remain recognizable
13
+
14
+ ### 2. Visual Identity
15
+ - Use approved brand colors in all graphics and visual directions
16
+ - Maintain consistent font usage across platforms
17
+ - Logo placement follows brand guidelines
18
+ - Image style should be consistent (e.g., always flat design, always photography)
19
+
20
+ ### 3. Messaging Hierarchy
21
+ - Lead with the value proposition, not the feature
22
+ - Use the approved tagline in profile bios and campaign headers
23
+ - Key messages should be repeated across platforms (rephrased, not copied)
24
+
25
+ ### 4. Content Pillars
26
+ - Every post must map to at least one defined content pillar
27
+ - Maintain the target content mix ratio (educational/engagement/promotional/community)
28
+ - Track pillar distribution in the weekly report
29
+
30
+ ### 5. Cross-Platform Consistency
31
+ - Same campaign runs on all active platforms (adapted per platform)
32
+ - Announcements go out simultaneously across platforms
33
+ - Profile information is kept in sync (bio, links, profile image)
34
+
35
+ ## Enforcement
36
+
37
+ - The Strategist (Maya) is responsible for brand consistency review
38
+ - Content that fails brand consistency must be revised before publication
39
+ - Weekly reports should include a brand consistency score or flag
40
+ - New team members must review the Brand Voice Guide before creating content