Evans gRPC Client

Evans cheatsheet — interactive gRPC client for calling services, exploring schemas. evans --host localhost --port 50051, call rpc methods, use reflection. gRPC testing tool.

6 min read

What it is

Evans is an interactive gRPC client that allows you to explore and call gRPC services from your terminal. It’s useful for debugging, testing, and interacting with gRPC APIs without writing client code.

Installation

Linux

# Using package managers (example for Debian/Ubuntu)
sudo apt update
sudo apt install evans

# Using Homebrew (if installed)
brew install evans

# From source (requires Go)
go install github.com/ktr0ggl/evans@latest

macOS

# Using Homebrew
brew install evans

Windows

# Using Scoop
scoop install evans

# Using Chocolatey
choco install evans

# From source (requires Go)
go install github.com/ktr0ggl/evans@latest

Core Concepts

  • Services: A collection of RPC methods. Evans discovers these from a .proto file or by connecting to a running gRPC server.
  • RPC Methods: The actual functions you can call on a gRPC service. Each method has a defined request and response message type.
  • Messages: The data structures used for requests and responses. Evans allows you to interactively define and populate these messages.
  • Reflection: Evans can use gRPC reflection to discover services and methods if the server supports it, making it easier to explore without pre-compiled .proto files.

Commands / Usage

Starting Evans

# Start Evans with a specific .proto file path
evans -p path/to/your/proto/file

# Start Evans with a gRPC server address (uses reflection)
evans -r grpc.example.com:50051

# Start Evans with both .proto file and server address
evans -p path/to/your/proto/file -r grpc.example.com:50051

# Start Evans with a package name filter
evans -p path/to/your/proto/file -P my.package.name

# Start Evans with a service name filter
evans -p path/to/your/proto/file -S MyService

# Start Evans with TLS enabled (requires server to support it)
evans -p path/to/your/proto/file -r grpc.example.com:50051 --tls

Exploring Services and Methods

Once Evans is running, you’ll see a prompt like evans>.

# List all available services
evans> services

# Select a service to work with
evans> use service.package.ServiceName

# List all methods within the currently selected service
evans> methods

# Select an RPC method to call
evans> use method.MethodName

Calling RPC Methods

After selecting a method (e.g., use method.CreateUser), you’ll be prompted to define the request message.

# Start defining the request message for the selected method
evans> call

# Evans will show the fields of the request message.
# For a message like: message CreateUserRequest { string name = 1; int32 age = 2; }
# You'll see:
# field name: (type: STRING)
# field age: (type: INT32)

# Enter values for the fields. For strings, type the string. For numbers, type the number.
# For nested messages or repeated fields, use 'new' or 'add'.

# Example interaction:
evans> call
field name: (type: STRING) "Alice"
field age: (type: INT32) 30

# If the request message has a nested message, e.g., UserInfo within CreateUserRequest
# message UserInfo { string email = 1; }
# message CreateUserRequest { string name = 1; UserInfo info = 2; }
evans> call
field name: (type: STRING) "Alice"
field info: (type: MESSAGE) new
  field email: (type: STRING) "alice@example.com"
  # After defining nested message, return to parent level
  # Evans will indicate returning from 'info'
  # Now back to CreateUserRequest fields
field age: (type: INT32) 30

# If the request message has a repeated field, e.g., tags: string[]
# message CreateUserRequest { string name = 1; repeated string tags = 2; }
evans> call
field name: (type: STRING) "Alice"
field tags: (type: REPEATED STRING) add
  # Evans prompts for each element to add
  # Enter value for element 1:
  "admin"
field tags: (type: REPEATED STRING) add
  # Enter value for element 2:
  "user"
field tags: (type: REPEATED STRING) # Press Enter to finish adding to repeated field

# Once all fields are defined, press Enter on an empty prompt to send the request.
evans> # Press Enter here

# Evans will display the response message.
# Example response:
# message CreateUserResponse { string id = 1; }
# {
#   "id": "a1b2c3d4"
# }

Other Commands

# Clear the screen
evans> clear

# Exit Evans
evans> exit

# Show help
evans> help

# Show current configuration
evans> config

# Set configuration options (e.g., timeout)
evans> config timeout 30s

# Show detailed information about a service, method, or message
evans> show service.package.ServiceName
evans> show method.MethodName
evans> show message.MessageName

# Inspect the currently selected service/method/message
evans> inspect

# Load a new .proto file
evans> load path/to/another/proto.proto

# Reload the current .proto file
evans> reload

# Set the server address if not provided at startup
evans> server grpc.example.com:50051

# Set the package filter
evans> package my.package.name

# Set the service filter
evans> service MyService

# Set the method filter
evans> method MethodName

Common Patterns

Interactively exploring an unknown API

  1. Start Evans pointing to the .proto file or server address.
    evans -r grpc.example.com:50051
    
  2. List services and use the one you’re interested in.
    evans> services
    evans> use grpc.example.com.UserService
    
  3. List methods and select one to inspect and call.
    evans> methods
    evans> use method.GetUser
    evans> show method.GetUser # See request/response types
    evans> call
    # ... define request fields ...
    # Press Enter to send
    

Calling a method with a specific ID

If you know the exact structure and want to pre-fill a request quickly:

# Example: Calling GetUser with ID "123"
evans> use service.UserService
evans> use method.GetUser
evans> call name:"123" # Directly provide field values
# Press Enter to send

Using JSON for complex requests

For very large or complex messages, typing can be tedious. Evans allows pasting JSON.

evans> use service.UserService
evans> use method.CreateUser
evans> call
# Paste a JSON object representing the request message
{
  "name": "Bob",
  "age": 25,
  "address": {
    "street": "123 Main St",
    "city": "Anytown"
  },
  "tags": ["test", "user"]
}
# Press Enter to send

Note: JSON input might require specific configurations or versions. The interactive prompt is the primary method.

Debugging with server reflection

If your server supports reflection, you don’t need the .proto files.

evans -r localhost:50051
# Evans will automatically discover services and methods
evans> services
evans> use service.MyService
evans> methods
evans> use method.DoSomething
evans> call
# ... fill fields ...

Gotchas

  • Proto File Paths: Ensure the .proto file path is correct and that any imported .proto files are accessible in the same directory or specified via include paths if Evans supports it.
  • Server Reflection: Not all gRPC servers implement reflection. If you start Evans with -r and it can’t discover services, reflection is likely not enabled on the server.
  • Message Types: Evans strictly enforces message types. If a field expects an integer and you provide a string, the call will likely fail.
  • Repeated Fields: When adding elements to a repeated field, remember to press Enter after each element and then press Enter on an empty prompt to signal the end of adding elements.
  • Nested Messages: Use new when prompted for a message field to enter the nested message definition.
  • TLS: If using --tls, ensure the server is configured for TLS and that you’re using the correct port. Certificate validation might be an issue in development environments.
  • Package/Service Filtering: The -P and -S flags filter services during startup. You can also use package and service commands interactively to change filters.
  • call Command Context: The call command always operates on the currently selected method. Make sure you’ve selected the correct method before calling.
  • Exit Behavior: Using exit will terminate Evans. Any unsaved configuration or state will be lost.