Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.**

<br>

Expand Down Expand Up @@ -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):**
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.

Expand Down
16 changes: 16 additions & 0 deletions guide/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
137 changes: 133 additions & 4 deletions scripts/install.sh
Original file line number Diff line number Diff line change
@@ -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)"

Expand All @@ -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
Expand All @@ -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
}

Expand Down Expand Up @@ -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" ;;
Expand Down Expand Up @@ -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
}

Expand All @@ -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
Expand All @@ -121,20 +138,21 @@ 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
}

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
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down