Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0fcb0c3
implement basic upsert functionality under the pc index upsert command
austin-denoble Nov 14, 2025
acb1b87
update off rebase, add basic index fetch command
austin-denoble Nov 16, 2025
3cd9f76
encapsulate logic for establishing and IndexConnection with a name an…
austin-denoble Nov 16, 2025
723dd6c
Implement `sdk.NewIndexConnection`, clean up `context.Context` passin…
austin-denoble Nov 17, 2025
1920cdd
implement basic upsert functionality under the pc index upsert command
austin-denoble Nov 14, 2025
a9b29ad
update off rebase, add basic index fetch command
austin-denoble Nov 16, 2025
ce67b83
encapsulate logic for establishing and IndexConnection with a name an…
austin-denoble Nov 16, 2025
023d8b5
add fetch-by-metadata functionality to the fetch command, unify prese…
austin-denoble Nov 18, 2025
d129473
add list-vectors and query commands + presentation logic
austin-denoble Nov 19, 2025
95a6164
Merge remote-tracking branch 'origin/adenoble/index-upsert-mvp' into …
austin-denoble Nov 19, 2025
a808152
remove duplicate varP flags
austin-denoble Nov 19, 2025
ebc786f
add index describe-stats command and presenter
austin-denoble Nov 19, 2025
2600550
add update-vector command to cover both by ID and metadata filter, ad…
austin-denoble Nov 19, 2025
55048ef
implement index delete-vector command
austin-denoble Nov 19, 2025
139eecd
fix describe-stats presentation output, add new commands to root inde…
austin-denoble Nov 20, 2025
db67603
add custom flags JSONObject, Float32List, and Int32List to allow easi…
austin-denoble Nov 20, 2025
d5f2b5c
improve fetch and query presentation logic
austin-denoble Nov 20, 2025
07dc1c0
default namespace properly and fix logic error
austin-denoble Nov 20, 2025
ab144f0
fix batch upsert message
austin-denoble Nov 20, 2025
9ac98cb
add bodyutil and stdin packages to handle various types of input: JSO…
austin-denoble Nov 22, 2025
9b05937
add input validation for fetch, query, and delete_vectors to avoid si…
austin-denoble Nov 22, 2025
01baaa5
clean up DecodeBodyArgs usage, return a SrcInfo object to identify in…
austin-denoble Nov 22, 2025
2102152
add InputPolicy to cap the overall size of JSON files that can be pas…
austin-denoble Nov 24, 2025
32afd74
restructure vector/record commands into sub-command under index
austin-denoble Nov 24, 2025
53256fb
rename bodyutil package to argsio, rename functions in package to be …
austin-denoble Nov 24, 2025
07047f7
fix argio.ReadAll call
austin-denoble Nov 24, 2025
8e4cc3c
clean up and expand coverage of flags_test.go
austin-denoble Nov 24, 2025
6e8ccc1
add Long summaries to new commands
austin-denoble Nov 25, 2025
999c684
update README to include new dataplane documentation
austin-denoble Nov 25, 2025
7a13949
clean up comments, document usage of pinecone SDK types for JSON bodies
austin-denoble Nov 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 107 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,11 @@ There are three ways to authenticate the Pinecone CLI: through a web browser wit

This table describes the Pinecone operations supported by each authentication method:

| Method | Admin API | Control plane |
| :-------------- | :-------- | :------------ |
| User login | ✅ | ✅ |
| Service account | ✅ | ✅ |
| API key | ❌ | ✅ |
| Method | Admin API | Control plane | Data plane |
| :-------------- | :-------- | :------------ | :--------- |
| User login | ✅ | ✅ | ✅ |
| Service account | ✅ | ✅ | ✅ |
| API key | ❌ | ✅ | ✅ |

- Admin API–related commands (organization and project management, API key operations):

Expand All @@ -110,7 +110,12 @@ This table describes the Pinecone operations supported by each authentication me
- `pc api-key` (`create`, `list`, `describe`, `update`, `delete`)

- Control plane–related commands (index management):
- `pc index` (`create`, `list`, `describe`, `configure`, `delete`)

- `pc index` (`create`, `list`, `describe`, `configure`, `delete`, `describe-stats`)

- Data plane-related commands (index data management):

- `pc index vector` (`upsert`, `query`, `fetch`, `list`, `update`, `delete`)

### 1. User Login (Recommended for Interactive use)

Expand Down Expand Up @@ -158,6 +163,22 @@ pc config set-api-key "YOUR_API_KEY"

For more detailed information, see the [CLI authentication](https://docs.pinecone.io/reference/cli/authentication) documentation.

## Data plane commands overview

Work with your vector data inside an index. These commands require `--index-name` and optionally `--namespace`:

- Ingest and manage records:
- `pc index vector upsert` — insert or update vectors from JSON/JSONL
- `pc index vector list` — list vectors (with pagination)
- `pc index vector fetch` — fetch by IDs or metadata filter
- `pc index vector update` — update a vector by ID or update many via metadata filter
- `pc index vector delete` — delete by IDs, by filter, or delete all in a namespace
- `pc index vector query` — nearest-neighbor search by values or vector ID
- Index statistics:
- `pc index describe-stats` — show dimension, vector counts, namespace summary, and metadata field counts (optionally filtered)

Tip: add `--json` to many commands to get structured output.

## Quickstart

After installing the CLI, authenticate with user login or set an API key, verify your auth status, and list indexes associated with your automatically targeted project.
Expand All @@ -176,3 +197,83 @@ pc auth status
# List your indexes
pc index list
```

### JSON input formats

Many flags accept JSON in three forms:

- Inline JSON for smaller payloads, for example:
```bash
pc index vector fetch --index-name my-index --namespace demo --ids '["vec-1","vec-2"]'
```
- From a file with `@path`:
```bash
pc index vector upsert --index-name my-index --namespace demo --body @./vectors.jsonl
```
- From stdin with `@-`:
```bash
cat vectors.jsonl | pc index vector upsert --index-name my-index --namespace demo --body @-
```

NOTE: stdin can only be used with one flag at a time.

## Data plane quickstart (end-to-end)

### Body JSON schemas

For commands that accept a `--body` JSON payload, the CLI uses these schemas:

- UpsertBody — vectors of `pinecone.Vector` (see `https://pkg.go.dev/github.com/pinecone-io/go-pinecone/v5/pinecone#Vector`)
- QueryBody — fields: id, vector, `sparse_values` (see `https://pkg.go.dev/github.com/pinecone-io/go-pinecone/v5/pinecone#SparseValues`), filter, top_k, include_values, include_metadata
- FetchBody — fields: ids, filter, limit, pagination_token
- UpdateBody — fields: id, values, `sparse_values` (see `https://pkg.go.dev/github.com/pinecone-io/go-pinecone/v5/pinecone#SparseValues`), metadata, filter, dry_run

The following walkthrough creates an index, ingests vectors, and runs queries.

Prepare sample vectors (JSONL)

Create a file named `vectors.jsonl` with two lines:

```json
{"id":"vec-1","values":[0.1,0.2,0.3],"metadata":{"genre":"sci-fi","title":"Voyager"}}
{"id":"vec-2","values":[0.3,0.1,0.2],"metadata":{"genre":"fantasy","title":"Dragon"}}
```

Alternatively, you can upsert using a JSON object with a `vectors` array:

```json
{
"vectors": [
{
"id": "vec-1",
"values": [0.1, 0.2, 0.3],
"metadata": { "genre": "sci-fi", "title": "Voyager" }
},
{
"id": "vec-2",
"values": [0.3, 0.1, 0.2],
"metadata": { "genre": "fantasy", "title": "Dragon" }
}
]
}
```

```bash
# Create a serverless index
pc index create --name my-index --dimension 3 --metric cosine --cloud aws --region us-east-1

# Upsert vectors into the index via JSON or JSONL
pc index vector upsert --index-name my-index --namespace my-namespace --body @./vectors.jsonl

# List vectors
pc index vector list --index-name my-index --namespace my-namespace

# Fetch a vector by ID
pc index vector fetch --index-name my-index --namespace my-namespace --ids '["vec-1"]'

# Query by dense vector values
pc index vector query --index-name my-index --namespace my-namespace --vector '[0.1,0.2,0.3]' --top-k 3 --include-metadata

# Query by existing vector ID
pc index vector query --index-name my-index --namespace my-namespace --id vec-1 --top-k 3
```
3 changes: 2 additions & 1 deletion internal/pkg/cli/command/apiKey/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ func NewCreateApiKeyCmd() *cobra.Command {
pc api-key create --id "project-id" --name "key-name"
`),
Run: func(cmd *cobra.Command, args []string) {
ac := sdk.NewPineconeAdminClient()
ctx := cmd.Context()
ac := sdk.NewPineconeAdminClient(ctx)

projId := options.projectId
var err error
Expand Down
3 changes: 2 additions & 1 deletion internal/pkg/cli/command/apiKey/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ func NewDeleteKeyCmd() *cobra.Command {
pc api-key delete --id "api-key-id"
`),
Run: func(cmd *cobra.Command, args []string) {
ac := sdk.NewPineconeAdminClient()
ctx := cmd.Context()
ac := sdk.NewPineconeAdminClient(ctx)

// Verify key exists before trying to delete it.
// This lets us give a more helpful error message than just
Expand Down
3 changes: 2 additions & 1 deletion internal/pkg/cli/command/apiKey/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ func NewDescribeAPIKeyCmd() *cobra.Command {
`),
GroupID: help.GROUP_API_KEYS.ID,
Run: func(cmd *cobra.Command, args []string) {
ac := sdk.NewPineconeAdminClient()
ctx := cmd.Context()
ac := sdk.NewPineconeAdminClient(ctx)

apiKey, err := ac.APIKey.Describe(cmd.Context(), options.apiKeyID)
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion internal/pkg/cli/command/apiKey/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ func NewListKeysCmd() *cobra.Command {
`),
GroupID: help.GROUP_API_KEYS.ID,
Run: func(cmd *cobra.Command, args []string) {
ac := sdk.NewPineconeAdminClient()
ctx := cmd.Context()
ac := sdk.NewPineconeAdminClient(ctx)

var err error
projId := options.projectID
Expand Down
3 changes: 2 additions & 1 deletion internal/pkg/cli/command/apiKey/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ func NewUpdateAPIKeyCmd() *cobra.Command {
`),
GroupID: help.GROUP_API_KEYS.ID,
Run: func(cmd *cobra.Command, args []string) {
ac := sdk.NewPineconeAdminClient()
ctx := cmd.Context()
ac := sdk.NewPineconeAdminClient(ctx)

// Only set non-empty values
updateParams := &pinecone.UpdateAPIKeyParams{}
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/cli/command/auth/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func Run(ctx context.Context, io IO, opts configureCmdOptions) {

// Use Admin API to fetch organization and project information for the service account
// so that we can set the target context, or allow the user to set it like they do through the login or target flow
ac := sdk.NewPineconeAdminClient()
ac := sdk.NewPineconeAdminClient(ctx)

// There should only be one organization listed for a service account
orgs, err := ac.Organization.List(ctx)
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/cli/command/auth/local_keys_prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func NewPruneLocalKeysCmd() *cobra.Command {
}

func runPruneLocalKeys(ctx context.Context, options pruneLocalKeysCmdOptions) {
ac := sdk.NewPineconeAdminClient()
ac := sdk.NewPineconeAdminClient(ctx)
managedKeys := secrets.GetManagedProjectKeys()

// Filter to projectId if provided
Expand Down
6 changes: 2 additions & 4 deletions internal/pkg/cli/command/collection/create.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package collection

import (
"context"

"github.com/pinecone-io/cli/internal/pkg/utils/exit"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/pinecone-io/cli/internal/pkg/utils/msg"
Expand Down Expand Up @@ -32,8 +30,8 @@ func NewCreateCollectionCmd() *cobra.Command {
pc collection create --name "collection-name" --source "index-source-name"
`),
Run: func(cmd *cobra.Command, args []string) {
pc := sdk.NewPineconeClient()
ctx := context.Background()
ctx := cmd.Context()
pc := sdk.NewPineconeClient(ctx)

req := &pinecone.CreateCollectionRequest{
Name: options.name,
Expand Down
6 changes: 2 additions & 4 deletions internal/pkg/cli/command/collection/delete.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package collection

import (
"context"

"github.com/pinecone-io/cli/internal/pkg/utils/exit"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/pinecone-io/cli/internal/pkg/utils/msg"
Expand All @@ -25,8 +23,8 @@ func NewDeleteCollectionCmd() *cobra.Command {
pc collection delete --name "collection-name"
`),
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
pc := sdk.NewPineconeClient()
ctx := cmd.Context()
pc := sdk.NewPineconeClient(ctx)

err := pc.DeleteCollection(ctx, options.name)
if err != nil {
Expand Down
6 changes: 2 additions & 4 deletions internal/pkg/cli/command/collection/describe.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package collection

import (
"context"

"github.com/pinecone-io/cli/internal/pkg/utils/exit"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/pinecone-io/cli/internal/pkg/utils/msg"
Expand All @@ -28,8 +26,8 @@ func NewDescribeCollectionCmd() *cobra.Command {
pc collection describe --name "collection-name"
`),
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
pc := sdk.NewPineconeClient()
ctx := cmd.Context()
pc := sdk.NewPineconeClient(ctx)

collection, err := pc.DescribeCollection(ctx, options.name)
if err != nil {
Expand Down
5 changes: 2 additions & 3 deletions internal/pkg/cli/command/collection/list.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package collection

import (
"context"
"os"
"sort"
"strconv"
Expand Down Expand Up @@ -33,8 +32,8 @@ func NewListCollectionsCmd() *cobra.Command {
pc collection list
`),
Run: func(cmd *cobra.Command, args []string) {
pc := sdk.NewPineconeClient()
ctx := context.Background()
ctx := cmd.Context()
pc := sdk.NewPineconeClient(ctx)

collections, err := pc.ListCollections(ctx)
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions internal/pkg/cli/command/index/cmd.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package index

import (
"github.com/pinecone-io/cli/internal/pkg/cli/command/index/vector"
"github.com/pinecone-io/cli/internal/pkg/utils/help"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -39,6 +40,10 @@ func NewIndexCmd() *cobra.Command {
cmd.AddCommand(NewCreatePodCmd())
cmd.AddCommand(NewConfigureIndexCmd())
cmd.AddCommand(NewDeleteCmd())
cmd.AddCommand(NewDescribeIndexStatsCmd())

cmd.AddGroup(help.GROUP_INDEX_DATA)
cmd.AddCommand(vector.NewVectorCmd())

return cmd
}
7 changes: 3 additions & 4 deletions internal/pkg/cli/command/index/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func NewConfigureIndexCmd() *cobra.Command {
pc index configure --name "index-name" --deletion-protection "enabled"
`),
Run: func(cmd *cobra.Command, args []string) {
runConfigureIndexCmd(options)
runConfigureIndexCmd(cmd.Context(), options)
},
}

Expand All @@ -48,9 +48,8 @@ func NewConfigureIndexCmd() *cobra.Command {
return cmd
}

func runConfigureIndexCmd(options configureIndexOptions) {
ctx := context.Background()
pc := sdk.NewPineconeClient()
func runConfigureIndexCmd(ctx context.Context, options configureIndexOptions) {
pc := sdk.NewPineconeClient(ctx)

idx, err := pc.ConfigureIndex(ctx, options.name, pinecone.ConfigureIndexParams{
PodType: options.podType,
Expand Down
7 changes: 3 additions & 4 deletions internal/pkg/cli/command/index/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func NewCreateIndexCmd() *cobra.Command {
Long: createIndexHelp,
Example: createIndexExample,
Run: func(cmd *cobra.Command, args []string) {
runCreateIndexCmd(options)
runCreateIndexCmd(cmd.Context(), options)
},
}

Expand Down Expand Up @@ -141,9 +141,8 @@ func NewCreateIndexCmd() *cobra.Command {
return cmd
}

func runCreateIndexCmd(options createIndexOptions) {
ctx := context.Background()
pc := sdk.NewPineconeClient()
func runCreateIndexCmd(ctx context.Context, options createIndexOptions) {
pc := sdk.NewPineconeClient(ctx)

idx, err := runCreateIndexWithService(ctx, pc, options)
if err != nil {
Expand Down
7 changes: 3 additions & 4 deletions internal/pkg/cli/command/index/create_pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func NewCreatePodCmd() *cobra.Command {
pc index create-pod --name "my-index" --dimension 1536 --metric "cosine" --environment "us-east-1-aws" --pod-type "p1.x1" --shards 2 --replicas 2
`),
Run: func(cmd *cobra.Command, args []string) {
runCreatePodCmd(options)
runCreatePodCmd(cmd.Context(), options)
},
}

Expand All @@ -65,9 +65,8 @@ func NewCreatePodCmd() *cobra.Command {
return cmd
}

func runCreatePodCmd(options createPodOptions) {
ctx := context.Background()
pc := sdk.NewPineconeClient()
func runCreatePodCmd(ctx context.Context, options createPodOptions) {
pc := sdk.NewPineconeClient(ctx)

// Deprecation warning
pcio.Fprintf(os.Stderr, "⚠️ Warning: The '%s' command is deprecated. Please use '%s' instead.", style.Code("index create-pod"), style.Code("index create"))
Expand Down
7 changes: 3 additions & 4 deletions internal/pkg/cli/command/index/create_serverless.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func NewCreateServerlessCmd() *cobra.Command {
pc index create-serverless --name "my-index" --dimension 1536 --metric "cosine" --cloud "aws" --region "us-east-1"
`),
Run: func(cmd *cobra.Command, args []string) {
runCreateServerlessCmd(options)
runCreateServerlessCmd(cmd.Context(), options)
},
}

Expand All @@ -58,9 +58,8 @@ func NewCreateServerlessCmd() *cobra.Command {
return cmd
}

func runCreateServerlessCmd(options createServerlessOptions) {
ctx := context.Background()
pc := sdk.NewPineconeClient()
func runCreateServerlessCmd(ctx context.Context, options createServerlessOptions) {
pc := sdk.NewPineconeClient(ctx)

// Deprecation warning
pcio.Fprintf(os.Stderr, "⚠️ Warning: The '%s' command is deprecated. Please use '%s' instead.", style.Code("index create-serverless"), style.Code("index create"))
Expand Down
Loading
Loading