Skip to content
Go to file


Failed to load latest commit information.
Latest commit message
Commit time

Welcome to oto project

Go driven rpc code generation tool for right now.

  • 100% Go
  • Describe services with Go interfaces (with structs, methods, comments, etc.)
  • Generate server and client code
  • Production ready templates (or copy and modify)


These templates are already being used in production.


Install the project:

go install

Create a project folder, and write your service definition as a Go interface:

// definitions/definitons.go
package definitions

// GreeterService makes nice greetings.
type GreeterService interface {
    // Greet makes a greeting.
    Greet(GreetRequest) GreetResponse

// GreetRequest is the request object for GreeterService.Greet.
type GreetRequest struct {
    // Name is the person to greet.
    // example: "Mat Ryer"
    Name string

// GreetResponse is the response object for GreeterService.Greet.
type GreetResponse struct {
    // Greeting is the greeting that was generated.
    // example: "Hello Mat Ryer"
    Greeting string

Download templates from otohttp

mkdir templates \
    && wget -q -O ./templates/server.go.plush \
    && wget -q -O ./templates/client.js.plush

Use the oto tool to generate a client and server:

mkdir generated
oto -template ./templates/server.go.plush \
    -out ./oto.gen.go \
    -ignore Ignorer \
    -pkg generated \
gofmt -w ./oto.gen.go ./oto.gen.go
oto -template ./templates/client.js.plush \
    -out ./oto.gen.js \
    -ignore Ignorer \
  • Run oto -help for more information about these flags

Implement the service in Go:

// greeter_service.go
package main

// GreeterService makes nice greetings.
type GreeterService struct{}

// Greet makes a greeting.
func (GreeterService) Greet(ctx context.Context, r GreetRequest) (*GreetResponse, error) {
    resp := &GreetResponse{
        Greeting: "Hello " + r.Name,
    return resp, nil

Use the generated Go code to write a main.go that exposes the server:

// main.go
package main

func main() {
    g := GreeterService{}
    server := otohttp.NewServer()
    generated.RegisterGreeterService(server, g)
    http.Handle("/oto/", server)
    log.Fatal(http.ListenAndServe(":8080", nil))

Use the generated client to access the service in JavaScript:

import { GreeterService } from "oto.gen.js";

const greeterService = new GreeterService();

        name: "Mat"
    .then(response => alert(response.greeting))
    .catch(e => alert(e));

Specifying additional template data

You can provide strings to your templates via the -params flag:

oto \
    -template ./templates/server.go.plush \
    -out ./oto.gen.go \
    -params "key1:value1,key2:value2" \

Within your templates, you may access these strings with <%= params["key1"] %>.

Comment metadata

It's possible to include additional metadata for services, methods, objects, and fields in the comments.

// Thing does something.
// field: "value"
type Thing struct {

The Metadata["field"] value will be the string value.

  • The value must be valid JSON (for strings, use quotes)

Examples are officially supported, but all data is available via the Metadata map fields.


To provide an example value for a field, you may use the example: prefix line in a comment.

// GreetRequest is the request object for GreeterService.Greet.
type GreetRequest struct {
    // Name is the person to greet.
    // example: "Mat Ryer"
    Name string
  • The example must be valid JSON

The example is extracted and made available via the Field.Example field.


Special thank you to:

  • @mgutz - for struct tag support
  • @sethcenterbar - for comment metadata support

A PACE. project

You can’t perform that action at this time.