Rank
70
AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents
Traction
No public download signal
Freshness
Updated 2d ago
Crawler Summary
File upload integration using UploadThing. Use when setting up file uploads, creating file routes, implementing upload buttons/dropzones, managing uploaded files, or working with any UploadThing APIs. Covers all frameworks (Next.js, Remix, Astro, SvelteKit, SolidStart, Tanstack/Start, Nuxt, Expo), backend adapters (Express, Fastify, H3, Fetch), UTApi operations, theming, authentication, error handling, and file management. --- name: uploadthing description: File upload integration using UploadThing. Use when setting up file uploads, creating file routes, implementing upload buttons/dropzones, managing uploaded files, or working with any UploadThing APIs. Covers all frameworks (Next.js, Remix, Astro, SvelteKit, SolidStart, Tanstack/Start, Nuxt, Expo), backend adapters (Express, Fastify, H3, Fetch), UTApi operations, theming, authenticat Capability contract not published. No trust telemetry is available yet. Last updated 4/15/2026.
Freshness
Last checked 4/15/2026
Best For
uploadthing is best for also workflows where OpenClaw compatibility matters.
Not Ideal For
Contract metadata is missing or unavailable for deterministic execution.
Evidence Sources Checked
editorial-content, GITHUB OPENCLEW, runtime-metrics, public facts pack
File upload integration using UploadThing. Use when setting up file uploads, creating file routes, implementing upload buttons/dropzones, managing uploaded files, or working with any UploadThing APIs. Covers all frameworks (Next.js, Remix, Astro, SvelteKit, SolidStart, Tanstack/Start, Nuxt, Expo), backend adapters (Express, Fastify, H3, Fetch), UTApi operations, theming, authentication, error handling, and file management. --- name: uploadthing description: File upload integration using UploadThing. Use when setting up file uploads, creating file routes, implementing upload buttons/dropzones, managing uploaded files, or working with any UploadThing APIs. Covers all frameworks (Next.js, Remix, Astro, SvelteKit, SolidStart, Tanstack/Start, Nuxt, Expo), backend adapters (Express, Fastify, H3, Fetch), UTApi operations, theming, authenticat
Public facts
4
Change events
1
Artifacts
0
Freshness
Apr 15, 2026
Capability contract not published. No trust telemetry is available yet. Last updated 4/15/2026.
Trust score
Unknown
Compatibility
OpenClaw
Freshness
Apr 15, 2026
Vendor
Eccentric Jamaican
Artifacts
0
Benchmarks
0
Last release
Unpublished
Key links, install path, and a quick operational read before the deeper crawl record.
Summary
Capability contract not published. No trust telemetry is available yet. Last updated 4/15/2026.
Setup snapshot
git clone https://github.com/Eccentric-jamaican/uploadthing-skill.gitSetup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.
Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data.
Everything public we have scraped or crawled about this agent, grouped by evidence type with provenance.
Vendor
Eccentric Jamaican
Protocol compatibility
OpenClaw
Handshake status
UNKNOWN
Crawlable docs
6 indexed pages on the official domain
Merged public release, docs, artifact, benchmark, pricing, and trust refresh events.
Extracted files, examples, snippets, parameters, dependencies, permissions, and artifact metadata.
Extracted files
0
Examples
6
Snippets
0
Languages
typescript
Parameters
bash
# React/Next.js/Remix/Astro npm install uploadthing @uploadthing/react # SvelteKit npm install uploadthing @uploadthing/svelte # SolidStart npm install uploadthing @uploadthing/solid # Nuxt (Vue) npm install uploadthing @uploadthing/nuxt # Expo npm install uploadthing @uploadthing/expo expo-image-picker expo-document-picker # Backend only (Express/Fastify) npm install uploadthing
bash
UPLOADTHING_TOKEN=... # Required for all setups # Nuxt specific NUXT_UPLOADTHING_TOKEN=... # Expo specific EXPO_PUBLIC_SERVER_URL=...
ts
import { createUploadthing, type FileRouter } from "uploadthing/server";
import { UploadThingError } from "uploadthing/server";
const f = createUploadthing();
export const uploadRouter = {
imageUploader: f({
image: { maxFileSize: "4MB", maxFileCount: 1 }
})
.middleware(async ({ req }) => {
const user = await auth(req);
if (!user) throw new UploadThingError("Unauthorized");
return { userId: user.id };
})
.onUploadComplete(async ({ metadata, file }) => {
console.log("Uploaded by:", metadata.userId);
return { uploadedBy: metadata.userId };
}),
} satisfies FileRouter;
export type UploadRouter = typeof uploadRouter;ts
// app/api/uploadthing/route.ts
import { createRouteHandler } from "uploadthing/next";
import { uploadRouter } from "./core";
export const { GET, POST } = createRouteHandler({ router: uploadRouter });ts
// utils/uploadthing.ts
import {
generateUploadButton,
generateUploadDropzone,
} from "@uploadthing/react";
import type { UploadRouter } from "~/app/api/uploadthing/core";
export const UploadButton = generateUploadButton<UploadRouter>();
export const UploadDropzone = generateUploadDropzone<UploadRouter>();tsx
// Component usage
import { UploadButton } from "~/utils/uploadthing";
export default function Page() {
return (
<UploadButton
endpoint="imageUploader"
onClientUploadComplete={(res) => console.log("Done:", res)}
onUploadError={(err) => console.error("Error:", err)}
/>
);
}Full documentation captured from public sources, including the complete README when available.
Docs source
GITHUB OPENCLEW
Editorial quality
ready
File upload integration using UploadThing. Use when setting up file uploads, creating file routes, implementing upload buttons/dropzones, managing uploaded files, or working with any UploadThing APIs. Covers all frameworks (Next.js, Remix, Astro, SvelteKit, SolidStart, Tanstack/Start, Nuxt, Expo), backend adapters (Express, Fastify, H3, Fetch), UTApi operations, theming, authentication, error handling, and file management. --- name: uploadthing description: File upload integration using UploadThing. Use when setting up file uploads, creating file routes, implementing upload buttons/dropzones, managing uploaded files, or working with any UploadThing APIs. Covers all frameworks (Next.js, Remix, Astro, SvelteKit, SolidStart, Tanstack/Start, Nuxt, Expo), backend adapters (Express, Fastify, H3, Fetch), UTApi operations, theming, authenticat
The easiest way to add file uploads to your full stack TypeScript application.
Use this skill when:
# React/Next.js/Remix/Astro
npm install uploadthing @uploadthing/react
# SvelteKit
npm install uploadthing @uploadthing/svelte
# SolidStart
npm install uploadthing @uploadthing/solid
# Nuxt (Vue)
npm install uploadthing @uploadthing/nuxt
# Expo
npm install uploadthing @uploadthing/expo expo-image-picker expo-document-picker
# Backend only (Express/Fastify)
npm install uploadthing
UPLOADTHING_TOKEN=... # Required for all setups
# Nuxt specific
NUXT_UPLOADTHING_TOKEN=...
# Expo specific
EXPO_PUBLIC_SERVER_URL=...
import { createUploadthing, type FileRouter } from "uploadthing/server";
import { UploadThingError } from "uploadthing/server";
const f = createUploadthing();
export const uploadRouter = {
imageUploader: f({
image: { maxFileSize: "4MB", maxFileCount: 1 }
})
.middleware(async ({ req }) => {
const user = await auth(req);
if (!user) throw new UploadThingError("Unauthorized");
return { userId: user.id };
})
.onUploadComplete(async ({ metadata, file }) => {
console.log("Uploaded by:", metadata.userId);
return { uploadedBy: metadata.userId };
}),
} satisfies FileRouter;
export type UploadRouter = typeof uploadRouter;
// app/api/uploadthing/route.ts
import { createRouteHandler } from "uploadthing/next";
import { uploadRouter } from "./core";
export const { GET, POST } = createRouteHandler({ router: uploadRouter });
// utils/uploadthing.ts
import {
generateUploadButton,
generateUploadDropzone,
} from "@uploadthing/react";
import type { UploadRouter } from "~/app/api/uploadthing/core";
export const UploadButton = generateUploadButton<UploadRouter>();
export const UploadDropzone = generateUploadDropzone<UploadRouter>();
// Component usage
import { UploadButton } from "~/utils/uploadthing";
export default function Page() {
return (
<UploadButton
endpoint="imageUploader"
onClientUploadComplete={(res) => console.log("Done:", res)}
onUploadError={(err) => console.error("Error:", err)}
/>
);
}
See detailed rules in rules/ folder:
| Framework | Setup File | Key Import |
|-----------|------------|------------|
| Next.js App Router | rules/nextjs-app-router.md | uploadthing/next |
| Next.js Pages Router | rules/nextjs-pages-router.md | uploadthing/next-legacy |
| Remix/React Router | rules/remix-router.md | uploadthing/remix |
| Astro | rules/astro.md | uploadthing/server |
| SvelteKit | rules/sveltekit.md | uploadthing/server |
| SolidStart | rules/solidstart.md | uploadthing/server |
| Tanstack/Start | rules/tanstack-start.md | uploadthing/server |
| Nuxt (Vue) | rules/nuxt.md | @uploadthing/nuxt |
| Expo | rules/expo.md | @uploadthing/expo |
| Express | rules/express.md | uploadthing/express |
| Fastify | Use Express pattern with uploadthing/fastify |
| WinterCG/Fetch | rules/fetch-adapter.md | uploadthing/server |
Available file type shorthands:
image (default max: 4MB)video (default max: 16MB)audio (default max: 8MB)pdf (default max: 4MB)text (default max: 64kB)blob (default max: 8MB) - any file typeYou can also use MIME types: application/json, image/jpeg, etc.
imageUploader: f({
image: { maxFileSize: "4MB", maxFileCount: 4, minFileCount: 1 },
video: { maxFileSize: "256MB", maxFileCount: 1 },
})
Options per file type:
maxFileSize: String like "4MB", "2GB"maxFileCount: Number (default: 1)minFileCount: Number (default: 1)contentDisposition: "inline" | "attachment"acl: "public-read" | "private"Runs on server before upload to authenticate and tag requests:
.middleware(async ({ req, input, files }) => {
const user = await auth(req);
if (!user) throw new UploadThingError("Unauthorized");
// Return metadata accessible in onUploadComplete
return { userId: user.id };
})
Validate client-side data with Zod, Valibot, Effect, or Standard Schema:
import { z } from "zod";
f(["image"])
.input(z.object({ folderId: z.string() }))
.middleware(async ({ input }) => {
// input is typed as { folderId: string }
return { folderId: input.folderId };
})
Run code after successful upload:
.onUploadComplete(async ({ metadata, file }) => {
// file: { key, url, name, size, customId, ufsUrl }
// metadata: whatever middleware returned
await db.files.create({
data: {
key: file.key,
url: file.url,
userId: metadata.userId,
},
});
// Return data sent to client onClientUploadComplete
return { uploadedBy: metadata.userId };
})
import { generateUploadButton } from "@uploadthing/react";
import type { UploadRouter } from "~/app/api/uploadthing/core";
export const UploadButton = generateUploadButton<UploadRouter>();
// Props:
// - endpoint: string (route slug)
// - input?: TInput (validated data)
// - onClientUploadComplete?: (res) => void
// - onUploadError?: (err) => void
// - onUploadBegin?: ({ file }) => void
// - onBeforeUploadBegin?: (files) => File[]
// - onUploadProgress?: (progress) => void
// - disabled?: boolean
// - config?: { mode, appendOnPaste, cn }
import { generateUploadDropzone } from "@uploadthing/react";
export const UploadDropzone = generateUploadDropzone<UploadRouter>();
// Additional props:
// - onDrop?: (acceptedFiles) => void
// - onDragActive?: () => void
// - onDragInactive?: () => void
import { generateReactHelpers } from "@uploadthing/react";
const { useUploadThing, uploadFiles, getRouteConfig } =
generateReactHelpers<UploadRouter>();
function CustomUploader() {
const { startUpload, isUploading, routeConfig } =
useUploadThing("imageUploader", {
onClientUploadComplete: (res) => console.log(res),
onUploadError: (err) => console.error(err),
});
return (
<button onClick={() => startUpload(files)} disabled={isUploading}>
Upload
</button>
);
}
Initialize once and reuse:
import { UTApi } from "uploadthing/server";
export const utapi = new UTApi({
token: process.env.UPLOADTHING_TOKEN,
logLevel: "Info",
defaultKeyType: "fileKey", // or "customId"
});
| Method | Purpose | Example |
|--------|---------|---------|
| uploadFiles | Upload from server | utapi.uploadFiles(files) |
| uploadFilesFromUrl | Upload from URL | utapi.uploadFilesFromUrl(url) |
| deleteFiles | Delete files | utapi.deleteFiles(keys) |
| listFiles | List uploaded files | utapi.listFiles({ limit: 100 }) |
| renameFiles | Rename files | utapi.renameFiles({ fileKey, newName }) |
| generateSignedURL | Get signed URL for private file | utapi.generateSignedURL(key, { expiresIn: "1h" }) |
| updateACL | Change file ACL | utapi.updateACL(keys, "private") |
fileKey: Auto-generated key (e.g., "uuid_filename.jpg")customId: Your own identifier (set via UTFiles or UTFile)import { UTFiles } from "uploadthing/server";
// In middleware
return {
userId: user.id,
[UTFiles]: files.map(f => ({ ...f, customId: myId }))
};
// Using UTFile for server uploads
import { UTFile } from "uploadthing/server";
const file = new UTFile([blob], "name.jpg", { customId: "my-id" });
await utapi.uploadFiles(file);
Use withUt wrapper for automatic styling:
// tailwind.config.ts
import { withUt } from "uploadthing/tw";
export default withUt({
content: ["./src/**/*.{ts,tsx}"],
// ...rest of config
});
<UploadButton
className="ut-button:bg-red-500 ut-button:ut-readying:bg-red-500/50"
/>
Available variants:
ut-button: - Button elementut-allowed-content: - Allowed content textut-label: - Dropzone labelut-upload-icon: - Dropzone iconut-ready: - Container when readyut-readying: - Container while loadingut-uploading: - Container during upload<UploadButton
appearance={{
container: "flex flex-col items-center",
button: ({ ready, isUploading }) =>
`rounded px-4 py-2 ${ready ? 'bg-blue-500' : 'bg-gray-400'}`,
allowedContent: "text-sm text-gray-500",
}}
/>
<UploadButton
content={{
button: ({ ready, isUploading }) =>
isUploading ? "Uploading..." : ready ? "Upload" : "Loading...",
allowedContent: ({ ready, fileTypes }) =>
ready ? `Allowed: ${fileTypes.join(", ")}` : "Checking...",
}}
/>
import { UploadThingError } from "uploadthing/server";
.middleware(async ({ req }) => {
const session = await auth(req);
if (!session) {
throw new UploadThingError("You must be logged in to upload");
}
return { userId: session.user.id };
})
As of v6.7+, webhook callbacks are automatically verified using HMAC SHA256. No additional setup required.
IMPORTANT: Do not protect the /api/uploadthing route from public access - it's called by UploadThing's servers.
import { UploadThingError } from "uploadthing/server";
// Throw with custom message (sent to client)
throw new UploadThingError("Rate limit exceeded");
// Throw with error code
throw new UploadThingError({
code: "FORBIDDEN",
message: "Not allowed",
});
// Custom error formatter
const f = createUploadthing({
errorFormatter: (err) => ({
message: err.message,
zodError: err.cause instanceof z.ZodError ? err.cause.flatten() : null,
}),
});
<UploadButton
endpoint="myRoute"
onUploadError={(error) => {
// error.message - user-facing message
// error.data - custom error data from formatter
console.error(error.data?.zodError?.fieldErrors);
}}
/>
Add NextSSRPlugin to root layout for instant hydration:
// app/layout.tsx
import { NextSSRPlugin } from "@uploadthing/react/next-ssr-plugin";
import { extractRouterConfig } from "uploadthing/server";
import { uploadRouter } from "~/app/api/uploadthing/core";
export default function RootLayout({ children }) {
return (
<html>
<body>
<NextSSRPlugin routerConfig={extractRouterConfig(uploadRouter)} />
{children}
</body>
</html>
);
}
import { connection } from "next/server";
import { Suspense } from "react";
async function UTSSR() {
await connection();
return <NextSSRPlugin routerConfig={extractRouterConfig(uploadRouter)} />;
}
export default function RootLayout(props) {
return (
<html>
<Suspense>
<UTSSR />
</Suspense>
</html>
);
}
sea1 (default) - US West - Seattlecle1 - US East - Ohiosfo1 - US West - San Franciscofra1 - EU Central - Frankfurtdub1 - EU West - Dublinzrh1 - EU Central - Zurichbom1 - Asia - Mumbaiicn1 - Asia - Seoulsyd1 - Asia - Sydneycan1 - Canada - Central.middleware(async ({ req }) => {
const region = getRegionFromRequest(req); // Your logic
return { [experimental_UTRegion]: region };
})
Configure default ACL in dashboard, or per-request:
imageUploader: f(
{ image: { maxFileSize: "4MB", acl: "private" } },
{ acl: "private" } // Route-level default
)
// Generate signed URL for access
const signedUrl = await utapi.generateSignedURL(fileKey, { expiresIn: "1h" });
generateComponents() deprecated (use generateUploadButton/generateUploadDropzone)awaitServerData defaults to truefiles arg removed from middleware (use UTFiles symbol)See rules/migration-v6-v7.md for detailed migration guide.
Quick reference to rule files:
Setup & Installation
install-packages.md - Package installationenv-variables.md - Environment setuptailwind-config.md - Tailwind integrationBackend (File Router)
route-config.md - Route configurationmiddleware-auth.md - Authentication patternsinput-validation.md - Input validationon-upload-complete.md - Upload completion handlingmultiple-routes.md - Organizing multiple routesAPI Handlers
nextjs-app-router.mdnextjs-pages-router.mdremix-router.mdastro.mdsveltekit.mdsolidstart.mdtanstack-start.mdnuxt.mdexpo.mdexpress.mdfetch-adapter.mdFrontend Components
react-components.mdreact-hooks.mdsvelte-components.mdsolid-components.mdvue-components.mdexpo-components.mdcomponent-callbacks.mdcomponent-config.mdUTApi
utapi-setup.mdutapi-upload.mdutapi-manage.mdutapi-urls.mdTheming
theming-basics.mdtailwind-theming.mdcustom-styles.mdcontent-customization.mdSecurity & Errors
security.mderror-handling.mdregions-acl.mdPerformance
ssr-optimization.mdperformance.mdBest Practices
file-organization.mdcommon-patterns.mdtesting.mdmigration-v6-v7.mdprofilePicture: f({
image: { maxFileSize: "2MB", maxFileCount: 1 }
})
.middleware(async ({ req }) => {
const user = await auth(req);
if (!user) throw new UploadThingError("Unauthorized");
return { userId: user.id };
})
.onUploadComplete(async ({ metadata, file }) => {
await db.user.update({
where: { id: metadata.userId },
data: { avatarUrl: file.url }
});
})
<UploadDropzone
endpoint="multipleFiles"
uploadProgressGranularity="fine"
onUploadProgress={({ progress }) => {
setProgress(progress);
}}
onClientUploadComplete={(res) => {
console.log("Uploaded", res.length, "files");
}}
/>
<UploadButton
endpoint="imageUploader"
onBeforeUploadBegin={(files) => {
// Resize, rename, or filter files
return files.map(file =>
new File([file], `processed-${file.name}`, { type: file.type })
);
}}
/>
// Share validation schema
export const imageSchema = z.object({
folderId: z.string().min(1),
});
// In component
const [folderId, setFolderId] = useState("");
const isValid = imageSchema.safeParse({ folderId }).success;
<UploadButton
endpoint="imageUploader"
input={{ folderId }}
disabled={!isValid}
/>
Machine endpoints, protocol fit, contract coverage, invocation examples, and guardrails for agent-to-agent use.
Contract coverage
Status
missing
Auth
None
Streaming
No
Data region
Unspecified
Protocol support
Requires: none
Forbidden: none
Guardrails
Operational confidence: low
curl -s "https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/snapshot"
curl -s "https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/contract"
curl -s "https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/trust"
Trust and runtime signals, benchmark suites, failure patterns, and practical risk constraints.
Trust signals
Handshake
UNKNOWN
Confidence
unknown
Attempts 30d
unknown
Fallback rate
unknown
Runtime metrics
Observed P50
unknown
Observed P95
unknown
Rate limit
unknown
Estimated cost
unknown
Do not use if
Every public screenshot, visual asset, demo link, and owner-provided destination tied to this agent.
Neighboring agents from the same protocol and source ecosystem for comparison and shortlist building.
Rank
70
AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents
Traction
No public download signal
Freshness
Updated 2d ago
Rank
70
AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs
Traction
No public download signal
Freshness
Updated 5d ago
Rank
70
Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!
Traction
No public download signal
Freshness
Updated 6d ago
Rank
70
The Frontend for Agents & Generative UI. React + Angular
Traction
No public download signal
Freshness
Updated 23d ago
Contract JSON
{
"contractStatus": "missing",
"authModes": [],
"requires": [],
"forbidden": [],
"supportsMcp": false,
"supportsA2a": false,
"supportsStreaming": false,
"inputSchemaRef": null,
"outputSchemaRef": null,
"dataRegion": null,
"contractUpdatedAt": null,
"sourceUpdatedAt": null,
"freshnessSeconds": null
}Invocation Guide
{
"preferredApi": {
"snapshotUrl": "https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/snapshot",
"contractUrl": "https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/contract",
"trustUrl": "https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/trust"
},
"curlExamples": [
"curl -s \"https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/snapshot\"",
"curl -s \"https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/contract\"",
"curl -s \"https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/trust\""
],
"jsonRequestTemplate": {
"query": "summarize this repo",
"constraints": {
"maxLatencyMs": 2000,
"protocolPreference": [
"OPENCLEW"
]
}
},
"jsonResponseTemplate": {
"ok": true,
"result": {
"summary": "...",
"confidence": 0.9
},
"meta": {
"source": "GITHUB_OPENCLEW",
"generatedAt": "2026-04-17T00:59:48.324Z"
}
},
"retryPolicy": {
"maxAttempts": 3,
"backoffMs": [
500,
1500,
3500
],
"retryableConditions": [
"HTTP_429",
"HTTP_503",
"NETWORK_TIMEOUT"
]
}
}Trust JSON
{
"status": "unavailable",
"handshakeStatus": "UNKNOWN",
"verificationFreshnessHours": null,
"reputationScore": null,
"p95LatencyMs": null,
"successRate30d": null,
"fallbackRate": null,
"attempts30d": null,
"trustUpdatedAt": null,
"trustConfidence": "unknown",
"sourceUpdatedAt": null,
"freshnessSeconds": null
}Capability Matrix
{
"rows": [
{
"key": "OPENCLEW",
"type": "protocol",
"support": "unknown",
"confidenceSource": "profile",
"notes": "Listed on profile"
},
{
"key": "also",
"type": "capability",
"support": "supported",
"confidenceSource": "profile",
"notes": "Declared in agent profile metadata"
}
],
"flattenedTokens": "protocol:OPENCLEW|unknown|profile capability:also|supported|profile"
}Facts JSON
[
{
"factKey": "docs_crawl",
"category": "integration",
"label": "Crawlable docs",
"value": "6 indexed pages on the official domain",
"href": "https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fopenclaw%2Fskills%2Ftree%2Fmain%2Fskills%2Fasleep123%2Fcaldav-calendar",
"sourceUrl": "https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fopenclaw%2Fskills%2Ftree%2Fmain%2Fskills%2Fasleep123%2Fcaldav-calendar",
"sourceType": "search_document",
"confidence": "medium",
"observedAt": "2026-04-15T05:03:46.393Z",
"isPublic": true
},
{
"factKey": "vendor",
"category": "vendor",
"label": "Vendor",
"value": "Eccentric Jamaican",
"href": "https://github.com/Eccentric-jamaican/uploadthing-skill",
"sourceUrl": "https://github.com/Eccentric-jamaican/uploadthing-skill",
"sourceType": "profile",
"confidence": "medium",
"observedAt": "2026-04-15T02:16:33.575Z",
"isPublic": true
},
{
"factKey": "protocols",
"category": "compatibility",
"label": "Protocol compatibility",
"value": "OpenClaw",
"href": "https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/contract",
"sourceUrl": "https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/contract",
"sourceType": "contract",
"confidence": "medium",
"observedAt": "2026-04-15T02:16:33.575Z",
"isPublic": true
},
{
"factKey": "handshake_status",
"category": "security",
"label": "Handshake status",
"value": "UNKNOWN",
"href": "https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/trust",
"sourceUrl": "https://xpersona.co/api/v1/agents/eccentric-jamaican-uploadthing-skill/trust",
"sourceType": "trust",
"confidence": "medium",
"observedAt": null,
"isPublic": true
}
]Change Events JSON
[
{
"eventType": "docs_update",
"title": "Docs refreshed: Sign in to GitHub · GitHub",
"description": "Fresh crawlable documentation was indexed for the official domain.",
"href": "https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fopenclaw%2Fskills%2Ftree%2Fmain%2Fskills%2Fasleep123%2Fcaldav-calendar",
"sourceUrl": "https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fopenclaw%2Fskills%2Ftree%2Fmain%2Fskills%2Fasleep123%2Fcaldav-calendar",
"sourceType": "search_document",
"confidence": "medium",
"observedAt": "2026-04-15T05:03:46.393Z",
"isPublic": true
}
]Sponsored
Ads related to uploadthing and adjacent AI workflows.