From c2ad993e75c2058e4d2f0e75d59fed4bbfb6b63c Mon Sep 17 00:00:00 2001 From: Auto Date: Wed, 4 Feb 2026 12:02:06 +0200 Subject: [PATCH] rebrand: rename AutoCoder to AutoForge across entire codebase Complete project rebrand from AutoCoder to AutoForge, touching 62 files across Python backend, FastAPI server, React UI, documentation, config, and CI/CD. Key changes: - Rename autocoder_paths.py -> autoforge_paths.py with backward-compat migration from .autocoder/ -> .autoforge/ directories - Update registry.py to migrate ~/.autocoder/ -> ~/.autoforge/ global config directory with fallback support - Update security.py with fallback reads from legacy .autocoder/ paths - Rename .claude/commands and skills from gsd-to-autocoder-spec to gsd-to-autoforge-spec - Update all Python modules: client, prompts, progress, agent, orchestrator, server routers and services - Update React UI: package.json name, index.html title, localStorage keys, all documentation sections, component references - Update start scripts (bat/sh/py), examples, and .env.example - Update CLAUDE.md and README.md with new branding and paths - Update test files for new .autoforge/ directory structure - Transfer git remote from leonvanzyl/autocoder to AutoForgeAI/autoforge Backward compatibility preserved: legacy .autocoder/ directories are auto-detected and migrated on next agent start. Config fallback chain checks both new and old paths. Co-Authored-By: Claude Opus 4.5 --- .claude/agents/coder.md | 2 +- .claude/commands/create-spec.md | 26 ++-- .claude/commands/expand-project.md | 4 +- .claude/commands/gsd-to-autocoder-spec.md | 10 -- .claude/commands/gsd-to-autoforge-spec.md | 10 ++ .../SKILL.md | 38 +++--- .../references/app-spec-format.md | 6 +- .env.example | 2 +- CLAUDE.md | 42 +++---- README.md | 6 +- api/database.py | 4 +- autocoder_paths.py => autoforge_paths.py | 113 +++++++++++------- autonomous_agent_demo.py | 6 +- client.py | 4 +- env_constants.py | 2 +- examples/OPTIMIZE_CONFIG.md | 2 +- examples/README.md | 40 +++---- examples/org_config.yaml | 10 +- examples/project_allowed_commands.yaml | 8 +- parallel_orchestrator.py | 16 +-- progress.py | 8 +- prompts.py | 14 +-- registry.py | 27 ++++- security.py | 22 +++- server/main.py | 4 +- server/routers/expand_project.py | 2 +- server/routers/features.py | 6 +- server/routers/projects.py | 8 +- server/routers/spec_creation.py | 2 +- server/services/assistant_chat_session.py | 4 +- server/services/assistant_database.py | 2 +- server/services/chat_constants.py | 2 +- server/services/dev_server_manager.py | 6 +- server/services/expand_chat_session.py | 4 +- server/services/process_manager.py | 6 +- server/services/project_config.py | 29 +++-- server/services/scheduler_service.py | 4 +- server/services/spec_chat_session.py | 4 +- start.bat | 2 +- start.py | 2 +- start.sh | 2 +- start_ui.bat | 4 +- start_ui.py | 12 +- start_ui.sh | 4 +- test_security.py | 46 +++---- test_security_integration.py | 58 ++++----- ui/index.html | 2 +- ui/package-lock.json | 18 +-- ui/package.json | 2 +- ui/src/App.tsx | 8 +- ui/src/components/AgentMissionControl.tsx | 2 +- ui/src/components/docs/DocsPage.tsx | 2 +- ui/src/components/docs/docsData.ts | 4 +- .../docs/sections/AdvancedConfig.tsx | 6 +- .../components/docs/sections/AppSpecSetup.tsx | 6 +- .../docs/sections/AppearanceThemes.tsx | 2 +- ui/src/components/docs/sections/FAQ.tsx | 10 +- .../docs/sections/GettingStarted.tsx | 18 +-- .../docs/sections/ProjectStructure.tsx | 20 ++-- .../components/docs/sections/Scheduling.tsx | 2 +- ui/src/components/docs/sections/Security.tsx | 16 +-- .../docs/sections/SettingsConfig.tsx | 2 +- ui/src/hooks/useTheme.ts | 4 +- 63 files changed, 405 insertions(+), 354 deletions(-) delete mode 100644 .claude/commands/gsd-to-autocoder-spec.md create mode 100644 .claude/commands/gsd-to-autoforge-spec.md rename .claude/skills/{gsd-to-autocoder-spec => gsd-to-autoforge-spec}/SKILL.md (85%) rename .claude/skills/{gsd-to-autocoder-spec => gsd-to-autoforge-spec}/references/app-spec-format.md (98%) rename autocoder_paths.py => autoforge_paths.py (70%) diff --git a/.claude/agents/coder.md b/.claude/agents/coder.md index d09f907..0da3127 100644 --- a/.claude/agents/coder.md +++ b/.claude/agents/coder.md @@ -97,7 +97,7 @@ Fix ALL issues before considering the implementation complete. Never leave linti ## Project-Specific Context -For this project (autocoder): +For this project (autoforge): - **Python Backend**: Uses SQLAlchemy, FastAPI, follows patterns in `api/`, `mcp_server/` - **React UI**: Uses React 18, TypeScript, TanStack Query, Tailwind CSS v4, Radix UI - **Design System**: Neobrutalism style with specific color tokens and animations diff --git a/.claude/commands/create-spec.md b/.claude/commands/create-spec.md index 9c23abe..f0555d2 100644 --- a/.claude/commands/create-spec.md +++ b/.claude/commands/create-spec.md @@ -8,7 +8,7 @@ This command **requires** the project directory as an argument via `$ARGUMENTS`. **Example:** `/create-spec generations/my-app` -**Output location:** `$ARGUMENTS/.autocoder/prompts/app_spec.txt` and `$ARGUMENTS/.autocoder/prompts/initializer_prompt.md` +**Output location:** `$ARGUMENTS/.autoforge/prompts/app_spec.txt` and `$ARGUMENTS/.autoforge/prompts/initializer_prompt.md` If `$ARGUMENTS` is empty, inform the user they must provide a project path and exit. @@ -347,13 +347,13 @@ First ask in conversation if they want to make changes. ## Output Directory -The output directory is: `$ARGUMENTS/.autocoder/prompts/` +The output directory is: `$ARGUMENTS/.autoforge/prompts/` Once the user approves, generate these files: ## 1. Generate `app_spec.txt` -**Output path:** `$ARGUMENTS/.autocoder/prompts/app_spec.txt` +**Output path:** `$ARGUMENTS/.autoforge/prompts/app_spec.txt` Create a new file using this XML structure: @@ -489,7 +489,7 @@ Create a new file using this XML structure: ## 2. Update `initializer_prompt.md` -**Output path:** `$ARGUMENTS/.autocoder/prompts/initializer_prompt.md` +**Output path:** `$ARGUMENTS/.autoforge/prompts/initializer_prompt.md` If the output directory has an existing `initializer_prompt.md`, read it and update the feature count. If not, copy from `.claude/templates/initializer_prompt.template.md` first, then update. @@ -512,7 +512,7 @@ After: **CRITICAL:** You must create exactly **25** features using the `feature ## 3. Write Status File (REQUIRED - Do This Last) -**Output path:** `$ARGUMENTS/.autocoder/prompts/.spec_status.json` +**Output path:** `$ARGUMENTS/.autoforge/prompts/.spec_status.json` **CRITICAL:** After you have completed ALL requested file changes, write this status file to signal completion to the UI. This is required for the "Continue to Project" button to appear. @@ -524,8 +524,8 @@ Write this JSON file: "version": 1, "timestamp": "[current ISO 8601 timestamp, e.g., 2025-01-15T14:30:00.000Z]", "files_written": [ - ".autocoder/prompts/app_spec.txt", - ".autocoder/prompts/initializer_prompt.md" + ".autoforge/prompts/app_spec.txt", + ".autoforge/prompts/initializer_prompt.md" ], "feature_count": [the feature count from Phase 4L] } @@ -539,9 +539,9 @@ Write this JSON file: "version": 1, "timestamp": "2025-01-15T14:30:00.000Z", "files_written": [ - ".autocoder/prompts/app_spec.txt", - ".autocoder/prompts/initializer_prompt.md", - ".autocoder/prompts/coding_prompt.md" + ".autoforge/prompts/app_spec.txt", + ".autoforge/prompts/initializer_prompt.md", + ".autoforge/prompts/coding_prompt.md" ], "feature_count": 35 } @@ -559,11 +559,11 @@ Write this JSON file: Once files are generated, tell the user what to do next: -> "Your specification files have been created in `$ARGUMENTS/.autocoder/prompts/`! +> "Your specification files have been created in `$ARGUMENTS/.autoforge/prompts/`! > > **Files created:** -> - `$ARGUMENTS/.autocoder/prompts/app_spec.txt` -> - `$ARGUMENTS/.autocoder/prompts/initializer_prompt.md` +> - `$ARGUMENTS/.autoforge/prompts/app_spec.txt` +> - `$ARGUMENTS/.autoforge/prompts/initializer_prompt.md` > > The **Continue to Project** button should now appear. Click it to start the autonomous coding agent! > diff --git a/.claude/commands/expand-project.md b/.claude/commands/expand-project.md index 0ddf027..731505e 100644 --- a/.claude/commands/expand-project.md +++ b/.claude/commands/expand-project.md @@ -42,7 +42,7 @@ You are the **Project Expansion Assistant** - an expert at understanding existin # FIRST: Read and Understand Existing Project **Step 1:** Read the existing specification: -- Read `$ARGUMENTS/.autocoder/prompts/app_spec.txt` +- Read `$ARGUMENTS/.autoforge/prompts/app_spec.txt` **Step 2:** Present a summary to the user: @@ -231,4 +231,4 @@ If they want to add more, go back to Phase 1. # BEGIN -Start by reading the app specification file at `$ARGUMENTS/.autocoder/prompts/app_spec.txt`, then greet the user with a summary of their existing project and ask what they want to add. +Start by reading the app specification file at `$ARGUMENTS/.autoforge/prompts/app_spec.txt`, then greet the user with a summary of their existing project and ask what they want to add. diff --git a/.claude/commands/gsd-to-autocoder-spec.md b/.claude/commands/gsd-to-autocoder-spec.md deleted file mode 100644 index dbaeff6..0000000 --- a/.claude/commands/gsd-to-autocoder-spec.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -allowed-tools: Read, Write, Bash, Glob, Grep -description: Convert GSD codebase mapping to Autocoder app_spec.txt ---- - -# GSD to Autocoder Spec - -Convert `.planning/codebase/*.md` (from `/gsd:map-codebase`) to Autocoder's `.autocoder/prompts/app_spec.txt`. - -@.claude/skills/gsd-to-autocoder-spec/SKILL.md diff --git a/.claude/commands/gsd-to-autoforge-spec.md b/.claude/commands/gsd-to-autoforge-spec.md new file mode 100644 index 0000000..48bb63d --- /dev/null +++ b/.claude/commands/gsd-to-autoforge-spec.md @@ -0,0 +1,10 @@ +--- +allowed-tools: Read, Write, Bash, Glob, Grep +description: Convert GSD codebase mapping to AutoForge app_spec.txt +--- + +# GSD to AutoForge Spec + +Convert `.planning/codebase/*.md` (from `/gsd:map-codebase`) to AutoForge's `.autoforge/prompts/app_spec.txt`. + +@.claude/skills/gsd-to-autoforge-spec/SKILL.md diff --git a/.claude/skills/gsd-to-autocoder-spec/SKILL.md b/.claude/skills/gsd-to-autoforge-spec/SKILL.md similarity index 85% rename from .claude/skills/gsd-to-autocoder-spec/SKILL.md rename to .claude/skills/gsd-to-autoforge-spec/SKILL.md index 167caf0..c389c47 100644 --- a/.claude/skills/gsd-to-autocoder-spec/SKILL.md +++ b/.claude/skills/gsd-to-autoforge-spec/SKILL.md @@ -1,21 +1,21 @@ --- -name: gsd-to-autocoder-spec +name: gsd-to-autoforge-spec description: | - Convert GSD codebase mapping to Autocoder app_spec.txt. This skill should be used when - the user has run /gsd:map-codebase and wants to use Autocoder on an existing project. - Triggers: "convert to autocoder", "gsd to spec", "create app_spec from codebase", - "use autocoder on existing project", after /gsd:map-codebase completion. + Convert GSD codebase mapping to AutoForge app_spec.txt. This skill should be used when + the user has run /gsd:map-codebase and wants to use AutoForge on an existing project. + Triggers: "convert to autoforge", "gsd to spec", "create app_spec from codebase", + "use autoforge on existing project", after /gsd:map-codebase completion. --- -# GSD to Autocoder Spec Converter +# GSD to AutoForge Spec Converter -Converts `.planning/codebase/*.md` (GSD mapping output) to `.autocoder/prompts/app_spec.txt` (Autocoder format). +Converts `.planning/codebase/*.md` (GSD mapping output) to `.autoforge/prompts/app_spec.txt` (AutoForge format). ## When to Use - After running `/gsd:map-codebase` on an existing project -- When onboarding an existing codebase to Autocoder -- User wants Autocoder to continue development on existing code +- When onboarding an existing codebase to AutoForge +- User wants AutoForge to continue development on existing code ## Prerequisites @@ -84,12 +84,12 @@ Extract: Create `prompts/` directory: ```bash -mkdir -p .autocoder/prompts +mkdir -p .autoforge/prompts ``` -**Mapping GSD Documents to Autocoder Spec:** +**Mapping GSD Documents to AutoForge Spec:** -| GSD Source | Autocoder Target | +| GSD Source | AutoForge Target | |------------|------------------| | STACK.md Languages | `` | | STACK.md Frameworks | ``, `` | @@ -114,7 +114,7 @@ mkdir -p .autocoder/prompts **Write the spec file** using the XML format from [references/app-spec-format.md](references/app-spec-format.md): ```bash -cat > .autocoder/prompts/app_spec.txt << 'EOF' +cat > .autoforge/prompts/app_spec.txt << 'EOF' {from package.json or directory} @@ -173,9 +173,9 @@ EOF ### Step 5: Verify Generated Spec ```bash -head -100 .autocoder/prompts/app_spec.txt +head -100 .autoforge/prompts/app_spec.txt echo "---" -grep -c "User can\|System\|API\|Feature" .autocoder/prompts/app_spec.txt || echo "0" +grep -c "User can\|System\|API\|Feature" .autoforge/prompts/app_spec.txt || echo "0" ``` **Validation checklist:** @@ -194,15 +194,15 @@ Output: app_spec.txt generated from GSD codebase mapping. Source: .planning/codebase/*.md -Output: .autocoder/prompts/app_spec.txt +Output: .autoforge/prompts/app_spec.txt -Next: Start Autocoder +Next: Start AutoForge cd {project_dir} - python ~/projects/autocoder/start.py + python ~/projects/autoforge/start.py Or via UI: - ~/projects/autocoder/start_ui.sh + ~/projects/autoforge/start_ui.sh The Initializer will create features.db from this spec. ``` diff --git a/.claude/skills/gsd-to-autocoder-spec/references/app-spec-format.md b/.claude/skills/gsd-to-autoforge-spec/references/app-spec-format.md similarity index 98% rename from .claude/skills/gsd-to-autocoder-spec/references/app-spec-format.md rename to .claude/skills/gsd-to-autoforge-spec/references/app-spec-format.md index fa5f9c8..806e387 100644 --- a/.claude/skills/gsd-to-autocoder-spec/references/app-spec-format.md +++ b/.claude/skills/gsd-to-autoforge-spec/references/app-spec-format.md @@ -1,6 +1,6 @@ -# Autocoder app_spec.txt XML Format +# AutoForge app_spec.txt XML Format -Complete reference for the XML structure expected by Autocoder's Initializer agent. +Complete reference for the XML structure expected by AutoForge's Initializer agent. ## Root Structure @@ -275,7 +275,7 @@ The Initializer agent expects features distributed across categories: | Medium web app | 200-250 | 10-15 | | Complex full-stack | 300-400 | 15-20 | -## GSD to Autocoder Mapping +## GSD to AutoForge Mapping When converting from GSD codebase mapping: diff --git a/.env.example b/.env.example index 9cb154a..2c139c3 100644 --- a/.env.example +++ b/.env.example @@ -36,7 +36,7 @@ # GLM/Alternative API Configuration (Optional) # To use Zhipu AI's GLM models instead of Claude, uncomment and set these variables. -# This only affects AutoCoder - your global Claude Code settings remain unchanged. +# This only affects AutoForge - your global Claude Code settings remain unchanged. # Get an API key at: https://z.ai/subscribe # # ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic diff --git a/CLAUDE.md b/CLAUDE.md index ef1d7d0..540ef6d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -140,7 +140,7 @@ Configuration in `pyproject.toml`: - `start.py` - CLI launcher with project creation/selection menu - `autonomous_agent_demo.py` - Entry point for running the agent (supports `--yolo`, `--parallel`, `--batch-size`, `--batch-features`) -- `autocoder_paths.py` - Central path resolution with dual-path backward compatibility and migration +- `autoforge_paths.py` - Central path resolution with dual-path backward compatibility and migration - `agent.py` - Agent session loop using Claude Agent SDK - `client.py` - ClaudeSDKClient configuration with security hooks, MCP servers, and Vertex AI support - `security.py` - Bash command allowlist validation (ALLOWED_COMMANDS whitelist) @@ -158,7 +158,7 @@ Configuration in `pyproject.toml`: ### Project Registry Projects can be stored in any directory. The registry maps project names to paths using SQLite: -- **All platforms**: `~/.autocoder/registry.db` +- **All platforms**: `~/.autoforge/registry.db` The registry uses: - SQLite database with SQLAlchemy ORM @@ -254,18 +254,18 @@ Keyboard shortcuts (press `?` for help): ### Project Structure for Generated Apps -Projects can be stored in any directory (registered in `~/.autocoder/registry.db`). Each project contains: -- `.autocoder/prompts/app_spec.txt` - Application specification (XML format) -- `.autocoder/prompts/initializer_prompt.md` - First session prompt -- `.autocoder/prompts/coding_prompt.md` - Continuation session prompt -- `.autocoder/features.db` - SQLite database with feature test cases -- `.autocoder/.agent.lock` - Lock file to prevent multiple agent instances -- `.autocoder/allowed_commands.yaml` - Project-specific bash command allowlist (optional) -- `.autocoder/.gitignore` - Ignores runtime files +Projects can be stored in any directory (registered in `~/.autoforge/registry.db`). Each project contains: +- `.autoforge/prompts/app_spec.txt` - Application specification (XML format) +- `.autoforge/prompts/initializer_prompt.md` - First session prompt +- `.autoforge/prompts/coding_prompt.md` - Continuation session prompt +- `.autoforge/features.db` - SQLite database with feature test cases +- `.autoforge/.agent.lock` - Lock file to prevent multiple agent instances +- `.autoforge/allowed_commands.yaml` - Project-specific bash command allowlist (optional) +- `.autoforge/.gitignore` - Ignores runtime files - `CLAUDE.md` - Stays at project root (SDK convention) - `app_spec.txt` - Root copy for agent template compatibility -Legacy projects with files at root level (e.g., `features.db`, `prompts/`) are auto-migrated to `.autocoder/` on next agent start. Dual-path resolution ensures old and new layouts work transparently. +Legacy projects with files at root level (e.g., `features.db`, `prompts/`) are auto-migrated to `.autoforge/` on next agent start. Dual-path resolution ensures old and new layouts work transparently. ### Security Model @@ -311,14 +311,14 @@ The agent's bash command access is controlled through a hierarchical configurati **Command Hierarchy (highest to lowest priority):** 1. **Hardcoded Blocklist** (`security.py`) - NEVER allowed (dd, sudo, shutdown, etc.) -2. **Org Blocklist** (`~/.autocoder/config.yaml`) - Cannot be overridden by projects -3. **Org Allowlist** (`~/.autocoder/config.yaml`) - Available to all projects +2. **Org Blocklist** (`~/.autoforge/config.yaml`) - Cannot be overridden by projects +3. **Org Allowlist** (`~/.autoforge/config.yaml`) - Available to all projects 4. **Global Allowlist** (`security.py`) - Default commands (npm, git, curl, etc.) -5. **Project Allowlist** (`.autocoder/allowed_commands.yaml`) - Project-specific commands +5. **Project Allowlist** (`.autoforge/allowed_commands.yaml`) - Project-specific commands **Project Configuration:** -Each project can define custom allowed commands in `.autocoder/allowed_commands.yaml`: +Each project can define custom allowed commands in `.autoforge/allowed_commands.yaml`: ```yaml version: 1 @@ -338,7 +338,7 @@ commands: **Organization Configuration:** -System administrators can set org-wide policies in `~/.autocoder/config.yaml`: +System administrators can set org-wide policies in `~/.autoforge/config.yaml`: ```yaml version: 1 @@ -405,7 +405,7 @@ Run coding agents using local models via Ollama v0.14.0+: ANTHROPIC_DEFAULT_OPUS_MODEL=qwen3-coder ANTHROPIC_DEFAULT_HAIKU_MODEL=qwen3-coder ``` -5. Run autocoder normally - it will use your local Ollama models +5. Run AutoForge normally - it will use your local Ollama models **Recommended coding models:** - `qwen3-coder` - Good balance of speed and capability @@ -427,7 +427,7 @@ Run coding agents using local models via Ollama v0.14.0+: **Slash commands** (`.claude/commands/`): - `/create-spec` - Interactive spec creation for new projects - `/expand-project` - Expand existing project with new features -- `/gsd-to-autocoder-spec` - Convert GSD codebase mapping to app_spec.txt +- `/gsd-to-autoforge-spec` - Convert GSD codebase mapping to app_spec.txt - `/check-code` - Run lint and type-check for code quality - `/checkpoint` - Create comprehensive checkpoint commit - `/review-pr` - Review pull requests @@ -439,7 +439,7 @@ Run coding agents using local models via Ollama v0.14.0+: **Skills** (`.claude/skills/`): - `frontend-design` - Distinctive, production-grade UI design -- `gsd-to-autocoder-spec` - Convert GSD codebase mapping to Autocoder app_spec format +- `gsd-to-autoforge-spec` - Convert GSD codebase mapping to AutoForge app_spec format **Other:** - `.claude/templates/` - Prompt templates copied to new projects @@ -449,12 +449,12 @@ Run coding agents using local models via Ollama v0.14.0+: ### Prompt Loading Fallback Chain -1. Project-specific: `{project_dir}/.autocoder/prompts/{name}.md` (or legacy `{project_dir}/prompts/{name}.md`) +1. Project-specific: `{project_dir}/.autoforge/prompts/{name}.md` (or legacy `{project_dir}/prompts/{name}.md`) 2. Base template: `.claude/templates/{name}.template.md` ### Agent Session Flow -1. Check if `.autocoder/features.db` has features (determines initializer vs coding agent) +1. Check if `.autoforge/features.db` has features (determines initializer vs coding agent) 2. Create ClaudeSDKClient with security settings 3. Send prompt and stream response 4. Auto-continue with 3-second delay between sessions diff --git a/README.md b/README.md index 3ed7f15..dcdeb43 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# AutoCoder +# AutoForge [![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-FFDD00?style=flat&logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/leonvanzyl) @@ -290,7 +290,7 @@ When test progress increases, the agent sends: ### Using GLM Models (Alternative to Claude) -To use Zhipu AI's GLM models instead of Claude, add these variables to your `.env` file in the AutoCoder directory: +To use Zhipu AI's GLM models instead of Claude, add these variables to your `.env` file in the AutoForge directory: ```bash ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic @@ -301,7 +301,7 @@ ANTHROPIC_DEFAULT_OPUS_MODEL=glm-4.7 ANTHROPIC_DEFAULT_HAIKU_MODEL=glm-4.5-air ``` -This routes AutoCoder's API requests through Zhipu's Claude-compatible API, allowing you to use GLM-4.7 and other models. **This only affects AutoCoder** - your global Claude Code settings remain unchanged. +This routes AutoForge's API requests through Zhipu's Claude-compatible API, allowing you to use GLM-4.7 and other models. **This only affects AutoForge** - your global Claude Code settings remain unchanged. Get an API key at: https://z.ai/subscribe diff --git a/api/database.py b/api/database.py index 4c5ef42..4381fbe 100644 --- a/api/database.py +++ b/api/database.py @@ -183,7 +183,7 @@ class ScheduleOverride(Base): def get_database_path(project_dir: Path) -> Path: """Return the path to the SQLite database for a project.""" - from autocoder_paths import get_features_db_path + from autoforge_paths import get_features_db_path return get_features_db_path(project_dir) @@ -385,7 +385,7 @@ def create_database(project_dir: Path) -> tuple: db_url = get_database_url(project_dir) - # Ensure parent directory exists (for .autocoder/ layout) + # Ensure parent directory exists (for .autoforge/ layout) db_path = get_database_path(project_dir) db_path.parent.mkdir(parents=True, exist_ok=True) diff --git a/autocoder_paths.py b/autoforge_paths.py similarity index 70% rename from autocoder_paths.py rename to autoforge_paths.py index 7d1db6f..8283a9b 100644 --- a/autocoder_paths.py +++ b/autoforge_paths.py @@ -1,17 +1,19 @@ """ -Autocoder Path Resolution +AutoForge Path Resolution ========================= -Central module for resolving paths to autocoder-generated files within a project. +Central module for resolving paths to autoforge-generated files within a project. -Implements a dual-path resolution strategy for backward compatibility: +Implements a tri-path resolution strategy for backward compatibility: - 1. Check ``project_dir / ".autocoder" / X`` (new layout) - 2. Check ``project_dir / X`` (legacy root-level layout) - 3. Default to the new location for fresh projects + 1. Check ``project_dir / ".autoforge" / X`` (current layout) + 2. Check ``project_dir / ".autocoder" / X`` (legacy layout) + 3. Check ``project_dir / X`` (legacy root-level layout) + 4. Default to the new location for fresh projects This allows existing projects with root-level ``features.db``, ``.agent.lock``, -etc. to keep working while new projects store everything under ``.autocoder/``. +etc. to keep working while new projects store everything under ``.autoforge/``. +Projects using the old ``.autocoder/`` directory are auto-migrated on next start. The ``migrate_project_layout`` function can move an old-layout project to the new layout safely, with full integrity checks for SQLite databases. @@ -25,10 +27,10 @@ from pathlib import Path logger = logging.getLogger(__name__) # --------------------------------------------------------------------------- -# .gitignore content written into every .autocoder/ directory +# .gitignore content written into every .autoforge/ directory # --------------------------------------------------------------------------- _GITIGNORE_CONTENT = """\ -# Autocoder runtime files +# AutoForge runtime files features.db features.db-wal features.db-shm @@ -49,15 +51,18 @@ assistant.db-shm # --------------------------------------------------------------------------- def _resolve_path(project_dir: Path, filename: str) -> Path: - """Resolve a file path using dual-path strategy. + """Resolve a file path using tri-path strategy. - Checks the new ``.autocoder/`` location first, then falls back to the - legacy root-level location. If neither exists, returns the new location - so that newly-created files land in ``.autocoder/``. + Checks the new ``.autoforge/`` location first, then the legacy + ``.autocoder/`` location, then the root-level location. If none exist, + returns the new location so that newly-created files land in ``.autoforge/``. """ - new = project_dir / ".autocoder" / filename + new = project_dir / ".autoforge" / filename if new.exists(): return new + legacy = project_dir / ".autocoder" / filename + if legacy.exists(): + return legacy old = project_dir / filename if old.exists(): return old @@ -65,14 +70,17 @@ def _resolve_path(project_dir: Path, filename: str) -> Path: def _resolve_dir(project_dir: Path, dirname: str) -> Path: - """Resolve a directory path using dual-path strategy. + """Resolve a directory path using tri-path strategy. Same logic as ``_resolve_path`` but intended for directories such as ``prompts/``. """ - new = project_dir / ".autocoder" / dirname + new = project_dir / ".autoforge" / dirname if new.exists(): return new + legacy = project_dir / ".autocoder" / dirname + if legacy.exists(): + return legacy old = project_dir / dirname if old.exists(): return old @@ -80,27 +88,27 @@ def _resolve_dir(project_dir: Path, dirname: str) -> Path: # --------------------------------------------------------------------------- -# .autocoder directory management +# .autoforge directory management # --------------------------------------------------------------------------- -def get_autocoder_dir(project_dir: Path) -> Path: - """Return the ``.autocoder`` directory path. Does NOT create it.""" - return project_dir / ".autocoder" +def get_autoforge_dir(project_dir: Path) -> Path: + """Return the ``.autoforge`` directory path. Does NOT create it.""" + return project_dir / ".autoforge" -def ensure_autocoder_dir(project_dir: Path) -> Path: - """Create the ``.autocoder/`` directory (if needed) and write its ``.gitignore``. +def ensure_autoforge_dir(project_dir: Path) -> Path: + """Create the ``.autoforge/`` directory (if needed) and write its ``.gitignore``. Returns: - The path to the ``.autocoder`` directory. + The path to the ``.autoforge`` directory. """ - autocoder_dir = get_autocoder_dir(project_dir) - autocoder_dir.mkdir(parents=True, exist_ok=True) + autoforge_dir = get_autoforge_dir(project_dir) + autoforge_dir.mkdir(parents=True, exist_ok=True) - gitignore_path = autocoder_dir / ".gitignore" + gitignore_path = autoforge_dir / ".gitignore" gitignore_path.write_text(_GITIGNORE_CONTENT, encoding="utf-8") - return autocoder_dir + return autoforge_dir # --------------------------------------------------------------------------- @@ -154,9 +162,9 @@ def get_prompts_dir(project_dir: Path) -> Path: def get_expand_settings_path(project_dir: Path, uuid_hex: str) -> Path: """Return the path for an ephemeral expand-session settings file. - These files are short-lived and always stored in ``.autocoder/``. + These files are short-lived and always stored in ``.autoforge/``. """ - return project_dir / ".autocoder" / f".claude_settings.expand.{uuid_hex}.json" + return project_dir / ".autoforge" / f".claude_settings.expand.{uuid_hex}.json" # --------------------------------------------------------------------------- @@ -166,8 +174,9 @@ def get_expand_settings_path(project_dir: Path, uuid_hex: str) -> Path: def has_agent_running(project_dir: Path) -> bool: """Check whether any agent or dev-server lock file exists at either location. - Inspects both the legacy root-level paths and the new ``.autocoder/`` - paths so that a running agent is detected regardless of project layout. + Inspects the legacy root-level paths, the old ``.autocoder/`` paths, and + the new ``.autoforge/`` paths so that a running agent is detected + regardless of project layout. Returns: ``True`` if any ``.agent.lock`` or ``.devserver.lock`` exists. @@ -176,8 +185,11 @@ def has_agent_running(project_dir: Path) -> bool: for name in lock_names: if (project_dir / name).exists(): return True + # Check both old and new directory names for backward compatibility if (project_dir / ".autocoder" / name).exists(): return True + if (project_dir / ".autoforge" / name).exists(): + return True return False @@ -186,7 +198,7 @@ def has_agent_running(project_dir: Path) -> bool: # --------------------------------------------------------------------------- def migrate_project_layout(project_dir: Path) -> list[str]: - """Migrate a project from the legacy root-level layout to ``.autocoder/``. + """Migrate a project from the legacy root-level layout to ``.autoforge/``. The migration is incremental and safe: @@ -199,7 +211,7 @@ def migrate_project_layout(project_dir: Path) -> list[str]: Returns: A list of human-readable descriptions of what was migrated, e.g. - ``["prompts/ -> .autocoder/prompts/", "features.db -> .autocoder/features.db"]``. + ``["prompts/ -> .autoforge/prompts/", "features.db -> .autoforge/features.db"]``. An empty list means nothing was migrated (either everything is already migrated, or the agent is running). """ @@ -208,18 +220,31 @@ def migrate_project_layout(project_dir: Path) -> list[str]: logger.warning("Migration skipped: agent or dev-server is running for %s", project_dir) return [] - autocoder_dir = ensure_autocoder_dir(project_dir) - migrated: list[str] = [] + # --- 0. Migrate .autocoder/ → .autoforge/ directory ------------------- + old_autocoder_dir = project_dir / ".autocoder" + new_autoforge_dir = project_dir / ".autoforge" + if old_autocoder_dir.exists() and old_autocoder_dir.is_dir() and not new_autoforge_dir.exists(): + try: + old_autocoder_dir.rename(new_autoforge_dir) + logger.info("Migrated .autocoder/ -> .autoforge/") + migrated: list[str] = [".autocoder/ -> .autoforge/"] + except Exception: + logger.warning("Failed to migrate .autocoder/ -> .autoforge/", exc_info=True) + migrated = [] + else: + migrated = [] + + autoforge_dir = ensure_autoforge_dir(project_dir) # --- 1. Migrate prompts/ directory ----------------------------------- try: old_prompts = project_dir / "prompts" - new_prompts = autocoder_dir / "prompts" + new_prompts = autoforge_dir / "prompts" if old_prompts.exists() and old_prompts.is_dir() and not new_prompts.exists(): shutil.copytree(str(old_prompts), str(new_prompts)) shutil.rmtree(str(old_prompts)) - migrated.append("prompts/ -> .autocoder/prompts/") - logger.info("Migrated prompts/ -> .autocoder/prompts/") + migrated.append("prompts/ -> .autoforge/prompts/") + logger.info("Migrated prompts/ -> .autoforge/prompts/") except Exception: logger.warning("Failed to migrate prompts/ directory", exc_info=True) @@ -228,7 +253,7 @@ def migrate_project_layout(project_dir: Path) -> list[str]: for db_name in db_names: try: old_db = project_dir / db_name - new_db = autocoder_dir / db_name + new_db = autoforge_dir / db_name if old_db.exists() and not new_db.exists(): # Flush WAL to ensure all data is in the main database file conn = sqlite3.connect(str(old_db)) @@ -263,8 +288,8 @@ def migrate_project_layout(project_dir: Path) -> list[str]: wal_file = project_dir / f"{db_name}{suffix}" wal_file.unlink(missing_ok=True) - migrated.append(f"{db_name} -> .autocoder/{db_name}") - logger.info("Migrated %s -> .autocoder/%s", db_name, db_name) + migrated.append(f"{db_name} -> .autoforge/{db_name}") + logger.info("Migrated %s -> .autoforge/%s", db_name, db_name) except Exception: logger.warning("Failed to migrate %s", db_name, exc_info=True) @@ -279,11 +304,11 @@ def migrate_project_layout(project_dir: Path) -> list[str]: for filename in simple_files: try: old_file = project_dir / filename - new_file = autocoder_dir / filename + new_file = autoforge_dir / filename if old_file.exists() and not new_file.exists(): shutil.move(str(old_file), str(new_file)) - migrated.append(f"{filename} -> .autocoder/{filename}") - logger.info("Migrated %s -> .autocoder/%s", filename, filename) + migrated.append(f"{filename} -> .autoforge/{filename}") + logger.info("Migrated %s -> .autoforge/%s", filename, filename) except Exception: logger.warning("Failed to migrate %s", filename, exc_info=True) diff --git a/autonomous_agent_demo.py b/autonomous_agent_demo.py index ed3db37..c5cd272 100644 --- a/autonomous_agent_demo.py +++ b/autonomous_agent_demo.py @@ -221,11 +221,11 @@ def main() -> None: print("Use an absolute path or register the project first.") return - # Migrate project layout to .autocoder/ if needed (idempotent, safe) - from autocoder_paths import migrate_project_layout + # Migrate project layout to .autoforge/ if needed (idempotent, safe) + from autoforge_paths import migrate_project_layout migrated = migrate_project_layout(project_dir) if migrated: - print(f"Migrated project files to .autocoder/: {', '.join(migrated)}", flush=True) + print(f"Migrated project files to .autoforge/: {', '.join(migrated)}", flush=True) # Parse batch testing feature IDs (comma-separated string -> list[int]) testing_feature_ids: list[int] | None = None diff --git a/client.py b/client.py index d31b5ad..3090415 100644 --- a/client.py +++ b/client.py @@ -382,7 +382,7 @@ def create_client( project_dir.mkdir(parents=True, exist_ok=True) # Write settings to a file in the project directory - from autocoder_paths import get_claude_settings_path + from autoforge_paths import get_claude_settings_path settings_file = get_claude_settings_path(project_dir) settings_file.parent.mkdir(parents=True, exist_ok=True) with open(settings_file, "w") as f: @@ -450,7 +450,7 @@ def create_client( # Build environment overrides for API endpoint configuration # These override system env vars for the Claude CLI subprocess, - # allowing AutoCoder to use alternative APIs (e.g., GLM) without + # allowing AutoForge to use alternative APIs (e.g., GLM) without # affecting the user's global Claude Code settings sdk_env = {} for var in API_ENV_VARS: diff --git a/env_constants.py b/env_constants.py index 2a8753d..e284c54 100644 --- a/env_constants.py +++ b/env_constants.py @@ -7,7 +7,7 @@ subprocesses. Imported by both ``client.py`` (agent sessions) and ``server/services/chat_constants.py`` (chat sessions) to avoid maintaining duplicate lists. -These allow autocoder to use alternative API endpoints (Ollama, GLM, +These allow autoforge to use alternative API endpoints (Ollama, GLM, Vertex AI) without affecting the user's global Claude Code settings. """ diff --git a/examples/OPTIMIZE_CONFIG.md b/examples/OPTIMIZE_CONFIG.md index 2fea54a..57236bd 100644 --- a/examples/OPTIMIZE_CONFIG.md +++ b/examples/OPTIMIZE_CONFIG.md @@ -179,7 +179,7 @@ To see what you can reduce: ```bash # Count commands by prefix -grep "^ - name:" .autocoder/allowed_commands.yaml | \ +grep "^ - name:" .autoforge/allowed_commands.yaml | \ sed 's/^ - name: //' | \ cut -d' ' -f1 | \ sort | uniq -c | sort -rn diff --git a/examples/README.md b/examples/README.md index 76b326e..21ba3c8 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,4 +1,4 @@ -# AutoCoder Security Configuration Examples +# AutoForge Security Configuration Examples This directory contains example configuration files for controlling which bash commands the autonomous coding agent can execute. @@ -18,11 +18,11 @@ This directory contains example configuration files for controlling which bash c ### For a Single Project (Most Common) -When you create a new project with AutoCoder, it automatically creates: +When you create a new project with AutoForge, it automatically creates: ```text my-project/ - .autocoder/ + .autoforge/ allowed_commands.yaml ← Automatically created from template ``` @@ -34,17 +34,17 @@ If you want commands available across **all projects**, manually create: ```bash # Copy the example to your home directory -cp examples/org_config.yaml ~/.autocoder/config.yaml +cp examples/org_config.yaml ~/.autoforge/config.yaml # Edit it to add org-wide commands -nano ~/.autocoder/config.yaml +nano ~/.autoforge/config.yaml ``` --- ## Project-Level Configuration -**File:** `{project_dir}/.autocoder/allowed_commands.yaml` +**File:** `{project_dir}/.autoforge/allowed_commands.yaml` **Purpose:** Define commands needed for THIS specific project. @@ -82,7 +82,7 @@ commands: ## Organization-Level Configuration -**File:** `~/.autocoder/config.yaml` +**File:** `~/.autoforge/config.yaml` **Purpose:** Define commands and policies for ALL projects. @@ -127,13 +127,13 @@ When the agent tries to run a command, the system checks in this order: └─────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ -│ 2. ORG BLOCKLIST (~/.autocoder/config.yaml) │ +│ 2. ORG BLOCKLIST (~/.autoforge/config.yaml) │ │ Commands you block organization-wide │ │ ❌ Projects CANNOT override these │ └─────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ -│ 3. ORG ALLOWLIST (~/.autocoder/config.yaml) │ +│ 3. ORG ALLOWLIST (~/.autoforge/config.yaml) │ │ Commands available to all projects │ │ ✅ Automatically available │ └─────────────────────────────────────────────────────┘ @@ -145,7 +145,7 @@ When the agent tries to run a command, the system checks in this order: └─────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────┐ -│ 5. PROJECT ALLOWLIST (.autocoder/allowed_commands) │ +│ 5. PROJECT ALLOWLIST (.autoforge/allowed_commands) │ │ Project-specific commands │ │ ✅ Available only to this project │ └─────────────────────────────────────────────────────┘ @@ -195,7 +195,7 @@ Matches: ### iOS Development -**Project config** (`.autocoder/allowed_commands.yaml`): +**Project config** (`.autoforge/allowed_commands.yaml`): ```yaml version: 1 commands: @@ -245,7 +245,7 @@ commands: ### Enterprise Organization (Restrictive) -**Org config** (`~/.autocoder/config.yaml`): +**Org config** (`~/.autoforge/config.yaml`): ```yaml version: 1 @@ -265,7 +265,7 @@ blocked_commands: ### Startup Team (Permissive) -**Org config** (`~/.autocoder/config.yaml`): +**Org config** (`~/.autoforge/config.yaml`): ```yaml version: 1 @@ -394,7 +394,7 @@ These commands are **NEVER allowed**, even with user approval: **Solution:** Add the command to your project config: ```yaml -# In .autocoder/allowed_commands.yaml +# In .autoforge/allowed_commands.yaml commands: - name: X description: What this command does @@ -405,7 +405,7 @@ commands: **Cause:** The command is in the org blocklist or hardcoded blocklist. **Solution:** -- If in org blocklist: Edit `~/.autocoder/config.yaml` to remove it +- If in org blocklist: Edit `~/.autoforge/config.yaml` to remove it - If in hardcoded blocklist: Cannot be allowed (by design) ### Error: "Could not parse YAML config" @@ -422,8 +422,8 @@ commands: **Solution:** 1. Restart the agent (changes are loaded on startup) 2. Verify file location: - - Project: `{project}/.autocoder/allowed_commands.yaml` - - Org: `~/.autocoder/config.yaml` (must be manually created) + - Project: `{project}/.autoforge/allowed_commands.yaml` + - Org: `~/.autoforge/config.yaml` (must be manually created) 3. Check YAML is valid (run through a YAML validator) --- @@ -432,7 +432,7 @@ commands: ### Running the Tests -AutoCoder has comprehensive tests for the security system: +AutoForge has comprehensive tests for the security system: **Unit Tests** (136 tests - fast): ```bash @@ -481,7 +481,7 @@ python start.py cd path/to/security-test # Edit the config -nano .autocoder/allowed_commands.yaml +nano .autoforge/allowed_commands.yaml ``` **3. Add a test command (e.g., Swift):** @@ -509,7 +509,7 @@ Or: ```text Command 'wget' is not allowed. To allow this command: - 1. Add to .autocoder/allowed_commands.yaml for this project, OR + 1. Add to .autoforge/allowed_commands.yaml for this project, OR 2. Request mid-session approval (the agent can ask) ``` diff --git a/examples/org_config.yaml b/examples/org_config.yaml index f86d9f3..efdd600 100644 --- a/examples/org_config.yaml +++ b/examples/org_config.yaml @@ -1,6 +1,6 @@ -# Organization-Level AutoCoder Configuration +# Organization-Level AutoForge Configuration # ============================================ -# Location: ~/.autocoder/config.yaml +# Location: ~/.autoforge/config.yaml # # IMPORTANT: This file is OPTIONAL and must be manually created by you. # It does NOT exist by default. @@ -22,7 +22,7 @@ version: 1 # Organization-Wide Allowed Commands # ========================================== # These commands become available to ALL projects automatically. -# Projects don't need to add them to their own .autocoder/allowed_commands.yaml +# Projects don't need to add them to their own .autoforge/allowed_commands.yaml # # By default, this is empty. Uncomment and add commands as needed. @@ -122,7 +122,7 @@ approval_timeout_minutes: 5 # Default commands: npm, git, curl, ls, cat, etc. # Always available to all projects. # -# 5. Project Allowed Commands (.autocoder/allowed_commands.yaml) +# 5. Project Allowed Commands (.autoforge/allowed_commands.yaml) # Project-specific commands defined in each project. # LOWEST PRIORITY (can't override blocks above). # @@ -165,7 +165,7 @@ approval_timeout_minutes: 5 # ========================================== # To Create This File # ========================================== -# 1. Copy this example to: ~/.autocoder/config.yaml +# 1. Copy this example to: ~/.autoforge/config.yaml # 2. Uncomment and customize the sections you need # 3. Leave empty lists if you don't need org-level controls # diff --git a/examples/project_allowed_commands.yaml b/examples/project_allowed_commands.yaml index 2a3bdf5..af956cf 100644 --- a/examples/project_allowed_commands.yaml +++ b/examples/project_allowed_commands.yaml @@ -1,12 +1,12 @@ # Project-Specific Allowed Commands # ================================== -# Location: {project_dir}/.autocoder/allowed_commands.yaml +# Location: {project_dir}/.autoforge/allowed_commands.yaml # # This file defines bash commands that the autonomous coding agent can use # for THIS SPECIFIC PROJECT, beyond the default allowed commands. # -# When you create a new project, AutoCoder automatically creates this file -# in your project's .autocoder/ directory. You can customize it for your +# When you create a new project, AutoForge automatically creates this file +# in your project's .autoforge/ directory. You can customize it for your # project's specific needs (iOS, Rust, Python, etc.). version: 1 @@ -115,7 +115,7 @@ commands: [] # Limits: # - Maximum 100 commands per project # - Commands in the blocklist (sudo, dd, shutdown, etc.) can NEVER be allowed -# - Org-level blocked commands (see ~/.autocoder/config.yaml) cannot be overridden +# - Org-level blocked commands (see ~/.autoforge/config.yaml) cannot be overridden # # Default Allowed Commands (always available): # File operations: ls, cat, head, tail, wc, grep, cp, mkdir, mv, rm, touch diff --git a/parallel_orchestrator.py b/parallel_orchestrator.py index e630a05..856e33c 100644 --- a/parallel_orchestrator.py +++ b/parallel_orchestrator.py @@ -40,11 +40,11 @@ from server.utils.process_utils import kill_process_tree logger = logging.getLogger(__name__) -# Root directory of autocoder (where this script and autonomous_agent_demo.py live) -AUTOCODER_ROOT = Path(__file__).parent.resolve() +# Root directory of autoforge (where this script and autonomous_agent_demo.py live) +AUTOFORGE_ROOT = Path(__file__).parent.resolve() # Debug log file path -DEBUG_LOG_FILE = AUTOCODER_ROOT / "orchestrator_debug.log" +DEBUG_LOG_FILE = AUTOFORGE_ROOT / "orchestrator_debug.log" class DebugLogger: @@ -823,7 +823,7 @@ class ParallelOrchestrator: cmd = [ sys.executable, "-u", # Force unbuffered stdout/stderr - str(AUTOCODER_ROOT / "autonomous_agent_demo.py"), + str(AUTOFORGE_ROOT / "autonomous_agent_demo.py"), "--project-dir", str(self.project_dir), "--max-iterations", "1", "--agent-type", "coding", @@ -889,7 +889,7 @@ class ParallelOrchestrator: cmd = [ sys.executable, "-u", - str(AUTOCODER_ROOT / "autonomous_agent_demo.py"), + str(AUTOFORGE_ROOT / "autonomous_agent_demo.py"), "--project-dir", str(self.project_dir), "--max-iterations", "1", "--agent-type", "coding", @@ -992,7 +992,7 @@ class ParallelOrchestrator: cmd = [ sys.executable, "-u", - str(AUTOCODER_ROOT / "autonomous_agent_demo.py"), + str(AUTOFORGE_ROOT / "autonomous_agent_demo.py"), "--project-dir", str(self.project_dir), "--max-iterations", "1", "--agent-type", "testing", @@ -1053,7 +1053,7 @@ class ParallelOrchestrator: cmd = [ sys.executable, "-u", - str(AUTOCODER_ROOT / "autonomous_agent_demo.py"), + str(AUTOFORGE_ROOT / "autonomous_agent_demo.py"), "--project-dir", str(self.project_dir), "--agent-type", "initializer", "--max-iterations", "1", @@ -1073,7 +1073,7 @@ class ParallelOrchestrator: "text": True, "encoding": "utf-8", "errors": "replace", - "cwd": str(AUTOCODER_ROOT), + "cwd": str(AUTOFORGE_ROOT), "env": {**os.environ, "PYTHONUNBUFFERED": "1"}, } if sys.platform == "win32": diff --git a/progress.py b/progress.py index f0795b6..aa632a8 100644 --- a/progress.py +++ b/progress.py @@ -46,7 +46,7 @@ def has_features(project_dir: Path) -> bool: return True # Check SQLite database - from autocoder_paths import get_features_db_path + from autoforge_paths import get_features_db_path db_file = get_features_db_path(project_dir) if not db_file.exists(): return False @@ -72,7 +72,7 @@ def count_passing_tests(project_dir: Path) -> tuple[int, int, int]: Returns: (passing_count, in_progress_count, total_count) """ - from autocoder_paths import get_features_db_path + from autoforge_paths import get_features_db_path db_file = get_features_db_path(project_dir) if not db_file.exists(): return 0, 0, 0 @@ -122,7 +122,7 @@ def get_all_passing_features(project_dir: Path) -> list[dict]: Returns: List of dicts with id, category, name for each passing feature """ - from autocoder_paths import get_features_db_path + from autoforge_paths import get_features_db_path db_file = get_features_db_path(project_dir) if not db_file.exists(): return [] @@ -147,7 +147,7 @@ def send_progress_webhook(passing: int, total: int, project_dir: Path) -> None: if not WEBHOOK_URL: return # Webhook not configured - from autocoder_paths import get_progress_cache_path + from autoforge_paths import get_progress_cache_path cache_file = get_progress_cache_path(project_dir) previous = 0 previous_passing_ids = set() diff --git a/prompts.py b/prompts.py index 5d83faa..40d0494 100644 --- a/prompts.py +++ b/prompts.py @@ -19,7 +19,7 @@ TEMPLATES_DIR = Path(__file__).parent / ".claude" / "templates" def get_project_prompts_dir(project_dir: Path) -> Path: """Get the prompts directory for a specific project.""" - from autocoder_paths import get_prompts_dir + from autoforge_paths import get_prompts_dir return get_prompts_dir(project_dir) @@ -315,9 +315,9 @@ def scaffold_project_prompts(project_dir: Path) -> Path: project_prompts = get_project_prompts_dir(project_dir) project_prompts.mkdir(parents=True, exist_ok=True) - # Create .autocoder directory with .gitignore for runtime files - from autocoder_paths import ensure_autocoder_dir - autocoder_dir = ensure_autocoder_dir(project_dir) + # Create .autoforge directory with .gitignore for runtime files + from autoforge_paths import ensure_autoforge_dir + autoforge_dir = ensure_autoforge_dir(project_dir) # Define template mappings: (source_template, destination_name) templates = [ @@ -340,14 +340,14 @@ def scaffold_project_prompts(project_dir: Path) -> Path: except (OSError, PermissionError) as e: print(f" Warning: Could not copy {dest_name}: {e}") - # Copy allowed_commands.yaml template to .autocoder/ + # Copy allowed_commands.yaml template to .autoforge/ examples_dir = Path(__file__).parent / "examples" allowed_commands_template = examples_dir / "project_allowed_commands.yaml" - allowed_commands_dest = autocoder_dir / "allowed_commands.yaml" + allowed_commands_dest = autoforge_dir / "allowed_commands.yaml" if allowed_commands_template.exists() and not allowed_commands_dest.exists(): try: shutil.copy(allowed_commands_template, allowed_commands_dest) - copied_files.append(".autocoder/allowed_commands.yaml") + copied_files.append(".autoforge/allowed_commands.yaml") except (OSError, PermissionError) as e: print(f" Warning: Could not copy allowed_commands.yaml: {e}") diff --git a/registry.py b/registry.py index 685d968..4668b15 100644 --- a/registry.py +++ b/registry.py @@ -3,7 +3,7 @@ Project Registry Module ======================= Cross-platform project registry for storing project name to path mappings. -Uses SQLite database stored at ~/.autocoder/registry.db. +Uses SQLite database stored at ~/.autoforge/registry.db. """ import logging @@ -23,6 +23,22 @@ from sqlalchemy.orm import DeclarativeBase, sessionmaker logger = logging.getLogger(__name__) +def _migrate_registry_dir() -> None: + """Migrate ~/.autocoder/ to ~/.autoforge/ if needed. + + Provides backward compatibility by automatically renaming the old + config directory to the new location on first access. + """ + old_dir = Path.home() / ".autocoder" + new_dir = Path.home() / ".autoforge" + if old_dir.exists() and not new_dir.exists(): + try: + old_dir.rename(new_dir) + logger.info("Migrated registry directory: ~/.autocoder/ -> ~/.autoforge/") + except Exception: + logger.warning("Failed to migrate ~/.autocoder/ to ~/.autoforge/", exc_info=True) + + # ============================================================================= # Model Configuration (Single Source of Truth) # ============================================================================= @@ -120,12 +136,15 @@ _engine_lock = threading.Lock() def get_config_dir() -> Path: """ - Get the config directory: ~/.autocoder/ + Get the config directory: ~/.autoforge/ + + Automatically migrates from ~/.autocoder/ if needed. Returns: - Path to ~/.autocoder/ (created if it doesn't exist) + Path to ~/.autoforge/ (created if it doesn't exist) """ - config_dir = Path.home() / ".autocoder" + _migrate_registry_dir() + config_dir = Path.home() / ".autoforge" config_dir.mkdir(parents=True, exist_ok=True) return config_dir diff --git a/security.py b/security.py index 1e7455f..8ed9ce7 100644 --- a/security.py +++ b/security.py @@ -553,14 +553,23 @@ def get_org_config_path() -> Path: Get the organization-level config file path. Returns: - Path to ~/.autocoder/config.yaml + Path to ~/.autoforge/config.yaml (falls back to ~/.autocoder/config.yaml) """ - return Path.home() / ".autocoder" / "config.yaml" + new_path = Path.home() / ".autoforge" / "config.yaml" + if new_path.exists(): + return new_path + # Backward compatibility: check old location + old_path = Path.home() / ".autocoder" / "config.yaml" + if old_path.exists(): + return old_path + return new_path def load_org_config() -> Optional[dict]: """ - Load organization-level config from ~/.autocoder/config.yaml. + Load organization-level config from ~/.autoforge/config.yaml. + + Falls back to ~/.autocoder/config.yaml for backward compatibility. Returns: Dict with parsed org config, or None if file doesn't exist or is invalid @@ -630,7 +639,10 @@ def load_project_commands(project_dir: Path) -> Optional[dict]: Returns: Dict with parsed YAML config, or None if file doesn't exist or is invalid """ - config_path = project_dir.resolve() / ".autocoder" / "allowed_commands.yaml" + # Check new location first, fall back to old for backward compatibility + config_path = project_dir.resolve() / ".autoforge" / "allowed_commands.yaml" + if not config_path.exists(): + config_path = project_dir.resolve() / ".autocoder" / "allowed_commands.yaml" if not config_path.exists(): return None @@ -909,7 +921,7 @@ async def bash_security_hook(input_data, tool_use_id=None, context=None): # Provide helpful error message with config hint error_msg = f"Command '{cmd}' is not allowed.\n" error_msg += "To allow this command:\n" - error_msg += " 1. Add to .autocoder/allowed_commands.yaml for this project, OR\n" + error_msg += " 1. Add to .autoforge/allowed_commands.yaml for this project, OR\n" error_msg += " 2. Request mid-session approval (the agent can ask)\n" error_msg += "Note: Some commands are blocked at org-level and cannot be overridden." return { diff --git a/server/main.py b/server/main.py index 687bf87..33fd348 100644 --- a/server/main.py +++ b/server/main.py @@ -94,7 +94,7 @@ logger = logging.getLogger(__name__) # Check if remote access is enabled via environment variable # Set by start_ui.py when --host is not 127.0.0.1 -ALLOW_REMOTE = os.environ.get("AUTOCODER_ALLOW_REMOTE", "").lower() in ("1", "true", "yes") +ALLOW_REMOTE = os.environ.get("AUTOFORGE_ALLOW_REMOTE", "").lower() in ("1", "true", "yes") if ALLOW_REMOTE: logger.warning( @@ -133,7 +133,7 @@ else: if not ALLOW_REMOTE: @app.middleware("http") async def require_localhost(request: Request, call_next): - """Only allow requests from localhost (disabled when AUTOCODER_ALLOW_REMOTE=1).""" + """Only allow requests from localhost (disabled when AUTOFORGE_ALLOW_REMOTE=1).""" client_host = request.client.host if request.client else None # Allow localhost connections diff --git a/server/routers/expand_project.py b/server/routers/expand_project.py index 3de2f44..5b55824 100644 --- a/server/routers/expand_project.py +++ b/server/routers/expand_project.py @@ -121,7 +121,7 @@ async def expand_project_websocket(websocket: WebSocket, project_name: str): return # Verify project has app_spec.txt - from autocoder_paths import get_prompts_dir + from autoforge_paths import get_prompts_dir spec_path = get_prompts_dir(project_dir) / "app_spec.txt" if not spec_path.exists(): await websocket.close(code=4004, reason="Project has no spec. Create spec first.") diff --git a/server/routers/features.py b/server/routers/features.py index 0c8c77d..488c088 100644 --- a/server/routers/features.py +++ b/server/routers/features.py @@ -126,7 +126,7 @@ async def list_features(project_name: str): if not project_dir.exists(): raise HTTPException(status_code=404, detail="Project directory not found") - from autocoder_paths import get_features_db_path + from autoforge_paths import get_features_db_path db_file = get_features_db_path(project_dir) if not db_file.exists(): return FeatureListResponse(pending=[], in_progress=[], done=[]) @@ -322,7 +322,7 @@ async def get_dependency_graph(project_name: str): if not project_dir.exists(): raise HTTPException(status_code=404, detail="Project directory not found") - from autocoder_paths import get_features_db_path + from autoforge_paths import get_features_db_path db_file = get_features_db_path(project_dir) if not db_file.exists(): return DependencyGraphResponse(nodes=[], edges=[]) @@ -388,7 +388,7 @@ async def get_feature(project_name: str, feature_id: int): if not project_dir.exists(): raise HTTPException(status_code=404, detail="Project directory not found") - from autocoder_paths import get_features_db_path + from autoforge_paths import get_features_db_path db_file = get_features_db_path(project_dir) if not db_file.exists(): raise HTTPException(status_code=404, detail="No features database found") diff --git a/server/routers/projects.py b/server/routers/projects.py index bfa5b9c..36f7ffd 100644 --- a/server/routers/projects.py +++ b/server/routers/projects.py @@ -276,7 +276,7 @@ async def delete_project(name: str, delete_files: bool = False): raise HTTPException(status_code=404, detail=f"Project '{name}' not found") # Check if agent is running - from autocoder_paths import has_agent_running + from autoforge_paths import has_agent_running if has_agent_running(project_dir): raise HTTPException( status_code=409, @@ -407,7 +407,7 @@ async def reset_project(name: str, full_reset: bool = False): raise HTTPException(status_code=404, detail="Project directory not found") # Check if agent is running - from autocoder_paths import has_agent_running + from autoforge_paths import has_agent_running if has_agent_running(project_dir): raise HTTPException( status_code=409, @@ -424,7 +424,7 @@ async def reset_project(name: str, full_reset: bool = False): deleted_files: list[str] = [] - from autocoder_paths import ( + from autoforge_paths import ( get_assistant_db_path, get_claude_assistant_settings_path, get_claude_settings_path, @@ -466,7 +466,7 @@ async def reset_project(name: str, full_reset: bool = False): # Full reset: also delete prompts directory if full_reset: - from autocoder_paths import get_prompts_dir + from autoforge_paths import get_prompts_dir # Delete prompts from both possible locations for prompts_dir in [get_prompts_dir(project_dir), project_dir / "prompts"]: if prompts_dir.exists(): diff --git a/server/routers/spec_creation.py b/server/routers/spec_creation.py index e6e917a..cb7263c 100644 --- a/server/routers/spec_creation.py +++ b/server/routers/spec_creation.py @@ -105,7 +105,7 @@ async def get_spec_file_status(project_name: str): if not project_dir.exists(): raise HTTPException(status_code=404, detail="Project directory not found") - from autocoder_paths import get_prompts_dir + from autoforge_paths import get_prompts_dir status_file = get_prompts_dir(project_dir) / ".spec_status.json" if not status_file.exists(): diff --git a/server/services/assistant_chat_session.py b/server/services/assistant_chat_session.py index 182232c..73d3dfb 100755 --- a/server/services/assistant_chat_session.py +++ b/server/services/assistant_chat_session.py @@ -64,7 +64,7 @@ def get_system_prompt(project_name: str, project_dir: Path) -> str: """Generate the system prompt for the assistant with project context.""" # Try to load app_spec.txt for context app_spec_content = "" - from autocoder_paths import get_prompts_dir + from autoforge_paths import get_prompts_dir app_spec_path = get_prompts_dir(project_dir) / "app_spec.txt" if app_spec_path.exists(): try: @@ -224,7 +224,7 @@ class AssistantChatSession: "allow": permissions_list, }, } - from autocoder_paths import get_claude_assistant_settings_path + from autoforge_paths import get_claude_assistant_settings_path settings_file = get_claude_assistant_settings_path(self.project_dir) settings_file.parent.mkdir(parents=True, exist_ok=True) with open(settings_file, "w") as f: diff --git a/server/services/assistant_database.py b/server/services/assistant_database.py index 1d0e9a6..6494cf1 100644 --- a/server/services/assistant_database.py +++ b/server/services/assistant_database.py @@ -64,7 +64,7 @@ class ConversationMessage(Base): def get_db_path(project_dir: Path) -> Path: """Get the path to the assistant database for a project.""" - from autocoder_paths import get_assistant_db_path + from autoforge_paths import get_assistant_db_path return get_assistant_db_path(project_dir) diff --git a/server/services/chat_constants.py b/server/services/chat_constants.py index 6af3c1b..0baddd2 100644 --- a/server/services/chat_constants.py +++ b/server/services/chat_constants.py @@ -14,7 +14,7 @@ from pathlib import Path from typing import AsyncGenerator # ------------------------------------------------------------------- -# Root directory of the autocoder project (repository root). +# Root directory of the autoforge project (repository root). # Used throughout the server package whenever the repo root is needed. # ------------------------------------------------------------------- ROOT_DIR = Path(__file__).parent.parent.parent diff --git a/server/services/dev_server_manager.py b/server/services/dev_server_manager.py index 41dac02..0e4e921 100644 --- a/server/services/dev_server_manager.py +++ b/server/services/dev_server_manager.py @@ -115,7 +115,7 @@ class DevServerProcessManager: self._callbacks_lock = threading.Lock() # Lock file to prevent multiple instances (stored in project directory) - from autocoder_paths import get_devserver_lock_path + from autoforge_paths import get_devserver_lock_path self.lock_file = get_devserver_lock_path(self.project_dir) @property @@ -504,10 +504,10 @@ def cleanup_orphaned_devserver_locks() -> int: continue # Check both legacy and new locations for lock files - from autocoder_paths import get_autocoder_dir + from autoforge_paths import get_autoforge_dir lock_locations = [ project_path / ".devserver.lock", - get_autocoder_dir(project_path) / ".devserver.lock", + get_autoforge_dir(project_path) / ".devserver.lock", ] lock_file = None for candidate in lock_locations: diff --git a/server/services/expand_chat_session.py b/server/services/expand_chat_session.py index 4fd0978..3522453 100644 --- a/server/services/expand_chat_session.py +++ b/server/services/expand_chat_session.py @@ -103,7 +103,7 @@ class ExpandChatSession: return # Verify project has existing spec - from autocoder_paths import get_prompts_dir + from autoforge_paths import get_prompts_dir spec_path = get_prompts_dir(self.project_dir) / "app_spec.txt" if not spec_path.exists(): yield { @@ -142,7 +142,7 @@ class ExpandChatSession: ], }, } - from autocoder_paths import get_expand_settings_path + from autoforge_paths import get_expand_settings_path settings_file = get_expand_settings_path(self.project_dir, uuid.uuid4().hex) settings_file.parent.mkdir(parents=True, exist_ok=True) self._settings_file = settings_file diff --git a/server/services/process_manager.py b/server/services/process_manager.py index 3340cd1..32a6a7e 100644 --- a/server/services/process_manager.py +++ b/server/services/process_manager.py @@ -92,7 +92,7 @@ class AgentProcessManager: self._callbacks_lock = threading.Lock() # Lock file to prevent multiple instances (stored in project directory) - from autocoder_paths import get_agent_lock_path + from autoforge_paths import get_agent_lock_path self.lock_file = get_agent_lock_path(self.project_dir) @property @@ -587,10 +587,10 @@ def cleanup_orphaned_locks() -> int: continue # Check both legacy and new locations for lock files - from autocoder_paths import get_autocoder_dir + from autoforge_paths import get_autoforge_dir lock_locations = [ project_path / ".agent.lock", - get_autocoder_dir(project_path) / ".agent.lock", + get_autoforge_dir(project_path) / ".agent.lock", ] lock_file = None for candidate in lock_locations: diff --git a/server/services/project_config.py b/server/services/project_config.py index f6e50d0..609aa33 100644 --- a/server/services/project_config.py +++ b/server/services/project_config.py @@ -6,7 +6,7 @@ Handles project type detection and dev command configuration. Detects project types by scanning for configuration files and provides default or custom dev commands for each project. -Configuration is stored in {project_dir}/.autocoder/config.json. +Configuration is stored in {project_dir}/.autoforge/config.json. """ import json @@ -88,13 +88,22 @@ def _get_config_path(project_dir: Path) -> Path: """ Get the path to the project config file. + Checks the new .autoforge/ location first, falls back to .autocoder/ + for backward compatibility. + Args: project_dir: Path to the project directory. Returns: - Path to the .autocoder/config.json file. + Path to the config.json file in the appropriate directory. """ - return project_dir / ".autocoder" / "config.json" + new_path = project_dir / ".autoforge" / "config.json" + if new_path.exists(): + return new_path + old_path = project_dir / ".autocoder" / "config.json" + if old_path.exists(): + return old_path + return new_path def _load_config(project_dir: Path) -> dict: @@ -137,7 +146,7 @@ def _save_config(project_dir: Path, config: dict) -> None: """ Save the project configuration to disk. - Creates the .autocoder directory if it doesn't exist. + Creates the .autoforge directory if it doesn't exist. Args: project_dir: Path to the project directory. @@ -148,7 +157,7 @@ def _save_config(project_dir: Path, config: dict) -> None: """ config_path = _get_config_path(project_dir) - # Ensure the .autocoder directory exists + # Ensure the .autoforge directory exists config_path.parent.mkdir(parents=True, exist_ok=True) try: @@ -408,11 +417,11 @@ def clear_dev_command(project_dir: Path) -> None: config_path.unlink(missing_ok=True) logger.info("Removed empty config file for %s", project_dir.name) - # Also remove .autocoder directory if empty - autocoder_dir = config_path.parent - if autocoder_dir.exists() and not any(autocoder_dir.iterdir()): - autocoder_dir.rmdir() - logger.debug("Removed empty .autocoder directory for %s", project_dir.name) + # Also remove .autoforge directory if empty + autoforge_dir = config_path.parent + if autoforge_dir.exists() and not any(autoforge_dir.iterdir()): + autoforge_dir.rmdir() + logger.debug("Removed empty .autoforge directory for %s", project_dir.name) except OSError as e: logger.warning("Failed to clean up config for %s: %s", project_dir.name, e) else: diff --git a/server/services/scheduler_service.py b/server/services/scheduler_service.py index 578aed2..3e0576d 100644 --- a/server/services/scheduler_service.py +++ b/server/services/scheduler_service.py @@ -92,7 +92,7 @@ class SchedulerService: async def _load_project_schedules(self, project_name: str, project_dir: Path) -> int: """Load schedules for a single project. Returns count of schedules loaded.""" from api.database import Schedule, create_database - from autocoder_paths import get_features_db_path + from autoforge_paths import get_features_db_path db_path = get_features_db_path(project_dir) if not db_path.exists(): @@ -568,7 +568,7 @@ class SchedulerService: ): """Check if a project should be started on server startup.""" from api.database import Schedule, ScheduleOverride, create_database - from autocoder_paths import get_features_db_path + from autoforge_paths import get_features_db_path db_path = get_features_db_path(project_dir) if not db_path.exists(): diff --git a/server/services/spec_chat_session.py b/server/services/spec_chat_session.py index b352cb5..4c0e485 100644 --- a/server/services/spec_chat_session.py +++ b/server/services/spec_chat_session.py @@ -95,7 +95,7 @@ class SpecChatSession: # Delete app_spec.txt so Claude can create it fresh # The SDK requires reading existing files before writing, but app_spec.txt is created new # Note: We keep initializer_prompt.md so Claude can read and update the template - from autocoder_paths import get_prompts_dir + from autoforge_paths import get_prompts_dir prompts_dir = get_prompts_dir(self.project_dir) app_spec_path = prompts_dir / "app_spec.txt" if app_spec_path.exists(): @@ -116,7 +116,7 @@ class SpecChatSession: ], }, } - from autocoder_paths import get_claude_settings_path + from autoforge_paths import get_claude_settings_path settings_file = get_claude_settings_path(self.project_dir) settings_file.parent.mkdir(parents=True, exist_ok=True) with open(settings_file, "w") as f: diff --git a/start.bat b/start.bat index d09ca37..9931c38 100644 --- a/start.bat +++ b/start.bat @@ -3,7 +3,7 @@ cd /d "%~dp0" echo. echo ======================================== -echo Autonomous Coding Agent +echo AutoForge - Autonomous Coding Agent echo ======================================== echo. diff --git a/start.py b/start.py index a230d13..0e303ef 100644 --- a/start.py +++ b/start.py @@ -82,7 +82,7 @@ def get_existing_projects() -> list[tuple[str, Path]]: def display_menu(projects: list[tuple[str, Path]]) -> None: """Display the main menu.""" print("\n" + "=" * 50) - print(" Autonomous Coding Agent Launcher") + print(" AutoForge - Autonomous Coding Agent") print("=" * 50) print("\n[1] Create new project") diff --git a/start.sh b/start.sh index 88eaa8e..25c8751 100755 --- a/start.sh +++ b/start.sh @@ -3,7 +3,7 @@ cd "$(dirname "$0")" echo "" echo "========================================" -echo " Autonomous Coding Agent" +echo " AutoForge - Autonomous Coding Agent" echo "========================================" echo "" diff --git a/start_ui.bat b/start_ui.bat index c8ad646..3fc67f5 100644 --- a/start_ui.bat +++ b/start_ui.bat @@ -1,11 +1,11 @@ @echo off cd /d "%~dp0" -REM AutoCoder UI Launcher for Windows +REM AutoForge UI Launcher for Windows REM This script launches the web UI for the autonomous coding agent. echo. echo ==================================== -echo AutoCoder UI +echo AutoForge UI echo ==================================== echo. diff --git a/start_ui.py b/start_ui.py index ad30112..e9b08be 100644 --- a/start_ui.py +++ b/start_ui.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """ -AutoCoder UI Launcher +AutoForge UI Launcher ===================== Automated launcher that handles all setup: @@ -265,7 +265,7 @@ def start_dev_server(port: int, host: str = "127.0.0.1") -> tuple: # Set environment for remote access if needed env = os.environ.copy() if host != "127.0.0.1": - env["AUTOCODER_ALLOW_REMOTE"] = "1" + env["AUTOFORGE_ALLOW_REMOTE"] = "1" # Start FastAPI backend = subprocess.Popen([ @@ -297,7 +297,7 @@ def start_production_server(port: int, host: str = "127.0.0.1"): # Enable remote access in server if not localhost if host != "127.0.0.1": - env["AUTOCODER_ALLOW_REMOTE"] = "1" + env["AUTOFORGE_ALLOW_REMOTE"] = "1" # NOTE: --reload is NOT used because on Windows it breaks asyncio subprocess # support (uvicorn's reload worker doesn't inherit the ProactorEventLoop policy). @@ -313,7 +313,7 @@ def start_production_server(port: int, host: str = "127.0.0.1"): def main() -> None: """Main entry point.""" - parser = argparse.ArgumentParser(description="AutoCoder UI Launcher") + parser = argparse.ArgumentParser(description="AutoForge UI Launcher") parser.add_argument("--dev", action="store_true", help="Run in development mode with Vite hot reload") parser.add_argument("--host", default="127.0.0.1", help="Host to bind to (default: 127.0.0.1)") parser.add_argument("--port", type=int, default=None, help="Port to bind to (default: auto-detect from 8888)") @@ -328,7 +328,7 @@ def main() -> None: print(" SECURITY WARNING") print("!" * 50) print(f" Remote access enabled on host: {host}") - print(" The AutoCoder UI will be accessible from other machines.") + print(" The AutoForge UI will be accessible from other machines.") print(" Ensure you understand the security implications:") print(" - The agent has file system access to project directories") print(" - The API can start/stop agents and modify files") @@ -336,7 +336,7 @@ def main() -> None: print("!" * 50 + "\n") print("=" * 50) - print(" AutoCoder UI Setup") + print(" AutoForge UI Setup") print("=" * 50) total_steps = 6 if not dev_mode else 5 diff --git a/start_ui.sh b/start_ui.sh index a95cd8a..4381bbe 100755 --- a/start_ui.sh +++ b/start_ui.sh @@ -1,11 +1,11 @@ #!/bin/bash cd "$(dirname "$0")" -# AutoCoder UI Launcher for Unix/Linux/macOS +# AutoForge UI Launcher for Unix/Linux/macOS # This script launches the web UI for the autonomous coding agent. echo "" echo "====================================" -echo " AutoCoder UI" +echo " AutoForge UI" echo "====================================" echo "" diff --git a/test_security.py b/test_security.py index 40c1fa1..1017d1b 100644 --- a/test_security.py +++ b/test_security.py @@ -273,11 +273,11 @@ def test_yaml_loading(): with tempfile.TemporaryDirectory() as tmpdir: project_dir = Path(tmpdir) - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() # Test 1: Valid YAML - config_path = autocoder_dir / "allowed_commands.yaml" + config_path = autoforge_dir / "allowed_commands.yaml" config_path.write_text("""version: 1 commands: - name: swift @@ -297,7 +297,7 @@ commands: failed += 1 # Test 2: Missing file returns None - (project_dir / ".autocoder" / "allowed_commands.yaml").unlink() + (project_dir / ".autoforge" / "allowed_commands.yaml").unlink() config = load_project_commands(project_dir) if config is None: print(" PASS: Missing file returns None") @@ -407,11 +407,11 @@ def test_project_commands(): with tempfile.TemporaryDirectory() as tmpdir: project_dir = Path(tmpdir) - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() # Create a config with Swift commands - config_path = autocoder_dir / "allowed_commands.yaml" + config_path = autoforge_dir / "allowed_commands.yaml" config_path.write_text("""version: 1 commands: - name: swift @@ -482,7 +482,7 @@ def test_org_config_loading(): with tempfile.TemporaryDirectory() as tmpdir: # Use temporary_home for cross-platform compatibility with temporary_home(tmpdir): - org_dir = Path(tmpdir) / ".autocoder" + org_dir = Path(tmpdir) / ".autoforge" org_dir.mkdir() org_config_path = org_dir / "config.yaml" @@ -576,7 +576,7 @@ def test_hierarchy_resolution(): with tempfile.TemporaryDirectory() as tmpproject: # Use temporary_home for cross-platform compatibility with temporary_home(tmphome): - org_dir = Path(tmphome) / ".autocoder" + org_dir = Path(tmphome) / ".autoforge" org_dir.mkdir() org_config_path = org_dir / "config.yaml" @@ -593,9 +593,9 @@ blocked_commands: """) project_dir = Path(tmpproject) - project_autocoder = project_dir / ".autocoder" - project_autocoder.mkdir() - project_config = project_autocoder / "allowed_commands.yaml" + project_autoforge = project_dir / ".autoforge" + project_autoforge.mkdir() + project_config = project_autoforge / "allowed_commands.yaml" # Create project config project_config.write_text("""version: 1 @@ -660,7 +660,7 @@ def test_org_blocklist_enforcement(): with tempfile.TemporaryDirectory() as tmpproject: # Use temporary_home for cross-platform compatibility with temporary_home(tmphome): - org_dir = Path(tmphome) / ".autocoder" + org_dir = Path(tmphome) / ".autoforge" org_dir.mkdir() org_config_path = org_dir / "config.yaml" @@ -671,8 +671,8 @@ blocked_commands: """) project_dir = Path(tmpproject) - project_autocoder = project_dir / ".autocoder" - project_autocoder.mkdir() + project_autoforge = project_dir / ".autoforge" + project_autoforge.mkdir() # Try to use terraform (should be blocked) input_data = {"tool_name": "Bash", "tool_input": {"command": "terraform apply"}} @@ -735,7 +735,7 @@ def test_pkill_extensibility(): with tempfile.TemporaryDirectory() as tmphome: with tempfile.TemporaryDirectory() as tmpproject: with temporary_home(tmphome): - org_dir = Path(tmphome) / ".autocoder" + org_dir = Path(tmphome) / ".autoforge" org_dir.mkdir() org_config_path = org_dir / "config.yaml" @@ -762,9 +762,9 @@ pkill_processes: with tempfile.TemporaryDirectory() as tmpproject: with temporary_home(tmphome): project_dir = Path(tmpproject) - project_autocoder = project_dir / ".autocoder" - project_autocoder.mkdir() - project_config = project_autocoder / "allowed_commands.yaml" + project_autoforge = project_dir / ".autoforge" + project_autoforge.mkdir() + project_config = project_autoforge / "allowed_commands.yaml" # Create project config with extra pkill processes project_config.write_text("""version: 1 @@ -804,7 +804,7 @@ pkill_processes: with tempfile.TemporaryDirectory() as tmphome: with tempfile.TemporaryDirectory() as tmpproject: with temporary_home(tmphome): - org_dir = Path(tmphome) / ".autocoder" + org_dir = Path(tmphome) / ".autoforge" org_dir.mkdir() org_config_path = org_dir / "config.yaml" @@ -829,7 +829,7 @@ pkill_processes: with tempfile.TemporaryDirectory() as tmphome: with tempfile.TemporaryDirectory() as tmpproject: with temporary_home(tmphome): - org_dir = Path(tmphome) / ".autocoder" + org_dir = Path(tmphome) / ".autoforge" org_dir.mkdir() org_config_path = org_dir / "config.yaml" @@ -851,7 +851,7 @@ pkill_processes: with tempfile.TemporaryDirectory() as tmphome: with tempfile.TemporaryDirectory() as tmpproject: with temporary_home(tmphome): - org_dir = Path(tmphome) / ".autocoder" + org_dir = Path(tmphome) / ".autoforge" org_dir.mkdir() org_config_path = org_dir / "config.yaml" @@ -875,7 +875,7 @@ pkill_processes: with tempfile.TemporaryDirectory() as tmphome: with tempfile.TemporaryDirectory() as tmpproject: with temporary_home(tmphome): - org_dir = Path(tmphome) / ".autocoder" + org_dir = Path(tmphome) / ".autoforge" org_dir.mkdir() org_config_path = org_dir / "config.yaml" diff --git a/test_security_integration.py b/test_security_integration.py index f189958..2753693 100644 --- a/test_security_integration.py +++ b/test_security_integration.py @@ -79,9 +79,9 @@ def test_blocked_command_via_hook(): project_dir = Path(tmpdir) # Create minimal project structure - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() - (autocoder_dir / "allowed_commands.yaml").write_text( + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() + (autoforge_dir / "allowed_commands.yaml").write_text( "version: 1\ncommands: []" ) @@ -114,9 +114,9 @@ def test_allowed_command_via_hook(): project_dir = Path(tmpdir) # Create minimal project structure - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() - (autocoder_dir / "allowed_commands.yaml").write_text( + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() + (autoforge_dir / "allowed_commands.yaml").write_text( "version: 1\ncommands: []" ) @@ -145,9 +145,9 @@ def test_non_allowed_command_via_hook(): project_dir = Path(tmpdir) # Create minimal project structure - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() - (autocoder_dir / "allowed_commands.yaml").write_text( + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() + (autoforge_dir / "allowed_commands.yaml").write_text( "version: 1\ncommands: []" ) @@ -179,9 +179,9 @@ def test_project_config_allows_command(): project_dir = Path(tmpdir) # Create project config with swift allowed - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() - (autocoder_dir / "allowed_commands.yaml").write_text("""version: 1 + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() + (autoforge_dir / "allowed_commands.yaml").write_text("""version: 1 commands: - name: swift description: Swift compiler @@ -214,9 +214,9 @@ def test_pattern_matching(): project_dir = Path(tmpdir) # Create project config with swift* pattern - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() - (autocoder_dir / "allowed_commands.yaml").write_text("""version: 1 + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() + (autoforge_dir / "allowed_commands.yaml").write_text("""version: 1 commands: - name: swift* description: All Swift tools @@ -247,7 +247,7 @@ def test_org_blocklist_enforcement(): with tempfile.TemporaryDirectory() as tmpproject: # Use context manager to safely set and restore HOME with temporary_home(tmphome): - org_dir = Path(tmphome) / ".autocoder" + org_dir = Path(tmphome) / ".autoforge" org_dir.mkdir() (org_dir / "config.yaml").write_text("""version: 1 allowed_commands: [] @@ -257,11 +257,11 @@ blocked_commands: """) project_dir = Path(tmpproject) - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() # Try to allow terraform in project config (should fail - org blocked) - (autocoder_dir / "allowed_commands.yaml").write_text("""version: 1 + (autoforge_dir / "allowed_commands.yaml").write_text("""version: 1 commands: - name: terraform description: Infrastructure as code @@ -295,7 +295,7 @@ def test_org_allowlist_inheritance(): with tempfile.TemporaryDirectory() as tmpproject: # Use context manager to safely set and restore HOME with temporary_home(tmphome): - org_dir = Path(tmphome) / ".autocoder" + org_dir = Path(tmphome) / ".autoforge" org_dir.mkdir() (org_dir / "config.yaml").write_text("""version: 1 allowed_commands: @@ -305,9 +305,9 @@ blocked_commands: [] """) project_dir = Path(tmpproject) - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() - (autocoder_dir / "allowed_commands.yaml").write_text( + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() + (autoforge_dir / "allowed_commands.yaml").write_text( "version: 1\ncommands: []" ) @@ -336,9 +336,9 @@ def test_invalid_yaml_ignored(): project_dir = Path(tmpdir) # Create invalid YAML - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() - (autocoder_dir / "allowed_commands.yaml").write_text("invalid: yaml: content:") + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() + (autoforge_dir / "allowed_commands.yaml").write_text("invalid: yaml: content:") # Try to run ls (should still work - falls back to defaults) input_data = {"tool_name": "Bash", "tool_input": {"command": "ls"}} @@ -365,13 +365,13 @@ def test_100_command_limit(): project_dir = Path(tmpdir) # Create config with 101 commands - autocoder_dir = project_dir / ".autocoder" - autocoder_dir.mkdir() + autoforge_dir = project_dir / ".autoforge" + autoforge_dir.mkdir() commands = [ f" - name: cmd{i}\n description: Command {i}" for i in range(101) ] - (autocoder_dir / "allowed_commands.yaml").write_text( + (autoforge_dir / "allowed_commands.yaml").write_text( "version: 1\ncommands:\n" + "\n".join(commands) ) diff --git a/ui/index.html b/ui/index.html index 9564da9..22ab6dd 100644 --- a/ui/index.html +++ b/ui/index.html @@ -4,7 +4,7 @@ - AutoCoder + AutoForge diff --git a/ui/package-lock.json b/ui/package-lock.json index b0864e6..5b96104 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,11 +1,11 @@ { - "name": "autocoder", + "name": "autoforge", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "autocoder", + "name": "autoforge", "version": "1.0.0", "dependencies": { "@radix-ui/react-checkbox": "^1.3.3", @@ -81,7 +81,6 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -2695,7 +2694,6 @@ "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -2706,7 +2704,6 @@ "integrity": "sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2717,7 +2714,6 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -2767,7 +2763,6 @@ "integrity": "sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.51.0", "@typescript-eslint/types": "8.51.0", @@ -3072,7 +3067,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3190,7 +3184,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3403,7 +3396,6 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -3595,7 +3587,6 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4579,7 +4570,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -4685,7 +4675,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4695,7 +4684,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -5005,7 +4993,6 @@ "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5144,7 +5131,6 @@ "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", diff --git a/ui/package.json b/ui/package.json index 71b5375..94ca053 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,5 +1,5 @@ { - "name": "autocoder", + "name": "autoforge", "private": true, "version": "1.0.0", "type": "module", diff --git a/ui/src/App.tsx b/ui/src/App.tsx index dcfe729..fc809c5 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -34,8 +34,8 @@ import { Button } from '@/components/ui/button' import { Card, CardContent } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' -const STORAGE_KEY = 'autocoder-selected-project' -const VIEW_MODE_KEY = 'autocoder-view-mode' +const STORAGE_KEY = 'autoforge-selected-project' +const VIEW_MODE_KEY = 'autoforge-view-mode' // Bottom padding for main content when debug panel is collapsed (40px header + 8px margin) const COLLAPSED_DEBUG_PANEL_CLEARANCE = 48 @@ -264,7 +264,7 @@ function App() {
{/* Logo and Title */}

- AutoCoder + AutoForge

{/* Controls */} @@ -376,7 +376,7 @@ function App() { {!selectedProject ? (

- Welcome to AutoCoder + Welcome to AutoForge

Select a project from the dropdown above or create a new one to get started. diff --git a/ui/src/components/AgentMissionControl.tsx b/ui/src/components/AgentMissionControl.tsx index 6710b06..07fd594 100644 --- a/ui/src/components/AgentMissionControl.tsx +++ b/ui/src/components/AgentMissionControl.tsx @@ -8,7 +8,7 @@ import { Card, CardContent } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' -const ACTIVITY_COLLAPSED_KEY = 'autocoder-activity-collapsed' +const ACTIVITY_COLLAPSED_KEY = 'autoforge-activity-collapsed' interface AgentMissionControlProps { agents: ActiveAgent[] diff --git a/ui/src/components/docs/DocsPage.tsx b/ui/src/components/docs/DocsPage.tsx index 25288cc..20fb235 100644 --- a/ui/src/components/docs/DocsPage.tsx +++ b/ui/src/components/docs/DocsPage.tsx @@ -110,7 +110,7 @@ export function DocsPage() { className="font-display text-xl font-bold tracking-tight uppercase text-foreground hover:text-primary transition-colors" > - AutoCoder + AutoForge diff --git a/ui/src/components/docs/docsData.ts b/ui/src/components/docs/docsData.ts index d7b2875..3f66d0a 100644 --- a/ui/src/components/docs/docsData.ts +++ b/ui/src/components/docs/docsData.ts @@ -34,7 +34,7 @@ export const DOC_SECTIONS: DocSection[] = [ title: 'Getting Started', icon: Rocket, subsections: [ - { id: 'what-is-autocoder', title: 'What is AutoCoder?' }, + { id: 'what-is-autoforge', title: 'What is AutoForge?' }, { id: 'quick-start', title: 'Quick Start' }, { id: 'creating-a-project', title: 'Creating a New Project' }, { id: 'existing-project', title: 'Adding to an Existing Project' }, @@ -60,7 +60,7 @@ export const DOC_SECTIONS: DocSection[] = [ title: 'Target Project Structure', icon: FolderTree, subsections: [ - { id: 'autocoder-directory', title: '.autocoder/ Directory Layout' }, + { id: 'autoforge-directory', title: '.autoforge/ Directory Layout' }, { id: 'features-db', title: 'Features Database' }, { id: 'prompts-directory', title: 'Prompts Directory' }, { id: 'allowed-commands-yaml', title: 'Allowed Commands Config' }, diff --git a/ui/src/components/docs/sections/AdvancedConfig.tsx b/ui/src/components/docs/sections/AdvancedConfig.tsx index 2ed1584..89d206a 100644 --- a/ui/src/components/docs/sections/AdvancedConfig.tsx +++ b/ui/src/components/docs/sections/AdvancedConfig.tsx @@ -129,7 +129,7 @@ ANTHROPIC_DEFAULT_SONNET_MODEL=qwen3-coder`} Environment Variables

- Key environment variables for configuring AutoCoder: + Key environment variables for configuring AutoForge:

@@ -193,7 +193,7 @@ ANTHROPIC_DEFAULT_SONNET_MODEL=qwen3-coder`} Webhook Support
    -
  • AutoCoder can send webhook notifications on feature completion
  • +
  • AutoForge can send webhook notifications on feature completion
  • Compatible with N8N and similar automation tools
  • Configure the webhook URL in project settings
  • @@ -208,7 +208,7 @@ ANTHROPIC_DEFAULT_SONNET_MODEL=qwen3-coder`}
    • All projects are registered in{' '} - ~/.autocoder/registry.db{' '} + ~/.autoforge/registry.db{' '} (SQLite)
    • Maps project names to filesystem paths
    • diff --git a/ui/src/components/docs/sections/AppSpecSetup.tsx b/ui/src/components/docs/sections/AppSpecSetup.tsx index a4084a9..50f9726 100644 --- a/ui/src/components/docs/sections/AppSpecSetup.tsx +++ b/ui/src/components/docs/sections/AppSpecSetup.tsx @@ -15,7 +15,7 @@ export function AppSpecSetup() {

      The app spec is an XML document that describes the application to be built. It lives at{' '} - .autocoder/prompts/app_spec.txt + .autoforge/prompts/app_spec.txt {' '} and tells the initializer agent what features to create. The spec defines your app's name, description, tech stack, and the features that should be implemented. @@ -56,7 +56,7 @@ export function AppSpecSetup() {

    • Create{' '} - .autocoder/prompts/app_spec.txt + .autoforge/prompts/app_spec.txt {' '} in your project directory
    • @@ -97,7 +97,7 @@ export function AppSpecSetup() {
    • Creates the feature database at{' '} - .autocoder/features.db + .autoforge/features.db
    diff --git a/ui/src/components/docs/sections/AppearanceThemes.tsx b/ui/src/components/docs/sections/AppearanceThemes.tsx index d713983..d501e6e 100644 --- a/ui/src/components/docs/sections/AppearanceThemes.tsx +++ b/ui/src/components/docs/sections/AppearanceThemes.tsx @@ -98,7 +98,7 @@ export function AppearanceThemes() { Themes Overview

    - AutoCoder comes with 6 built-in themes. Each theme provides a complete visual identity including + AutoForge comes with 6 built-in themes. Each theme provides a complete visual identity including colors, accents, and dark mode variants.

    diff --git a/ui/src/components/docs/sections/FAQ.tsx b/ui/src/components/docs/sections/FAQ.tsx index 82b4f66..c557f3d 100644 --- a/ui/src/components/docs/sections/FAQ.tsx +++ b/ui/src/components/docs/sections/FAQ.tsx @@ -13,7 +13,7 @@ export function FAQ() { Starting a New Project

    - How do I use AutoCoder on a new project? + How do I use AutoForge on a new project?

    From the UI, select "Create New Project" in the project dropdown. Choose a folder and @@ -27,12 +27,12 @@ export function FAQ() { Adding to Existing Project

    - How do I add AutoCoder to an existing project? + How do I add AutoForge to an existing project?

    Register the project folder through the UI project selector using "Add Existing". - AutoCoder creates a{' '} - .autocoder/ directory + AutoForge creates a{' '} + .autoforge/ directory alongside your existing code. Write an app spec describing what to build (new features), and the agent works within your existing codebase.

    @@ -60,7 +60,7 @@ export function FAQ() {

    Create{' '} - .autocoder/allowed_commands.yaml + .autoforge/allowed_commands.yaml {' '} in your project with a list of allowed commands. Supports exact names, wildcards (e.g.,{' '} swift*), and local diff --git a/ui/src/components/docs/sections/GettingStarted.tsx b/ui/src/components/docs/sections/GettingStarted.tsx index 1ee560b..5976dc0 100644 --- a/ui/src/components/docs/sections/GettingStarted.tsx +++ b/ui/src/components/docs/sections/GettingStarted.tsx @@ -1,7 +1,7 @@ /** * GettingStarted Documentation Section * - * Covers what AutoCoder is, quick start commands, + * Covers what AutoForge is, quick start commands, * creating and adding projects, and system requirements. */ @@ -10,12 +10,12 @@ import { Badge } from '@/components/ui/badge' export function GettingStarted() { return (

    - {/* What is AutoCoder? */} -

    - What is AutoCoder? + {/* What is AutoForge? */} +

    + What is AutoForge?

    - AutoCoder is an autonomous coding agent system that builds complete applications over multiple + AutoForge is an autonomous coding agent system that builds complete applications over multiple sessions using a two-agent pattern:

      @@ -38,7 +38,7 @@ export function GettingStarted() { Quick Start

      - Launch AutoCoder with a single command. The CLI menu lets you create or select a project, + Launch AutoForge with a single command. The CLI menu lets you create or select a project, while the Web UI provides a full dashboard experience.

      @@ -76,12 +76,12 @@ start_ui.bat # Web UI
      • Register the project folder via the UI project selector
      • - AutoCoder creates a{' '} - .autocoder/{' '} + AutoForge creates a{' '} + .autoforge/{' '} directory inside your project
      • - Existing code is preserved — AutoCoder adds its configuration alongside it + Existing code is preserved — AutoForge adds its configuration alongside it
      • Write or generate an app spec describing what to build
      diff --git a/ui/src/components/docs/sections/ProjectStructure.tsx b/ui/src/components/docs/sections/ProjectStructure.tsx index 0b6aa6b..2217d3c 100644 --- a/ui/src/components/docs/sections/ProjectStructure.tsx +++ b/ui/src/components/docs/sections/ProjectStructure.tsx @@ -1,7 +1,7 @@ /** * ProjectStructure Documentation Section * - * Covers the .autocoder/ directory layout, features database, + * Covers the .autoforge/ directory layout, features database, * prompts directory, allowed commands, CLAUDE.md convention, * legacy migration, and Claude inheritance. */ @@ -9,18 +9,18 @@ export function ProjectStructure() { return (
      - {/* .autocoder/ Directory Layout */} -

      - .autocoder/ Directory Layout + {/* .autoforge/ Directory Layout */} +

      + .autoforge/ Directory Layout

      - Every AutoCoder project stores its configuration and runtime files in a{' '} - .autocoder/{' '} + Every AutoForge project stores its configuration and runtime files in a{' '} + .autoforge/{' '} directory at the project root.

      {`your-project/
      -\u251C\u2500\u2500 .autocoder/
      +\u251C\u2500\u2500 .autoforge/
       \u2502   \u251C\u2500\u2500 features.db              # SQLite feature database
       \u2502   \u251C\u2500\u2500 .agent.lock              # Lock file (prevents multiple instances)
       \u2502   \u251C\u2500\u2500 .gitignore               # Ignores runtime files
      @@ -41,7 +41,7 @@ export function ProjectStructure() {
               
    1. SQLite database managed by SQLAlchemy, stored at{' '} - .autocoder/features.db + .autoforge/features.db
    2. @@ -96,7 +96,7 @@ export function ProjectStructure() {

      The optional{' '} - .autocoder/allowed_commands.yaml + .autoforge/allowed_commands.yaml {' '} file lets you grant project-specific bash commands to the agent. This is useful when your project requires tools beyond the default allowlist (e.g., language-specific compilers or @@ -138,7 +138,7 @@ export function ProjectStructure() {

      • On the next agent start, these files are automatically migrated into{' '} - .autocoder/ + .autoforge/
      • Dual-path resolution ensures both old and new layouts work transparently
      • No manual migration is needed — it happens seamlessly
      • diff --git a/ui/src/components/docs/sections/Scheduling.tsx b/ui/src/components/docs/sections/Scheduling.tsx index 913bb78..1e47046 100644 --- a/ui/src/components/docs/sections/Scheduling.tsx +++ b/ui/src/components/docs/sections/Scheduling.tsx @@ -15,7 +15,7 @@ export function Scheduling() { What Scheduling Does

        - Scheduling automates agent runs at specific times. Set up a schedule and AutoCoder will automatically + Scheduling automates agent runs at specific times. Set up a schedule and AutoForge will automatically start agents on your project — useful for overnight builds, periodic maintenance, or continuous development.

        diff --git a/ui/src/components/docs/sections/Security.tsx b/ui/src/components/docs/sections/Security.tsx index 2e4e09a..f3e2b1b 100644 --- a/ui/src/components/docs/sections/Security.tsx +++ b/ui/src/components/docs/sections/Security.tsx @@ -16,7 +16,7 @@ export function Security() { Command Validation Overview

        - AutoCoder uses a defense-in-depth approach for security. All three layers must pass before any + AutoForge uses a defense-in-depth approach for security. All three layers must pass before any command is executed:

          @@ -49,12 +49,12 @@ export function Security() {
        1. Org Blocklist{' '} - ~/.autocoder/config.yaml{' '} + ~/.autoforge/config.yaml{' '} — org-wide blocks, cannot be project-overridden
        2. Org Allowlist{' '} - ~/.autocoder/config.yaml{' '} + ~/.autoforge/config.yaml{' '} — available to all projects
        3. @@ -65,7 +65,7 @@ export function Security() {
        4. Project Allowlist{' '} - .autocoder/allowed_commands.yaml + .autoforge/allowed_commands.yaml {' '} — project-specific additions
        5. @@ -120,12 +120,12 @@ export function Security() {

          Each project can define additional allowed commands in{' '} - .autocoder/allowed_commands.yaml + .autoforge/allowed_commands.yaml :

          -
          {`# .autocoder/allowed_commands.yaml
          +        
          {`# .autoforge/allowed_commands.yaml
           version: 1
           commands:
             # Exact command name
          @@ -155,10 +155,10 @@ commands:
                 
                 

          System administrators can set org-wide policies in{' '} - ~/.autocoder/config.yaml: + ~/.autoforge/config.yaml:

          -
          {`# ~/.autocoder/config.yaml
          +        
          {`# ~/.autoforge/config.yaml
           version: 1
           
           # Commands available to ALL projects
          diff --git a/ui/src/components/docs/sections/SettingsConfig.tsx b/ui/src/components/docs/sections/SettingsConfig.tsx
          index 6045c5a..c5a5eb5 100644
          --- a/ui/src/components/docs/sections/SettingsConfig.tsx
          +++ b/ui/src/components/docs/sections/SettingsConfig.tsx
          @@ -177,7 +177,7 @@ export function SettingsConfig() {
                 
          • Global settings stored in SQLite registry at{' '} - ~/.autocoder/registry.db + ~/.autoforge/registry.db
          • Per-project settings (like default concurrency) stored in the project registry entry
          • UI settings (theme, dark mode) stored in browser localStorage
          • diff --git a/ui/src/hooks/useTheme.ts b/ui/src/hooks/useTheme.ts index f364a84..a0665d9 100644 --- a/ui/src/hooks/useTheme.ts +++ b/ui/src/hooks/useTheme.ts @@ -52,8 +52,8 @@ export const THEMES: ThemeOption[] = [ } ] -const THEME_STORAGE_KEY = 'autocoder-theme' -const DARK_MODE_STORAGE_KEY = 'autocoder-dark-mode' +const THEME_STORAGE_KEY = 'autoforge-theme' +const DARK_MODE_STORAGE_KEY = 'autoforge-dark-mode' function getThemeClass(themeId: ThemeId): string { switch (themeId) {