Workers binding
Use the Artifacts Workers binding to create, import, inspect, fork, and delete repos directly from your Worker. The Artifacts binding returns repo handles that allow repo-scoped operations such as token management and forking.
Add the Artifacts binding to your Wrangler config file:
{ "$schema": "./node_modules/wrangler/config-schema.json", "artifacts": [ { "binding": "ARTIFACTS", "namespace": "default" } ]}[[artifacts]]binding = "ARTIFACTS"namespace = "default" # any name works — use namespaces to organise reposAfter you run npx wrangler types, your Worker environment looks like this:
export interface Env { ARTIFACTS: Artifacts;}Wrangler generates the Artifacts type for consumers and binds it directly in your environment.
If you authenticate with wrangler login, Wrangler requests artifacts:write by default.
Use namespace methods on env.ARTIFACTS to create, list, inspect, import, or delete repos.
nameRepoNamerequiredopts.readOnlybooleanoptionalopts.descriptionstringoptionalopts.setDefaultBranchstringoptional- Returns
Promise<ArtifactsCreateRepoResult>
async function createRepo(artifacts) { const created = await artifacts.create("starter-repo", { description: "Repository for automation experiments", readOnly: false, setDefaultBranch: "main", });
return { defaultBranch: created.defaultBranch, name: created.name, remote: created.remote, initialToken: created.token, };}async function createRepo(artifacts: Artifacts) { const created = await artifacts.create("starter-repo", { description: "Repository for automation experiments", readOnly: false, setDefaultBranch: "main", });
return { defaultBranch: created.defaultBranch, name: created.name, remote: created.remote, initialToken: created.token, };}nameRepoNamerequired- Returns
Promise<ArtifactsRepo> - Throws if the repo does not exist.
async function getRepoHandle(artifacts) { const repo = await artifacts.get("starter-repo"); return repo;}async function getRepoHandle(artifacts: Artifacts) { const repo = await artifacts.get("starter-repo"); return repo;}opts.limitnumberoptionalopts.cursorCursoroptional- Returns
Promise<ArtifactsRepoListResult>
async function listRepos(artifacts) { const page = await artifacts.list({ limit: 10 });
return { names: page.repos.map((repo) => repo.name), nextCursor: page.cursor ?? null, };}async function listRepos(artifacts: Artifacts) { const page = await artifacts.list({ limit: 10 });
return { names: page.repos.map((repo) => repo.name), nextCursor: page.cursor ?? null, };}Import a repository from an external git remote.
params.source.urlstringrequired — HTTPS URL of the source repository.params.source.branchstringoptional — Branch to import (defaults to the remote's default branch).params.source.depthnumberoptional — Shallow clone depth.params.target.nameRepoNamerequired — Name for the imported repo.params.target.opts.descriptionstringoptionalparams.target.opts.readOnlybooleanoptional- Returns
Promise<ArtifactsCreateRepoResult>
async function importFromGitHub(artifacts) { const imported = await artifacts.import({ source: { url: "https://github.com/cloudflare/workers-sdk", branch: "main", }, target: { name: "workers-sdk", }, });
return { name: imported.name, remote: imported.remote, token: imported.token, };}async function importFromGitHub(artifacts: Artifacts) { const imported = await artifacts.import({ source: { url: "https://github.com/cloudflare/workers-sdk", branch: "main", }, target: { name: "workers-sdk", }, });
return { name: imported.name, remote: imported.remote, token: imported.token, };}nameRepoNamerequired- Returns
Promise<boolean>
async function deleteRepo(artifacts) { return artifacts.delete("starter-repo");}async function deleteRepo(artifacts: Artifacts) { return artifacts.delete("starter-repo");}Call await artifacts.get(name) to get a repo handle. The handle extends ArtifactsRepoInfo, so repo metadata (id, name, remote, defaultBranch, etc.) is available directly as properties.
async function getRemoteUrl(artifacts) { const repo = await artifacts.get("starter-repo"); return repo.remote;}async function getRemoteUrl(artifacts: Artifacts) { const repo = await artifacts.get("starter-repo"); return repo.remote;}scope"read" | "write"optional (default: "write")ttlnumberoptional (seconds)- Returns
Promise<ArtifactsCreateTokenResult>
async function mintReadToken(artifacts) { const repo = await artifacts.get("starter-repo"); return repo.createToken("read", 3600);}async function mintReadToken(artifacts: Artifacts) { const repo = await artifacts.get("starter-repo"); return repo.createToken("read", 3600);}- Returns
Promise<ArtifactsTokenListResult>
async function listRepoTokens(artifacts) { const repo = await artifacts.get("starter-repo"); const result = await repo.listTokens(); return { total: result.total, tokens: result.tokens, };}async function listRepoTokens(artifacts: Artifacts) { const repo = await artifacts.get("starter-repo"); const result = await repo.listTokens(); return { total: result.total, tokens: result.tokens, };}tokenOrIdstringrequired- Returns
Promise<boolean>
async function revokeToken(artifacts, tokenOrId) { const repo = await artifacts.get("starter-repo"); return repo.revokeToken(tokenOrId);}async function revokeToken(artifacts: Artifacts, tokenOrId: string) { const repo = await artifacts.get("starter-repo"); return repo.revokeToken(tokenOrId);}nameRepoNamerequiredopts.descriptionstringoptionalopts.readOnlybooleanoptionalopts.defaultBranchOnlybooleanoptional- Returns
Promise<ArtifactsCreateRepoResult>
async function forkRepo(artifacts) { const repo = await artifacts.get("starter-repo"); const forked = await repo.fork("starter-repo-copy", { description: "Fork for testing", defaultBranchOnly: true, readOnly: false, });
return forked.remote;}async function forkRepo(artifacts: Artifacts) { const repo = await artifacts.get("starter-repo"); const forked = await repo.fork("starter-repo-copy", { description: "Fork for testing", defaultBranchOnly: true, readOnly: false, });
return forked.remote;}This example combines the binding methods in one Worker route.
export default { async fetch(request, env) { const url = new URL(request.url);
if (request.method === "POST" && url.pathname === "/repos") { const created = await env.ARTIFACTS.create("starter-repo"); return Response.json({ name: created.name, remote: created.remote, }); }
if (request.method === "GET" && url.pathname === "/repos/starter-repo") { const repo = await env.ARTIFACTS.get("starter-repo"); return Response.json({ id: repo.id, name: repo.name, remote: repo.remote, defaultBranch: repo.defaultBranch, }); }
if (request.method === "POST" && url.pathname === "/tokens") { const repo = await env.ARTIFACTS.get("starter-repo"); const token = await repo.createToken("read", 3600); return Response.json(token); }
return Response.json( { message: "Use POST /repos, GET /repos/starter-repo, or POST /tokens." }, { status: 404 }, ); },};interface Env { ARTIFACTS: Artifacts;}
export default { async fetch(request: Request, env: Env): Promise<Response> { const url = new URL(request.url);
if (request.method === "POST" && url.pathname === "/repos") { const created = await env.ARTIFACTS.create("starter-repo"); return Response.json({ name: created.name, remote: created.remote, }); }
if (request.method === "GET" && url.pathname === "/repos/starter-repo") { const repo = await env.ARTIFACTS.get("starter-repo"); return Response.json({ id: repo.id, name: repo.name, remote: repo.remote, defaultBranch: repo.defaultBranch, }); }
if (request.method === "POST" && url.pathname === "/tokens") { const repo = await env.ARTIFACTS.get("starter-repo"); const token = await repo.createToken("read", 3600); return Response.json(token); }
return Response.json( { message: "Use POST /repos, GET /repos/starter-repo, or POST /tokens." }, { status: 404 }, ); },} satisfies ExportedHandler<Env>;Run npx wrangler types in your own project and treat the generated worker-configuration.d.ts file as the source of truth for the Artifacts binding types in that environment.