agentsclimarketplace

Self learn config

Skill secondfry/claude-code-self-learn/skills/self-learn-config

Use this when the user wants to change how the self-learn out-of-band loop behaves — the model/gateway the headless learner agents run on, processing thresholds (idle time, batch sizes, per-pass cap), toggling fact/skill extraction on or off, or the claude binary path. Guides edits to ~/.claude/self-learn/config.json so the model id stays coupled to the gateway it's addressed to and the auth token is never stored in the file.From its SKILL.md

Install
npx -y skills add secondfry/claude-code-self-learn --skill self-learn-config

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

7.7 KB, as published. Nobody here has run it

Editing the self-learn dispatcher config

When this applies

The user wants to tune the out-of-band self-learn loop: change the model the fact-extractor / skill-distiller headless runs use, point them at a different gateway, raise/lower the idle-gate or batch thresholds, disable fact or skill extraction, or pin the claude binary. All of these live in ONE file:

~/.claude/self-learn/config.json

The file is optional — every key has a built-in default. Edit it by hand (wipe or omit any key to revert to its default). Changes take effect on the next 30-min launchd pass — no launchctl reload, no plugin reinstall.

Schema

Source of truth: pipeline/lib/config.py (the _SETTINGS table). Every key can also be set by an SL_* env var. Precedence: env var > config.json > default — so an env var (e.g. in a one-off shell or the launchd plist) wins over the file, and the file wins over the built-in default.

keyenv vartypedefaultmeaning
idle_minSL_IDLE_MINint30Minutes a finished transcript must be quiet before processing (idle-gate).
batch_msgsSL_BATCH_MSGSint1Min NEW real-user messages since watermark to look for facts (1 = any).
distill_thresholdSL_DISTILL_THRESHOLDint1Min NEW tool calls to look for a skill.
min_file_editsSL_MIN_FILE_EDITSint1Min file edits in those calls to distill a skill.
agent_timeoutSL_AGENT_TIMEOUTint600Per-headless-run wall-clock ceiling, seconds.
max_per_passSL_MAX_PER_PASSint8Cap transcripts handed to learners per pass (backlog drains gradually).
learn_modelSL_LEARN_MODELstrclaude-sonnet-4-6Model id passed via --model. Format depends on learn_gateway — see below.
claude_binSL_CLAUDE_BINstr""Explicit claude binary path. Empty = auto-resolve (PATH, then fnm default).
facts_enabledSL_FACT_NUDGEbooltruefalse disables fact extraction entirely.
skills_enabledSL_SKILL_NUDGEbooltruefalse disables skill distillation entirely.
dispatch_enabledSL_DISPATCHbooltrueMaster switch — false makes the dispatcher a no-op.
learn_gatewaySL_LEARN_GATEWAYstr""ANTHROPIC_BASE_URL for the headless runs only. Empty = use whatever claude loads from settings.json.
learn_token_envSL_LEARN_TOKEN_ENVstr""Name of the env var holding the upstream gateway's auth token. Empty = don't inject.
stale_after_daysSL_STALE_AFTER_DAYSint30Curator: idle days → mark an agent skill stale.
archive_after_daysSL_ARCHIVE_AFTER_DAYSint90Curator: idle days → archive (×2 if use_count ≥ 3).
curate_interval_daysSL_CURATE_INTERVAL_DAYSint7Curator: min days between SessionStart auto-curate passes.
curate_min_skillsSL_CURATE_MIN_SKILLSint5Curator: min agent-distilled skills before auto-curate acts.

Booleans accept true/false (JSON) or 1/0 (env). Ints parse loosely.

Model ↔ gateway coupling (the part that bites)

The model id format is gateway-specific. They MUST be set together, or the headless run will send a perfectly-valid id to a gateway that doesn't recognise it and fail:

  • https://your-gateway.example.com/raw/anthropic → bare id: claude-sonnet-4-6
  • https://your-gateway.example.com/raw/openrouter → vendor-prefixed: anthropic/claude-sonnet-4-6

So a correct openrouter config looks like:

{
  "learn_gateway": "https://your-gateway.example.com/raw/openrouter",
  "learn_model": "anthropic/claude-sonnet-4-6",
  "learn_token_env": "SL_LEARN_TOKEN"
}

…and a correct /raw/anthropic config keeps the bare id:

{
  "learn_gateway": "https://your-gateway.example.com/raw/anthropic",
  "learn_model": "claude-sonnet-4-6",
  "learn_token_env": "SL_LEARN_TOKEN"
}

Leaving learn_gateway empty means the headless claude -p uses the same gateway the interactive session does (from ~/.claude/settings.json's env block). If that is a local/proxy gateway that rewrites model aliases to some fixed backing model, an empty gateway + a specific learn_model may be silently rewritten. If you want a specific real upstream model, set learn_gateway explicitly to bypass the local gateway for learner traffic only (interactive sessions are untouched).

Token discipline — never store the token in config.json

config.json may be shared, screenshotted, or read by other agents. The auth token for the upstream gateway must NEVER be written into it. Instead:

  1. Put the token in an environment variable (e.g. export it in the shell that bootstraps the launchd agent, or in ~/.zshrc / a private file the user sources — NOT in the plugin repo, NOT in ~/.claude/settings.json's tracked env block unless the user accepts that surface).
  2. Set learn_token_env to the NAME of that variable, e.g. "SL_LEARN_TOKEN".

At pass time the dispatcher reads os.environ["SL_LEARN_TOKEN"] and writes ONLY {ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN} into a 0600 file at ~/.claude/self-learn/learner-settings.json, passed to the headless runs via claude -p --settings <that file>. Why --settings and not subprocess env: ~/.claude/settings.json's env block is applied on top of the parent process env at startup, so it would silently clobber ANTHROPIC_BASE_URL back to the local gateway — --settings is CLI-arg-scope (tier 2, above user settings) and is the only thing that actually overrides it. The file is unlinked at the end of the pass. Its trust surface is the same as ~/.claude/settings.json itself (which already holds an auth token literally); it is never in the repo and never in config.json.

If learn_gateway is set but learn_token_env is empty (or the named var is unset), the dispatcher sends no ANTHROPIC_AUTH_TOKEN — the run will fall back to whatever auth the gateway itself provides, and may fail closed.

Editing checklist

When the user asks to change a setting:

  1. Read the current ~/.claude/self-learn/config.json (create it if absent — start from {} and add only the keys you're changing; absent keys use defaults).
  2. Make the edit. For ANY model change, check learn_gateway too — flip them as a pair per the table above.
  3. Never write a literal token. Use learn_token_env.
  4. Confirm the file is valid JSON before finishing (python3 -m json.tool on it).
  5. Tell the user it takes effect on the next 30-min pass — no reload needed.

Verifying the effective config

To see what the dispatcher will actually use this pass (after env > file > default resolution), from the plugin root:

python3 -c "import sys; sys.path.insert(0,'pipeline/lib'); import config; \
import json; print(json.dumps(config.load_all(), indent=2))"

Keep looking

Skills are one crate of 628,853. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.