Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Ship parcels via any configured carrier — MyParcel, Sendcloud, DHL Parcel NL, PostNL, DPD, UPS, FedEx. Auto-selects the first carrier whose credentials are configured, or pass --carrier <name> to override. Verbs: ship, label, track, list, carriers.
.claude/skills/davepoon-ops-package/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 30% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 158% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 55% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 9% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 55% | 0% |
One skill, seven carriers. The router picks the carrier automatically based on which credentials are configured.
| Condition | Selected carrier | | -------------------------------------------------------------------- | ------------------------- | | --carrier <name> flag passed | That carrier (validated) | | Exactly one carrier has credentials | That carrier | | Multiple carriers have credentials | First match in this order | | No carrier has credentials | Exit 2 with setup help |
Preference order: myparcel → sendcloud → dhl → postnl → dpd → ups → fedex.
Each carrier resolves its credential(s) from, in order:
preferences.json key (lowercase of the env var name) at ${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json.doppler secrets get <NAME> --plain.| Carrier | Env vars required | Docs | | ---------- | ---------------------------------------------------------------------- | --------------------------------------------------- | | MyParcel | MYPARCEL_API_KEY | https://developer.myparcel.nl/api-reference/ | | Sendcloud | SENDCLOUD_PUBLIC_KEY + SENDCLOUD_PRIVATE_KEY | https://api.sendcloud.dev/docs/ | | DHL NL | DHL_PARCEL_USER_ID + DHL_PARCEL_KEY | https://api-gw.dhlparcel.nl/docs | | PostNL | POSTNL_API_KEY + POSTNL_CUSTOMER_CODE + POSTNL_CUSTOMER_NUMBER | https://developer.postnl.nl/ | | DPD | DPD_DELIS_ID + DPD_PASSWORD | https://esolutions.dpd.com/ | | UPS | UPS_CLIENT_ID + UPS_CLIENT_SECRET + UPS_SHIPPER_NUMBER | https://developer.ups.com/api/reference/shipping | | FedEx | FEDEX_CLIENT_ID + FEDEX_CLIENT_SECRET + FEDEX_ACCOUNT_NUMBER | https://developer.fedex.com/api/en-us/catalog/ |
All API calls are delegated to ${CLAUDE_PLUGIN_ROOT}/skills/ops-package/ops-package.sh. Do not re-implement curl logic inline — pass args through.
| First token | Action | | ----------- | ------------------------------------------------------------------ | | carriers | Show configured vs unconfigured carriers | | ship | Create a shipment | | label | Download + open label PDF | | track | Show status + tracking barcode | | list | List last 10 shipments (MyParcel / Sendcloud; others unsupported) | | (empty) | Show usage |
Required: --to "<address>". Address format:
"Person / Company, Street 12A, 1011AB Amsterdam, NL"/ Company segment is optional.Flags (not every carrier honours every flag — unsupported flags are safely ignored per adapter):
--from "<address>" override sender; default is the account's configured sender.--weight <grams> integer grams.--package-type 1|2|3 1=parcel (default), 2=mailbox, 3=letter (MyParcel only).--signature require signature on delivery.--insurance <EUR> integer EUR; 0 disables (MyParcel only).--description "<text>" label reference (carriers differ; ~45 char max).--pickup request home pickup at sender (MyParcel only).bash${CLAUDE_PLUGIN_ROOT}/skills/ops-package/ops-package.sh \ [--carrier myparcel|sendcloud|dhl|postnl|dpd|ups|fedex] \ ship --to "$TO" [--from "$FROM"] [--weight "$W"] \ [--signature] [--insurance "$INS"] [--description "$DESC"] \ [--package-type "$TYPE"] [--pickup]
Returns:
json{"carrier": "<name>", "shipment_id": "<id>", "response": { /* raw carrier JSON */ }}
Summarise to the user as:
Shipment created — <carrier> #<id>
Next: /ops:ops-package label <id> to download the PDF.Offer via AskUserQuestion (≤4 options):
[Download label now] — call label <id> immediately[Track it] — call track <id>[Ship another][Done]<shipment-id>bash${CLAUDE_PLUGIN_ROOT}/skills/ops-package/ops-package.sh label "$ID"
Behaviour per carrier:
/tmp/myparcel_label_<id>.pdf and opened on macOS. If unpaid, returns {"status":"payment_required","payment_url":"..."} and opens the MultiSafepay URL./labels/<id>) and saves locally./labels/<id>?format=PDF&printerType=A4./v1/parcellabelnumber/<id>?paperFormat=A4.ship call and cached to /tmp/<carrier>_label_<id>.pdf. Calling label re-opens that cached file. If the cache is gone, re-run ship (none of these carriers expose a stable label-recovery endpoint here).<shipment-id>Returns a normalised object across all carriers:
json{"carrier":"<n>","id":"<id>","status":"<s>","barcode":"<b>","tracking_url":"<u>","recipient":<o>,"updated":"<ts>"}
MyParcel returns the last 10 shipments. Sendcloud returns the last 10 parcels. All other carriers return {"shipments":[],"note":"..."} because their APIs don't expose a customer-facing list endpoint — track by id instead.
Prints which carriers are configured (✓) vs which are missing credentials (·). Use this when deciding which --carrier to pass.
AskUserQuestion:[Paste key now] [Open carriers doc] [Skip — configure later] On "Paste key now", collect via AskUserQuestion free-text and write to preferences.json.
| Carrier | Status | | ---------- | ------------------------------------------------------------------ | | MyParcel | Verified against api.myparcel.nl v1.1 (same working reference) | | Sendcloud | Verified request/response shapes against Sendcloud Panel API v3 | | DHL NL | UNVERIFIED — modelled on My DHL Parcel Swagger, needs live account | | PostNL | UNVERIFIED — modelled on Send API v2.2 docs, needs live account | | DPD | UNVERIFIED — modelled on DPD eSolutions REST, needs live account | | UPS | UNVERIFIED — modelled on UPS v2403 Ship/Track REST, needs account | | FedEx | UNVERIFIED — modelled on FedEx Ship v1 + Track v1 REST |
Unverified adapters are tagged with # UNVERIFIED - pending live test with account in the source. Payloads match the documented contract; adjustments may be needed when tested against live accounts.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 13,483 | 8,913 | -34% | 1 | 1 | 0% | 1,358 | 2,640 | +94% | 0 | 0 | — |
case-02 | fail→fail | 3,711 | 6,920 | +86% | 1 | 1 | 0% | 575 | 2,231 | +288% | 0 | 0 | — |
case-03 | fail→fail | 5,278 | 6,374 | +21% | 1 | 1 | 0% | 982 | 2,333 | +138% | 0 | 0 | — |
case-04 | pass→pass | 11,915 | 3,981 | -67% | 1 | 1 | 0% | 1,628 | 2,290 | +41% | 0 | 0 | — |
case-05 | fail→pass | 10,990 | 2,686 | -76% | 1 | 1 | 0% | 1,727 | 2,241 | +30% | 0 | 0 | — |
case-06 | fail→pass | 15,879 | 3,563 | -78% | 1 | 1 | 0% | 957 | 2,465 | +158% | 0 | 0 | — |
case-07 | pass→pass | 8,625 | 2,605 | -70% | 1 | 1 | 0% | 1,563 | 2,294 | +47% | 0 | 0 | — |
case-08 | pass→pass | 4,570 | 1,825 | -60% | 1 | 1 | 0% | 817 | 2,263 | +177% | 0 | 0 | — |
case-09 | fail→pass | 8,655 | 1,984 | -77% | 1 | 1 | 0% | 1,477 | 2,296 | +55% | 0 | 0 | — |
case-10 | fail→pass | 12,011 | 2,883 | -76% | 1 | 1 | 0% | 2,268 | 2,467 | +9% | 0 | 0 | — |
case-11 | pass→pass | 14,882 | 2,304 | -85% | 1 | 1 | 0% | 2,538 | 2,301 | -9% | 0 | 0 | — |
case-12 | fail→fail | 5,499 | 2,205 | -60% | 1 | 1 | 0% | 960 | 2,197 | +129% | 0 | 0 | — |
case-13 | pass→pass | 8,042 | 2,395 | -70% | 1 | 1 | 0% | 1,363 | 2,269 | +66% | 0 | 0 | — |
case-23 | pass→pass | 12,882 | 3,911 | -70% | 1 | 1 | 0% | 2,134 | 2,618 | +23% | 0 | 0 | — |
case-14 | fail→pass | 8,927 | 1,733 | -81% | 1 | 1 | 0% | 1,444 | 2,233 | +55% | 0 | 0 | — |
case-15 | fail→pass | 4,763 | 4,200 | -12% | 1 | 1 | 0% | 870 | 2,235 | +157% | 0 | 0 | — |
case-16 | fail→pass | 11,067 | 4,254 | -62% | 1 | 1 | 0% | 1,842 | 2,502 | +36% | 0 | 0 | — |
case-17 | pass→pass | 10,648 | 1,530 | -86% | 1 | 1 | 0% | 1,902 | 2,180 | +15% | 0 | 0 | — |
case-18 | pass→pass | 4,031 | 1,841 | -54% | 1 | 1 | 0% | 700 | 2,218 | +217% | 0 | 0 | — |
case-19 | fail→pass | 11,301 | 3,925 | -65% | 1 | 1 | 0% | 2,034 | 2,409 | +18% | 0 | 0 | — |
case-20 | pass→pass | 13,267 | 4,297 | -68% | 1 | 1 | 0% | 2,334 | 2,546 | +9% | 0 | 0 | — |
case-21 | fail→fail | 16,518 | 13,672 | -17% | 1 | 1 | 0% | 3,122 | 4,667 | +49% | 0 | 0 | — |
case-22 | fail→pass | 13,479 | 4,909 | -64% | 1 | 1 | 0% | 1,900 | 2,800 | +47% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 19 counted toward the lift figure. The other 4 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +39 percentage points is the difference between those two pass rates over the 19 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.