diff --git a/.gitignore b/.gitignore index 8ada863..eedc513 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ coverage.xml docs/data-catalog/ history/ .opencode/rules/data-agent.md +.cursor/rules/data-agent.mdc evals/results/ # BMAD framework installation (tool infrastructure, not project code) diff --git a/AGENTS.md b/AGENTS.md index 5c21b16..2591241 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -15,9 +15,12 @@ customers?", "Show me top products by revenue", "How many orders last month?"): 4. Read the relevant per-table doc under `docs/data-catalog/` for column names and types. 5. Run `uv run oda query ""` to execute the query and return results to the user. -The active database connection and full command reference are in `.opencode/rules/data-agent.md`. -Read that file if you need to know which database is active or how to use `oda` commands. -That file is generated by running `uv run oda connect ` from the project root. +The active database connection and full command reference are in the IDE rules file: +- **Cursor:** `.cursor/rules/data-agent.mdc` (auto-loaded via `alwaysApply`) +- **OpenCode:** `.opencode/rules/data-agent.md` + +Both files are generated by running `uv run oda connect ` from the project root. +Read the appropriate file if you need to know which database is active or how to use `oda` commands. ## What this project does diff --git a/src/open_data_agent/cli_connections.py b/src/open_data_agent/cli_connections.py index 74f69fc..7d6d5cb 100644 --- a/src/open_data_agent/cli_connections.py +++ b/src/open_data_agent/cli_connections.py @@ -196,6 +196,7 @@ def connect(name: str) -> None: console.print(f"[green]✓[/green] Connected to {name} ({db_type} @ {host}/{database})") _render_opencode_rules(name, params) + _render_cursor_rules(name, params) from pathlib import Path @@ -246,3 +247,43 @@ def _render_opencode_rules(name: str, params: dict[str, object]) -> None: rules_file.write_text(rendered) console.print(f"[green]✓[/green] OpenCode rules written to {rules_file}") + + +def _render_cursor_rules(name: str, params: dict[str, object]) -> None: + """Render the Cursor IDE rules file from the same template with .mdc frontmatter.""" + import importlib.resources + from datetime import datetime + from pathlib import Path + + template_content: str | None = None + + if hasattr(importlib.resources, "files"): + try: + ref = importlib.resources.files("open_data_agent") / "templates" / "data-agent.md.tmpl" + template_content = ref.read_text(encoding="utf-8") + except (FileNotFoundError, OSError, TypeError): + pass + + if template_content is None: + return + + rendered = template_content.replace("{{connection_name}}", str(name)) + rendered = rendered.replace("{{db_type}}", str(params.get("db_type", ""))) + rendered = rendered.replace("{{db_host}}", str(params.get("host", ""))) + rendered = rendered.replace("{{db_name}}", str(params.get("database", ""))) + rendered = rendered.replace("{{generated_at}}", datetime.now(UTC).isoformat(timespec="seconds")) + + frontmatter = ( + "---\n" + "description: Data agent rules — active DB connection context, " + "ODA CLI commands, and self-healing guidance\n" + "alwaysApply: true\n" + "---\n\n" + ) + + rules_dir = Path(".cursor") / "rules" + rules_dir.mkdir(parents=True, exist_ok=True) + rules_file = rules_dir / "data-agent.mdc" + rules_file.write_text(frontmatter + rendered) + + console.print(f"[green]✓[/green] Cursor rules written to {rules_file}") diff --git a/src/open_data_agent/cli_init.py b/src/open_data_agent/cli_init.py index ec7c21d..cb7a1f7 100644 --- a/src/open_data_agent/cli_init.py +++ b/src/open_data_agent/cli_init.py @@ -64,6 +64,7 @@ def init() -> None: r" 2. Activate it: oda connect " + "\n" " 3. Generate schema docs: oda docs generate\n" ' 4. Start querying! oda query "SELECT ..."\n' - "\nOpenCode users: rules file will be at .opencode/rules/data-agent.md\n" - r"after you run 'oda connect '" + "\nIDE agent rules are generated after you run 'oda connect ':\n" + " - Cursor: .cursor/rules/data-agent.mdc\n" + " - OpenCode: .opencode/rules/data-agent.md" )