| name | create-template |
| description | Creates a new Earl HCL template for a specific API, database, or shell command. Use when adding a new service to Earl's template library, or when a pre-built template doesn't cover a needed command. |
Create Template
Creates an Earl HCL template file for a specific service and protocol. Each template defines
the commands, parameters, authentication, and protocol shape for one provider.
Process
- Discover — understand what service and command to build
- Infer protocol — map the user's description to one of Earl's 5 protocols
- Load reference — read the protocol reference for HCL shapes and patterns
- Write template — create the HCL file
- Review — show the user the complete template before running it
- Validate — run
earl templates validate
- Secrets — print checklist for the human to set secrets
- Verify — run a test
earl call
Phase 1: Discover Intent
If the request doesn't name a provider, command, and protocol, ask one question:
"What service do you want to call, and what should the command do? For example:
'Call the GitHub API to create an issue' or 'Query my PostgreSQL database for user records'."
Check for pre-built templates first
Earl ships with 26 ready-made provider templates. If the user names a known service, check
whether it is already imported before offering to import it:
earl templates list
Check the list carefully:
- If the specific command needed is already present (e.g.
github.create_issue appears in
the list), skip the import and go directly to Phase 7 to set any missing secrets.
- If the provider is imported but the specific command is not in the list (e.g.
github
commands appear but not github.create_issue), skip the import and proceed to custom template
authoring (phases 2–6) to add the missing command to the existing file.
- If the provider is not imported at all, offer to import the pre-built template:
earl templates import https://raw.githubusercontent.com/mathematic-inc/earl/main/examples/<provider>.hcl
If a pre-built template was imported, skip to Phase 7: Set Secrets — phases 2–6 are not
needed. Then continue to Phase 8 to verify the template works.
Only proceed to custom template authoring (phases 2–6) if no pre-built template covers the
needed command.
Phase 2: Infer Protocol
Map the user's description to a protocol:
| User mentions | Protocol | Reference file |
|---|
| REST, HTTP, API, endpoint, JSON API, webhook | http | ../references/http-templates.md (raw) |
| GraphQL, query/mutation (in API context) | graphql | ../references/graphql-templates.md (raw) |
| gRPC, protobuf, service mesh | grpc | ../references/grpc-templates.md (raw) |
| shell, bash, CLI, script, command line | bash | ../references/bash-templates.md (raw) |
| SQL, database, postgres, mysql, sqlite | sql | ../references/sql-templates.md (raw) |
If the answer is genuinely ambiguous, ask one follow-up question.
SSRF Warning
If the user mentions localhost, 127.0.0.1, 0.0.0.0, or any private IP range (10.x, 172.16-31.x,
192.168.x), warn immediately:
Earl blocks requests to private and loopback IP addresses (SSRF protection). This cannot be
bypassed. Use a publicly accessible URL, or use the bash protocol to call local services.
Phase 3: Load Reference
Read the reference file for the chosen protocol before writing any HCL. The reference file
contains the complete template shape, required fields, auth patterns, and known gotchas.
Critical rule for all protocols: HCL parses before Jinja renders. All {{ }} expressions
must be inside valid HCL string values.
# WRONG — invalid HCL:
params = [{{ args.limit }}]
# CORRECT — Jinja expression inside a string, rendered to a number at call time:
params = ["{{ args.limit }}"]
Phase 4: Draft Template
Do NOT write the file to disk yet. Compose the template content in memory — it will be
written to disk only after Phase 5 human review and approval.
Target path (determine now, write after approval):
- Local (project-specific):
./templates/<provider>.hcl
- Global (all projects):
~/.config/earl/templates/<provider>.hcl (macOS/Linux) or
%APPDATA%\earl\templates\<provider>.hcl (Windows)
Default to local if the current directory is a project (contains .git/, package.json,
Cargo.toml, or similar). Default to global otherwise.
Provider naming: lowercase letters and underscores only. No hyphens, dots, or uppercase.
Examples: github, my_company_api, internal_db.
If the file already exists: Read it first. Add the new command block to the existing
file rather than overwriting it.
Environments (optional): If the user needs staging/production separation, add an
environments block at the provider level. Environment variables are available as vars.*
in all template expressions. See the template schema docs
for full syntax. Only add environments when the user explicitly needs them — most templates
don't.
Template structure:
version = 1
provider = "<provider_name>"
command "<command_name>" {
title = "<Short title, shown in tool listings>"
summary = "<One-line summary>"
description = <<-EOT
<Full description of what this command does.>
Parameters:
- param_name: description
## Guidance for AI agents
Use this command to <explain when to use it>.
Example: `earl call --yes --json <provider>.<command> --param_name value`
EOT
annotations {
mode = "<read|write>"
secrets = ["<provider>.<secret_key>"]
}
param "<param_name>" {
type = "<string|number|boolean>"
description = "<What this parameter controls>"
required = <true|false>
default = "<default_value>" # omit if required = true
}
operation {
protocol = "<http|graphql|grpc|bash|sql>"
# ... protocol-specific fields from the reference file
}
result {
output = "{{ result }}"
}
}
Required for every template:
annotations.mode: "read" if the command reads data, "write" if it creates/modifies/deletes
annotations.secrets: list all secret keys the template needs (format: "provider.key_name")
description must include a ## Guidance for AI agents section
Phase 5: Human Review (Required)
Show the user the complete template content before writing the file:
"Here is the template I've drafted. Please review it before I write it to disk:
[show full template content]
Does this look correct? Should I write it and run earl templates validate?"
Do not write the file or proceed until the user explicitly approves. Once written to disk,
the template is immediately callable — there is no staging step. Approval here is the only
gate before it becomes live.
Phase 6: Validate
earl templates validate
Fix any errors reported and re-validate. Common errors:
| Error | Cause | Fix |
|---|
HCL parse error / unexpected token | Invalid HCL syntax | Check structure and quotes |
template root must be an object | Missing version/provider fields | Add version = 1 and provider = "..." |
undefined variable in Jinja | {{ args.x }} doesn't match a param name | Check param names match references |
params = [{{ ... }}] syntax error | Bare Jinja in HCL array | Wrap in string: ["{{ ... }}"] |
Phase 7: Set Secrets
Check annotations.secrets in the template file for required secret keys. For pre-built
imports, read the imported file at ~/.config/earl/templates/<provider>.hcl (macOS/Linux)
or %APPDATA%\earl\templates\<provider>.hcl (Windows) to find them.
Print a checklist:
Template ready. Set the required secrets in your terminal:
earl secrets set <provider>.<key>
(Repeat for each secret listed above)
Tell me when you're done and I'll verify they're set.
On macOS: Warn the user that the first earl secrets set run may show a system dialog asking
to allow Earl keychain access — click "Always Allow" to avoid repeated prompts.
After the user confirms, verify:
earl secrets list
Check that all required keys appear. If any are missing, re-print just the missing ones.
Phase 8: Verify
Run a test call with representative parameters:
earl call --yes --json <provider>.<command> --<param> <test_value>
Important: If annotations.mode = "write", the test call will create/modify/delete real
data. If the template defines environments (check the environments block for valid names),
use --env <name> to select a non-production environment for the test call. Otherwise, use a
test or sandbox account, a safe test value (e.g. a dedicated test repo), or choose a read-only
command for the initial verification. Warn the user before running write-mode test calls.
If the call fails:
- HTTP 401/403 → secret not set or wrong key name
no such command → template not loaded, check earl templates list
- Any other error → invoke
troubleshoot-earl
Next Steps
- To add another command to this template: invoke
create-template again for the same provider
- To replace existing CLI calls with Earl: invoke
migrate-to-earl
- To enforce Earl usage at the platform level: invoke
secure-agent
- If something isn't working: invoke
troubleshoot-earl