Bring your own model
nicheclock collects with plain code and, when you bring a model, uses it to judge. You use your key or your own sign-in, set your own budget and pick your provider. nicheclock has no model of its own and never routes your calls through a server of ours. Nothing is on by default: no llm: section means no model call, ever.
Status. Released. Gemini and Codex are untested live: they have unit tests with recorded replies but have not run against the real service yet, so expect rough edges and report them. Without a model, run uses rule-based scoring and works as described elsewhere in these docs.
What a model does
Four jobs in nicheclock run, each switchable with llm.tasks, and a fifth during init:
| Task | What the model does | You see |
|---|---|---|
fit |
Scores each candidate topic 0 to 100 for your niche and says why in one sentence. | The feed score blends the rule score and the fit score; the reason is in why. |
junk |
Flags ephemeral or off-topic items that slipped through the keyword match. | Fewer items. |
merge |
Merges duplicates of one story reported by several sources. | One item with all sources. |
gaps |
Suggests angles and reader questions for your Search Console gaps. | Text next to each gap. |
profile |
Proposes niches from up to 50 page titles during init --llm. |
A better first draft. |
Blend: score = (1 - fit_weight) * rule_score + fit_weight * fit, with fit_weight 0.6 by default. A topic the model did not judge counts as fit 50. Collection, matching, clustering and publish_by stay deterministic code. Judgements of the same input are cached for a week.
Configuration
llm:
provider: anthropic # anthropic | openai | gemini | ollama | claude-code | codex
model: claude-haiku-4-5 # required for API providers
api_key_env: ANTHROPIC_API_KEY # the NAME of an environment variable; or api_key_file: path
daily_budget_usd: 1.0 # hard stop for the UTC day; null means no cap
max_items_per_run: 40 # topics judged per run, all projects together
tasks: [fit, junk, merge, gaps]
send_gsc_rows: false # true also sends Search Console rows (page, clicks, position)
fit_weight: 0.6
timeout_s: 120
Keys are read from the environment variable or file you name, never from the YAML. An inline api_key: is rejected. base_url points at an OpenAI-compatible server, a proxy or a remote Ollama. price_per_mtok: [input, output] sets a price for a model the built-in table does not know; without a price the call is counted in tokens but not in dollars.
projects[].profile tells the model who the site is. init fills it from your home page, and you can edit it:
profile:
title: Birdclub Demo
description: Reviews and guides for bird feeders, birding optics and field guides.
Check the setup with one tiny call, which prints provider, model, latency, tokens and estimated cost, never the key:
nicheclock llm test
nicheclock llm usage --days 7
Anthropic
llm:
provider: anthropic
model: claude-haiku-4-5
api_key_env: ANTHROPIC_API_KEY
Create a key in the Anthropic Console, then export ANTHROPIC_API_KEY=... (in Docker: put it in .env). model is required; there is no built-in default, so pick one your account can use. A small, cheap model is enough for fit.
OpenAI
llm:
provider: openai
model: gpt-6-luna
api_key_env: OPENAI_API_KEY
With base_url, any OpenAI-compatible server works and the key becomes optional:
llm: {provider: openai, model: my-model, base_url: "http://localhost:8000/v1"}
Gemini untested live
llm:
provider: gemini
model: gemini-3.5-flash-lite
api_key_env: GEMINI_API_KEY
Not yet run against the real service; unit-tested only. The key is sent in the x-goog-api-key header, never in the URL. Thinking tokens count as output tokens in the cost estimate.
Ollama, a local model
No key, no cost, nothing leaves your machine.
ollama pull llama3.2
llm: {provider: ollama, model: llama3.2, base_url: "http://localhost:11434"}
base_url defaults to http://localhost:11434. In Docker Compose, start the optional service and use its service name as the host:
docker compose --profile ollama up -d
docker compose exec ollama ollama pull llama3.2
llm: {provider: ollama, model: llama3.2, base_url: "http://ollama:11434"}
Small local models judge less reliably than large hosted ones, and they need RAM: plan on a few GB for a 3B model. Compare before you trust the ranking (see the last section on nicheclock eval export).
Claude Code or Codex sign-in
If you already pay for a Claude or ChatGPT plan, nicheclock can call the claude or codex command line tool you are signed in to, instead of using an API key.
llm: {provider: claude-code} # or: {provider: codex}; model is optional, the CLI's default is used
Codex is not yet run against the real service; unit-tested only. On your own machine, sign in once (claude, then log in; or codex login) and make sure the command is on your PATH. cli_path names a different binary. nicheclock runs the tool as a text backend only: for Claude Code with tools, user settings, hooks, MCP servers and session storage switched off; for Codex in a read-only sandbox without approvals. The child process gets a minimal environment (HOME, PATH, the sign-in directory, proxy and CA variables).
Your plan's terms apply to you. Using a subscription this way is covered by the terms of that plan, not by nicheclock. Read them, and the usage limits, before you schedule daily runs: Anthropic consumer terms, OpenAI terms of use. If a plan does not allow automated use, use an API key instead.