neon-object-storage – Data & Science skill for AI agents
S3-compatible object storage that branches with your Neon project, so files and the database stay in sync across every branch.
Install the neon-object-storage skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/neon-object-storage-178be.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /neon-object-storage – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/neon-object-storage-178be.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $neon-object-storage – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/neon-object-storage-178be.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /neon-object-storage – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/neon-object-storage-178be.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /neon-object-storage – then describe the task you want done.
SKILL.md content
Neon Object Storage
This is a preview feature and only available in us-east-2. Neon Object Storage is S3-compatible object storage that branches with your projects: every branch gets its own isolated storage state, so files and database rows stay in sync across dev, preview, staging, and production.
Use this skill to help the user store and serve files that branch alongside their database. Deliver a working bucket and upload/download flow, a branch-aware S3 client wired to the injected env vars, or a precise answer from the official Neon docs.
When to Use
Reach for Neon Object Storage when the user needs to store files (images, uploads, generated assets, documents, backups) and any of the following are true:
- They already use Neon Postgres and don't want a second provider. One backend, one bill, one CLI, one set of branches — instead of standing up and wiring a separate AWS S3 / R2 / Supabase Storage account. The same Neon credential that backs the database backs storage.
- Files must stay in sync with the database across environments. Storage branches _together with_ your Postgres data. Fork a branch and the child instantly inherits the parent's buckets and objects at that point in time — copy-on-write, so no data is duplicated. This is what makes agent, dev, preview, and test environments seamless: a preview branch gets a consistent snapshot of _both_ the rows and the files they reference, and writes on the child never touch the parent.
- They want safe, throwaway environments. Upload, overwrite, and delete files in a preview/CI branch within the verified branch and credential boundaries, then drop the branch.
- They want standard S3 tooling. It's built on S3 semantics and speaks the S3 API, so the AWS SDKs,
boto3, the AWS CLI, and presigned URLs all work — reliable and familiar, with no proprietary client.
If the user has no Neon project, isn't on Postgres, and just needs a standalone CDN-backed asset store, a dedicated object store may fit better — but the moment branch-consistent files + rows matter, this is the reason to use it.
What It Does
- S3-compatible — Works with existing S3 SDKs,
boto3, the AWS CLI, and presigned URLs. Path-style addressing and SigV4 only. - Branches with your database — Every Neon branch gets its own isolated, copy-on-write storage state. Forking copies no data.
- Two access modes —
privatebuckets require a credential for every operation;public_readbuckets allow anonymous reads with authenticated writes. - One credential system — The same Neon credential system used by Functions and the AI Gateway.
Verify current preview availability, CLI/SDK versions and project eligibility in the official docs before provisioning. Confirm the linked branch and inspect the plan before applying. Treat inherited production objects as sensitive in preview branches; descendant-capable credentials are broader than a single child branch. Protect and gitignore pulled environment files, keep credentials server-side, and use short-lived presigned URLs only for intended recipients. public_read is anonymous publication, requiring explicit scope.
Setup
Object storage is part of the neon.ts infrastructure-as-code config (see the neon skill for the branch-first workflow, link/checkout, and neon.ts basics). Declare buckets under preview.buckets, keyed by bucket name:
// neon.ts
import { defineConfig } from "@neon/config/v1";
export default defineConfig({
preview: {
buckets: {
images: {}, // private by default
"public-assets": { access: "public_read" },
},
},
});Provision the declared buckets on the linked branch:
neon deploy # alias for `neon config apply`Neon Infrastructure as Code (neon.ts)
The preview.buckets block above is part of neon.ts, Neon's infrastructure-as-code file — one TypeScript file declares your buckets alongside every other service the branch should have (see the neon skill for the full reference). Reconcile the declaration against a branch the Terraform way:
neon config status # print the branch's live config (which buckets exist)
neon config plan # dry-run diff of what apply would change
neon config apply # create the declared buckets (neon deploy is an alias)Buckets are branch-scoped: when a neon.ts is present, neon checkout applies the policy as it _creates_ a branch, so a fresh preview/CI branch comes up with its buckets already provisioned (and copy-on-write objects inherited from the parent). Checking out an _existing_ branch doesn't reconcile it — run neon deploy to apply changes. Provisioning (config apply / deploy), link, and checkout also pull the branch's S3 credentials into your local .env.local, so the same env pull step shown below happens for you on those commands.
For typed, validated access to the injected S3 credentials, pass the same config object to parseEnv from @neon/env — it returns an env.storage namespace (accessKeyId, secretAccessKey, endpoint, region) derived from your neon.ts.
Environment variables
When preview.buckets is declared, Neon injects AWS-standard S3 env vars so the AWS SDKs work from the environment with zero extra config. Inside a deployed Neon Function these are injected automatically; locally, pull them onto disk (or inject them at runtime) via the CLI:
neon env pull # writes the branch's vars into .env (or .env.local)
# or, without writing a file, inject at runtime:
neon-env run -- <your dev command>| Variable | Meaning |
| ----------------------- | --------------------------------------------------- |
| AWS_ACCESS_KEY_ID | S3 Access Key ID (the branch credential's token id) |
| AWS_SECRET_ACCESS_KEY | S3 Secret Access Key |
| AWS_ENDPOINT_URL_S3 | Branch S3 endpoint URL |
| AWS_REGION | Region, e.g. us-east-2 |
Because the names are AWS-standard, the AWS SDK picks up the credentials, endpoint, and region from the environment automatically. Credentials are branch-scoped and valid for that branch and all its descendants.
Working with objects: the Files SDK (recommended)
The simplest, most portable way to read and write objects is the [Files SDK](https://files-sdk.dev) with its neon adapter — a small, unified storage API (upload, download, url, list, exists, copy, delete, signedUploadUrl) over web-standard I/O. It uses the AWS S3 client under the hood, configured appropriately for Neon, and relabels errors as Neon error — so there's nothing to misconfigure. Reach for this first.
Install it alongside the AWS S3 peer dependencies the adapter uses internally:
npm install files-sdk @aws-sdk/client-s3 @aws-sdk/s3-presigned-post @aws-sdk/s3-request-presignerThe adapter resolves its endpoint, region, and credentials from the same injected AWS_* env vars — pass only the bucket name:
import { Files } from "files-sdk";
import { neon } from "files-sdk/neon";
const files = new Files({ adapter: neon({ bucket: "images" }) });
// Upload — body may be a Buffer, Uint8Array, Blob, File, ReadableStream, or string
await files.upload("generated/cat.jpg", fileBuffer, { contentType: "image/jpeg" });
// Download
const file = await files.download("generated/cat.jpg");
const bytes = new Uint8Array(await file.arrayBuffer());
// Presigned GET — share without exposing credentials (defaults to a 1h expiry)
const url = await files.url("generated/cat.jpg", { expiresIn: 3600 });
// Plus: files.exists(), files.list({ prefix }), files.copy(), files.delete(), files.signedUploadUrl()Swap the adapter import (files-sdk/s3, files-sdk/r2, files-sdk/gcs, …) and the rest of your code is unchanged.
Working with objects: the AWS S3 client (alternative)
Neon speaks the S3 API directly, so you can drop down to the AWS SDK whenever you prefer the native client or already depend on it. The credentials, endpoint, and region are read from the standard AWS env chain, so the only setting you pass is forcePathStyle: true — Neon requires path-style addressing, so the S3 client must set it:
import { S3Client } from "@aws-sdk/client-s3";
const s3 = new S3Client({
forcePathStyle: true, // required: Neon uses path-style addressing
});If you prefer typed access instead of reading process.env directly, parseEnv (from @neon/env) returns a validated env.storage namespace (accessKeyId, secretAccessKey, endpoint, region) derived from your neon.ts — see the neon skill.
Then upload, download, and presign with the raw command objects:
import { PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";… (full content is in the download package)
Related skills
- news-sentiment-engine – Multi-source RSS news aggregation with Claude-powered sentiment analysis and structured…
- nexrad-product-access – Discover and access NEXRAD data for a selected radar site, time, product, or Level II…
- nextjs-best-practices – Next.js App Router principles. Server Components, data fetching, routing patterns.
- ontoly-software-graph – Use Ontoly's deterministic Software Graph, MCP server, and agent skills for architecture…
- pangolinfo-amazon-data-research – Plan and run read-only Amazon product, review, category, seller, and market research…
- pci-compliance – Review payment data flows and engineering control evidence for a scoped PCI assessment…
- pci-dss-compliance – Implement PCI DSS requirements for payment card data. Configure cardholder data…
- people-data – Research LinkedIn professional profiles and public business-contact data, including…