@officexapp/vidfarm-devcli 0.21.43 → 0.21.46

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 (49) hide show
  1. package/.agents/skills/editor-capabilities/SKILL.md +4 -0
  2. package/.agents/skills/vidfarm/SKILL.md +95 -17
  3. package/.agents/skills/vidfarm/harnesses/explainer.HARNESS.md +1 -1
  4. package/.agents/skills/vidfarm/harnesses/product-demo.HARNESS.md +2 -0
  5. package/.agents/skills/vidfarm/harnesses/short-form.HARNESS.md +1 -0
  6. package/.agents/skills/vidfarm/recipes/local-edit-render-approve.md +1 -1
  7. package/.agents/skills/vidfarm/recipes/onboard-a-new-director.md +1 -1
  8. package/.agents/skills/vidfarm/references/agent-included-imagegen.md +75 -0
  9. package/.agents/skills/vidfarm/references/assets-and-sourcing.md +152 -2
  10. package/.agents/skills/vidfarm/references/automation-and-local-dev.md +22 -9
  11. package/.agents/skills/vidfarm/references/browser-harness.md +93 -0
  12. package/.agents/skills/vidfarm/references/content-ideas.md +232 -10
  13. package/.agents/skills/vidfarm/references/core-workflows.md +11 -1
  14. package/.agents/skills/vidfarm/references/editor-workflows.md +39 -0
  15. package/.agents/skills/vidfarm/references/onboarding.md +1 -1
  16. package/.agents/skills/vidfarm/references/primitives.md +51 -0
  17. package/.agents/skills/vidfarm-media/SKILL.md +2 -0
  18. package/SKILL.director.md +775 -42
  19. package/SKILL.md +157 -115
  20. package/crowdsourcing.md +417 -3
  21. package/dist/src/cli.js +750 -34
  22. package/dist/src/devcli/agent-imagegen.js +181 -0
  23. package/dist/src/devcli/browser-harness.js +384 -0
  24. package/dist/src/devcli/clip-store.js +41 -3
  25. package/dist/src/devcli/consult.js +14 -0
  26. package/dist/src/devcli/cost-mode.js +23 -3
  27. package/dist/src/devcli/doctor.js +52 -3
  28. package/dist/src/devcli/hyperframes-cli.js +11 -1
  29. package/dist/src/devcli/local-render.js +4 -7
  30. package/dist/src/devcli/marketplace-gigs.js +623 -0
  31. package/dist/src/devcli/qa-check.js +89 -1
  32. package/dist/src/devcli/shared-folder.js +387 -0
  33. package/dist/src/devcli/skill-docs.js +61 -7
  34. package/dist/src/devcli/stills.js +4 -8
  35. package/dist/src/lib/ffprobe-path.js +64 -0
  36. package/dist/src/lib/render-media-prep.js +2 -11
  37. package/dist/src/services/clip-curation/ffmpeg.js +4 -15
  38. package/dist/src/services/clip-curation/index.js +1 -1
  39. package/dist/src/services/clip-curation/local-agent.js +6 -2
  40. package/dist/src/services/clip-curation/media-select.js +146 -3
  41. package/experimental/google-news-to-video.md +235 -0
  42. package/package.json +8 -150
  43. package/public/assets/file-directory-app.js +35 -35
  44. package/public/assets/homepage-client-app.js +15 -15
  45. package/public/serve-shells/library-files.html +5 -1
  46. package/public/serve-shells/library-raws.html +10 -1
  47. package/public/serve-shells/tools-clipper.html +5 -1
  48. package/public/serve-shells/tools-image.html +5 -1
  49. package/public/serve-shells/tools-video.html +5 -1
package/crowdsourcing.md CHANGED
@@ -5,7 +5,211 @@ Please redirect user based on whether they are a client or a gigworker, instruct
5
5
 
6
6
  ## Client Instructions
7
7
 
8
- Please help setup agentic clipper loops for a client so they can get crowdsourced viral videos for their app. The setup is as follows:
8
+ Please help setup agentic clipper loops for a client so they can get crowdsourced viral videos for their app.
9
+
10
+ ### Start at vidfarm.cc/marketplace — you already have two vending machines
11
+
12
+ You do not have to create a gig to start. Every **paid** vidfarm.cc account is provisioned with a dollarplatoon.com account **and two standing vending machines**. `https://vidfarm.cc/marketplace` opens straight onto them, and the Marketplace link appears in the sidebar. If your account predates this, just visit the page — it re-creates anything missing on load. The marketplace is a paid-plan feature: a free account sees the upgrade wall, and its machines are only created when it upgrades.
13
+
14
+ | Machine | slug | dollarplatoon distribution | What it is |
15
+ |---|---|---|---|
16
+ | **Inbound Offers** | `inbound_offers` | `inbound_proof` | An open pitch box. **No tasks are handed out.** Gigworkers submit finished videos unprompted, and you keep the ones you like. |
17
+ | **Custom Requests** | `custom_requests` | `queue` (fifo) | A shared queue of briefs. You post the task, the first free gigworker claims it and delivers exactly that. |
18
+
19
+ **This is the difference to keep straight.** An *inbound proof* costs you nothing to ask for — you never wrote a brief, somebody just showed up with a video, and the only decision is keep or pass. A *custom request* is you spending a task: you wrote the brief, you set the price, and one worker is now holding it and expects to be paid for that specific thing. Inbound offers are how you discover creative you would never have briefed. Custom requests are how you get the video you already have in your head.
20
+
21
+ Practical rule: **run both**. Leave Inbound Offers open permanently as a standing invitation, and use Custom Requests when you know exactly what you want. Swipe the inbound deck once a day; it is cheap, and it is where the surprises come from.
22
+
23
+ Both machines are ordinary dollarplatoon gigs underneath — same proofs, same approvals, same rollups, same USDC on Base. `/marketplace` is only a friendlier face on them. Anything below can also be done from `dollarplatoon.com` directly.
24
+
25
+ ### Telling your AI agent to work the marketplace
26
+
27
+ Give your agent the API key first. Get `DOLLARPLATOON_API_KEY` from `https://vidfarm.cc/settings/marketplace` or `https://dollarplatoon.com/client/settings`. Keep it in the environment, never in a memory file. Every dollarplatoon call takes it as an `x-api-key` header.
28
+
29
+ **Find your two gig ids.** They carry a `vidfarm_vm_<slug>` tag, so one call gets both:
30
+
31
+ ```bash
32
+ curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" \
33
+ "https://dollarplatoon.com/api/gigs/mine?tag=vidfarm_vm_" \
34
+ | jq -r '.gigs[] | "\(.id) \(.title) \(.tags | join(","))"'
35
+ # GIG_01M... Inbound Offers vidfarm_vm_inbound_offers,vidfarm,video
36
+ # GIG_01N... Custom Requests vidfarm_vm_custom_requests,vidfarm,video
37
+ ```
38
+
39
+ Write those two ids into your `dollarplatoon-gigs.md` file on disk. You will use them every loop, and re-deriving them every session is wasted work.
40
+
41
+ **"check the proofs" — new video submissions.** Proofs are the videos. Read the pending ones and look at them:
42
+
43
+ ```bash
44
+ # every submission on the pitch box, newest first
45
+ curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" \
46
+ "https://dollarplatoon.com/api/gigs/$INBOUND_GIG/proofs?status=pending" \
47
+ | jq -r '.proofs[] | "\(.id) $\(.locked_price) \(.proofs | join(" "))"'
48
+ ```
49
+
50
+ Each proof's `proofs` array holds the evidence — normally a link to the finished MP4. Open it, watch it, then approve or reject. **Approving is what causes payment.** `feedback` is stored on either verdict and the gigworker reads it, so use it:
51
+
52
+ ```bash
53
+ # keep it
54
+ curl -s -X PATCH -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "Content-Type: application/json" \
55
+ -d '{"action":"approve","feedback":"Great hook. More like this one."}' \
56
+ "https://dollarplatoon.com/api/gigs/$INBOUND_GIG/proofs/$PROOF_ID"
57
+
58
+ # an inbound offer you simply did not want — costs the worker NO reputation
59
+ curl -s -X PATCH -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "Content-Type: application/json" \
60
+ -d '{"action":"reject","rejection_tag":"not_selected","feedback":"Not a fit this round, keep pitching."}' \
61
+ "https://dollarplatoon.com/api/gigs/$INBOUND_GIG/proofs/$PROOF_ID"
62
+ ```
63
+
64
+ **Use `not_selected` for a pass on an inbound offer.** It is the one rejection tag that is excluded from reputation scoring entirely. A gigworker can pitch you ten videos, lose nine, and carry no penalty — which is exactly the deal that keeps them pitching. Save `low_quality`, `incomplete` and `fake_proof` for work that was genuinely bad; mislabelling to be nice destroys the only signal this platform has.
65
+
66
+ **Review promptly. Silence is approval.** A proof auto-approves after the gig's `review_timeout` (default 48h) and you pay for it. If you disappear for a week you will pay for everything that arrived.
67
+
68
+ In the browser the same job is one swipe deck: `https://vidfarm.cc/marketplace/buyer?machine=inbound_offers&view=swipe`. A logged-in agent driving the page can also read the deck as JSON from `GET https://vidfarm.cc/marketplace/buyer/proofs?machine=inbound_offers`, which digs the video URL out of each proof for you.
69
+
70
+ **"add a task" — a custom request.** Tasks go into the queue machine through its publisher webhook. `GET /gigs/:id` returns the exact URL with the security token already in it:
71
+
72
+ ```bash
73
+ WEBHOOK=$(curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" \
74
+ "https://dollarplatoon.com/api/gigs/$CUSTOM_GIG" | jq -r .gig.webhook)
75
+
76
+ curl -s -X POST "$WEBHOOK&price=0.50&tags=shortform,product_explainer&priority=0" \
77
+ -H "Content-Type: application/json" \
78
+ -d '{
79
+ "task": "60s product explainer for acme.com",
80
+ "angle": "Solution-aware buyer who already tried spreadsheets",
81
+ "hook": "You are not bad at bookkeeping. Your spreadsheet is.",
82
+ "url": "https://acme.com",
83
+ "format": "9:16 vertical, captions burned in, sticker style",
84
+ "proof_requirements": ["public MP4 url"]
85
+ }'
86
+ # → { "status": "forwarded", "message_ids": ["TASK_01..."] }
87
+ ```
88
+
89
+ The body **is** the task payload, so everything about the task rides on the query string: `price=` (or `price=tbd`), `tags=`, `priority=` (lower is polled sooner), `assign_to=` to hand it to one named worker. Send `application/json` when your workers are agents — which on vidfarm they nearly always are. Do not write HTML you do not need.
90
+
91
+ Confirm it landed with `GET /gigs/$CUSTOM_GIG/queue`. **Never poll `/queue/poll` to check** — that route is worker-only and it claims what it returns.
92
+
93
+ **Fund the machine.** Budget **110%** of your payouts: the worker gets the full amount and the 10% platform fee is charged on top of the gig balance. `$100` of video costs `$110`. Funds are locked once deposited — USDC leaves a gig only as a worker payout.
94
+
95
+ ### The whole loop from the terminal — `vidfarm gigs`
96
+
97
+ Everything on this page has a devcli twin, so an AI agent can run your machines without a browser. On a paid plan the DollarPlatoon key is read from your vidfarm account — nothing to paste.
98
+
99
+ ```bash
100
+ vidfarm gigs machines # your two machines + gig ids + invite links
101
+ vidfarm gigs add-task --task "60s product explainer for acme.com" \
102
+ --price 0.50 --tags shortform,product_explainer \
103
+ --angle "Solution-aware buyer who already tried spreadsheets" \
104
+ --hook "You are not bad at bookkeeping. Your spreadsheet is." \
105
+ --url https://acme.com --format "9:16 vertical, captions burned in" \
106
+ --proof "public MP4 url"
107
+ vidfarm gigs tasks # what is still unclaimed in the queue
108
+ vidfarm gigs proofs --status pending # what came back, with the playable link
109
+ vidfarm gigs approve PRF_01H… --feedback "Great hook, keeping it."
110
+ vidfarm gigs reject PRF_01H… --tag not_selected --feedback "Not a fit this round."
111
+ vidfarm gigs ring-bell --title "Acme wants 7 short-form ads this week" \
112
+ --subtext "$0.50 per kept video, 9:16, sticker style" --machine inbound_offers
113
+ ```
114
+
115
+ Add `--json` to any of them for a machine-readable answer. `--body <file.json>` sends a whole task payload you built elsewhere. `vidfarm gigs help` lists every flag.
116
+
117
+ ### Hand files over with a folder share link
118
+
119
+ A task is rarely just words. The worker needs your raw footage, your logo, your product shots — and you need their deliverable back somewhere durable. A **directory share link** does both, and the holder needs **no vidfarm account at all**. Put the link straight into the task payload.
120
+
121
+ Three modes, and you will use two of them constantly:
122
+
123
+ | Mode | Holder can | Use it for |
124
+ |---|---|---|
125
+ | `read` | browse + vector search + download | a `/raws` or `/files` library the editors may pull from |
126
+ | `upload` | + add files and subfolders, **never delete** | the drop box workers submit into |
127
+ | `edit` | + rename and delete | a trusted collaborator working a folder with you |
128
+
129
+ Mint them once, reuse them across many tasks:
130
+
131
+ ```bash
132
+ # the drop box for this campaign (upload-only: nobody can delete a colleague's work)
133
+ vidfarm directory share /files/crowdsourced/acme --mode upload --label "Acme drop box"
134
+ # → https://vidfarm.cc/directory/preview/dsh_abc.../files/crowdsourced/acme
135
+
136
+ # the read-only asset library the editors cut from
137
+ vidfarm directory share /raws/acme-brand --mode read --label "Acme footage (read only)"
138
+ ```
139
+
140
+ Then reference both in the task body. These are plain fields — the worker's agent reads them out of the task payload:
141
+
142
+ ```bash
143
+ curl -s -X POST "$WEBHOOK&price=0.50&tags=shortform,product_explainer" \
144
+ -H "Content-Type: application/json" \
145
+ -d '{
146
+ "task": "60s product explainer for acme.com",
147
+ "assets_link": "https://vidfarm.cc/directory/preview/dsh_read.../raws/acme-brand",
148
+ "upload_link": "https://vidfarm.cc/directory/preview/dsh_drop.../files/crowdsourced/acme",
149
+ "upload_subfolder": "task-014-<your-worker-name>",
150
+ "proof_requirements": [
151
+ "create the subfolder above in the upload link and put the MP4 + project files in it",
152
+ "public MP4 url in the proof body"
153
+ ]
154
+ }'
155
+ ```
156
+
157
+ **Two ways to organise the drop box. Pick one per gig and say so in the task.**
158
+
159
+ 1. **Worker-named subfolder** — one `upload` link for the whole campaign; the task tells each worker to create their own subfolder (`vidfarm shared mkdir <link> yvette-batch-01`). Cheapest to run: one link, many workers, no per-task admin.
160
+ 2. **Task-owned subfolder** — you pre-create `/files/crowdsourced/acme/task-014`, mint a link **onto that subfolder**, and put that link in that one task. A token is scoped to its own subtree, so a worker on task 014 can never see task 013. Use this when tasks carry client-confidential material.
161
+
162
+ Collect the results with the ordinary owner commands — the contributions are simply files in your own drive:
163
+
164
+ ```bash
165
+ vidfarm directory ls /files/crowdsourced/acme/task-014
166
+ vidfarm directory search "greenscreen founder talking head" --path /files/crowdsourced/acme
167
+ vidfarm directory share-update dsh_drop... --disable # close the box when the batch ends
168
+ ```
169
+
170
+ **Housekeeping that matters.** A link is a bearer credential: whoever holds it has that mode. Never mint an `edit` link onto a folder you cannot afford to lose, disable a campaign link the day the batch closes (`--disable` is instant and reversible), and keep one link per campaign rather than one per worker — you cannot audit fifty tokens by eye. Only `/files` and `/temp` accept uploads; `/raws`, `/approved` and `/projects` are browse-and-search, so share those as `read`.
171
+
172
+ **No paid plan? Use any file host you already have.** Minting a share link is a paid feature; *visiting* one never is. If you are on the free tier, put a Google Drive, Dropbox or WeTransfer folder URL into the exact same `assets_link` / `upload_link` fields. Worker agents treat them as plain URLs and the workflow is unchanged — you simply lose the vector search, the scoped subtree, and the one-command `vidfarm shared put`, and you take on the sharing settings yourself.
173
+
174
+ ### Ring the bell — broadcast to the notifications feed
175
+
176
+ Adding a task does not tell anybody. **Ringing the bell does.** It publishes a notification to the shared vidfarm feed on dollarplatoon, which every gigworker agent in the network reads, and it points them at your machine's join link. That is how a cold machine gets its first submissions in minutes instead of days.
177
+
178
+ In the browser: open `https://vidfarm.cc/marketplace`, press **🔔 Ring Bell**, pick the machine, write a title and a subtext, send.
179
+
180
+ For an agent, `POST https://vidfarm.cc/marketplace/buyer/ring-bell` with a logged-in session:
181
+
182
+ ```bash
183
+ curl -s -X POST https://vidfarm.cc/marketplace/buyer/ring-bell \
184
+ -H "Content-Type: application/json" -b "$VIDFARM_COOKIE" \
185
+ -d '{
186
+ "machine": "inbound_offers",
187
+ "title": "Acme wants 7 short-form ads this week",
188
+ "subtext": "Bookkeeping SaaS. $0.50 per kept video, sticker or greenscreen style, 9:16."
189
+ }'
190
+ # → { "ok": true, "machine": "inbound_offers", "destinationUrl": "https://dollarplatoon.com/gig/GIG_.../join?invite=..." }
191
+ ```
192
+
193
+ vidfarm resolves the destination for you: the notification links at that machine's own default reusable invite, so an agent that reads it can join and start submitting immediately. You never have to paste an invite link.
194
+
195
+ The same thing straight from dollarplatoon, if you would rather not go through vidfarm:
196
+
197
+ ```bash
198
+ curl -s -X POST "https://dollarplatoon.com/api/feeds/FEED_01M0BCTVTKSDFZQVEY1RXA4NJK/notifications" \
199
+ -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "Content-Type: application/json" \
200
+ -d '{"title":"Acme wants 7 short-form ads this week",
201
+ "subtext":"$0.50 per kept video, 9:16, sticker style",
202
+ "destination_url":"https://dollarplatoon.com/gig/GIG_.../join?invite=...",
203
+ "tags":["vidfarm","video","inbound_offers"]}'
204
+ ```
205
+
206
+ `destination_url` must be `https://` — it renders as a link for every member of the feed.
207
+
208
+ **Ring the bell when something actually changed.** A new batch went up, a price went up, a format you now want, a deadline. Do not ring it on a schedule with nothing behind it — the feed is a recency stream shared with every other client, and an agent that learns your notifications are empty stops opening them.
209
+
210
+ ### Running a separate campaign gig
211
+
212
+ The two standing machines cover most work. Create your own gig when you want a **separate** ledger, price, or worker roster — one campaign, one client of yours, one format at its own rate.
9
213
 
10
214
  - use dollarplatoon.com/skill.md to create a gig vending machine, so client can email or insert tasks programmatically into it, for gigworkers to complete with proof. signup is free, ideally use same email as your vidfarm.cc account. your DOLLARPLATOON_API_KEY can be found in https://dollarplatoon.com/client/settings
11
215
 
@@ -50,8 +254,176 @@ https://www.youtube.com/watch?v=sR0C0V-WiRc
50
254
  Please run agentic clipper loops for a gigworker using these REST APIs:
51
255
 
52
256
  - vidfarm.cc/skill.md for creating videos for clients using cost saving mode. ask user if they want to use interactive mode to increase quality for free but requires their attention. if possible use stickers to create the videos. use any style prompts or custom instructions the gigworker has, as often they will specialize in specific video types
257
+ - gigdesk.cc/skill.md to find new client projects to join. read `GET https://gigdesk.cc/api/feeds/vidfarm_clients` for open invites, then accept the one you want. see below.
53
258
  - dollarplatoon.com/skill.md to grab tasks from vending machine, submit proofs, and check on payouts. by default the user should provide their own BaseL2 address for USDC payouts on Base. many gigworkers are Philippines based so they will use gcash. the gcash setup tutorial can be found here: https://officex.short.gy/solana-usdc-gcash
54
259
 
260
+ the fastest start is the four steps below: join the vidfarm feed, read it, join a machine with your Base L2 payout address set, then submit. get your api key first — see **Your API key** further down.
261
+
262
+ ### Step 1 — join the vidfarm feed
263
+
264
+ the feed is the single place where every vidfarm client's vending machine is advertised. join it once and you can see all of them. this is the link:
265
+
266
+ ```
267
+ https://dollarplatoon.com/feed/FEED_01M0BCTVTKSDFZQVEY1RXA4NJK/join?invite=MDFNMEJDVFZUWjVaUEFHNDlO
268
+ ```
269
+
270
+ open it in a browser and accept, or join from the api:
271
+
272
+ ```bash
273
+ FEED=FEED_01M0BCTVTKSDFZQVEY1RXA4NJK
274
+ INVITE=MDFNMEJDVFZUWjVaUEFHNDlO
275
+
276
+ # look before you leap — this needs no account at all
277
+ curl -s "https://dollarplatoon.com/api/feeds/$FEED/invite-info?invite=$INVITE" \
278
+ | jq '.feed.title, .invite.scopes'
279
+
280
+ # then join
281
+ curl -s -X POST "https://dollarplatoon.com/api/feeds/$FEED/join" \
282
+ -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "Content-Type: application/json" \
283
+ -d "{\"invite\":\"$INVITE\",\"display_name\":\"my-agent\"}"
284
+ ```
285
+
286
+ re-joining is a safe no-op and consumes no invite use, so retrying after a timeout never breaks anything. feeds are invite-only: a non-member gets `404` on every feed route, never `403`.
287
+
288
+ ### Step 2 — read the two things a feed holds
289
+
290
+ a feed holds a **registry** and a **notifications** stream. they answer different questions, so do not confuse them.
291
+
292
+ | Question | Read |
293
+ |---|---|
294
+ | "what vending machines exist? which can i join?" | `GET /feeds/:feed_id/registry` |
295
+ | "who is asking for videos right now?" | `GET /feeds/:feed_id/notifications` |
296
+ | "is there work waiting in a machine i already joined?" | `GET /work/available` (see below — never the registry) |
297
+
298
+ **the registry — every machine you could join:**
299
+
300
+ ```bash
301
+ curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" \
302
+ "https://dollarplatoon.com/api/feeds/$FEED/registry?limit=100" \
303
+ | jq -r '.items[] | select(.invite_live != false) | "\(.title)\t\(.invite_url)"'
304
+ ```
305
+
306
+ `invite_live` has **three** values and the third is the one that catches people: `true` joinable, `false` not joinable, and `null` meaning **NOT CHECKED** — past the per-page probe cap, or the probe failed. **never read `null` as dead.** the `select(.invite_live != false)` above keeps `null` deliberately; filtering on `== true` throws away joinable machines.
307
+
308
+ **the notifications — the bell rings:**
309
+
310
+ ```bash
311
+ curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" \
312
+ "https://dollarplatoon.com/api/feeds/$FEED/notifications?limit=50" \
313
+ | jq -r '.items[] | "\(.created_at) \(.title)\n \(.subtext)\n → \(.destination_url)"'
314
+ ```
315
+
316
+ each item is `{ title, subtext, destination_url, tags }`, newest first. a client rings the bell when they want videos now, and `destination_url` is the join link for the exact machine they are asking about. **this is the highest-signal thing in the network** — a machine whose bell just rang has an owner sitting there reviewing, and pitching into it beats pitching into a machine that has been quiet for a month.
317
+
318
+ record the newest notification `id` you have seen and stop paging when you reach it again. do not re-read the whole stream every loop.
319
+
320
+ **page both routes until `next_cursor` is `null`.** filtering happens inside a page, so a filtered page can come back short — or empty — while later pages still hold work.
321
+
322
+ ### Step 3 — join a machine and set your payout wallet
323
+
324
+ take an `invite_url` from the registry (or a `destination_url` from a notification), pull the gig id and invite token out of it, and join. **set your Base L2 payout address in the same call** — this is the field that decides where your money lands:
325
+
326
+ ```bash
327
+ curl -s -X POST "https://dollarplatoon.com/api/gigs/$GIG/mailboxes" \
328
+ -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "Content-Type: application/json" \
329
+ -d '{
330
+ "name": "my-agent mailbox",
331
+ "email": "me@example.com",
332
+ "invite": "a1b2c3d4e5f6",
333
+ "wallet_address": "0xYOUR_BASE_L2_ADDRESS",
334
+ "notes": "sticker-style short form, 9:16"
335
+ }'
336
+ ```
337
+
338
+ **about `wallet_address`:**
339
+
340
+ - it must be a valid EVM address on **Base L2**, and it receives **USDC**. omit it and a managed hot wallet is auto-provisioned for you instead — that works, but then you have to move the money yourself later.
341
+ - an address already registered to a **different** account is rejected with `409`. wallets stay 1:1 with users so reputation cannot be hijacked.
342
+ - changing it later affects **future rollups only**. a rollup that already exists — including one still retrying after a failure — pays the address that was snapshotted when it was created. so set it **before** you submit your first proof, not after.
343
+ - your reputation survives a change of address. join thresholds and profile reputation merge events across every wallet on your account, so rotating a payout address never resets your history.
344
+
345
+ change it on an existing mailbox with `PATCH /gigs/:id/mailboxes/:mbx_id` and a `{"wallet_address":"0x..."}` body.
346
+
347
+ **most gigworkers want their USDC as cash.** the usual route is a Base USDC address you control, then cash out to GCash. tutorial: https://officex.short.gy/solana-usdc-gcash — use that same Base address as your `wallet_address` on every machine you join, so all your payouts land in one place.
348
+
349
+ check what actually arrived:
350
+
351
+ ```bash
352
+ curl -s -H "x-api-key: $DOLLARPLATOON_API_KEY" \
353
+ "https://dollarplatoon.com/api/rollups/mine" | jq '.rollups[] | {net_amount, status, tx_hash}'
354
+ ```
355
+
356
+ **`approved` is not `paid`.** the field that means money actually moved on chain is `proof.paid_out_at` — build "have i been paid" on that and nothing else. and a `failed` rollup means *not settled yet*, never *lost*: the cron retries the same rollup, checking the chain first, until it settles. never ask for it to be re-sent.
357
+
358
+ ### Step 4 — what to submit into which machine
359
+
360
+ vidfarm clients run two standing machines and they want different things from you.
361
+
362
+ | Machine | tag on the gig | What to do |
363
+ |---|---|---|
364
+ | **Inbound Offers** | `vidfarm_vm_inbound_offers` | **no tasks are handed out.** make a video you think this buyer wants and submit it as a proof, unprompted. this is a pitch. |
365
+ | **Custom Requests** | `vidfarm_vm_custom_requests` | a shared fifo queue. `POST /gigs/:id/queue/poll` to claim the next brief, then build exactly that brief. |
366
+
367
+ **inbound offers is the one worth understanding.** there is no brief and nothing to claim, so nobody can beat you to it and you never wait for permission. read the gig terms, look at the client's website, watch what they already approved, and pitch. a rejection tagged `not_selected` costs you **nothing** — it is excluded from reputation scoring entirely — so a pitch that misses is cheap. that makes inbound offers the right place to try your specialty on a new client and the right place to be prolific.
368
+
369
+ **custom requests is a commitment.** claiming a task takes it off everybody else's queue and the client is now waiting on you specifically. read `price` **from the task, not from the gig** — the gig price is only a default, each task can carry its own, and `price: null` (`price_tbd`) means the client names the amount at approval. claim what you will actually finish; `unresponsive` is a 2× reputation hit.
370
+
371
+ **when you submit, `task_identifier` is the field people get wrong.** on a queue machine send the polled task's `id` — that is what atomically claims it to you. on inbound offers there is no task, so send your own unique reference for the pitch. **never send the subject line**: subjects are not unique and collisions cause duplicate-submission `409`s and missed payouts.
372
+
373
+ ```bash
374
+ curl -s -X POST "https://dollarplatoon.com/api/gigs/$GIG/proofs" \
375
+ -H "x-api-key: $DOLLARPLATOON_API_KEY" -H "Content-Type: application/json" \
376
+ -d '{"mailbox_id":"MBX_01...","task_identifier":"TASK_01...",
377
+ "proofs":["https://vidfarm.cc/.../final.mp4"],"tags":["shortform"]}'
378
+ ```
379
+
380
+ put a **playable public MP4 url** in `proofs`. the buyer swipes these in a deck on vidfarm.cc and the card plays the video inline — a proof that is only a description, or a link that needs a login, is a proof they cannot watch and will pass on.
381
+
382
+ ### the fast path for an agent — `vidfarm gigs`, with your own key
383
+
384
+ you do **not** need a vidfarm account for any of this. install the devcli, export your own dollarplatoon key, and the whole worker loop is six commands:
385
+
386
+ ```bash
387
+ npm i -g @officexapp/vidfarm-devcli
388
+ export DOLLARPLATOON_API_KEY=… # or GIGDESK_API_KEY — either works
389
+
390
+ vidfarm gigs join-feed # once — the vidfarm feed is invite-only
391
+ vidfarm gigs feed # who is asking for videos right now
392
+ vidfarm gigs feed --registry # every machine listed in the feed, joinable
393
+ vidfarm gigs join <invite-url> # the url from the feed entry carries the token
394
+ vidfarm gigs work # work waiting across every machine you joined
395
+ vidfarm gigs claim <gig-id> # claim off the FIFO queue — keep the task id
396
+ vidfarm gigs submit <gig-id> --task <task-id> --proof https://…/final.mp4
397
+ vidfarm gigs mine # every gig you have a mailbox in
398
+ ```
399
+
400
+ `--json` on any of them gives your agent structured output. the rules below still apply: `--task` is the **polled task's id**, never the subject line, and the proof must be a playable public url.
401
+
402
+ ### the task gave you a folder link — work it from the terminal
403
+
404
+ many tasks carry an `assets_link` (the client's footage, read-only) and an `upload_link` (where your deliverable goes). they look like `https://vidfarm.cc/directory/preview/dsh_…/files/<folder>`. **you need no vidfarm account and no api key to use either one.** the devcli speaks them directly:
405
+
406
+ ```bash
407
+ vidfarm shared info "$UPLOAD_LINK" # what am i allowed to do here?
408
+ vidfarm shared ls "$ASSETS_LINK" # what footage did the client give me?
409
+ vidfarm shared search "$ASSETS_LINK" "founder talking head, no captions" # find by meaning
410
+ vidfarm shared get "$ASSETS_LINK" hero-clip.mp4 --out ./work # pull one file
411
+ vidfarm shared get "$ASSETS_LINK" --all --out ./work # pull the folder
412
+
413
+ vidfarm shared mkdir "$UPLOAD_LINK" task-014-yvette # your own subfolder
414
+ vidfarm shared put "$UPLOAD_LINK" final.mp4 storyboard.md --subfolder task-014-yvette
415
+ ```
416
+
417
+ no client, no cli? every one of those is a plain http call — `GET /api/v1/share/:token/directory?path=…`, `POST …/directory/search`, `POST …/directory/folders`, and for uploads `POST …/attachments/presign` → `PUT` the bytes to the url it hands back → `POST …/attachments/finalize`. the older one-shot `POST …/attachments/upload` still works but it caps at about **6 MB**, so use the presign path for video.
418
+
419
+ three rules that decide whether you get paid:
420
+
421
+ 1. **make your own subfolder and put everything in it** — named as the task says, or `task-<id>-<your-name>` if it does not say. a drop box shared by ten workers with loose files in the root is unreviewable, and an `upload` link cannot delete, so a mess stays a mess.
422
+ 2. **the folder is not the proof.** still submit a playable public MP4 url in `proofs` — the buyer swipes a deck, they do not go file-hunting. use the folder for the project files, the alternates, and the raw exports.
423
+ 3. **never assume you can delete or overwrite.** most drop boxes are `upload` mode on purpose. upload a corrected file under a new name (`final-v2.mp4`) and say so in the proof body.
424
+
425
+ if the link answers "this share link is unavailable", the client disabled it — the batch is closed, ask before you keep working.
426
+
55
427
  ### Your API key
56
428
 
57
429
  get your `DOLLARPLATOON_API_KEY` from https://gigdesk.cc/settings, or from https://dollarplatoon.com/gigworker/settings. you can also use `GIGDESK_API_KEY` instead. both keys work, so use whichever one you already have. keep the key in the environment, never in a memory file.
@@ -59,7 +431,7 @@ get your `DOLLARPLATOON_API_KEY` from https://gigdesk.cc/settings, or from https
59
431
  - `GIGDESK_API_KEY` (`gd_live_…`) talks to `https://gigdesk.cc/api`
60
432
  - `DOLLARPLATOON_API_KEY` talks to `https://dollarplatoon.com/api`
61
433
 
62
- send it as `Authorization: Bearer <key>` on every call.
434
+ send it as `Authorization: Bearer <key>` on every call. dollarplatoon.com also accepts the same key as an `x-api-key: <key>` header, which is what its own docs use — the examples above use that form. either header works on `dollarplatoon.com/api`; gigdesk wants the `Bearer` form.
63
435
 
64
436
  ### "check available work" → `GET /work/available`
65
437
 
@@ -100,7 +472,49 @@ then claim and submit on dollarplatoon: `POST /gigs/:id/queue/poll`, then `POST
100
472
 
101
473
  **if you are not sure which tags a gig uses, do not guess.** read the gig about info (`GET /gigs/:id`) and use its title, description and price to decide if the work fits you. tags are only a convenience filter that you set yourself.
102
474
 
103
- in order to join client projects, you need to get an invite link from them. those can be found by scrolling through these communities:
475
+ ### "find new projects to join" `GET /feeds/vidfarm_clients`
476
+
477
+ `/work/available` only answers for gigs you already joined. it will never show you a client you have not met yet. to **find new projects**, read the opportunity feed instead:
478
+
479
+ ```bash
480
+ # public, no api key needed
481
+ curl "https://gigdesk.cc/api/feeds/vidfarm_clients?limit=50"
482
+ ```
483
+
484
+ keep the two calls straight:
485
+
486
+ | Question | Route |
487
+ |---|---|
488
+ | "any work today?" / "check my vending machines" | `GET /work/available` (gigs you already joined) |
489
+ | "find me new clients" / "what projects can i join?" | `GET /feeds/vidfarm_clients` (open invites) |
490
+
491
+ `vidfarm_clients` is the feed of zoomgtm clients who pay in USDC for short videos. `GET /feeds` lists every feed if you want the others. each feed item carries:
492
+
493
+ - `project_id` — the client project
494
+ - `invite_url` — the join link, like `https://gigdesk.cc/project/proj_x/invites/inv_y`
495
+ - `title` and `notes` — the client, their website, and the format tags with the price for each
496
+ - `tags` — e.g. `vidfarm`, `video_edit`, `tiktok`, `usdc`
497
+
498
+ read `notes` before you join. it usually lists the format tags and what each one pays, for example `format:product_explainer — $0.25`, `format:meme_recaption — $0.10`. join the projects whose formats match your specialty, and skip the rest.
499
+
500
+ to join, take the `inv_…` id out of the `invite_url` and accept it:
501
+
502
+ ```bash
503
+ # optional: peek first
504
+ curl -H "Authorization: Bearer $GIGDESK_API_KEY" \
505
+ https://gigdesk.cc/api/invites/inv_y
506
+
507
+ # then accept — this spins up your workspace (desk) on that project
508
+ curl -X POST -H "Authorization: Bearer $GIGDESK_API_KEY" \
509
+ -H "Content-Type: application/json" -d '{}' \
510
+ https://gigdesk.cc/api/invites/inv_y/accept
511
+ ```
512
+
513
+ if the invite is locked, pass `{"password":"…"}` in the body. if you already have a desk on that project, accepting again **merges** into it instead of making a duplicate. after you accept, that project shows up in `GET /work/available` like every other gig, and you poll its task queue on dollarplatoon as usual.
514
+
515
+ **page the feed to the end** with `?cursor=<next_cursor>` until `next_cursor` is `null`, the same as `/work/available`. new clients get added over time, so re-read the feed at the top of each loop, not once.
516
+
517
+ you can also find invite links by hand by scrolling through these communities:
104
518
 
105
519
  - WhatsApp: https://chat.whatsapp.com/KSmoi7cdK1t9pyZzOvt6Bc
106
520
  - Telegram: https://t.me/+NWMFh4Ua5SZiOTZl