Skip to content
grepvine.aiJoin preview

CLI

gv is the Grepvine command-line client. It searches like grep, uploads directories, S3 prefixes and zip archives, keeps an index in step with a git repository, and manages organizations, members and API keys. Its source is at grepvine-ai/grepvine-cli.

Terminal window
curl -fsSL https://get.grepvine.ai/install.sh | sh

The script installs the latest release into ~/.local/bin after checking it against the release’s checksums.txt. Pass --version or --bin-dir to change either:

Terminal window
curl -fsSL https://get.grepvine.ai/install.sh | sh -s -- --version v0.3.0 --bin-dir ~/bin

Archives for each platform are also on the releases page. Run gv --version to check what you have.

Terminal window
gv login
gv whoami

gv login prints a URL and a code and opens a browser, where you approve the device. It then creates an API key named gv, or the name you pass with --name, and saves it in the configuration file.

gv logout removes the key from the file but doesn’t revoke it. To revoke a key, find its ID with gv key ls and run gv key rm ID.

Create a key for the job, store it as a secret, and pass it to gv as GREPVINE_API_KEY. gv key create prints only the key, and only once:

Terminal window
gv key create github-actions > gh.key

Best practices has a GitHub Actions workflow that syncs a repository on every push.

gv has three settings. Each one is read from its environment variable, then from the configuration file, then from the default:

Setting Environment variable Default
endpoint GREPVINE_API_ENDPOINT https://api.grepvine.ai
api_key GREPVINE_API_KEY None.
organization GREPVINE_ORGANIZATION None.

The configuration file is the one you pass with --config, else $GREPVINE_CONFIG, else ~/.grepvine/config.yaml. gv creates it with mode 0600 and refuses to read it if other users can.

gv config ls shows where each value comes from, with API keys shown only in part:

$ gv config ls
KEY VALUE SOURCE
endpoint https://api.grepvine.ai default
api_key gvk_0123**** GREPVINE_API_KEY
organization acme config file
Terminal window
gv config set organization acme
gv config set api_key - < gh.key # read the value from standard input
gv config get endpoint
gv config unset organization

gv config get exits with status 1 when the setting has no value.

With organization set, you can name an index without its organization: monorepo means acme/monorepo. gv index ls, gv org info and gv member ls then need no argument. A full ORGANIZATION/INDEX still takes precedence.

Terminal window
gv config set organization acme
gv search monorepo -F OrderNotFound

Run gv COMMAND --help for every flag of a command.

Command What it does More
gv search Searches an index with grep’s flags: -F, -i, -w, -U, -A, -B, -C, plus --filter and --max-results. Searching
gv upload Uploads a file, a directory, an S3 prefix, a zip archive or NDJSON records. Indexing
gv sync Makes an index mirror a directory or git repository, including deletions. Indexing
gv put Stores one document from a file or standard input, with metadata and conditions. Indexing
gv list, gv get, gv delete List keys, download a document or a byte range, and delete documents. Indexing
gv index ls, info, create, update, rm, and tag ls, tag set and tag rm. Indexing
gv org ls, info, create, rm and transfer organizations. Concepts
gv member ls, add, set-role and rm members of an organization. Concepts
gv key ls, create and rm your API keys. Sign in
gv config ls, get, set and unset settings. Configure
gv skills install, ls, show and uninstall the skill that teaches coding agents to use gv. Agent skill
gv completion Prints a completion script for bash, zsh, fish or PowerShell. Shell completion

gv index rm, gv org rm, gv org transfer and gv member rm ask you to type the name of what they change. Pass --force to skip the question in a script.

Results go to standard output. Progress, warnings and confirmation questions go to standard error. The upload progress line is drawn only on a terminal.

On a terminal, gv search groups results under each key and colours them as ripgrep does. Piped, it prints grep’s format: key:line:text for a matching line, key-line-text for a context line, and -- between groups that aren’t adjacent:

$ gv search acme/monorepo 'func \w+Handler\(' -A 1 | head -3
services/billing/refund.go:42:func RefundHandler(w http.ResponseWriter, r *http.Request) {
services/billing/refund.go-43- ctx := r.Context()
--

--color always keeps colours in a pipe, and --color never or NO_COLOR turns them off on a terminal.

--json prints one JSON object per line, with the API’s field names, so you can process the output with jq:

Terminal window
# Every key under services/ that still calls the v1 client.
gv search acme/monorepo -F 'billingv1.New(' --filter "path STARTSWITH 'services/'" --json \
| jq -r .key | sort -u
Command Each line
gv search One result.
gv list One document. With --delimiter, each common prefix comes first as {"prefix": ...}.
gv put The stored document’s {"key", "revision"}.
gv delete One result per key, in order: {"key", "revision"} when deleted, {"key", "error"} when not.
gv upload, gv sync Each document that wasn’t stored or deleted, then a last line of totals: {"uploaded", "bytes", "deleted", "failed"}.
gv sync --dry-run One planned change: {"action", "key"}, where action is upload, delete or tag. A tag change also carries its new value, or null when the tag is removed.
whoami, org, member, key, index, skills ls The objects they show.
Status Meaning
0 The command succeeded. gv search found at least one match.
1 gv search found no match, or gv config get found no value.
2 An error, including an upload or sync that left any document unstored or undeleted.

gv retries for you, so a script doesn’t need its own loop:

  • A 429 pauses every request of the gv process for the Retry-After interval, give or take 25%. One wait lasts at most a minute, and a request gives up after 10 minutes of waiting in total.
  • A batch in gv upload or gv sync that fails with a 5xx or a dropped connection is sent again, up to 8 times over about 45 seconds.
  • An interrupted upload can be run again as it was. Over an unchanged source, each batch carries the same idempotency key as before, so a batch the service already stored isn’t written twice.

gv upload keeps 16 batches in flight (--concurrency, from 1 to 64) and gzips them, except to an endpoint on your own machine (--compress auto, always or never).

gv completion prints a completion script for commands and flags. To load it in the current shell:

Terminal window
source <(gv completion bash) # bash
source <(gv completion zsh) # zsh
gv completion fish | source # fish
gv completion powershell | Out-String | Invoke-Expression # PowerShell

To load it in every new shell, save it where your shell looks for completions, as in gv completion zsh > "${fpath[1]}/_gv". gv completion SHELL --help gives the location for each shell and platform.