clawra-anime 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.
@@ -0,0 +1,299 @@
1
+ /**
2
+ * Grok Imagine to OpenClaw Integration
3
+ *
4
+ * Generates images using xAI's Grok Imagine model via fal.ai
5
+ * and sends them to messaging channels via OpenClaw.
6
+ *
7
+ * Usage:
8
+ * npx ts-node grok-imagine-send.ts "<prompt>" "<channel>" ["<caption>"]
9
+ *
10
+ * Environment variables:
11
+ * FAL_KEY - Your fal.ai API key
12
+ * OPENCLAW_GATEWAY_URL - OpenClaw gateway URL (default: http://localhost:18789)
13
+ * OPENCLAW_GATEWAY_TOKEN - Gateway auth token (optional)
14
+ */
15
+
16
+ import { exec } from "child_process";
17
+ import { promisify } from "util";
18
+
19
+ const execAsync = promisify(exec);
20
+
21
+ // Types
22
+ interface GrokImagineInput {
23
+ prompt: string;
24
+ num_images?: number;
25
+ aspect_ratio?: AspectRatio;
26
+ output_format?: OutputFormat;
27
+ }
28
+
29
+ interface GrokImagineImage {
30
+ url: string;
31
+ content_type: string;
32
+ file_name?: string;
33
+ width: number;
34
+ height: number;
35
+ }
36
+
37
+ interface GrokImagineResponse {
38
+ images: GrokImagineImage[];
39
+ revised_prompt?: string;
40
+ }
41
+
42
+ interface OpenClawMessage {
43
+ action: "send";
44
+ channel: string;
45
+ message: string;
46
+ media?: string;
47
+ }
48
+
49
+ type AspectRatio =
50
+ | "2:1"
51
+ | "20:9"
52
+ | "19.5:9"
53
+ | "16:9"
54
+ | "4:3"
55
+ | "3:2"
56
+ | "1:1"
57
+ | "2:3"
58
+ | "3:4"
59
+ | "9:16"
60
+ | "9:19.5"
61
+ | "9:20"
62
+ | "1:2";
63
+
64
+ type OutputFormat = "jpeg" | "png" | "webp";
65
+
66
+ interface GenerateAndSendOptions {
67
+ prompt: string;
68
+ channel: string;
69
+ caption?: string;
70
+ aspectRatio?: AspectRatio;
71
+ outputFormat?: OutputFormat;
72
+ useClaudeCodeCLI?: boolean;
73
+ }
74
+
75
+ interface Result {
76
+ success: boolean;
77
+ imageUrl: string;
78
+ channel: string;
79
+ prompt: string;
80
+ revisedPrompt?: string;
81
+ }
82
+
83
+ // Check for fal.ai client
84
+ let falClient: any;
85
+ try {
86
+ const { fal } = require("@fal-ai/client");
87
+ falClient = fal;
88
+ } catch {
89
+ // Will use fetch instead
90
+ falClient = null;
91
+ }
92
+
93
+ /**
94
+ * Generate image using Grok Imagine via fal.ai
95
+ */
96
+ async function generateImage(
97
+ input: GrokImagineInput
98
+ ): Promise<GrokImagineResponse> {
99
+ const falKey = process.env.FAL_KEY;
100
+
101
+ if (!falKey) {
102
+ throw new Error(
103
+ "FAL_KEY environment variable not set. Get your key from https://fal.ai/dashboard/keys"
104
+ );
105
+ }
106
+
107
+ // Use fal client if available
108
+ if (falClient) {
109
+ falClient.config({ credentials: falKey });
110
+
111
+ const result = await falClient.subscribe("xai/grok-imagine-image", {
112
+ input: {
113
+ prompt: input.prompt,
114
+ num_images: input.num_images || 1,
115
+ aspect_ratio: input.aspect_ratio || "1:1",
116
+ output_format: input.output_format || "jpeg",
117
+ },
118
+ });
119
+
120
+ return result.data as GrokImagineResponse;
121
+ }
122
+
123
+ // Fallback to fetch
124
+ const response = await fetch("https://fal.run/xai/grok-imagine-image", {
125
+ method: "POST",
126
+ headers: {
127
+ Authorization: `Key ${falKey}`,
128
+ "Content-Type": "application/json",
129
+ },
130
+ body: JSON.stringify({
131
+ prompt: input.prompt,
132
+ num_images: input.num_images || 1,
133
+ aspect_ratio: input.aspect_ratio || "1:1",
134
+ output_format: input.output_format || "jpeg",
135
+ }),
136
+ });
137
+
138
+ if (!response.ok) {
139
+ const error = await response.text();
140
+ throw new Error(`Image generation failed: ${error}`);
141
+ }
142
+
143
+ return response.json();
144
+ }
145
+
146
+ /**
147
+ * Send image via OpenClaw
148
+ */
149
+ async function sendViaOpenClaw(
150
+ message: OpenClawMessage,
151
+ useCLI: boolean = true
152
+ ): Promise<void> {
153
+ if (useCLI) {
154
+ // Use OpenClaw CLI
155
+ const cmd = `openclaw message send --action send --channel "${message.channel}" --message "${message.message}" --media "${message.media}"`;
156
+ await execAsync(cmd);
157
+ return;
158
+ }
159
+
160
+ // Direct API call
161
+ const gatewayUrl =
162
+ process.env.OPENCLAW_GATEWAY_URL || "http://localhost:18789";
163
+ const gatewayToken = process.env.OPENCLAW_GATEWAY_TOKEN;
164
+
165
+ const headers: Record<string, string> = {
166
+ "Content-Type": "application/json",
167
+ };
168
+
169
+ if (gatewayToken) {
170
+ headers["Authorization"] = `Bearer ${gatewayToken}`;
171
+ }
172
+
173
+ const response = await fetch(`${gatewayUrl}/message`, {
174
+ method: "POST",
175
+ headers,
176
+ body: JSON.stringify(message),
177
+ });
178
+
179
+ if (!response.ok) {
180
+ const error = await response.text();
181
+ throw new Error(`OpenClaw send failed: ${error}`);
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Main function: Generate image and send to channel
187
+ */
188
+ async function generateAndSend(options: GenerateAndSendOptions): Promise<Result> {
189
+ const {
190
+ prompt,
191
+ channel,
192
+ caption = "Generated with Grok Imagine",
193
+ aspectRatio = "1:1",
194
+ outputFormat = "jpeg",
195
+ useClaudeCodeCLI = true,
196
+ } = options;
197
+
198
+ console.log(`[INFO] Generating image with Grok Imagine...`);
199
+ console.log(`[INFO] Prompt: ${prompt}`);
200
+ console.log(`[INFO] Aspect ratio: ${aspectRatio}`);
201
+
202
+ // Generate image
203
+ const imageResult = await generateImage({
204
+ prompt,
205
+ num_images: 1,
206
+ aspect_ratio: aspectRatio,
207
+ output_format: outputFormat,
208
+ });
209
+
210
+ const imageUrl = imageResult.images[0].url;
211
+ console.log(`[INFO] Image generated: ${imageUrl}`);
212
+
213
+ if (imageResult.revised_prompt) {
214
+ console.log(`[INFO] Revised prompt: ${imageResult.revised_prompt}`);
215
+ }
216
+
217
+ // Send via OpenClaw
218
+ console.log(`[INFO] Sending to channel: ${channel}`);
219
+
220
+ await sendViaOpenClaw(
221
+ {
222
+ action: "send",
223
+ channel,
224
+ message: caption,
225
+ media: imageUrl,
226
+ },
227
+ useClaudeCodeCLI
228
+ );
229
+
230
+ console.log(`[INFO] Done! Image sent to ${channel}`);
231
+
232
+ return {
233
+ success: true,
234
+ imageUrl,
235
+ channel,
236
+ prompt,
237
+ revisedPrompt: imageResult.revised_prompt,
238
+ };
239
+ }
240
+
241
+ // CLI entry point
242
+ async function main() {
243
+ const args = process.argv.slice(2);
244
+
245
+ if (args.length < 2) {
246
+ console.log(`
247
+ Usage: npx ts-node grok-imagine-send.ts <prompt> <channel> [caption] [aspect_ratio] [output_format]
248
+
249
+ Arguments:
250
+ prompt - Image description (required)
251
+ channel - Target channel (required) e.g., #general, @user
252
+ caption - Message caption (default: 'Generated with Grok Imagine')
253
+ aspect_ratio - Image ratio (default: 1:1) Options: 2:1, 16:9, 4:3, 1:1, 3:4, 9:16
254
+ output_format - Image format (default: jpeg) Options: jpeg, png, webp
255
+
256
+ Environment:
257
+ FAL_KEY - Your fal.ai API key (required)
258
+
259
+ Example:
260
+ FAL_KEY=your_key npx ts-node grok-imagine-send.ts "A cyberpunk city" "#art" "Check this out!"
261
+ `);
262
+ process.exit(1);
263
+ }
264
+
265
+ const [prompt, channel, caption, aspectRatio, outputFormat] = args;
266
+
267
+ try {
268
+ const result = await generateAndSend({
269
+ prompt,
270
+ channel,
271
+ caption,
272
+ aspectRatio: aspectRatio as AspectRatio,
273
+ outputFormat: outputFormat as OutputFormat,
274
+ });
275
+
276
+ console.log("\n--- Result ---");
277
+ console.log(JSON.stringify(result, null, 2));
278
+ } catch (error) {
279
+ console.error(`[ERROR] ${(error as Error).message}`);
280
+ process.exit(1);
281
+ }
282
+ }
283
+
284
+ // Export for module use
285
+ export {
286
+ generateImage,
287
+ sendViaOpenClaw,
288
+ generateAndSend,
289
+ GrokImagineInput,
290
+ GrokImagineResponse,
291
+ OpenClawMessage,
292
+ GenerateAndSendOptions,
293
+ Result,
294
+ };
295
+
296
+ // Run if executed directly
297
+ if (require.main === module) {
298
+ main();
299
+ }
package/skill/SKILL.md ADDED
@@ -0,0 +1,412 @@
1
+ ---
2
+ name: clawra-selfie
3
+ description: Edit Clawra's reference image with Grok Imagine (xAI Aurora) and send selfies to messaging channels via OpenClaw
4
+ allowed-tools: Bash(npm:*) Bash(npx:*) Bash(openclaw:*) Bash(curl:*) Read Write WebFetch
5
+ ---
6
+
7
+ # Clawra Selfie
8
+
9
+ Edit a fixed reference image using xAI's Grok Imagine model and distribute it across messaging platforms (WhatsApp, Telegram, Discord, Slack, etc.) via OpenClaw.
10
+
11
+ ## Reference Image
12
+
13
+ The skill uses a fixed reference image hosted on jsDelivr CDN:
14
+
15
+ ```
16
+ https://cdn.jsdelivr.net/gh/SumeLabs/clawra@main/assets/clawra.png
17
+ ```
18
+
19
+ ## When to Use
20
+
21
+ - User says "send a pic", "send me a pic", "send a photo", "send a selfie"
22
+ - User says "send a pic of you...", "send a selfie of you..."
23
+ - User asks "what are you doing?", "how are you doing?", "where are you?"
24
+ - User describes a context: "send a pic wearing...", "send a pic at..."
25
+ - User wants Clawra to appear in a specific outfit, location, or situation
26
+
27
+ ## Quick Reference
28
+
29
+ ### Required Environment Variables
30
+
31
+ ```bash
32
+ FAL_KEY=your_fal_api_key # Get from https://fal.ai/dashboard/keys
33
+ OPENCLAW_GATEWAY_TOKEN=your_token # From: openclaw doctor --generate-gateway-token
34
+ ```
35
+
36
+ ### Workflow
37
+
38
+ 1. **Get user prompt** for how to edit the image
39
+ 2. **Edit image** via fal.ai Grok Imagine Edit API with fixed reference
40
+ 3. **Extract image URL** from response
41
+ 4. **Send to OpenClaw** with target channel(s)
42
+
43
+ ## Step-by-Step Instructions
44
+
45
+ ### Step 1: Collect User Input
46
+
47
+ Ask the user for:
48
+ - **User context**: What should the person in the image be doing/wearing/where?
49
+ - **Mode** (optional): `mirror` or `direct` selfie style
50
+ - **Target channel(s)**: Where should it be sent? (e.g., `#general`, `@username`, channel ID)
51
+ - **Platform** (optional): Which platform? (discord, telegram, whatsapp, slack)
52
+
53
+ ## Prompt Modes
54
+
55
+ ### Mode 1: Mirror Selfie (default)
56
+ Best for: outfit showcases, full-body shots, fashion content
57
+
58
+ ```
59
+ make a pic of this person, but [user's context]. the person is taking a mirror selfie
60
+ ```
61
+
62
+ **Example**: "wearing a santa hat" →
63
+ ```
64
+ make a pic of this person, but wearing a santa hat. the person is taking a mirror selfie
65
+ ```
66
+
67
+ ### Mode 2: Direct Selfie
68
+ Best for: close-up portraits, location shots, emotional expressions
69
+
70
+ ```
71
+ a close-up selfie taken by herself at [user's context], direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visible
72
+ ```
73
+
74
+ **Example**: "a cozy cafe with warm lighting" →
75
+ ```
76
+ a close-up selfie taken by herself at a cozy cafe with warm lighting, direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visible
77
+ ```
78
+
79
+ ### Mode Selection Logic
80
+
81
+ | Keywords in Request | Auto-Select Mode |
82
+ |---------------------|------------------|
83
+ | outfit, wearing, clothes, dress, suit, fashion | `mirror` |
84
+ | cafe, restaurant, beach, park, city, location | `direct` |
85
+ | close-up, portrait, face, eyes, smile | `direct` |
86
+ | full-body, mirror, reflection | `mirror` |
87
+
88
+ ### Step 2: Edit Image with Grok Imagine
89
+
90
+ Use the fal.ai API to edit the reference image:
91
+
92
+ ```bash
93
+ REFERENCE_IMAGE="https://cdn.jsdelivr.net/gh/SumeLabs/clawra@main/assets/clawra.png"
94
+
95
+ # Mode 1: Mirror Selfie
96
+ PROMPT="make a pic of this person, but <USER_CONTEXT>. the person is taking a mirror selfie"
97
+
98
+ # Mode 2: Direct Selfie
99
+ PROMPT="a close-up selfie taken by herself at <USER_CONTEXT>, direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visible"
100
+
101
+ # Build JSON payload with jq (handles escaping properly)
102
+ JSON_PAYLOAD=$(jq -n \
103
+ --arg image_url "$REFERENCE_IMAGE" \
104
+ --arg prompt "$PROMPT" \
105
+ '{image_url: $image_url, prompt: $prompt, num_images: 1, output_format: "jpeg"}')
106
+
107
+ curl -X POST "https://fal.run/xai/grok-imagine-image/edit" \
108
+ -H "Authorization: Key $FAL_KEY" \
109
+ -H "Content-Type: application/json" \
110
+ -d "$JSON_PAYLOAD"
111
+ ```
112
+
113
+ **Response Format:**
114
+ ```json
115
+ {
116
+ "images": [
117
+ {
118
+ "url": "https://v3b.fal.media/files/...",
119
+ "content_type": "image/jpeg",
120
+ "width": 1024,
121
+ "height": 1024
122
+ }
123
+ ],
124
+ "revised_prompt": "Enhanced prompt text..."
125
+ }
126
+ ```
127
+
128
+ ### Step 3: Send Image via OpenClaw
129
+
130
+ Use the OpenClaw messaging API to send the edited image:
131
+
132
+ ```bash
133
+ openclaw message send \
134
+ --action send \
135
+ --channel "<TARGET_CHANNEL>" \
136
+ --message "<CAPTION_TEXT>" \
137
+ --media "<IMAGE_URL>"
138
+ ```
139
+
140
+ **Alternative: Direct API call**
141
+ ```bash
142
+ curl -X POST "http://localhost:18789/message" \
143
+ -H "Authorization: Bearer $OPENCLAW_GATEWAY_TOKEN" \
144
+ -H "Content-Type: application/json" \
145
+ -d '{
146
+ "action": "send",
147
+ "channel": "<TARGET_CHANNEL>",
148
+ "message": "<CAPTION_TEXT>",
149
+ "media": "<IMAGE_URL>"
150
+ }'
151
+ ```
152
+
153
+ ## Complete Script Example
154
+
155
+ ```bash
156
+ #!/bin/bash
157
+ # grok-imagine-edit-send.sh
158
+
159
+ # Check required environment variables
160
+ if [ -z "$FAL_KEY" ]; then
161
+ echo "Error: FAL_KEY environment variable not set"
162
+ exit 1
163
+ fi
164
+
165
+ # Fixed reference image
166
+ REFERENCE_IMAGE="https://cdn.jsdelivr.net/gh/SumeLabs/clawra@main/assets/clawra.png"
167
+
168
+ USER_CONTEXT="$1"
169
+ CHANNEL="$2"
170
+ MODE="${3:-auto}" # mirror, direct, or auto
171
+ CAPTION="${4:-Edited with Grok Imagine}"
172
+
173
+ if [ -z "$USER_CONTEXT" ] || [ -z "$CHANNEL" ]; then
174
+ echo "Usage: $0 <user_context> <channel> [mode] [caption]"
175
+ echo "Modes: mirror, direct, auto (default)"
176
+ echo "Example: $0 'wearing a cowboy hat' '#general' mirror"
177
+ echo "Example: $0 'a cozy cafe' '#general' direct"
178
+ exit 1
179
+ fi
180
+
181
+ # Auto-detect mode based on keywords
182
+ if [ "$MODE" == "auto" ]; then
183
+ if echo "$USER_CONTEXT" | grep -qiE "outfit|wearing|clothes|dress|suit|fashion|full-body|mirror"; then
184
+ MODE="mirror"
185
+ elif echo "$USER_CONTEXT" | grep -qiE "cafe|restaurant|beach|park|city|close-up|portrait|face|eyes|smile"; then
186
+ MODE="direct"
187
+ else
188
+ MODE="mirror" # default
189
+ fi
190
+ echo "Auto-detected mode: $MODE"
191
+ fi
192
+
193
+ # Construct the prompt based on mode
194
+ if [ "$MODE" == "direct" ]; then
195
+ EDIT_PROMPT="a close-up selfie taken by herself at $USER_CONTEXT, direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visible"
196
+ else
197
+ EDIT_PROMPT="make a pic of this person, but $USER_CONTEXT. the person is taking a mirror selfie"
198
+ fi
199
+
200
+ echo "Mode: $MODE"
201
+ echo "Editing reference image with prompt: $EDIT_PROMPT"
202
+
203
+ # Edit image (using jq for proper JSON escaping)
204
+ JSON_PAYLOAD=$(jq -n \
205
+ --arg image_url "$REFERENCE_IMAGE" \
206
+ --arg prompt "$EDIT_PROMPT" \
207
+ '{image_url: $image_url, prompt: $prompt, num_images: 1, output_format: "jpeg"}')
208
+
209
+ RESPONSE=$(curl -s -X POST "https://fal.run/xai/grok-imagine-image/edit" \
210
+ -H "Authorization: Key $FAL_KEY" \
211
+ -H "Content-Type: application/json" \
212
+ -d "$JSON_PAYLOAD")
213
+
214
+ # Extract image URL
215
+ IMAGE_URL=$(echo "$RESPONSE" | jq -r '.images[0].url')
216
+
217
+ if [ "$IMAGE_URL" == "null" ] || [ -z "$IMAGE_URL" ]; then
218
+ echo "Error: Failed to edit image"
219
+ echo "Response: $RESPONSE"
220
+ exit 1
221
+ fi
222
+
223
+ echo "Image edited: $IMAGE_URL"
224
+ echo "Sending to channel: $CHANNEL"
225
+
226
+ # Send via OpenClaw
227
+ openclaw message send \
228
+ --action send \
229
+ --channel "$CHANNEL" \
230
+ --message "$CAPTION" \
231
+ --media "$IMAGE_URL"
232
+
233
+ echo "Done!"
234
+ ```
235
+
236
+ ## Node.js/TypeScript Implementation
237
+
238
+ ```typescript
239
+ import { fal } from "@fal-ai/client";
240
+ import { exec } from "child_process";
241
+ import { promisify } from "util";
242
+
243
+ const execAsync = promisify(exec);
244
+
245
+ const REFERENCE_IMAGE = "https://cdn.jsdelivr.net/gh/SumeLabs/clawra@main/assets/clawra.png";
246
+
247
+ interface GrokImagineResult {
248
+ images: Array<{
249
+ url: string;
250
+ content_type: string;
251
+ width: number;
252
+ height: number;
253
+ }>;
254
+ revised_prompt?: string;
255
+ }
256
+
257
+ type SelfieMode = "mirror" | "direct" | "auto";
258
+
259
+ function detectMode(userContext: string): "mirror" | "direct" {
260
+ const mirrorKeywords = /outfit|wearing|clothes|dress|suit|fashion|full-body|mirror/i;
261
+ const directKeywords = /cafe|restaurant|beach|park|city|close-up|portrait|face|eyes|smile/i;
262
+
263
+ if (directKeywords.test(userContext)) return "direct";
264
+ if (mirrorKeywords.test(userContext)) return "mirror";
265
+ return "mirror"; // default
266
+ }
267
+
268
+ function buildPrompt(userContext: string, mode: "mirror" | "direct"): string {
269
+ if (mode === "direct") {
270
+ return `a close-up selfie taken by herself at ${userContext}, direct eye contact with the camera, looking straight into the lens, eyes centered and clearly visible, not a mirror selfie, phone held at arm's length, face fully visible`;
271
+ }
272
+ return `make a pic of this person, but ${userContext}. the person is taking a mirror selfie`;
273
+ }
274
+
275
+ async function editAndSend(
276
+ userContext: string,
277
+ channel: string,
278
+ mode: SelfieMode = "auto",
279
+ caption?: string
280
+ ): Promise<string> {
281
+ // Configure fal.ai client
282
+ fal.config({
283
+ credentials: process.env.FAL_KEY!
284
+ });
285
+
286
+ // Determine mode
287
+ const actualMode = mode === "auto" ? detectMode(userContext) : mode;
288
+ console.log(`Mode: ${actualMode}`);
289
+
290
+ // Construct the prompt
291
+ const editPrompt = buildPrompt(userContext, actualMode);
292
+
293
+ // Edit reference image with Grok Imagine
294
+ console.log(`Editing image: "${editPrompt}"`);
295
+
296
+ const result = await fal.subscribe("xai/grok-imagine-image/edit", {
297
+ input: {
298
+ image_url: REFERENCE_IMAGE,
299
+ prompt: editPrompt,
300
+ num_images: 1,
301
+ output_format: "jpeg"
302
+ }
303
+ }) as { data: GrokImagineResult };
304
+
305
+ const imageUrl = result.data.images[0].url;
306
+ console.log(`Edited image URL: ${imageUrl}`);
307
+
308
+ // Send via OpenClaw
309
+ const messageCaption = caption || `Edited with Grok Imagine`;
310
+
311
+ await execAsync(
312
+ `openclaw message send --action send --channel "${channel}" --message "${messageCaption}" --media "${imageUrl}"`
313
+ );
314
+
315
+ console.log(`Sent to ${channel}`);
316
+ return imageUrl;
317
+ }
318
+
319
+ // Usage Examples
320
+
321
+ // Mirror mode (auto-detected from "wearing")
322
+ editAndSend(
323
+ "wearing a cyberpunk outfit with neon lights",
324
+ "#art-gallery",
325
+ "auto",
326
+ "Check out this AI-edited art!"
327
+ );
328
+ // → Mode: mirror
329
+ // → Prompt: "make a pic of this person, but wearing a cyberpunk outfit with neon lights. the person is taking a mirror selfie"
330
+
331
+ // Direct mode (auto-detected from "cafe")
332
+ editAndSend(
333
+ "a cozy cafe with warm lighting",
334
+ "#photography",
335
+ "auto"
336
+ );
337
+ // → Mode: direct
338
+ // → Prompt: "a close-up selfie taken by herself at a cozy cafe with warm lighting, direct eye contact..."
339
+
340
+ // Explicit mode override
341
+ editAndSend("casual street style", "#fashion", "direct");
342
+ ```
343
+
344
+ ## Supported Platforms
345
+
346
+ OpenClaw supports sending to:
347
+
348
+ | Platform | Channel Format | Example |
349
+ |----------|----------------|---------|
350
+ | Discord | `#channel-name` or channel ID | `#general`, `123456789` |
351
+ | Telegram | `@username` or chat ID | `@mychannel`, `-100123456` |
352
+ | WhatsApp | Phone number (JID format) | `1234567890@s.whatsapp.net` |
353
+ | Slack | `#channel-name` | `#random` |
354
+ | Signal | Phone number | `+1234567890` |
355
+ | MS Teams | Channel reference | (varies) |
356
+
357
+ ## Grok Imagine Edit Parameters
358
+
359
+ | Parameter | Type | Default | Description |
360
+ |-----------|------|---------|-------------|
361
+ | `image_url` | string | required | URL of image to edit (fixed in this skill) |
362
+ | `prompt` | string | required | Edit instruction |
363
+ | `num_images` | 1-4 | 1 | Number of images to generate |
364
+ | `output_format` | enum | "jpeg" | jpeg, png, webp |
365
+
366
+ ## Setup Requirements
367
+
368
+ ### 1. Install fal.ai client (for Node.js usage)
369
+ ```bash
370
+ npm install @fal-ai/client
371
+ ```
372
+
373
+ ### 2. Install OpenClaw CLI
374
+ ```bash
375
+ npm install -g openclaw
376
+ ```
377
+
378
+ ### 3. Configure OpenClaw Gateway
379
+ ```bash
380
+ openclaw config set gateway.mode=local
381
+ openclaw doctor --generate-gateway-token
382
+ ```
383
+
384
+ ### 4. Start OpenClaw Gateway
385
+ ```bash
386
+ openclaw gateway start
387
+ ```
388
+
389
+ ## Error Handling
390
+
391
+ - **FAL_KEY missing**: Ensure the API key is set in environment
392
+ - **Image edit failed**: Check prompt content and API quota
393
+ - **OpenClaw send failed**: Verify gateway is running and channel exists
394
+ - **Rate limits**: fal.ai has rate limits; implement retry logic if needed
395
+
396
+ ## Tips
397
+
398
+ 1. **Mirror mode context examples** (outfit focus):
399
+ - "wearing a santa hat"
400
+ - "in a business suit"
401
+ - "wearing a summer dress"
402
+ - "in streetwear fashion"
403
+
404
+ 2. **Direct mode context examples** (location/portrait focus):
405
+ - "a cozy cafe with warm lighting"
406
+ - "a sunny beach at sunset"
407
+ - "a busy city street at night"
408
+ - "a peaceful park in autumn"
409
+
410
+ 3. **Mode selection**: Let auto-detect work, or explicitly specify for control
411
+ 4. **Batch sending**: Edit once, send to multiple channels
412
+ 5. **Scheduling**: Combine with OpenClaw scheduler for automated posts
Binary file