---
title: Templates
description: Author, install, and manage HCL template files
icon: FileCode2
---

Templates are HCL files that define constrained API operations. Place them in `./templates/` (workspace) or `~/.config/earl/templates/` (global). Workspace templates override global ones when both define the same `provider.command`.

## Installing Templates

```bash
# Local path
earl templates install ./my-template.hcl
earl templates install /opt/templates/github.hcl

# Remote URL
earl templates install https://example.com/templates/github.hcl

# Install globally instead of the current workspace
earl templates install https://example.com/templates/github.hcl --scope global
```

`--scope local` (default) writes to `./templates/`. `--scope global` writes to `~/.config/earl/templates/`.

Requirements:
- Source must be a `.hcl` file (not a directory).
- Remote sources must use `http://` or `https://`.
- Installation fails if the destination file already exists.

## Authoring Templates

```hcl
version = 1
provider = "github"
categories = ["scm"]

command "search_issues" {
  title = "Search Issues"
  summary = "Search GitHub issues using a query string"
  description = <<-EOF
Search for GitHub issues and pull requests using GitHub's search syntax.
EOF

  annotations {
    mode = "read"
    secrets = ["github.token"]
  }

  param "query" {
    type = "string"
    required = true
  }

  param "per_page" {
    type = "integer"
    required = false
    default = 10
  }

  operation {
    protocol = "http"
    method = "GET"
    url = "https://api.github.com/search/issues"

    headers = {
      Accept = "application/vnd.github+json"
      X-GitHub-Api-Version = "2022-11-28"
    }

    query = {
      q = "{{ args.query }}"
      per_page = "{{ args.per_page }}"
    }

    auth {
      kind = "bearer"
      secret = "github.token"
    }
  }

  result {
    decode = "json"
    output = "{{ result }}"
  }
}
```

For field-level details, see the [Template Schema Reference](/docs/template-schema).

### Operation Protocols

| Protocol  | Description           |
| --------- | --------------------- |
| `http`    | Standard HTTP request |
| `graphql` | GraphQL over HTTP     |
| `grpc`    | gRPC over HTTP/2      |
| `cli`     | Local CLI command     |

#### GraphQL

```hcl
operation {
  protocol = "graphql"
  method = "POST"
  url = "https://api.example.com/graphql"

  graphql {
    query = "query User($id: ID!) { user(id: $id) { login } }"
    operation_name = "User"
    variables = {
      id = "{{ args.user_id }}"
    }
  }
}

result {
  decode = "json"
  output = "{{ result }}"
}
```

#### gRPC

```hcl
operation {
  protocol = "grpc"
  url = "http://127.0.0.1:50051"
  headers = {
    x-trace-id = "{{ args.trace_id }}"
  }

  auth {
    kind = "bearer"
    secret = "service.token"
  }

  grpc {
    service = "grpc.health.v1.Health"
    method = "Check"
    body = {
      service = ""
    }
    # Optional when server reflection is unavailable:
    # descriptor_set_file = "./descriptors/health.fds.bin"
  }
}

result {
  decode = "json"
  output = "{{ result }}"
}
```

#### CLI

CLI templates execute local commands. The command must be listed in [`network.allow_cli_commands`](/docs/configuration#cli-command-allowlist) in your config.

```hcl
operation {
  protocol = "cli"

  cli {
    command = "cargo"
    args = ["--version", "{{ args.extra_flag }}"]
    env = {
      CARGO_TERM_COLOR = "always"
    }
    cwd = "{{ args.working_dir }}"
  }
}

result {
  decode = "text"
  output = "{{ result }}"
}
```

## Managing Templates

```bash
earl templates list                       # List all commands
earl templates list --mode read           # Filter by mode
earl templates list --category scm        # Filter by category
earl templates search 'find open PRs'    # Semantic search
earl templates validate                   # Validate all templates
```

### Generating Templates

Delegate template authoring to a coding CLI:

```bash
earl templates generate -- claude --dangerously-skip-permissions
```

Earl passes the template schema as context to the coding CLI, which generates a valid `.hcl` file.
