Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gcvx

A thin Google Cloud Vertex AI execution wrapper for Claude Code, plus a Claude Code plugin that delegates work to the Vertex-backed agent over the Agent Client Protocol (ACP).

gcvx does not reimplement anything Claude Code, the Claude Agent SDK, ACP, acpx, or claude-agent-acp already provide. It only selects the provider (Vertex AI) and a default model via environment variables, then hands off to the real tools. The one exception is claude-teammate, which additionally rewrites --model on the argv it was handed — the model a teammate runs cannot be held by environment variables alone, because Claude Code passes it on argv and argv wins. The whole runtime is two wrapper scripts, one plugin companion script, and three command Markdown files.

Command surface

gcvx init          # initial local setup
gcvx doctor        # read-only diagnostics (no model requests)
gcvx claude [...]  # ordinary Claude Code CLI, backed by Vertex AI
gcvx claude-acp    # ACP agent (claude-agent-acp), backed by Vertex AI
gcvx team [...]    # Claude Code on your own provider, teammates on Vertex AI

Claude Code plugin commands:

/gcvx:rescue              delegate investigation / fixing / implementation
/gcvx:review              read-only review of the working tree or branch
/gcvx:adversarial-review  challenge design direction and assumptions

The default model is fable, but it is configuration, not part of any command name.

Architecture

Direct interactive use:

gcvx claude
  └── Vertex environment wrapper
        └── ordinary claude CLI
              └── Google Cloud Vertex AI

Split-provider teams (gcvx team):

gcvx team
  └── ordinary claude CLI, on YOUR provider (e.g. a Claude subscription)
        └── teammate spawned as a tmux pane
              └── gcvx-teammate
                    └── Vertex environment wrapper + model policy
                          └── ordinary claude CLI
                                └── Google Cloud Vertex AI

Claude Code runs tmux-mode teammates as separate processes, so the leader and its teammates can sit on different providers and credentials while keeping the in-session teammate protocol intact — teammates still appear in the team list, and SendMessage still reaches a running one. The leader deliberately keeps your own provider; only teammates go to Vertex.

Requires tmux, and a leader started with gcvx team (the plain claude command spawns in-process teammates, which necessarily share the leader's provider).

Plugin delegation (ACP is used only at the plugin-to-agent boundary):

Claude Code parent session
  └── /gcvx:rescue | /gcvx:review | /gcvx:adversarial-review
        └── plugin/scripts/gcvx-companion
              └── acpx --agent "gcvx claude-acp"
                    └── claude-agent-acp (Claude Agent SDK)
                          └── Google Cloud Vertex AI

Installation

Dependencies:

npm install -g @anthropic-ai/claude-code
npm install -g @agentclientprotocol/claude-agent-acp
npm install -g acpx
# and the gcloud CLI: https://cloud.google.com/sdk/docs/install

Install gcvx:

scripts/install.sh          # preserves existing files; --force overwrites
gcvx init
gcvx doctor

This installs ~/.local/bin/gcvx and ~/.local/bin/gcvx-teammate, a reference config example, and the plugin at ~/.local/share/gcvx/plugin. Shell profiles are never modified. gcvx-teammate must stay beside gcvx: it locates gcvx relative to its own path, and gcvx team refuses to start without it.

Load the plugin in Claude Code:

claude --plugin-dir ~/.local/share/gcvx/plugin

During development, point --plugin-dir at the plugin/ directory of this repository instead.

Configuration

gcvx init creates ~/.config/gcvx/config (never overwriting an existing file). It is plain shell, sourced by the wrapper:

GCVX_GCP_PROJECT_ID="example-project"   # required
GCVX_GCP_REGION="global"                # default: global
GCVX_CLAUDE_MODEL="fable"               # default: fable

# Teammates spawned by `gcvx team`:
GCVX_TEAMMATE_MODEL="claude-sonnet-5"
GCVX_TEAMMATE_ALLOWED_MODELS="sonnet claude-sonnet-5"

# Optional binary overrides:
#GCVX_CLAUDE_BIN="claude"
#GCVX_CLAUDE_ACP_BIN="claude-agent-acp"
#GCVX_ACPX_BIN="acpx"

Google Cloud authentication uses Application Default Credentials:

gcloud auth application-default login

Usage

gcvx claude is a transparent wrapper — every ordinary Claude Code option and positional argument passes through unchanged, and stdin/stdout/stderr, the working directory, signals, and the exit status are preserved:

gcvx claude
gcvx claude -p "Review this implementation"
gcvx claude --resume
gcvx claude --permission-mode plan
gcvx claude --model opus     # overrides the configured default

The wrapper sets only CLAUDE_CODE_USE_VERTEX, ANTHROPIC_VERTEX_PROJECT_ID, CLOUD_ML_REGION, and ANTHROPIC_MODEL in the launched process. Your ordinary claude login and global settings are untouched, so subscription and Vertex use coexist.

gcvx team starts a leader on your own provider and routes its teammates to Vertex:

gcvx team
gcvx team --resume            # options pass through to claude

Teammate model policy is enforced in gcvx claude-teammate, not in prose, because Claude Code passes the leader's chosen model on the teammate's argv and argv beats ANTHROPIC_MODEL. Environment pinning alone would let a leader asking for an expensive model get it, billed to Vertex. A requested model outside GCVX_TEAMMATE_ALLOWED_MODELS is rewritten to GCVX_TEAMMATE_MODEL and a warning goes to stderr, which is visible in the teammate's pane. To let teammates reach another model, add both its alias and its explicit id to the allowlist — the leader may request either form.

Teammate processes outlive their tmux pane: killing the window or the tmux session leaves them running, and they must be terminated explicitly. Each teammate also pays a full session startup cost (system prompt, CLAUDE.md, skills) on its first request, so many short-lived teammates are more expensive than their task sizes suggest.

Plugin commands:

/gcvx:rescue investigate why the integration tests fail
/gcvx:rescue --background fix the race condition with the smallest safe patch
/gcvx:review
/gcvx:review --base main
/gcvx:adversarial-review challenge the authentication boundary

rescue is write-capable by default (acpx --approve-all). The review commands run read-only (--approve-reads with non-read permissions denied) and never apply fixes. --background uses Claude Code's native background execution; there is no gcvx job manager.

Tests

tests/test.sh

The suite uses fake executables and makes no network or model requests. It covers argument passthrough, stdio/cwd/exit-status preservation, the Vertex environment, ACP stdout purity, init/doctor behaviour, companion prompt selection, permission posture per mode, and shell-injection safety of task text.

Design constraints

  • No Python package, daemon, database, custom job manager, session store, or generic backend framework.
  • The single extension seam is ACP: replacing the agent later means changing the companion's agent command (gcvx claude-acp) and prompts only.
  • gcvx claude-acp never writes wrapper output to stdout; ACP owns it.

Deferred (see plan §24)

  • ACP session resume through /gcvx:rescue (--resume / --fresh).
  • Per-invocation model/effort flags for the plugin commands.
  • Version-pinning claude-agent-acp.
  • /gcvx:status / /gcvx:result / /gcvx:cancel job commands — only if native background execution proves insufficient.
  • A separate read-only advisor command.
  • Reverse invocation (a Vertex session launching a subscription-authenticated claude); the wrapper already keeps this possible by touching only its own child process environment.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages