{"slug": "tanstack-ais-sandbox-api", "title": "TanStack AI’s Sandbox API", "summary": "TanStack AI's Sandbox API lets developers drive Claude Code in a remote cloud sandbox to clone a GitHub repository, branch it, add a requested feature and open a pull request, according to a tutorial published on the Master.dev blog. The walkthrough configures a GitHub personal access token with read/write access to Contents and Pull requests, an Anthropic API key, and provider credentials for Vercel (VERCEL_TOKEN, VERCEL_TEAM_ID, VERCEL_PROJECT_ID) or Railway (project and environment IDs). The author positions the approach as a slower, paid alternative to pairing a laptop with a phone via tools like T3 and Codex, suited to occasional use when no always-on machine is available.", "body_md": "TanStack AI is a fantastic SDK for integrating AI features into software. I’ve written about it [here](https://blog.master.dev/unlocking-ai-in-your-apps-with-tanstack-ai/) and [here](https://blog.master.dev/structured-output-with-tanstack-ai/). Those posts covered basic prompt-based requests; we provided context and asked AI to generate some workouts for us. We went through streaming, persistence, and structured output.\n\nThis post is about doing actual agentic work through TanStack AI, via their Sandbox API. Specifically, we’ll use TanStack AI to drive Claude Code in a remote sandbox, make changes to a GitHub repo, and open a pull request. Why would you want to do this? Sometimes you’re away from your computer with some downtime and nothing better to do than get a few tasks done.\n\nI want to be clear: this is already possible with tools like T3, Codex, etc. You can pair your laptop and your phone, and drive the former from the latter. But your laptop needs to be up and running for that to work. Ideally, you’d have a PC set up and always on, running a simple Linux distro, for this very purpose. But if you don’t have that set up, and don’t care to, what I’ll show you here is a decent next-best alternative. It won’t be nearly as fast, and you’ll have to pay a small amount to providers like Vercel or Railway to use the remote sandboxes. But as an occasional fill-in, it’s more than good enough in my opinion.\n\n## \n\nI have a dirt-simple web app [here](https://github.com/arackaf/tanstack-ai-sandboxes-blog-post). It has pages for different programming languages, with brief descriptions of each. I also have some admin pages that let me add features by prompting Claude Code in a remote sandbox with GitHub access.\n\nThe app has admin pages for Vercel and Railway, and both providers can clone our repo, branch, add the requested feature, and open a PR.\n\nLet’s take a look!\n\n## \n\nYou’ll need a few tokens. We’ll use Claude Code in our sandbox and connect it to GitHub so we can clone the repo and create PRs.\n\nLet’s set up GitHub first. Go over to [https://github.com/settings/personal-access-tokens](https://github.com/settings/personal-access-tokens) and generate a new token. Make sure you select either “All Repositories” or “Only select repositories” (and select the repositories you want to provide access to). Then, for permissions, choose “Contents” and “Pull requests” with read/write access, and Metadata should auto-populate.\n\nGenerate the token and copy it into this environment var:\n\n```\nGH_TOKEN=\"github_pat_abc_xyz\"\n```\n\nNext, head over to the [Anthropic console](https://platform.claude.com/settings/keys), generate an API key, and copy it into a new env var:\n\n```\nANTHROPIC_API_KEY=\"sk-ant-xyz-abc\"\n```\n\n## \n\nWe’ll be running code in a cloud sandbox. TanStack AI supports [a lot of different options](https://tanstack.com/ai/latest/docs/sandbox/providers#set-up-a-provider). We’ll cover Vercel and Railway here, but of course check the docs if you want to use something else.\n\n### \n\nIf you want to use Vercel, we’ll need three new env vars.\n\nFirst, head over to your account settings page, which you can access from the bottom left.\n\nClick that top section with your name and email, then click the tokens link in the left nav. Create your token, and add it into this env var:\n\n```\nVERCEL_TOKEN=\"vcp_abc_xyz\"\n```\n\nNext, go to your Vercel team in the top left, then click on Settings, and grab your team ID.\n\nCopy it into a new env var:\n\n```\nVERCEL_TEAM_ID=\"team_xyz\"\n```\n\nLastly, create the Vercel project you want to associate with this work, click Settings, and copy the project ID.\n\nThen add it:\n\n```\nVERCEL_PROJECT_ID=\"prj_kBL24CmynuMNcclr4k5s55lqg2xf\"\n```\n\n### \n\nIf you want to use Railway, you’ll need two values. First, for the environment ID, go to the project settings page and click **Environments**. It should look something like this:\n\nIt’s a little wonky, but look at the URL, and you should see something like this:\n\n```\n?environmentId=abcd-efgh-ijkl\n```\n\nGrab that `environmentId` and put it in a new env var:\n\n```\nRAILWAY_ENVIRONMENT_ID=\"abcd-efgh-ijkl\"\n```\n\nThen, hit the tokens link on the same page in the left navigation list, create yourself a token, and, as always, add it as a new env var:\n\n```\nRAILWAY_TOKEN=\"c0903fad-4336-4f0f-a0bf-3edc7abcfc51\"\n```\n\n## \n\nIf you’ve read my prior posts on TanStack AI, almost everything is the same. Persistence, resumability with a memory stream, etc., are all the same. The main difference is that, rather than routing our request through something like Vercel’s AI Gateway, we’ll provide a sandbox where the `chat` function can execute our request. That sandbox will have access to Claude Code and GitHub (via the setup we did above). This allows it to clone our repo, do work, and open pull requests.\n\nWe’ll review Vercel and Railway sandboxes, then put them to work.\n\n### \n\nHere’s my code for creating a Vercel sandbox:\n\n``` js\nimport { createSecrets, defineSandbox, defineWorkspace, githubRepo } from \"@tanstack/ai-sandbox\";\nimport { vercelSandbox } from \"@tanstack/ai-sandbox-vercel\";\n\nexport const sandboxVercel = defineSandbox({\n  id: \"repo-agent\",\n  provider: vercelSandbox({}),\n  workspace: defineWorkspace({\n    source: githubRepo({ repo: \"arackaf/tanstack-ai-sandboxes-blog-post\" }),\n    setup: [\n      \"sudo npm install -g @anthropic-ai/claude-code\",\n\n      \"sudo dnf install -y 'dnf-command(config-manager)'\",\n      \"sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo\",\n      \"sudo dnf install -y gh\",\n\n      \"npm install\",\n    ],\n    secrets: createSecrets({\n      ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY ?? \"\",\n      GH_TOKEN: process.env.GH_TOKEN ?? \"\",\n    }),\n    instructions:\n      \"Accomplish the user's request and create a pull request. To publish work: run `gh auth setup-git` once, then `git push -u origin <branch>` and `gh pr create`. GH_TOKEN is already in the environment.\",\n  }),\n  lifecycle: { reuse: \"thread\" },\n});\n```\n\nVercel requires a few more setup steps than Railway because its default container doesn’t include the GitHub CLI or Claude Code, so we have to install them ourselves. Also note this line:\n\n```\nlifecycle: { reuse: \"thread\" },\n```\n\nThis tells TanStack AI to reuse the same sandbox within the same `threadId` (on the same server instance), so follow-up prompts and clarifications should maintain context.\n\n### \n\nRailway is pretty similar, but with less setup, since their sandbox image comes with more batteries included.\n\n``` js\nimport { createSecrets, defineSandbox, defineWorkspace, githubRepo } from \"@tanstack/ai-sandbox\";\nimport { railwaySandbox } from \"@tanstack/ai-sandbox-railway\";\n\nexport const sandboxRailway = defineSandbox({\n  id: \"repo-agent\",\n  provider: railwaySandbox({}),\n  workspace: defineWorkspace({\n    source: githubRepo({\n      repo: \"arackaf/tanstack-ai-sandboxes-blog-post\",\n    }),\n    setup: [\"npm install\"],\n    secrets: createSecrets({\n      ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY ?? \"\",\n      GH_TOKEN: process.env.GH_TOKEN ?? \"\",\n    }),\n    instructions:\n      \"Accomplish the user's request and create a pull request. To publish work: run `gh auth setup-git` once, then `git push -u origin <branch>` and `gh pr create`. GH_TOKEN is already in the environment.\",\n  }),\n  lifecycle: { reuse: \"thread\" },\n});\n```\n\n## \n\nWith all that set up, everything else is the same. If you’ve read my prior posts on TanStack AI, you now have pretty much everything you need to run code inside of a sandbox, with access to your GitHub repository. Here’s what my call to `chat` in my API endpoint looks like:\n\n``` js\nconst stream = chat({\n  adapter: claudeCodeText(\"claude-opus-4-8\"),\n  messages,\n  threadId,\n  runId,\n  middleware: [withPersistence(chatPersistence), withSandbox(sandboxVercel)],\n});\n```\n\nThe sandbox is simply a new middleware entry.\n\nIf you want to see the full code, the repo [is here](https://github.com/arackaf/tanstack-ai-sandboxes-blog-post).\n\n## \n\nLet’s make a feature request on the Vercel route.\n\nWe can see the actual sandbox if we go to our Vercel dashboard:\n\nEventually, our PR is created:\n\n## \n\nYou’ll probably want to clean up the resources you’ve created. Our sandbox object has a `destroy` method, and we’ll also want to remove the relevant rows from the persistence DB. Here’s what my Vercel cleanup looks like:\n\n``` js\nimport { createServerFn } from \"@tanstack/react-start\";\nimport { eq } from \"drizzle-orm\";\n\nimport { db } from \"../drizzle/db\";\nimport { chatRuns, chatThreads } from \"../drizzle/schema\";\nimport { sandboxVercel } from \"#/lib/vercel-sandbox\";\n\nexport const deleteVercelSession = createServerFn({ method: \"POST\" })\n  .validator((data: { threadId: string }) => data)\n  .handler(async ({ data }) => {\n    const { threadId } = data;\n    const runs = await db.select({ runId: chatRuns.runId }).from(chatRuns).where(eq(chatRuns.threadId, threadId));\n\n    try {\n      console.log(\"Deleting threadId \" + threadId + \" ...\");\n      for (const run of runs) {\n        await sandboxVercel.destroy({ runId: run.runId, threadId });\n      }\n      await db.delete(chatRuns).where(eq(chatRuns.threadId, threadId));\n      await db.delete(chatThreads).where(eq(chatThreads.threadId, threadId));\n      console.log(\"Deleted\");\n    } catch (error) {\n      console.log(\"error deleting vercel sandbox\\n\\n\", error);\n      throw error;\n    }\n  });\n```\n\nRailway is identical except, of course, we call `destroy` on `sandboxRailway`.\n\n**Note:** As of this writing, the Vercel cleanup provided by `@tanstack/ai-sandbox-vercel` isn’t quite… effective. The sandbox is only stopped, not deleted, and any disk snapshots aren’t deleted either. Hopefully this will be fixed soon, but whip up a cleanup script using the Vercel API if you plan to use it.\n\nRailway does not have this problem. That said, Railway doesn’t delete disk checkpoints, but you’re not charged for them.\n\n## \n\nTanStack AI’s Sandbox API is a joy to use. It makes remote AI request execution a breeze. The flow, performance, and overall UX don’t quite compare to running Claude Code or Codex directly, but when you’re away from your laptop, it gets the job done well enough.", "url": "https://wpnews.pro/news/tanstack-ais-sandbox-api", "canonical_source": "https://blog.master.dev/tanstack-ai-sandbox-api/", "published_at": "2026-11-09 12:56:45+00:00", "updated_at": "2026-11-09 13:21:37.884325+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-products"], "entities": ["TanStack AI", "Claude Code", "GitHub", "Anthropic", "Vercel", "Railway", "T3", "Codex"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/tanstack-ais-sandbox-api", "markdown": "https://wpnews.pro/news/tanstack-ais-sandbox-api.md", "text": "https://wpnews.pro/news/tanstack-ais-sandbox-api.txt", "jsonld": "https://wpnews.pro/news/tanstack-ais-sandbox-api.jsonld"}}