How to Integrate OpenClaude into CI/CD Pipelines Using Its gRPC Service

OpenClaude exposes a full‑featured duplex streaming gRPC API through the AgentService.Chat RPC, enabling automated CI/CD systems to execute prompts, stream incremental results, handle tool permissions, and maintain conversational state across pipeline stages.

The open‑source Gitlawb/openclaude repository provides a language‑agnostic gRPC interface that allows any continuous integration system to leverage AI‑driven automation. By integrating the gRPC service into your CI/CD workflows, you can trigger the model to run linting, execute tests, or perform deployments while retaining context across multiple job stages.

Understanding the OpenClaude gRPC Architecture

The gRPC implementation centers on a duplex streaming model defined in src/proto/openclaude.proto and implemented in src/grpc/server.ts. This architecture enables real‑time bidirectional communication between your CI runner and the AI agent.

Core Server Components

The GrpcServer class in src/grpc/server.ts instantiates a native grpc.Server, registers the AgentService.Chat method, and manages the streaming lifecycle. When a CI client connects, the server initializes a QueryEngine instance through the handleChat function to process the request.

Key architectural elements include:

  • Session persistence – An in‑memory Map<string, Message[]> stored in the server maintains conversation history for up to 1,000 concurrent sessions, allowing CI pipelines to resume context across discrete steps by reusing the same session_id.
  • Tool permission flow – When the model invokes a tool (e.g., run_command), the server emits a tool_start event followed by an action_required message. The CI client must respond with a permission reply, after which the server returns the tool_result.
  • Streaming response protocol – The server streams text_chunk events for incremental output, terminates with a done message containing the full response text and token usage metrics (prompt_tokens, completion_tokens).

The Protocol Buffer Service Definition

The service contract lives in src/proto/openclaude.proto and is loaded at runtime using @grpc/proto-loader. The AgentService exposes a single bidirectional streaming RPC:

service AgentService {
  rpc Chat(stream ChatRequest) returns (stream ChatResponse);
}

This design permits the CI client to send configuration updates or permission responses while simultaneously receiving streamed output from the model.

Setting Up the gRPC Server in CI/CD Environments

Before any client can interact with OpenClaude, the gRPC server must be running as a background process within your CI environment. The server binds to port 50051 by default.

Start the server from your CI configuration:


# Start the gRPC server in the background

node -r ./src/grpc/server.ts &
echo $! > server.pid

# Or using the built distribution

node dist/grpc/server.js &

Verify the server is ready by checking for the startup log:


# Wait for server initialization

until grep -q "gRPC Server running at localhost:50051" server.log; do
  sleep 1
done

Building a CI/CD Client for OpenClaude

Any CI system capable of running a gRPC client (Node.js, Python, Go, etc.) can interact with OpenClaude. The reference implementation in scripts/grpc-cli.ts demonstrates the required interaction patterns.

Connecting to the Service

Establish an insecure connection (suitable for localhost CI environments) using the generated service definition:

// ci-client.ts
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
import path from 'path';

const PROTO_PATH = path.resolve(import.meta.dirname, '../src/proto/openclaude.proto');
const pkg = protoLoader.loadSync(PROTO_PATH, {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true
});

const { openclaude } = grpc.loadPackageDefinition(pkg) as any;
const client = new openclaude.v1.AgentService(
  'localhost:50051',
  grpc.credentials.createInsecure()
);

Handling Streamed Responses

Open a duplex streaming call and handle the message types appropriately:

const call = client.Chat();

call.on('data', (msg) => {
  if (msg.text_chunk) {
    process.stdout.write(msg.text_chunk.text);
  }
  
  if (msg.done) {
    console.log('\n--- FINAL OUTPUT ---\n', msg.done.full_text);
    console.log('Token usage:', {
      prompt: msg.done.prompt_tokens,
      completion: msg.done.completion_tokens
    });
    process.exit(0);
  }
});

call.on('error', (err) => {
  console.error('gRPC stream error:', err.message);
  process.exit(1);
});

Send the initial request with a persistent session identifier:

call.write({
  request: {
    session_id: 'ci-pipeline-123',
    message: 'Run `npm run lint` then `npm test` and report the outcome.',
    working_directory: process.cwd(),
    model: 'claude-3-5-sonnet-20240620'
  }
});

Managing Tool Permissions Automatically

In CI environments, you typically auto‑approve safe operations rather than waiting for human input. Handle the action_required message to programmatically approve tool execution:

call.on('data', (msg) => {
  if (msg.action_required) {
    // Auto‑approve command execution in CI context
    call.write({
      input: {
        prompt_id: msg.action_required.prompt_id,
        reply: 'y'
      }
    });
  }
  
  if (msg.tool_start) {
    console.log(`Executing tool: ${msg.tool_start.tool_name}`);
  }
  
  if (msg.tool_result) {
    console.log('Tool output:', msg.tool_result.stdout);
  }
});

This pattern ensures that when the QueryEngine invokes run_command or other tools, the pipeline continues without interruption.

Complete CI/CD Integration Examples

GitLab CI Configuration

Integrate OpenClaude into a GitLab pipeline by starting the server as a background service and running the client as a script job:


# .gitlab-ci.yml

stages:
  - lint
  - test

variables:
  OPENCLAUDE_PORT: "50051"

start-openclaude:
  stage: .pre
  image: node:22
  script:
    - bun install
    - node src/grpc/server.ts > server.log 2>&1 &
    - |
      until grep -q "gRPC Server running at localhost:$OPENCLAUDE_PORT" server.log; do
        sleep 1
      done
    - echo "Server ready"
  artifacts:
    paths:
      - server.log
      - node_modules/

ai-lint:
  stage: lint
  image: node:22
  dependencies:
    - start-openclaude
  script:
    - node ci-client.ts "Run ESLint and fix any auto-fixable issues, then report remaining errors"

ai-test:
  stage: test
  image: node:22
  dependencies:
    - start-openclaude
    - ai-lint
  script:
    - node ci-client.ts "Execute the test suite and analyze any failures. Use session_id: ci-pipeline-123"

GitHub Actions Workflow

For GitHub Actions, use a job step to initialize the server and subsequent steps to interact with it:


# .github/workflows/ai-ci.yml

name: AI-Driven CI

on: [push]

jobs:
  ai-validation:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '22'
          
      - name: Install dependencies
        run: bun install
        
      - name: Start OpenClaude gRPC Server
        run: |
          node src/grpc/server.ts &
          echo "SERVER_PID=$!" >> $GITHUB_ENV
          sleep 3
          
      - name: Run AI Linting
        run: node ci-client.ts "Run npm run lint and summarize findings"
        env:
          SESSION_ID: ${{ github.run_id }}
          
      - name: Run AI Tests
        run: node ci-client.ts "Run npm test with coverage. Use session_id: ${{ github.run_id }}"
        
      - name: Cleanup Server
        if: always()
        run: kill $SERVER_PID || true

Summary

  • OpenClaude's gRPC service provides a AgentService.Chat duplex streaming RPC that enables real‑time AI automation within CI/CD pipelines.
  • Session persistence allows you to maintain context across pipeline stages by reusing session_id values; the server stores up to 1,000 sessions in memory.
  • Tool execution requires handling action_required messages to approve commands; CI implementations should auto‑respond with 'y' to prevent blocking.
  • Token metrics in the done message enable cost tracking and usage monitoring for budget-conscious CI environments.
  • Language independence means you can implement clients in Node.js, Python, Go, or any gRPC‑supported language, as demonstrated by the reference CLI in scripts/grpc-cli.ts.

Frequently Asked Questions

How do I persist conversation context across multiple CI/CD stages?

Pass a consistent session_id string in each request message sent to the Chat stream. The server implementation in src/grpc/server.ts maintains an in‑memory Map<string, Message[]> that associates your session ID with the conversation history, allowing subsequent pipeline steps to reference previous tool results and AI decisions.

What is the default port for the OpenClaude gRPC server, and can it be customized?

The default port is 50051, as indicated by the server startup log message. You can override this by modifying the server configuration in src/grpc/server.ts before instantiation, or by setting the appropriate environment variable if the implementation supports it (check the server initialization code for process.env references).

How should I handle errors when the AI attempts to execute commands in a CI environment?

Implement the action_required handler in your client to programmatically respond to tool permission prompts. In src/grpc/server.ts, when a tool is invoked, the server emits an action_required message containing a prompt_id. Your CI client must write an input message back to the stream with the matching prompt_id and reply: 'y' to authorize execution, preventing the pipeline from hanging indefinitely.

Can I use the provided CLI script for CI integration, or do I need a custom client?

You can use scripts/grpc-cli.ts for prototyping and simple pipelines, as it handles the duplex streaming, tool permissions, and session management interactively. However, for production CI/CD workflows, a custom client is recommended because it allows you to programmatically handle the done message for exit codes, parse token usage metrics, and implement specific error handling logic tailored to your deployment requirements.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →