diff --git a/README.md b/README.md index ec8f1f4..a943bfa 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,13 @@ # Autoresearch -**Turn [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [OpenCode](https://opencode.ai), or [OpenAI Codex](https://developers.openai.com/codex) into a relentless improvement engine.** +**Turn [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [OpenCode](https://opencode.ai), [Kilo](https://kilo.ai/docs/code-with-ai/platforms/cli), or [OpenAI Codex](https://developers.openai.com/codex) into a relentless improvement engine.** Based on [Karpathy's autoresearch](https://github.com/karpathy/autoresearch) — constraint + mechanical metric + autonomous iteration = compounding gains. [![Claude Code Skill](https://img.shields.io/badge/Claude_Code-Skill-blue?logo=anthropic&logoColor=white)](https://docs.anthropic.com/en/docs/claude-code) [![OpenCode](https://img.shields.io/badge/OpenCode-Skill-purple)](https://opencode.ai) +[![Kilo](https://img.shields.io/badge/Kilo-Skill-blue)](https://kilo.ai/docs/code-with-ai/platforms/cli) [![Codex](https://img.shields.io/badge/Codex-Skill-green?logo=openai&logoColor=white)](https://developers.openai.com/codex) [![Version](https://img.shields.io/badge/version-2.0.0--beta.0.2-blue.svg)](https://github.com/uditgoenka/autoresearch/releases) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) @@ -22,7 +23,7 @@ Based on [Karpathy's autoresearch](https://github.com/karpathy/autoresearch) — *You don't need AGI. You need a goal, a metric, and a loop that never quits.* -**Now supports Claude Code, OpenCode, and OpenAI Codex.** +**Now supports Claude Code, OpenCode, Kilo, and OpenAI Codex.**
@@ -230,6 +231,32 @@ cp autoresearch/.opencode/agents/docs-manager.md ~/.config/opencode/agents/docs- > **OpenCode command names:** Use underscores instead of colons — `/autoresearch_debug`, `/autoresearch_fix`, `/autoresearch_plan`, etc. All 10 commands are available. +### Kilo Quick Start + +**Option A — Guided installer (recommended):** +```bash +git clone https://github.com/uditgoenka/autoresearch.git +cd autoresearch +./scripts/install.sh --kilo --global +``` + +**Option B — Manual copy:** +```bash +git clone https://github.com/uditgoenka/autoresearch.git + +# Copy to your project +cp -r autoresearch/.opencode/skills/autoresearch .kilo/skills/autoresearch +cp autoresearch/.opencode/commands/autoresearch*.md .kilo/commands/ +``` + +Or install globally: +```bash +cp -r autoresearch/.opencode/skills/autoresearch ~/.config/kilo/skills/autoresearch +cp autoresearch/.opencode/commands/autoresearch*.md ~/.config/kilo/commands/ +``` + +The installer also configures permissions in `kilo.jsonc` to allow reading the skills directory. + ### Codex Quick Start **Option A — Guided installer (recommended):** @@ -513,7 +540,7 @@ autoresearch/ ├── COMPARISON.md ← Karpathy's Autoresearch vs Claude Autoresearch ├── guide/ ← Comprehensive guides — one per command + advanced patterns ├── scripts/ -│ ├── install.sh ← Guided installer (Claude Code + OpenCode + Codex) +│ ├── install.sh ← Guided installer (Claude Code + OpenCode + Kilo + Codex) │ ├── sync-opencode.sh ← Sync .claude/ → .opencode/ with adaptations │ ├── sync-codex.sh ← Sync .claude/ → .agents/ with Codex adaptations │ ├── release.sh ← Release automation @@ -544,11 +571,14 @@ autoresearch/ A: Run `/autoresearch:plan` — it analyzes your codebase, suggests metrics, and dry-runs the verify command before you launch. **Q: Does this work with any project?** -A: Yes. Any language, framework, or domain. Install via `/plugin marketplace add uditgoenka/autoresearch` (Claude Code), `./scripts/install.sh --opencode --global` (OpenCode), `./scripts/install.sh --codex --global` (Codex), or manually copy files. +A: Yes. Any language, framework, or domain. Install via `/plugin marketplace add uditgoenka/autoresearch` (Claude Code), `./scripts/install.sh --opencode --global` (OpenCode), `./scripts/install.sh --kilo --global` (Kilo), `./scripts/install.sh --codex --global` (Codex), or manually copy files. **Q: Does this work with OpenCode?** A: Yes, as of v2.0.0-beta. Run `./scripts/install.sh --opencode --global` or manually copy `.opencode/` files. Commands use underscore naming (`/autoresearch_debug` instead of `/autoresearch:debug`). +**Q: Does this work with Kilo?** +A: Yes, as of v2.0.0-beta.0.3. Run `./scripts/install.sh --kilo --global` or manually copy `.opencode/skills/autoresearch/` to `~/.config/kilo/skills/`. The installer also configures permissions in `kilo.jsonc` for reading skills. + **Q: Does this work with OpenAI Codex?** A: Yes, as of v2.0.0-beta.0.2. Run `./scripts/install.sh --codex --global` or copy `.agents/skills/autoresearch/` to `~/.agents/skills/`. Invoke via `$autoresearch` mention syntax in Codex. diff --git a/guide/getting-started.md b/guide/getting-started.md index ebc8cbd..b029741 100644 --- a/guide/getting-started.md +++ b/guide/getting-started.md @@ -104,11 +104,27 @@ cp -r autoresearch/.agents/skills/autoresearch ~/.agents/skills/autoresearch > **Codex uses `$` mention syntax:** Type `$autoresearch` in your prompt, or `$autoresearch plan`, `$autoresearch debug`, etc. Codex discovers skills automatically from `.agents/skills/` directories. +### Kilo Installation + +```bash +git clone https://github.com/uditgoenka/autoresearch.git +cd autoresearch +./scripts/install.sh --kilo --global +``` + +Or manually: +```bash +cp -r autoresearch/.opencode/skills/autoresearch ~/.config/kilo/skills/autoresearch +``` + +> **Kilo requires permission configuration:** The installer writes permissions to `~/.config/kilo/kilo.json`. Ensure Kilo can read the skills directory by adding permissions as needed. + ### Verify Installation - **Claude Code:** Type `/autoresearch` — if you see the interactive setup wizard, you're ready. - **OpenCode:** Type `/autoresearch` — same wizard with underscore commands. - **Codex:** Type `$autoresearch` or run `/skills` to see it listed. +- **Kilo:** Type `/autoresearch` — Kilo should auto-discover skills from `~/.config/kilo/skills/`. ### Complete Initialization (Iteration #0 — Baseline) diff --git a/scripts/install.sh b/scripts/install.sh index 562b8c9..aeb0bdd 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,8 +1,14 @@ #!/usr/bin/env bash -# Autoresearch installer — supports Claude Code and OpenCode, local or global. +# Autoresearch installer — supports Claude Code, OpenCode, Codex, and Kilo. set -euo pipefail +cyan='\033[0;36m' +green='\033[0;32m' +yellow='\033[0;33m' +dim='\033[2m' +reset='\033[0m' + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" @@ -22,6 +28,7 @@ Options: --claude Install for Claude Code --opencode Install for OpenCode --codex Install for OpenAI Codex + --kilo Install for Kilo -g, --global Install globally -l, --local Install in the current project -c, --config-dir Override the global config directory @@ -33,6 +40,7 @@ Examples: ./scripts/install.sh --claude --global ./scripts/install.sh --opencode --local ./scripts/install.sh --codex --global + ./scripts/install.sh --kilo --global EOF } @@ -61,6 +69,9 @@ parse_args() { --codex) if [[ -n "$TOOL" && "$TOOL" != "codex" ]]; then die "choose only one tool"; fi TOOL="codex" ;; + --kilo) + if [[ -n "$TOOL" && "$TOOL" != "kilo" ]]; then die "choose only one tool"; fi + TOOL="kilo" ;; -g|--global) if [[ -n "$LOCATION" && "$LOCATION" != "global" ]]; then die "choose --global or --local"; fi LOCATION="global" ;; @@ -103,6 +114,11 @@ get_global_dir() { codex) if [[ -n "${CODEX_HOME:-}" ]]; then expand_path "$CODEX_HOME" else printf '%s\n' "$HOME/.agents"; fi ;; + kilo) + if [[ -n "${KILO_CONFIG_DIR:-}" ]]; then expand_path "$KILO_CONFIG_DIR" + elif [[ -n "${KILO_CONFIG:-}" ]]; then dirname "$(expand_path "$KILO_CONFIG")" + elif [[ -n "${XDG_CONFIG_HOME:-}" ]]; then printf '%s\n' "$(expand_path "$XDG_CONFIG_HOME")/kilo" + else printf '%s\n' "$HOME/.config/kilo"; fi ;; esac } @@ -113,6 +129,7 @@ get_target_dir() { claude) printf '%s\n' "$PWD/.claude" ;; opencode) printf '%s\n' "$PWD/.opencode" ;; codex) printf '%s\n' "$PWD/.agents" ;; + kilo) printf '%s\n' "$PWD/.kilo" ;; esac return fi @@ -121,12 +138,13 @@ get_target_dir() { prompt_tool() { local answer - printf 'Select the tool to install:\n 1) Claude Code\n 2) OpenCode\n 3) OpenAI Codex\nChoice [1]: ' + printf 'Select the tool to install:\n 1) Claude Code\n 2) OpenCode\n 3) OpenAI Codex\n 4) Kilo\nChoice [1]: ' read -r answer || cancelled case "${answer:-1}" in 1) TOOL="claude" ;; 2) TOOL="opencode" ;; 3) TOOL="codex" ;; + 4) TOOL="kilo" ;; *) die "invalid selection: $answer" ;; esac } @@ -134,7 +152,7 @@ prompt_tool() { prompt_location() { local global_dir answer local_dir global_dir="$(get_global_dir "$TOOL")" - case "$TOOL" in claude) local_dir="$PWD/.claude" ;; opencode) local_dir="$PWD/.opencode" ;; codex) local_dir="$PWD/.agents" ;; esac + case "$TOOL" in claude) local_dir="$PWD/.claude" ;; opencode) local_dir="$PWD/.opencode" ;; codex) local_dir="$PWD/.agents" ;; kilo) local_dir="$PWD/.kilo" ;; esac printf 'Install location:\n 1) Global (%s)\n 2) Local (%s)\nChoice [1]: ' "$global_dir" "$local_dir" read -r answer || cancelled case "${answer:-1}" in @@ -200,6 +218,115 @@ install_codex() { sync_dir "$REPO_ROOT/.agents/skills/autoresearch" "$t/skills/autoresearch" } +install_kilo() { + local t="$1" + mkdir -p "$t/skills" "$t/command" + sync_dir "$REPO_ROOT/.opencode/skills/autoresearch" "$t/skills/autoresearch" + for src in "$REPO_ROOT"/.opencode/commands/autoresearch*.md; do + if [[ -f "$src" ]]; then + sync_file "$src" "$t/command/$(basename "$src")" + fi + done + configure_kilo_permissions "$t" +} + +configure_kilo_permissions() { + local kilo_dir="$1" + local config_file + if [[ -f "$kilo_dir/kilo.jsonc" ]]; then + config_file="$kilo_dir/kilo.jsonc" + elif [[ -f "$kilo_dir/kilo.json" ]]; then + config_file="$kilo_dir/kilo.json" + else + config_file="$kilo_dir/kilo.json" + fi + + # Determine the Autoresearch path to permit + local ar_path + ar_path="$kilo_dir/autoresearch/*" + if [[ "$kilo_dir" == "$HOME/.config/kilo" ]]; then + ar_path="~/.config/kilo/autoresearch/*" + elif [[ "$kilo_dir" == "$PWD/.kilo" ]]; then + ar_path="./.kilo/autoresearch/*" + else + ar_path="${kilo_dir}/autoresearch/*" + fi + + # Create default config if missing + if [[ ! -f "$kilo_dir/kilo.json" && ! -f "$kilo_dir/kilo.jsonc" ]]; then + config_file="$kilo_dir/kilo.jsonc" + cat > "$config_file" <<'CONFIGEOF' +{ + // Autoresearch permissions - allows reading skills and reference docs + "permission": { + "read": {}, + "external_directory": {} + } +} +CONFIGEOF + fi + + # Use JSONC if exists, otherwise JSON + if [[ -f "$kilo_dir/kilo.jsonc" ]]; then + config_file="$kilo_dir/kilo.jsonc" + else + config_file="$kilo_dir/kilo.json" + fi + + # Python script to validate and update JSONC (handles both .json and .jsonc) + local tmp_file + tmp_file=$(mktemp) || return 1 + + python3 - "$config_file" "$ar_path" "$tmp_file" <<'PYEOF' +import json +import sys +import re + +config_path = sys.argv[1] +ar_path = sys.argv[2] +tmp_path = sys.argv[3] + +# Read and strip JSONC comments and parse +with open(config_path, 'r') as f: + content = f.read() + +# Strip single-line comments (only at start of line after whitespace) +content = re.sub(r'^(\s*)//.*$', r'\1', content, flags=re.MULTILINE) +# Strip multi-line comments +content = re.sub(r'/\*.*?\*/', '', content, flags=re.DOTALL) +# Remove trailing commas before } or ] +content = re.sub(r',(\s*[}\]])', r'\1', content) + +try: + config = json.loads(content) +except Exception as e: + print(f'Error: {e}') + sys.exit(1) + +if 'permission' not in config: + config['permission'] = {} +if 'read' not in config['permission']: + config['permission']['read'] = {} +if ar_path not in config['permission']['read']: + config['permission']['read'][ar_path] = 'allow' +if 'external_directory' not in config['permission']: + config['permission']['external_directory'] = {} +if ar_path not in config['permission']['external_directory']: + config['permission']['external_directory'][ar_path] = 'allow' + +with open(tmp_path, 'w') as f: + json.dump(config, f, indent=2) +PYEOF + + if [[ -f "$tmp_file" ]] && [[ -s "$tmp_file" ]]; then + mv "$tmp_file" "$config_file" + printf ' %s✓%s Configured read permission for Autoresearch skills\n' "$green" "$reset" + else + printf ' %s⚠%s Could not parse kilo.json - skipping permission config\n' "$yellow" "$reset" + fi + rm -f "$tmp_file" +} + main() { parse_args "$@" ensure_context @@ -208,17 +335,19 @@ main() { confirm_overwrite "$target_root" local label - case "$TOOL" in claude) label="Claude Code" ;; opencode) label="OpenCode" ;; codex) label="OpenAI Codex" ;; esac + case "$TOOL" in claude) label="Claude Code" ;; opencode) label="OpenCode" ;; codex) label="OpenAI Codex" ;; kilo) label="Kilo" ;; esac printf 'Installing Autoresearch for %s (%s)\nTarget: %s\n' "$label" "$LOCATION" "$target_root" case "$TOOL" in claude) install_claude "$target_root" ;; opencode) install_opencode "$target_root" ;; codex) install_codex "$target_root" ;; + kilo) install_kilo "$target_root" ;; esac case "$TOOL" in codex) printf 'Done. Use $autoresearch in Codex to start.\n' ;; + kilo) printf 'Done. Run /autoresearch in Kilo to start.\n' ;; *) printf 'Done. Run /autoresearch to start.\n' ;; esac }