Skip to content

Commit e4570e2

Browse files
Merge pull request #84 from VioletCranberry/feat/init-controller-config
feat(init): make the generated cocosearch.yaml a complete config reference
2 parents 5d8176e + ffd1009 commit e4570e2

4 files changed

Lines changed: 94 additions & 3 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,10 @@ controller:
617617
model: qwen2.5:3b # default depends on provider
618618
# baseUrl: http://localhost:11434
619619
# timeout: 5.0 # seconds; on timeout, falls back to the original query
620+
621+
# Optional file logging (default: disabled)
622+
logging:
623+
file: false # true -> ~/.cocosearch/logs/cocosearch.log (10MB rotation)
620624
```
621625
622626
### Remote Embedding Providers

docs/cli-reference.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,14 @@ uv run cocosearch index . --deps
224224

225225
**Initialize project configuration:** `uv run cocosearch init [options]`
226226

227-
Creates a `cocosearch.yaml` starter configuration file in the current directory. After creating the config file, interactively offers to:
227+
Creates a `cocosearch.yaml` starter configuration file in the current directory. The generated config documents every section as commented examples — `indexing`, `search`, `embedding` (provider/model/baseUrl for ollama/openai/openrouter), the optional query-rewrite `controller`, and file `logging` — so it doubles as a config reference. After creating the config file, interactively offers to:
228228
1. Add a CocoSearch tool routing table to CLAUDE.md (local project or global `~/.claude/CLAUDE.md`)
229229
2. Add a CocoSearch tool routing table to AGENTS.md (local project or global `~/.config/opencode/AGENTS.md`)
230230
3. Register CocoSearch MCP server with OpenCode (local or global `opencode.json`)
231231
4. Install CocoSearch workflow skills for OpenCode (local or global skills directory)
232232
5. Install CocoSearch plugin for Claude Code (via `claude` CLI)
233+
6. Configure Claude Code tool permissions for CocoSearch (local `.claude/settings.local.json` or shared `.claude/settings.json`)
234+
7. Install the Claude Code nudge hook that steers the agent toward `search_code` instead of raw grep/glob (local or shared settings)
233235

234236
| Flag | Description |
235237
| ---- | ----------- |
@@ -238,13 +240,15 @@ Creates a `cocosearch.yaml` starter configuration file in the current directory.
238240
| `--no-opencode-mcp` | Skip the OpenCode MCP server registration prompt |
239241
| `--no-opencode-skills` | Skip the OpenCode workflow skills installation prompt |
240242
| `--no-claude-mcp` | Skip the Claude Code plugin installation prompt |
243+
| `--no-claude-settings` | Skip the Claude Code tool permissions prompt |
244+
| `--no-claude-hook` | Skip the Claude Code nudge hook prompt |
241245

242246
```bash
243247
# Interactive: creates cocosearch.yaml, then prompts for all integrations
244248
uv run cocosearch init
245249

246250
# Non-interactive: creates cocosearch.yaml only
247-
uv run cocosearch init --no-claude-md --no-agents-md --no-opencode-mcp --no-opencode-skills --no-claude-mcp
251+
uv run cocosearch init --no-claude-md --no-agents-md --no-opencode-mcp --no-opencode-skills --no-claude-mcp --no-claude-settings --no-claude-hook
248252
```
249253

250254
All interactive prompts are skipped automatically when stdin is not a TTY (e.g., in CI pipelines or when piping input).

src/cocosearch/config/generator.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,37 @@
4848
4949
# Embedding settings
5050
embedding: {}
51-
# Ollama model for embeddings
51+
# Provider: ollama (default, local), openai, or openrouter
52+
# provider: ollama
53+
# Model (default depends on provider: ollama -> nomic-embed-text,
54+
# openai -> text-embedding-3-small, openrouter -> openai/text-embedding-3-small)
5255
# model: nomic-embed-text
56+
# Custom / OpenAI-compatible endpoint (Infinity, TEI, vLLM). For the ollama
57+
# provider this overrides COCOSEARCH_OLLAMA_URL.
58+
# baseUrl: http://localhost:8080
59+
# Override the embedding vector size (only if your model needs it)
60+
# outputDimension: 768
61+
# NOTE: remote providers also need COCOSEARCH_EMBEDDING_API_KEY (env var),
62+
# unless baseUrl points at a local server. Switching provider/model requires
63+
# a `cocosearch index . --fresh` reindex.
64+
65+
# Optional query-rewrite controller (default: disabled)
66+
# An LLM expands vague natural-language queries into better search terms before
67+
# retrieval (e.g. "how does login work" -> "authentication session credential
68+
# login user token"). When disabled, search is byte-for-byte identical and no
69+
# generative model is ever called. Configured just like the embedding provider.
70+
# controller:
71+
# enabled: false
72+
# provider: ollama # ollama (default), openai, openrouter
73+
# model: qwen2.5:3b # default depends on provider
74+
# # baseUrl: http://localhost:11434 # custom / OpenAI-compatible endpoint
75+
# # timeout: 5.0 # seconds; falls back to the original query on timeout
76+
77+
# Logging (default: file output disabled)
78+
# When enabled, logs are written to ~/.cocosearch/logs/cocosearch.log
79+
# (10MB rotation, 3 backups). Equivalent to COCOSEARCH_LOG_FILE=true.
80+
# logging:
81+
# file: false
5382
"""
5483

5584

tests/unit/config/test_generator.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
COCOSEARCH_MCP_TOOL_PERMISSIONS,
1414
COCOSEARCH_NUDGE_MARKER,
1515
CONFIG_TEMPLATE,
16+
CocoSearchConfig,
1617
ConfigError,
1718
check_claude_plugin_installed,
1819
generate_agents_md_routing,
@@ -67,6 +68,59 @@ def test_config_template_contains_linked_indexes_comment():
6768
assert "common-utils" in CONFIG_TEMPLATE
6869

6970

71+
def _uncomment_block(marker: str) -> dict:
72+
"""Uncomment one '# ' level of the CONFIG_TEMPLATE block beginning at `marker`
73+
(a fully-commented section like '# controller:') up to its trailing blank
74+
line, then parse it as YAML. Double-commented sub-fields stay commented."""
75+
lines = CONFIG_TEMPLATE.splitlines()
76+
start = next(i for i, ln in enumerate(lines) if ln.strip() == marker)
77+
block = []
78+
for ln in lines[start:]:
79+
if not ln.startswith("#"): # blank line ends the block
80+
break
81+
block.append(ln[2:] if ln.startswith("# ") else ln)
82+
return yaml.safe_load("\n".join(block))
83+
84+
85+
def test_config_template_contains_controller_comment():
86+
"""Test that CONFIG_TEMPLATE documents the optional query-rewrite controller."""
87+
assert "# controller:" in CONFIG_TEMPLATE
88+
assert "enabled: false" in CONFIG_TEMPLATE
89+
assert "provider: ollama" in CONFIG_TEMPLATE
90+
assert "qwen2.5:3b" in CONFIG_TEMPLATE
91+
92+
93+
def test_config_template_controller_example_is_schema_valid():
94+
"""The commented controller example must validate against ControllerSection
95+
once uncommented — guards the docs from drifting out of sync with the schema."""
96+
config = CocoSearchConfig(**_uncomment_block("# controller:"))
97+
assert config.controller.enabled is False
98+
assert config.controller.provider == "ollama"
99+
assert config.controller.model == "qwen2.5:3b"
100+
101+
102+
def test_config_template_documents_embedding_provider():
103+
"""Test that CONFIG_TEMPLATE documents the multi-provider embedding options."""
104+
assert "provider: ollama" in CONFIG_TEMPLATE
105+
assert "baseUrl" in CONFIG_TEMPLATE
106+
assert "openrouter" in CONFIG_TEMPLATE
107+
assert "COCOSEARCH_EMBEDDING_API_KEY" in CONFIG_TEMPLATE
108+
109+
110+
def test_config_template_contains_logging_comment():
111+
"""Test that CONFIG_TEMPLATE documents the optional file logging toggle."""
112+
assert "# logging:" in CONFIG_TEMPLATE
113+
assert "file: false" in CONFIG_TEMPLATE
114+
assert "COCOSEARCH_LOG_FILE" in CONFIG_TEMPLATE
115+
116+
117+
def test_config_template_logging_example_is_schema_valid():
118+
"""The commented logging example must validate against LoggingSection once
119+
uncommented — guards the docs from drifting out of sync with the schema."""
120+
config = CocoSearchConfig(**_uncomment_block("# logging:"))
121+
assert config.logging.file is False
122+
123+
70124
class TestClaudeMdRouting:
71125
"""Tests for generate_claude_md_routing."""
72126

0 commit comments

Comments
 (0)