diff --git a/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/inject-workspace-cwd.py b/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/inject-workspace-cwd.py deleted file mode 100644 index 64a3efb..0000000 --- a/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/inject-workspace-cwd.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python3 -""" -CWD context injector — injects working directory into Claude's context -on every session start, user prompt, tool call, and subagent spawn. - -Fires on: SessionStart, UserPromptSubmit, PreToolUse, SubagentStart -Always exits 0 (advisory, never blocking). -""" - -import json -import os -import sys - - -def main(): - cwd = os.getcwd() - try: - input_data = json.load(sys.stdin) - # Some hook events provide cwd override - cwd = input_data.get("cwd", cwd) - hook_event = input_data.get("hook_event_name", "PreToolUse") - except (json.JSONDecodeError, ValueError): - hook_event = "PreToolUse" - - context = ( - f"Working Directory: {cwd}\n" - f"All file operations and commands MUST target paths within {cwd}. " - f"Do not read, write, or execute commands against paths outside this directory." - ) - - json.dump( - { - "hookSpecificOutput": { - "hookEventName": hook_event, - "additionalContext": context, - } - }, - sys.stdout, - ) - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/.github/dependabot.yml b/.github/dependabot.yml index cef2c79..c9d1903 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,12 @@ version: 2 updates: - package-ecosystem: "npm" - directory: "/" + directory: "/container" + schedule: + interval: "weekly" + + - package-ecosystem: "npm" + directory: "/cli" schedule: interval: "weekly" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 60d01a8..29aa5f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,8 +3,10 @@ name: CI on: push: branches: [main, staging] + paths: ['container/**'] pull_request: branches: [main, staging] + paths: ['container/**'] jobs: test: @@ -15,6 +17,7 @@ jobs: with: node-version: 18 - run: npm test + working-directory: container lint: runs-on: ubuntu-latest @@ -24,6 +27,7 @@ jobs: with: node-version: 18 - run: npx @biomejs/biome check setup.js test.js + working-directory: container test-plugins: runs-on: ubuntu-latest @@ -34,3 +38,14 @@ jobs: python-version: "3.x" - run: pip install pytest - run: pytest tests/ -v + working-directory: container + + test-cli: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: oven-sh/setup-bun@v2 + - run: bun install + working-directory: cli + - run: bun test + working-directory: cli diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index da53372..26ed88d 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -3,7 +3,7 @@ name: Deploy Docs on: push: branches: [main] - paths: ['docs/**', '.devcontainer/CHANGELOG.md'] + paths: ['docs/**', 'container/.devcontainer/CHANGELOG.md'] workflow_dispatch: permissions: diff --git a/.github/workflows/docs-ci.yml b/.github/workflows/docs-ci.yml index eedb48c..ed50f71 100644 --- a/.github/workflows/docs-ci.yml +++ b/.github/workflows/docs-ci.yml @@ -2,7 +2,7 @@ name: Docs CI on: pull_request: - paths: ['docs/**', '.devcontainer/CHANGELOG.md'] + paths: ['docs/**', 'container/.devcontainer/CHANGELOG.md'] jobs: build: diff --git a/.github/workflows/publish-features.yml b/.github/workflows/publish-features.yml index b63eec5..694db62 100644 --- a/.github/workflows/publish-features.yml +++ b/.github/workflows/publish-features.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: push: branches: [main] - paths: ['.devcontainer/features/**'] + paths: ['container/.devcontainer/features/**'] jobs: publish: @@ -19,7 +19,7 @@ jobs: uses: devcontainers/action@v1 with: publish-features: "true" - base-path-to-features: "./.devcontainer/features" + base-path-to-features: "./container/.devcontainer/features" generate-docs: "false" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2b376f3..d6e07cb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: name: Extract and validate version run: | TAG="${GITHUB_REF#refs/tags/v}" - PKG=$(node -p "require('./package.json').version") + PKG=$(node -p "require('./container/package.json').version") echo "version=$TAG" >> "$GITHUB_OUTPUT" if [ "$TAG" != "$PKG" ]; then echo "::error::Tag v${TAG} does not match package.json version ${PKG}" @@ -38,9 +38,11 @@ jobs: - name: Run tests run: npm test + working-directory: container - name: Publish to npm run: npm publish + working-directory: container env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -48,7 +50,7 @@ jobs: id: changelog run: | VERSION="${{ needs.validate.outputs.version }}" - NOTES=$(sed -n "/^## \[v${VERSION}\]/,/^## \[v/{ /^## \[v${VERSION}\]/d; /^## \[v/d; p; }" .devcontainer/CHANGELOG.md) + NOTES=$(sed -n "/^## \[v${VERSION}\]/,/^## \[v/{ /^## \[v${VERSION}\]/d; /^## \[v/d; p; }" container/.devcontainer/CHANGELOG.md) if [ -z "$NOTES" ]; then NOTES="Release v${VERSION}" fi diff --git a/.gitignore b/.gitignore index 14980e1..7376f80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,84 +1,64 @@ -# CodeForge Git Ignore - -# Environment files with API keys +# Shared +node_modules/ +dist/ .env -.env.local -.env.development.local -.env.test.local -.env.production.local - -# DevContainer build cache -.devcontainer/.dockercache/ - -# IDE files -.vscode/settings.json -*.swp -*.swo -*~ - -# Temporary files -*.tmp -*.temp +.env.* +!.env.example +!.env.*.example +*.log .DS_Store Thumbs.db - -# Logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Coverage directory used by tools like istanbul +__pycache__/ +*.pyc coverage/ *.lcov - -# nyc test coverage .nyc_output -logs -dev-debug.log -# Python bytecode -__pycache__/ -*.pyc +# Temporary files +*.tmp +*.temp +*.swp +*.swo +*~ -# Dependency directories -node_modules/ -# Environment variables -# Editor directories and files -.idea -.vscode +# IDE +.vscode/ +.idea/ *.suo *.ntvs* *.njsproj *.sln -*.sw? -# OS specific -# Claude Code directory (user-specific) -.claude/ +# Runtime +pids/ +*.pid +*.seed +*.pid.lock -# All hidden directories except devcontainer and codeforge -.* -!.devcontainer/ -!.devcontainer/**/.claude-plugin/ -!.codeforge/ -!.git/ -!.github/ -!.gitignore -!.gitattributes -!.npmignore +# Container-specific +container/.claude/ +container/.tmp/ +container/.codeforge/.checksums/ +container/.codeforge/.markers/ +container/.devcontainer/.env +container/.devcontainer/.secrets +container/.devcontainer/state/ +container/.devcontainer/config/backups/ +container/.devcontainer/.dockercache/ +container/.devcontainer/**/*.codeforge-new +container/.devcontainer/**/*.bak +container/.devcontainer/.codeforge-preserve -# .codeforge per-installation state (not tracked) -.codeforge/.checksums/ -.codeforge/.markers/ +# CLI-specific +cli/.pytest_cache/ +cli/.ruff_cache/ -# Docs -docs/node_modules/ -docs/dist/ +# Docs-specific docs/.astro/ + +# OS-generated +logs/ +dev-debug.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/CLAUDE.md b/CLAUDE.md index 8e7a882..02a2f69 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,8 +1,14 @@ -# CodeForge +# CodeForge Monorepo -DevContainer configuration project for AI-assisted development with Claude Code. +This repository contains three packages. Each package manages its own dependencies independently. -See `.devcontainer/CLAUDE.md` for full devcontainer documentation. +## Packages + +| Package | Runtime | Package Manager | +|---------|---------|-----------------| +| `container/` | Node.js | npm | +| `cli/` | Bun | bun | +| `docs/` | Node.js | npm | ## Development Rules @@ -13,25 +19,23 @@ See `.devcontainer/CLAUDE.md` for full devcontainer documentation. - Feature and fix branches should be created from `staging` and PRed back to `staging`. - PRs from `staging` to `main` are used for releases. -### Changelog +### Package-Specific Rules -Every change MUST have a corresponding entry in `.devcontainer/CHANGELOG.md`. +Each package has its own `CLAUDE.md` with package-specific development rules: -- New features, enhancements, fixes, and removals each get their own bullet -- Group related changes under domain headings (`###`) by area (e.g., `### Security`, `### Agent System`, `### Documentation`, `### Configuration`) -- If an unreleased version section doesn't exist, add changes to the current version's section -- Write entries from the user's perspective — what changed, not how it was implemented +- [`container/CLAUDE.md`](container/CLAUDE.md) — changelog, documentation, and configuration rules for the devcontainer package +- `cli/` — Bun/TypeScript CLI; run `bun test` for tests +- `docs/` — Astro/Starlight site; run `npm run build` to verify -### Documentation +### Cross-Package Changes -All user-facing changes MUST be reflected in documentation: +When a change spans multiple packages, make the changes in a single branch and PR. +Group related changes in the commit message by package. -- **Plugin changes** → update the plugin's `README.md` -- **Feature changes** → update `features/README.md` and the feature's `devcontainer-feature.json` if applicable -- **Config system changes** → update `.devcontainer/CLAUDE.md` -- **New config files in `.codeforge/config/`** → add entry to `.codeforge/file-manifest.json` -- **Docs site** → update relevant pages in `docs/` if the docs site exists +### Testing -### User Configuration +Run tests for each affected package before committing: -All user-customizable configuration files belong in `.codeforge/`. New config files go in `.codeforge/config/`, with a corresponding entry in `.codeforge/file-manifest.json`. +- **Container**: `cd container && npm test` +- **CLI**: `cd cli && bun test` +- **Docs**: `cd docs && npm run build` diff --git a/README.md b/README.md index 11bfeb1..5b7f244 100644 --- a/README.md +++ b/README.md @@ -1,146 +1,47 @@ -# CodeForge DevContainer +# CodeForge -[![License: GPL-3.0](https://img.shields.io/badge/License-GPL%203.0-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) -[![npm version](https://img.shields.io/npm/v/codeforge-dev.svg)](https://www.npmjs.com/package/codeforge-dev) -[![Changelog](https://img.shields.io/badge/changelog-view-blue)](.devcontainer/CHANGELOG.md) -[![GitHub last commit](https://img.shields.io/github/last-commit/AnExiledDev/CodeForge)](https://github.com/AnExiledDev/CodeForge/commits) -[![npm downloads](https://img.shields.io/npm/dm/codeforge-dev)](https://www.npmjs.com/package/codeforge-dev) -[![Node.js](https://img.shields.io/badge/node-%3E%3D14.0.0-brightgreen)](https://nodejs.org/) -[![GitHub issues](https://img.shields.io/github/issues/AnExiledDev/CodeForge)](https://github.com/AnExiledDev/CodeForge/issues) -[![CI](https://github.com/AnExiledDev/CodeForge/actions/workflows/ci.yml/badge.svg)](https://github.com/AnExiledDev/CodeForge/actions/workflows/ci.yml) +Monorepo for CodeForge — an AI-powered development environment for Claude Code. -A curated development environment optimized for AI-powered coding with Claude Code. CodeForge comes pre-configured with language servers, code intelligence tools, and official Anthropic plugins to streamline your development workflow. +## Packages -## Why CodeForge? +| Package | Description | Version | +|---------|-------------|---------| +| [`container/`](container/) | CodeForge DevContainer (`codeforge-dev` on npm) | 2.0.0 | +| [`cli/`](cli/) | CodeForge CLI (`codeforge-cli`) | 0.1.0 | +| [`docs/`](docs/) | Documentation site ([codeforge.core-directive.com](https://codeforge.core-directive.com)) | — | -Claude Code is powerful out of the box, but getting the most from it takes significant configuration — custom agents, safety plugins, code quality hooks, system prompts, and development tools that aren't obvious from the docs. CodeForge is a Claude Code power user's personal development environment, packaged so anyone can use it. - -Instead of spending hours discovering and configuring advanced features like built-in agent replacement, automated code quality pipelines, or spec-driven workflows, you get a production-tested setup in one command. It's opinionated by design — every default reflects real daily use, not theoretical best practices. - -## Installation - -Add CodeForge to any project: +## Quick Start ```bash +# Install the devcontainer into any project npx codeforge-dev ``` -This copies the `.devcontainer/` directory to your project. Then open in VS Code and select "Reopen in Container". +See [`container/README.md`](container/README.md) for full setup instructions, prerequisites, and usage. -### Options - -```bash -npx codeforge-dev --force # Smart update (preserves your customizations) -npx codeforge-dev -f # Short form -npx codeforge-dev --reset # Fresh install (wipes .devcontainer, keeps .codeforge) -``` +## Development -### Alternative Install Methods +Each package manages its own dependencies independently: ```bash -# Install globally -npm install -g codeforge-dev -codeforge-dev - -# Run specific version -npx codeforge-dev@1.2.3 -``` - -## Prerequisites - -- **Docker Desktop** (or compatible container runtime like Podman) -- **A DevContainer client** — any of: - - **VS Code** with the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) - - **DevContainer CLI** — `npm install -g @devcontainers/cli` ([docs](https://containers.dev/supporting#devcontainer-cli)) - - **GitHub Codespaces** — zero local setup - - **JetBrains Gateway** with [Dev Containers plugin](https://plugins.jetbrains.com/plugin/21962-dev-containers) - - **DevPod** — open-source, editor-agnostic ([devpod.sh](https://devpod.sh/)) -- **Claude Code authentication** — run `claude` on first start to authenticate - -## What's Included - -### Languages & Runtimes - -Python 3.14, Node.js LTS, TypeScript, Rust, Bun, Go (optional) - -### Package Managers - -`uv`, `npm`, `bun`, `pip` / `pipx` - -### Development Tools - -`gh` (GitHub CLI), `docker`, `git`, `jq`, `curl`, `tmux`, `biome`, `ruff`, `ccms`, `agent-browser` - -### Code Intelligence - -tree-sitter (JS/TS/Python), ast-grep, Pyright, TypeScript LSP - -### Claude Code Tools - -`claude`, `cc` (wrapper), `ccw` (writing mode wrapper), `ccusage`, `ccburn`, `ccstatusline`, `claude-monitor` - -### Custom Features (21) - -tmux, agent-browser, claude-monitor, ccusage, ccburn, ccstatusline, ast-grep, tree-sitter, lsp-servers, biome, ruff, shfmt, shellcheck, hadolint, dprint, ccms, notify-hook, mcp-qdrant, chromaterm, kitty-terminfo, claude-session-dashboard - -### Agents (17) & Skills (35) - -The `agent-system` plugin includes 17 specialized agents (architect, explorer, test-writer, security-auditor, etc.). The `skill-engine` plugin provides 22 general coding skills, `spec-workflow` adds 8 spec lifecycle skills, and `ticket-workflow` provides 4 ticket management skills. +# Container (npm) +cd container && npm test -## Architecture +# CLI (Bun) +cd cli && bun test -CodeForge operates in three layers, each building on the one below: - -``` -┌──────────────────────────────────────────────┐ -│ Claude Code │ -│ AI assistant, tool execution, Agent Teams │ -├──────────────────────────────────────────────┤ -│ CodeForge Layer │ -│ Plugins · Agents · Skills · Hooks · Rules │ -├──────────────────────────────────────────────┤ -│ DevContainer │ -│ Runtimes · CLI Tools · LSP Servers │ -└──────────────────────────────────────────────┘ +# Docs (npm) +cd docs && npm run build ``` -**DevContainer** — The foundation. A Python 3.14 container with Node.js, Rust, and Bun runtimes, plus 22 custom features that install development tools (ast-grep, tree-sitter, biome, ruff, and others). - -**CodeForge Layer** — The intelligence. 17 plugins register hooks that validate commands, inject context, and enforce safety. 21 agents provide specialized personas. 38 skills offer on-demand reference material. System prompts and rules shape behavior. - -**Claude Code** — The AI assistant, executing tools and coordinating work. CodeForge enhances it through configuration — replacing built-in subagents, adding safety guardrails, and wiring up quality checks that run automatically. - -For the full architecture breakdown — hook pipeline, agent routing, skill loading, and design principles — see the [Architecture Reference](https://codeforge.core-directive.com/reference/architecture/). - -## Configuration - -All configuration lives in `.devcontainer/` and deploys automatically on container start. Key files: +See [`CLAUDE.md`](CLAUDE.md) for branching strategy and development rules. -| File | What It Configures | User-Modifiable? | -|------|--------------------|------------------| -| `config/defaults/settings.json` | Model, plugins, permissions, environment variables | Yes | -| `config/defaults/main-system-prompt.md` | Claude's behavioral guidelines and directives | Yes | -| `config/defaults/keybindings.json` | Keyboard shortcuts | Yes | -| `config/defaults/ccstatusline-settings.json` | Terminal status bar widgets and layout | Yes | -| `config/file-manifest.json` | Which config files deploy and how they update | Yes | -| `devcontainer.json` | Container image, features, runtimes, ports | Yes | -| `.env` | Setup phase toggles (auth, plugins, aliases, etc.) | Yes | +## Links -Config files use SHA-256 change detection — your edits persist across container rebuilds unless the source changes. Set a file's overwrite mode to `"never"` in `file-manifest.json` to permanently preserve your customizations. - -For the complete configuration guide, see the [documentation site](https://codeforge.core-directive.com/customization/configuration/). - -## Quick Start - -1. **Install**: `npx codeforge-dev` -2. **Open in Container**: - - **VS Code**: "Reopen in Container" from the Command Palette - - **CLI**: `devcontainer up --workspace-folder .` then `docker exec -it zsh` - - **Codespaces**: Create a Codespace from the repo -3. **Authenticate**: Run `claude` and follow prompts -4. **Start coding**: Run `cc` - -CodeForge uses the open [Dev Containers specification](https://containers.dev/) — any compatible client works. For full usage documentation — authentication, configuration, tools, agents, and keybindings — see [`.devcontainer/README.md`](.devcontainer/README.md). +- [Documentation](https://codeforge.core-directive.com) +- [npm package](https://www.npmjs.com/package/codeforge-dev) +- [GitHub](https://github.com/AnExiledDev/CodeForge) +- [Changelog](container/.devcontainer/CHANGELOG.md) ## Contributing @@ -157,32 +58,3 @@ without GPL-3.0 obligations. Contact [696222+AnExiledDev@users.noreply.github.com](mailto:696222+AnExiledDev@users.noreply.github.com) or [open a GitHub issue](https://github.com/AnExiledDev/CodeForge/issues/new) for terms. - -## Development - -### Testing Locally - -```bash -git clone https://github.com/AnExiledDev/CodeForge.git -cd CodeForge -npm test -``` - -### Publishing - -```bash -# Bump version in package.json, then: -npm publish -``` - -## Changelog - -See [CHANGELOG.md](.devcontainer/CHANGELOG.md) for release history. Current version: **2.0.0**. - -## Further Reading - -- [Full Usage Guide](.devcontainer/README.md) -- [Changelog](.devcontainer/CHANGELOG.md) -- [Claude Code Documentation](https://docs.anthropic.com/en/docs/claude-code) -- [Dev Containers Specification](https://containers.dev/) -- [GitHub CLI Manual](https://cli.github.com/manual/) diff --git a/cli/bun.lock b/cli/bun.lock new file mode 100644 index 0000000..8b83519 --- /dev/null +++ b/cli/bun.lock @@ -0,0 +1,70 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "codeforge-cli", + "dependencies": { + "chalk": "^5.4.0", + "commander": "^13.0.0", + "fast-glob": "^3.3.0", + }, + "devDependencies": { + "@types/bun": "^1.3.10", + "@types/node": "^22.0.0", + "typescript": "^5.7.0", + }, + }, + }, + "packages": { + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="], + + "@types/node": ["@types/node@22.19.13", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], + + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="], + + "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "commander": ["commander@13.1.0", "", {}, "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + } +} diff --git a/cli/package.json b/cli/package.json new file mode 100644 index 0000000..ecd65cc --- /dev/null +++ b/cli/package.json @@ -0,0 +1,38 @@ +{ + "name": "codeforge-cli", + "version": "0.1.0", + "description": "CLI for CodeForge development workflows", + "type": "module", + "bin": { + "codeforge": "./dist/codeforge.js" + }, + "scripts": { + "build": "bun build src/index.ts --outdir dist --target bun", + "dev": "bun run src/index.ts", + "test": "bun test" + }, + "dependencies": { + "commander": "^13.0.0", + "chalk": "^5.4.0", + "fast-glob": "^3.3.0" + }, + "devDependencies": { + "@types/bun": "^1.3.10", + "@types/node": "^22.0.0", + "typescript": "^5.7.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "license": "GPL-3.0", + "author": "AnExiledDev", + "repository": { + "type": "git", + "url": "git+https://github.com/AnExiledDev/CodeForge.git", + "directory": "cli" + }, + "homepage": "https://github.com/AnExiledDev/CodeForge/tree/main/cli#readme", + "bugs": { + "url": "https://github.com/AnExiledDev/CodeForge/issues" + } +} diff --git a/cli/src/commands/plan/search.ts b/cli/src/commands/plan/search.ts new file mode 100644 index 0000000..d4df661 --- /dev/null +++ b/cli/src/commands/plan/search.ts @@ -0,0 +1,107 @@ +import chalk from "chalk"; +import type { Command } from "commander"; +import { loadPlans } from "../../loaders/plan-loader.js"; +import { + formatPlanJson, + formatPlanText, + type PlanSearchResult, +} from "../../output/plan-text.js"; +import { evaluate, parse } from "../../search/query-parser.js"; + +interface PlanSearchOptions { + limit: string; + format: string; + color?: boolean; + fullText?: boolean; +} + +function extractContextLines(content: string, query: string): string[] { + const contentLines = content.split("\n"); + // Extract individual terms from the query (simple word extraction) + const terms = query + .replace(/\b(AND|OR|NOT)\b/gi, "") + .replace(/[()]/g, "") + .split(/\s+/) + .filter((t) => t.length > 0) + .map((t) => t.replace(/^["']|["']$/g, "").toLowerCase()); + + if (terms.length === 0) return []; + + const matchingIndices = new Set(); + + for (let i = 0; i < contentLines.length; i++) { + const lower = contentLines[i].toLowerCase(); + for (const term of terms) { + if (lower.includes(term)) { + matchingIndices.add(i); + break; + } + } + } + + // Add context lines (+/- 1 line) + const contextIndices = new Set(); + for (const idx of matchingIndices) { + if (idx > 0) contextIndices.add(idx - 1); + contextIndices.add(idx); + if (idx < contentLines.length - 1) contextIndices.add(idx + 1); + } + + // Sort and deduplicate, cap at 5 + const sorted = [...contextIndices].sort((a, b) => a - b).slice(0, 5); + return sorted.map((i) => contentLines[i]); +} + +export function registerPlanSearchCommand(parent: Command): void { + parent + .command("search") + .description("Search across plan files") + .argument("[query]", "Search query (supports AND, OR, NOT, quotes)") + .option("-n, --limit ", "Maximum number of results", "20") + .option("-f, --format ", "Output format: text|json", "text") + .option("--no-color", "Disable colored output") + .option("--full-text", "Disable content truncation") + .action(async (query: string | undefined, options: PlanSearchOptions) => { + try { + if (!options.color) { + chalk.level = 0; + } + + const plans = await loadPlans(); + + let results: PlanSearchResult[]; + + if (query) { + const queryNode = parse(query); + results = []; + for (const plan of plans) { + if (evaluate(queryNode, plan.content)) { + const matchingLines = extractContextLines(plan.content, query); + results.push({ plan, matchingLines }); + } + } + } else { + results = plans.map((plan) => ({ plan })); + } + + // Apply limit + const limit = parseInt(options.limit, 10); + results = results.slice(0, limit); + + if (options.format === "json") { + console.log(formatPlanJson(results)); + } else { + console.log( + formatPlanText(results, { + noColor: !options.color, + fullText: options.fullText, + }), + ); + } + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + console.error(`Error: ${message}`); + process.exit(1); + } + }); +} diff --git a/cli/src/commands/session/list.ts b/cli/src/commands/session/list.ts new file mode 100644 index 0000000..4e78c1a --- /dev/null +++ b/cli/src/commands/session/list.ts @@ -0,0 +1,96 @@ +import chalk from "chalk"; +import type { Command } from "commander"; +import { loadHistory } from "../../loaders/history-loader.js"; +import { extractSessionMeta } from "../../loaders/session-meta.js"; +import { + formatSessionListJson, + formatSessionListText, + type SessionListEntry, +} from "../../output/session-list.js"; +import { discoverSessionFiles } from "../../utils/glob.js"; +import { parseRelativeTime, parseTime } from "../../utils/time.js"; + +interface ListCommandOptions { + project?: string; + since?: string; + after?: string; + before?: string; + limit: string; + format: string; + color?: boolean; +} + +export function registerListCommand(parent: Command): void { + parent + .command("list") + .description("List previous Claude Code sessions") + .option("--project ", "Project directory filter") + .option("--since