From cfc2e898cbbf2dbad3495f6fec783339880d36cf Mon Sep 17 00:00:00 2001 From: OpenCode Agent Date: Mon, 27 Apr 2026 16:26:26 +0530 Subject: [PATCH 1/8] add opencode agent support --- config.toml | 6 +++ macos-linux/start_opencode.sh | 64 ++++++++++++++++++++++++++++++ macos-linux/start_opencode_yolo.sh | 64 ++++++++++++++++++++++++++++++ windows/start_opencode.bat | 40 +++++++++++++++++++ windows/start_opencode_yolo.bat | 40 +++++++++++++++++++ 5 files changed, 214 insertions(+) create mode 100644 macos-linux/start_opencode.sh create mode 100644 macos-linux/start_opencode_yolo.sh create mode 100644 windows/start_opencode.bat create mode 100644 windows/start_opencode_yolo.bat diff --git a/config.toml b/config.toml index ea58875e..2772dbdb 100644 --- a/config.toml +++ b/config.toml @@ -47,6 +47,12 @@ cwd = ".." color = "#f7f677" label = "Kilo" +[agents.opencode] +command = "opencode" +cwd = ".." +color = "#808080" +label = "OpenCode" + [agents.codebuddy] command = "codebuddy" cwd = ".." diff --git a/macos-linux/start_opencode.sh b/macos-linux/start_opencode.sh new file mode 100644 index 00000000..3ac64580 --- /dev/null +++ b/macos-linux/start_opencode.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env sh +# agentchattr - starts server (if not running) + OpenCode wrapper +cd "$(dirname "$0")/.." + +PYTHON_BIN="" +if command -v python3 >/dev/null 2>&1; then + PYTHON_BIN="python3" +elif command -v python >/dev/null 2>&1; then + PYTHON_BIN="python" +else + echo "Python 3 is required but was not found on PATH." + exit 1 +fi + +ensure_venv() { + if [ -d ".venv" ] && [ ! -x ".venv/bin/python" ]; then + echo "Recreating .venv for this platform..." + rm -rf .venv + fi + + if [ ! -x ".venv/bin/python" ]; then + echo "Creating virtual environment..." + "$PYTHON_BIN" -m venv .venv || { + echo "Error: failed to create .venv with $PYTHON_BIN." + exit 1 + } + .venv/bin/python -m pip install -q -r requirements.txt || { + echo "Error: failed to install Python dependencies." + exit 1 + } + fi +} + +is_server_running() { + lsof -i :8300 -sTCP:LISTEN >/dev/null 2>&1 || \ + ss -tlnp 2>/dev/null | grep -q ':8300 ' +} + +ensure_venv + +if ! is_server_running; then + if [ "$(uname -s)" = "Darwin" ]; then + osascript -e "tell app \"Terminal\" to do script \"cd '$(pwd)' && .venv/bin/python run.py\"" > /dev/null 2>&1 + else + if command -v gnome-terminal >/dev/null 2>&1; then + gnome-terminal -- sh -c "cd '$(pwd)' && .venv/bin/python run.py; printf 'Press Enter to close... '; read _" + elif command -v xterm >/dev/null 2>&1; then + xterm -e sh -c "cd '$(pwd)' && .venv/bin/python run.py" & + else + .venv/bin/python run.py > data/server.log 2>&1 & + fi + fi + + i=0 + while [ "$i" -lt 30 ]; do + if is_server_running; then + break + fi + sleep 0.5 + i=$((i + 1)) + done +fi + +.venv/bin/python wrapper.py opencode diff --git a/macos-linux/start_opencode_yolo.sh b/macos-linux/start_opencode_yolo.sh new file mode 100644 index 00000000..f90be529 --- /dev/null +++ b/macos-linux/start_opencode_yolo.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env sh +# agentchattr - starts server (if not running) + OpenCode wrapper (yolo mode) +cd "$(dirname "$0")/.." + +PYTHON_BIN="" +if command -v python3 >/dev/null 2>&1; then + PYTHON_BIN="python3" +elif command -v python >/dev/null 2>&1; then + PYTHON_BIN="python" +else + echo "Python 3 is required but was not found on PATH." + exit 1 +fi + +ensure_venv() { + if [ -d ".venv" ] && [ ! -x ".venv/bin/python" ]; then + echo "Recreating .venv for this platform..." + rm -rf .venv + fi + + if [ ! -x ".venv/bin/python" ]; then + echo "Creating virtual environment..." + "$PYTHON_BIN" -m venv .venv || { + echo "Error: failed to create .venv with $PYTHON_BIN." + exit 1 + } + .venv/bin/python -m pip install -q -r requirements.txt || { + echo "Error: failed to install Python dependencies." + exit 1 + } + fi +} + +is_server_running() { + lsof -i :8300 -sTCP:LISTEN >/dev/null 2>&1 || \ + ss -tlnp 2>/dev/null | grep -q ':8300 ' +} + +ensure_venv + +if ! is_server_running; then + if [ "$(uname -s)" = "Darwin" ]; then + osascript -e "tell app \"Terminal\" to do script \"cd '$(pwd)' && .venv/bin/python run.py\"" > /dev/null 2>&1 + else + if command -v gnome-terminal >/dev/null 2>&1; then + gnome-terminal -- sh -c "cd '$(pwd)' && .venv/bin/python run.py; printf 'Press Enter to close... '; read _" + elif command -v xterm >/dev/null 2>&1; then + xterm -e sh -c "cd '$(pwd)' && .venv/bin/python run.py" & + else + .venv/bin/python run.py > data/server.log 2>&1 & + fi + fi + + i=0 + while [ "$i" -lt 30 ]; do + if is_server_running; then + break + fi + sleep 0.5 + i=$((i + 1)) + done +fi + +.venv/bin/python wrapper.py opencode -- --dangerously-skip-permissions diff --git a/windows/start_opencode.bat b/windows/start_opencode.bat new file mode 100644 index 00000000..75988019 --- /dev/null +++ b/windows/start_opencode.bat @@ -0,0 +1,40 @@ +@echo off +REM agentchattr — starts server (if not running) + OpenCode wrapper +cd /d "%~dp0.." + +REM Auto-create venv and install deps on first run +if not exist ".venv" ( + python -m venv .venv + .venv\Scripts\pip install -q -r requirements.txt >nul 2>nul +) +call .venv\Scripts\activate.bat + +REM Pre-flight: check that opencode CLI is installed +where opencode >nul 2>&1 +if %errorlevel% neq 0 ( + echo. + echo Error: "opencode" was not found on PATH. + echo Install it first, then try again. + echo. + pause + exit /b 1 +) + +REM Start server if not already running, then wait for it +netstat -ano | findstr :8300 | findstr LISTENING >nul 2>&1 +if %errorlevel% neq 0 ( + start "agentchattr server" cmd /c "python run.py" +) +:wait_server +netstat -ano | findstr :8300 | findstr LISTENING >nul 2>&1 +if %errorlevel% neq 0 ( + timeout /t 1 /nobreak >nul + goto :wait_server +) + +python wrapper.py opencode +if %errorlevel% neq 0 ( + echo. + echo Agent exited unexpectedly. Check the output above. + pause +) diff --git a/windows/start_opencode_yolo.bat b/windows/start_opencode_yolo.bat new file mode 100644 index 00000000..df83ca0a --- /dev/null +++ b/windows/start_opencode_yolo.bat @@ -0,0 +1,40 @@ +@echo off +REM agentchattr — starts server (if not running) + OpenCode wrapper (yolo mode) +cd /d "%~dp0.." + +REM Auto-create venv and install deps on first run +if not exist ".venv" ( + python -m venv .venv + .venv\Scripts\pip install -q -r requirements.txt >nul 2>nul +) +call .venv\Scripts\activate.bat + +REM Pre-flight: check that opencode CLI is installed +where opencode >nul 2>&1 +if %errorlevel% neq 0 ( + echo. + echo Error: "opencode" was not found on PATH. + echo Install it first, then try again. + echo. + pause + exit /b 1 +) + +REM Start server if not already running, then wait for it +netstat -ano | findstr :8300 | findstr LISTENING >nul 2>&1 +if %errorlevel% neq 0 ( + start "agentchattr server" cmd /c "python run.py" +) +:wait_server +netstat -ano | findstr :8300 | findstr LISTENING >nul 2>&1 +if %errorlevel% neq 0 ( + timeout /t 1 /nobreak >nul + goto :wait_server +) + +python wrapper.py opencode -- --dangerously-skip-permissions +if %errorlevel% neq 0 ( + echo. + echo Agent exited unexpectedly. Check the output above. + pause +) From 34f7a866c2a7fcde1546ad8891c33a95f6e07f8b Mon Sep 17 00:00:00 2001 From: OpenCode Agent Date: Mon, 27 Apr 2026 19:03:50 +0530 Subject: [PATCH 2/8] feat: implement OpenCode-specific MCP settings injection and add AGENTS.md --- AGENTS.md | 36 ++++++++++++++++++++++++++++++++++++ config.toml | 3 +++ wrapper.py | 53 +++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..a69b4448 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,36 @@ +# Agent Instructions: agentchattr + +## Developer Commands + +- **Setup**: `python -m venv venv && source venv/bin/activate && pip install -r requirements.txt` +- **Start server**: `python run.py` +- **Start agent wrapper**: `python wrapper.py ` +- **Start API agent**: `python wrapper_api.py ` +- **Run all tests**: `python -m unittest discover tests` +- **Run single test**: `python -m unittest tests/test_.py` +- **Web UI**: http://localhost:8300 (default) + +## Architecture & Key Files + +- **Entry Point**: `run.py` starts both the MCP and web server. +- **Web Server**: `app.py` (FastAPI) handles WebSocket communication and REST endpoints. +- **Agent Wrapper**: `wrapper.py` manages agent life cycles and injects prompts into agent terminals. + - **Windows**: `wrapper_windows.py` uses Win32 API. + - **Mac/Linux**: `wrapper_unix.py` requires `tmux`. +- **API Agent**: `wrapper_api.py` connects to OpenAI-compatible local models. +- **MCP Layer**: `mcp_bridge.py` (tool definitions) and `mcp_proxy.py` (identity injection). +- **Persistence**: `store.py` (messages), `jobs.py` (tasks), `rules.py` (rules), `summaries.py` (summaries) use JSONL/JSON files in `data/`. +- **Routing**: `router.py` handles @mention parsing and agent targeting. + +## Configuration + +- **`config.toml`**: Primary configuration for agents, ports, and routing (including `max_agent_hops` for loop guard). +- **`config.local.toml`**: Local overrides (gitignored), used for API endpoints and local model settings. + +## Conventions & Constraints + +- **Python Version**: 3.11+ (required for `tomllib`). +- **Platform dependency**: `tmux` must be installed on macOS/Linux for the agent wrapper to function. +- **Localhost only**: The server is designed for localhost use; use `--allow-network` only on trusted networks. +- **Security**: All API/WS requests must present the session token generated on server start. +- **Loop Guard**: Agent-to-agent chains are paused after `max_agent_hops`; use `/continue` in chat to resume. diff --git a/config.toml b/config.toml index 2772dbdb..6a0cdd3c 100644 --- a/config.toml +++ b/config.toml @@ -52,6 +52,9 @@ command = "opencode" cwd = ".." color = "#808080" label = "OpenCode" +mcp_inject = "opencode_json" +mcp_settings_path = "opencode.json" +mcp_transport = "http" [agents.codebuddy] command = "codebuddy" diff --git a/wrapper.py b/wrapper.py index c7fde420..0d303a93 100644 --- a/wrapper.py +++ b/wrapper.py @@ -31,9 +31,33 @@ SERVER_NAME = "agentchattr" -# --------------------------------------------------------------------------- -# Per-instance provider config -# --------------------------------------------------------------------------- +def _write_opencode_mcp_settings(config_file: Path, url: str, + *, token: str = "") -> Path: + """Write/merge an OpenCode-specific config file with 'mcp' key. + + OpenCode expects: + - "mcp" key instead of "mcpServers" + - "type": "remote" for remote servers + - "enabled": true + """ + config_file.parent.mkdir(parents=True, exist_ok=True) + existing: dict = {} + if config_file.exists(): + try: + existing = json.loads(config_file.read_text("utf-8")) + except Exception: + pass + + mcp_servers = existing.get("mcp", {}) + entry: dict = {"type": "remote", "url": url, "enabled": True, "oauth": False} + if token: + entry["headers"] = {"Authorization": f"Bearer {token}"} + + mcp_servers[SERVER_NAME] = entry + existing["mcp"] = mcp_servers + + config_file.write_text(json.dumps(existing, indent=2) + "\n", "utf-8") + return config_file def _write_json_mcp_settings(config_file: Path, url: str, transport: str = "http", *, token: str = "", http_key: str = "httpUrl") -> Path: @@ -160,7 +184,7 @@ def _write_claude_mcp_config( }, } -_VALID_INJECT_MODES = {"settings_file", "env", "flag", "proxy_flag", "env_content"} +_VALID_INJECT_MODES = {"settings_file", "env", "flag", "proxy_flag", "env_content", "opencode_json"} def _resolve_mcp_inject(agent: str, agent_cfg: dict) -> dict: @@ -290,12 +314,21 @@ def _apply_mcp_inject( payload = {"mcp": {SERVER_NAME: entry}} inject_env[env_var] = json.dumps(payload) - elif mode == "proxy_flag": - # Pass the proxy URL as CLI flags (e.g. codex -c ...) - template = inject_cfg.get("mcp_proxy_flag_template", - '-c mcp_servers.{server}.url="{url}"') - expanded = template.format(server=SERVER_NAME, url=proxy_url or "") - launch_args = expanded.split() + elif mode == "opencode_json": + # OpenCode specific config format (mcp key, type=remote, enabled=true) + raw_path = inject_cfg.get("mcp_settings_path", "") + if not raw_path: + raise ValueError(f"mcp_inject = 'opencode_json' requires mcp_settings_path") + target = Path(raw_path).expanduser() + if not target.is_absolute(): + base = Path(project_dir) if project_dir else Path.cwd() + target = base / target + settings_path = _write_opencode_mcp_settings(target, server_url, token=token) + + env_var = inject_cfg.get("mcp_env_var") + if env_var: + inject_env[env_var] = str(settings_path) + return launch_args, inject_env, settings_path From bf1773354e8b2b5758277ef4a8c37bfe8c239dc8 Mon Sep 17 00:00:00 2001 From: OpenCode Agent Date: Mon, 27 Apr 2026 21:52:00 +0530 Subject: [PATCH 3/8] feat: implement global project root for agent working directories --- config.toml | 1 + wrapper.py | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/config.toml b/config.toml index 6a0cdd3c..d156b902 100644 --- a/config.toml +++ b/config.toml @@ -2,6 +2,7 @@ port = 8300 host = "127.0.0.1" data_dir = "./data" +project_root = "/home/hamdan/Desktop/Meta-Heuristic-Feature-Selection/" # Global root directory for all agents. If set, agent 'cwd' is relative to this. # Add agents here. Each gets a status pill, @mention routing, and color. # "cwd" is the working directory for the agent's terminal session. diff --git a/wrapper.py b/wrapper.py index 0d303a93..6f1b8695 100644 --- a/wrapper.py +++ b/wrapper.py @@ -620,7 +620,24 @@ def main(): agent = args.agent agent_cfg = config.get("agents", {}).get(agent, {}) - cwd = agent_cfg.get("cwd", ".") + + # Resolve project root (global) vs agent cwd (specific) + global_root = config.get("server", {}).get("project_root") + agent_cwd = agent_cfg.get("cwd", ".") + + if global_root: + # Resolve agent_cwd relative to global_root. + # We ignore ".." as it's usually a legacy value relative to the wrapper's ROOT. + project_dir = Path(global_root).expanduser().resolve() + if Path(agent_cwd).is_absolute(): + project_dir = Path(agent_cwd).resolve() + elif agent_cwd not in (".", ".."): + project_dir = (project_dir / agent_cwd).resolve() + else: + # Maintain existing behavior: resolve agent_cwd relative to ROOT + project_dir = (ROOT / agent_cwd).resolve() + + cwd = str(project_dir) command = agent_cfg.get("command", agent) data_dir = ROOT / config.get("server", {}).get("data_dir", "./data") data_dir.mkdir(parents=True, exist_ok=True) @@ -698,7 +715,7 @@ def _rewrite_mcp_config(instance_name: str, new_token: str): _apply_mcp_inject( inject_cfg, instance_name, data_dir, proxy_url, token=new_token, mcp_cfg=mcp_cfg, - project_dir=(ROOT / cwd).resolve(), + project_dir=project_dir, ) except Exception: pass @@ -772,6 +789,7 @@ def set_runtime_identity(new_name: str | None = None, new_token: str | None = No elif proxy_url: print(f" Local MCP proxy: {proxy_url}") print(f" @{assigned_name} mentions auto-inject MCP reads") + # Start the agent in the resolved directory print(f" Starting {command} in {cwd}...\n") def _heartbeat(): From 06b90e14645883028ec6433d89773d923d64894d Mon Sep 17 00:00:00 2001 From: OpenCode Agent Date: Tue, 28 Apr 2026 16:41:51 +0530 Subject: [PATCH 4/8] feat: add support for custom agent parameters and identity injection --- AGENTS.md | 5 ++++- config.toml | 3 ++- wrapper.py | 25 +++++++++++++++++++++---- wrapper_api.py | 7 ++++++- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index a69b4448..b9ac339c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,8 @@ ## Developer Commands -- **Setup**: `python -m venv venv && source venv/bin/activate && pip install -r requirements.txt` +- **Quickstart**: Use scripts in `windows/` or `macos-linux/` (e.g., `sh start_claude.sh`) to auto-setup venv and MCP. +- **Manual Setup**: `python -m venv venv && source venv/bin/activate && pip install -r requirements.txt` - **Start server**: `python run.py` - **Start agent wrapper**: `python wrapper.py ` - **Start API agent**: `python wrapper_api.py ` @@ -21,11 +22,13 @@ - **MCP Layer**: `mcp_bridge.py` (tool definitions) and `mcp_proxy.py` (identity injection). - **Persistence**: `store.py` (messages), `jobs.py` (tasks), `rules.py` (rules), `summaries.py` (summaries) use JSONL/JSON files in `data/`. - **Routing**: `router.py` handles @mention parsing and agent targeting. +- **Sessions**: `session_engine.py` and `session_store.py` orchestrate multi-agent workflows using templates in `session_templates/`. ## Configuration - **`config.toml`**: Primary configuration for agents, ports, and routing (including `max_agent_hops` for loop guard). - **`config.local.toml`**: Local overrides (gitignored), used for API endpoints and local model settings. +- **Isolation**: Use `AGENTCHATTR_DATA_DIR`, `AGENTCHATTR_PORT`, `AGENTCHATTR_MCP_HTTP_PORT`, and `AGENTCHATTR_MCP_SSE_PORT` env vars to run isolated project instances. ## Conventions & Constraints diff --git a/config.toml b/config.toml index d156b902..e1676a97 100644 --- a/config.toml +++ b/config.toml @@ -2,7 +2,7 @@ port = 8300 host = "127.0.0.1" data_dir = "./data" -project_root = "/home/hamdan/Desktop/Meta-Heuristic-Feature-Selection/" # Global root directory for all agents. If set, agent 'cwd' is relative to this. +project_root = "/home/hamdan/Desktop/Password_Library/" # Global root directory for all agents. If set, agent 'cwd' is relative to this. # Add agents here. Each gets a status pill, @mention routing, and color. # "cwd" is the working directory for the agent's terminal session. @@ -50,6 +50,7 @@ label = "Kilo" [agents.opencode] command = "opencode" +args = ["-m google/gemma-4-26b-a4b-it"] cwd = ".." color = "#808080" label = "OpenCode" diff --git a/wrapper.py b/wrapper.py index 6f1b8695..5fd05171 100644 --- a/wrapper.py +++ b/wrapper.py @@ -381,7 +381,7 @@ def _build_provider_launch( project_dir: Path | None = None, ) -> tuple[list[str], dict[str, str], dict[str, str], Path | None]: """Return provider-specific launch args/env/inject_env/settings_path. - + inject_env: env vars that must propagate INTO the agent process. On Mac/Linux these are prefixed onto the tmux command via ``env VAR=val`` because subprocess.run(env=...) only affects the tmux client binary. @@ -393,12 +393,22 @@ def _build_provider_launch( token=token, mcp_cfg=mcp_cfg, project_dir=project_dir, ) - launch_args = [*mcp_args, *extra_args] - launch_env = dict(env) + # Merge config-defined args and env + config_args = agent_cfg.get("args", []) + if not isinstance(config_args, list): + config_args = [str(config_args)] + + config_env = agent_cfg.get("env", {}) + if not isinstance(config_env, dict): + config_env = {} + + launch_args = [*mcp_args, *config_args, *extra_args] + launch_env = {**env, **config_env} return launch_args, launch_env, inject_env, settings_path + def _register_instance(server_port: int, base: str, label: str | None = None) -> dict: import urllib.request @@ -489,7 +499,8 @@ def _queue_watcher(get_identity_fn, inject_fn, *, is_multi_instance: bool = Fals refresh_interval: int = 10): """Poll queue file and inject an MCP read task when triggered.""" first_mention = True - last_rules_epoch = 0 # 0 = unknown/cold start — will inject on first trigger + last_rules_epoch = 0 + last_injected_name = None trigger_count = 0 while True: try: @@ -546,6 +557,12 @@ def _queue_watcher(get_identity_fn, inject_fn, *, is_multi_instance: bool = Fals # Use current identity (may have changed via rename) current_name, _ = get_identity_fn() + + # Inform agent of its identity if it's the first time or name has changed + if last_injected_name != current_name: + prompt = f"You are {current_name}. {prompt}" + last_injected_name = current_name + # Append role if set — check both current name and base name role = _fetch_role(server_port, current_name) if not role and current_name != agent_name: diff --git a/wrapper_api.py b/wrapper_api.py index 824a88ef..75bb4d10 100644 --- a/wrapper_api.py +++ b/wrapper_api.py @@ -93,6 +93,11 @@ def main(): temperature = 0.01 if temperature > 2.0: temperature = 2.0 + + custom_params = agent_cfg.get("custom_params", {}) + if not isinstance(custom_params, dict): + custom_params = {} + context_messages = int(agent_cfg.get("context_messages", 20)) system_prompt = agent_cfg.get("system_prompt", f"You are {agent_cfg.get('label', agent)}, a helpful AI assistant participating " @@ -227,7 +232,7 @@ def send_message(text, channel="general"): # Call OpenAI-compatible chat completions API def call_model(messages): url = f"{base_url}/chat/completions" - payload = {"messages": messages} + payload = {**custom_params, "messages": messages} if model: payload["model"] = model if temperature is not None: From 020674debc9d0aecdd5e2a639df60a049cda71db Mon Sep 17 00:00:00 2001 From: OpenCode Agent Date: Tue, 28 Apr 2026 16:45:49 +0530 Subject: [PATCH 5/8] docs: update README with new features --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 68cdfb5e..22d9f607 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,12 @@ A local chat server for real-time coordination between AI coding agents and huma Agents and humans talk in a shared chat room with multiple channels — when anyone @mentions an agent, the server auto-injects a prompt into that agent's terminal, the agent reads the conversation and responds, and the loop continues hands-free. No copy-pasting between ugly terminals. No manual prompting. +## What's New +- **Agent Identity**: Agents are now informed of their name (e.g., "You are claude-2") when triggered, improving coordination in multi-instance sessions. +- **Custom Agent Parameters**: + - **CLI Agents**: Support for custom `args` and `env` per agent in `config.toml`. + - **API Agents**: Support for `custom_params` to pass extra parameters to model endpoints. + *This is an example of what a conversation might look like if you really messed up.* ![screenshot](screenshot.png) From 3dda4692025d37cea7d5e9985759eda2c1e2e8d8 Mon Sep 17 00:00:00 2001 From: OpenCode Agent Date: Tue, 28 Apr 2026 16:54:21 +0530 Subject: [PATCH 6/8] chore: remove AGENTS.md from PR --- AGENTS.md | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index b9ac339c..00000000 --- a/AGENTS.md +++ /dev/null @@ -1,39 +0,0 @@ -# Agent Instructions: agentchattr - -## Developer Commands - -- **Quickstart**: Use scripts in `windows/` or `macos-linux/` (e.g., `sh start_claude.sh`) to auto-setup venv and MCP. -- **Manual Setup**: `python -m venv venv && source venv/bin/activate && pip install -r requirements.txt` -- **Start server**: `python run.py` -- **Start agent wrapper**: `python wrapper.py ` -- **Start API agent**: `python wrapper_api.py ` -- **Run all tests**: `python -m unittest discover tests` -- **Run single test**: `python -m unittest tests/test_.py` -- **Web UI**: http://localhost:8300 (default) - -## Architecture & Key Files - -- **Entry Point**: `run.py` starts both the MCP and web server. -- **Web Server**: `app.py` (FastAPI) handles WebSocket communication and REST endpoints. -- **Agent Wrapper**: `wrapper.py` manages agent life cycles and injects prompts into agent terminals. - - **Windows**: `wrapper_windows.py` uses Win32 API. - - **Mac/Linux**: `wrapper_unix.py` requires `tmux`. -- **API Agent**: `wrapper_api.py` connects to OpenAI-compatible local models. -- **MCP Layer**: `mcp_bridge.py` (tool definitions) and `mcp_proxy.py` (identity injection). -- **Persistence**: `store.py` (messages), `jobs.py` (tasks), `rules.py` (rules), `summaries.py` (summaries) use JSONL/JSON files in `data/`. -- **Routing**: `router.py` handles @mention parsing and agent targeting. -- **Sessions**: `session_engine.py` and `session_store.py` orchestrate multi-agent workflows using templates in `session_templates/`. - -## Configuration - -- **`config.toml`**: Primary configuration for agents, ports, and routing (including `max_agent_hops` for loop guard). -- **`config.local.toml`**: Local overrides (gitignored), used for API endpoints and local model settings. -- **Isolation**: Use `AGENTCHATTR_DATA_DIR`, `AGENTCHATTR_PORT`, `AGENTCHATTR_MCP_HTTP_PORT`, and `AGENTCHATTR_MCP_SSE_PORT` env vars to run isolated project instances. - -## Conventions & Constraints - -- **Python Version**: 3.11+ (required for `tomllib`). -- **Platform dependency**: `tmux` must be installed on macOS/Linux for the agent wrapper to function. -- **Localhost only**: The server is designed for localhost use; use `--allow-network` only on trusted networks. -- **Security**: All API/WS requests must present the session token generated on server start. -- **Loop Guard**: Agent-to-agent chains are paused after `max_agent_hops`; use `/continue` in chat to resume. From 765b025492da4a7ebda5ef0dc172a3a75e9a8833 Mon Sep 17 00:00:00 2001 From: OpenCode Agent Date: Tue, 28 Apr 2026 17:00:21 +0530 Subject: [PATCH 7/8] chore: add AGENTS.md to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1116a8de..a375117c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ agents_lineup.svg docs/ goals.py pr-reviews/ +AGENTS.md agentchattr-*.zip From 01dad180823f66b6a5aac1c60feb783622454a88 Mon Sep 17 00:00:00 2001 From: OpenCode Agent Date: Tue, 28 Apr 2026 17:05:13 +0530 Subject: [PATCH 8/8] feat: add tmux kill-server to start.sh --- README.md | 2 +- macos-linux/start.sh | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 22d9f607..49212b64 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ On first launch, the script auto-creates a virtual environment, installs Python
All agent launchers (click to expand) -- `sh start.sh` — starts the chat server only +- `sh start.sh` — starts the chat server only (and cleans up existing tmux sessions) - `sh start_claude.sh` — starts Claude - `sh start_codex.sh` — starts Codex - `sh start_gemini.sh` — starts Gemini diff --git a/macos-linux/start.sh b/macos-linux/start.sh index 5ed4892e..9bc674e0 100755 --- a/macos-linux/start.sh +++ b/macos-linux/start.sh @@ -33,6 +33,9 @@ ensure_venv() { ensure_venv +# Kill any existing tmux sessions to ensure a clean start +tmux kill-server 2>/dev/null + .venv/bin/python run.py code=$? echo ""