- Go 96.1%
- Shell 3.7%
- Makefile 0.2%
|
All checks were successful
CI / Lint (push) Successful in 58s
CI / Test (push) Successful in 1m6s
Release / Vulnerability Scan (release) Successful in 51s
Release / darwin/arm64 (release) Successful in 1m11s
Release / darwin/amd64 (release) Successful in 1m12s
Release / Checksums (release) Successful in 10s
Release / Notify (release) Successful in 5s
|
||
|---|---|---|
| .forgejo/workflows | ||
| cmd | ||
| internal | ||
| .gitignore | ||
| build.sh | ||
| config.example.toml | ||
| go.mod | ||
| go.sum | ||
| install.sh | ||
| main.go | ||
| Makefile | ||
| README.md | ||
modelgen
A small Go CLI that generates AI model configuration files for the Raycast AI extensions and the Zed editor from an LLM gateway.
The tool reads a gateway's /v1/models endpoint, fetches metadata from each upstream source, and emits a provider configuration for Raycast and Zed with model display names suffixed by the upstream provider name.
Outputs
- Raycast:
providers.yamlfor Raycast AI. - Zed: a
settings.jsonsnippet forlanguage_models.openai_compatible.
Installation
Pre-built binary (macOS)
curl -fsSL https://code.paulg.it/paulgit/modelgen/raw/branch/main/install.sh | sh
The script detects your OS and architecture, downloads the matching binary from
the latest release, verifies it against the published SHA256SUMS, and
installs it to ~/.local/bin. If ~/.local/bin is not already on your PATH,
the script prints a one-line command to add it.
To review the script before running it:
curl -fsSL https://code.paulg.it/paulgit/modelgen/raw/branch/main/install.sh | less
To install to a custom directory:
curl -fsSL https://code.paulg.it/paulgit/modelgen/raw/branch/main/install.sh | sh -s -- --prefix /opt/bin
Build from source
go build -o modelgen .
# or install via go install if the repo is published
Configuration
Copy config.example.toml to ~/.config/modelgen/config.toml and adjust as needed.
[general]
generators = ["raycast", "zed"]
[raycast]
base_url = "https://ai.paulg.it/v1"
api_key = "pg-..."
allow_upstream = ["openrouter", "ollama", "openai"]
allow_patterns = [".*"]
exclude_patterns = []
[zed]
base_url = "https://ai.paulg.it/v1"
api_key = "pg-..."
allow_upstream = ["openrouter", "ollama", "openai"]
allow_patterns = [".*"]
exclude_patterns = []
Each target (raycast and zed) has its own API key, gateway URL, and filtering options. API keys can also be provided via the RAYCAST_API_KEY and ZED_API_KEY environment variables. The Raycast API key is written directly into the generated providers.yaml. Zed does not read API keys from settings.json — configure the key in Zed's UI or keychain instead.
1Password Integration
API keys can optionally be retrieved from 1Password using the op CLI, keeping secrets out of config files and environment variables.
Setup
- Install the 1Password CLI.
- Sign in:
op signin - Store your API key as a 1Password item (e.g. a "Secure Note" or "API Key" item).
- Reference the item in your config using an
op://URI in theapi_keyfield:
[raycast]
base_url = "https://ai.paulg.it/v1"
api_key = "op://Personal/modelgen/raycast-api-key"
[zed]
base_url = "https://ai.paulg.it/v1"
api_key = "op://Personal/modelgen/zed-api-key"
You can also use op:// references in environment variables:
RAYCAST_API_KEY="op://Personal/modelgen/raycast-api-key" ./modelgen
Resolution Order
API keys are resolved in the following order (first match wins):
api_keyin the config file (if value starts withop://, resolved via 1Password)<TARGET>_API_KEYenvironment variable (if value starts withop://, resolved via 1Password)- Error: no API key found
This means you can use 1Password for local development and literal keys for CI/CD without changing your config.
Usage
# Generate configured outputs
./modelgen
# Dry-run: print outputs to stdout instead of writing files
./modelgen --dry-run
# Merge generated Zed config into an existing settings.json
./modelgen --merge-zed ~/Library/Application\ Support/Zed/settings.json
# Run only the Zed generator
./modelgen --generators zed
# Use a custom config file
./modelgen --config /path/to/config.toml
# Print version
./modelgen --version
# Clear the on-disk metadata cache (forces a re-fetch on next run)
./modelgen --clear-cache
How It Works
- Fetches the list of available models from the configured gateway
/v1/modelsendpoint for each enabled generator. - Parses the upstream provider prefix from each model ID, e.g.:
openrouter/anthropic/claude-sonnet-4-5ollama/llama3.1:latest
- Enriches each model from the appropriate upstream metadata source:
- OpenRouter models use OpenRouter's
/v1/model/{id}endpoint. - Ollama models use Ollama Cloud's
/api/tagsendpoint. - Other upstreams fall back to models.dev metadata, then to sensible defaults.
- OpenRouter models use OpenRouter's
- Caches metadata locally in
~/.cache/modelgen/metadata-cache-<target>.jsonwith a default TTL of 30 days. - Generates a provider named Paul Git with model display names such as
Claude Sonnet 4.5 (OpenRouter).
Project Layout
modelgen/
cmd/root.go # CLI orchestration
internal/
cache/ # On-disk metadata cache
config/ # TOML config loading
fetch/ # Gateway fetcher and upstream enrichment
generate/ # Raycast and Zed output generators
secret/ # Pluggable secret providers (1Password, etc.)
types/ # Canonical model/provider types
.forgejo/workflows/ # Forgejo Actions CI and release workflows
config.example.toml
install.sh # One-line macOS install script (curl | sh)
Makefile
Development
make test # run tests
make vet # run go vet
make build # build the binary
make dry-run # run with --dry-run
Security Notes
- The Raycast fetch API key is written directly into the generated
providers.yaml. Zed does not read API keys fromsettings.json— configure the key in Zed's UI or keychain instead. - Secret-bearing output files are written with restrictive permissions.
- API keys can be stored in 1Password and retrieved at runtime by setting
api_keyto anop://reference. This works for both config file values and environment variables. - See
config.example.tomlfor the recommended configuration style.