* feat(cli): Add git repository safety check
Add validation to ensure CLI workflows only run from within a git
repository. If the user runs from a subdirectory, the CLI resolves
to the repo root. Running from a non-git directory produces a clear
error message with guidance.
- Add git.findRepoRoot() check before workflow commands
- Bypass check for version/help commands
- Add tests for git repo validation behavior
* docs: Update CLI documentation for git repository requirement
* fix(cli): Improve error handling and tests for git repo check
- Move git.findRepoRoot() inside try-catch block to ensure proper error
handling and database cleanup on unexpected errors
- Add path existence validation before git check for clearer error messages
- Improve tests: test real git.findRepoRoot behavior instead of mocks
- Add tests for path validation and command categorization logic
* docs: Add CLI user guide and developer guide
- Add docs/cli-user-guide.md with command reference, flags, and examples
- Add docs/cli-developer-guide.md with architecture and ASCII flow diagrams
- Update README CLI section with proper setup order (install → auth → run)
- Link README to user guide, user guide to developer guide
* docs: Update CLI docs to reflect source-based usage
Binary distribution not yet available. Update all docs to use
`bun run cli` from cloned repo instead of `archon` binary.
* docs: Add bun link for global CLI availability
- Add step to run `bun link` from packages/cli for global `archon` command
- Update all examples to use `archon` instead of `bun run cli`
- Update Windows WSL2 section with bun link step
* docs: Add Phase 5 CLI binary distribution plan
- Create detailed implementation plan for binary distribution
- Add Phase 5.0: Bundle defaults for binary (depends on #322)
- Add Phase 5.1-5.7: Build scripts, GitHub Actions, curl install,
Homebrew formula, Windows docs, version command, release guide
- Update research doc with Phase 6 (auto-update command)
- Renumber dashboard to Phase 7, workflow builder to Phase 8
- Mark Phases 1-4 as complete in research doc
* feat: Phase 5 - CLI binary distribution
Implement standalone binary distribution for Archon CLI:
- Bundle default commands and workflows into binaries at compile time
- Add build scripts for cross-platform compilation (macOS/Linux, ARM64/x64)
- Create GitHub Actions release workflow triggered on version tags
- Add curl install script with checksum verification
- Create Homebrew formula for macOS/Linux installation
- Update version command to show platform, build type, and database info
- Add developer release guide documentation
- Update README with CLI installation instructions
Binary compilation uses Bun's --compile flag to create standalone
executables that include the Bun runtime and all dependencies.
Default workflows and commands are imported as text at compile time
and embedded directly into the binary.
* fix: Pin Dockerfile to Bun 1.3.4 to match lockfile version
The Docker build was failing because oven/bun:1-slim resolved to 1.3.6
while the lockfile was created with 1.3.4, causing --frozen-lockfile to fail.
* docs: Clarify binary vs source builds for default commands/workflows
* fix: Address PR review issues for CLI binary distribution
Security fixes:
- install.sh: Require SKIP_CHECKSUM=true to bypass checksum verification
instead of silently skipping (addresses security vulnerability)
- install.sh: Show actual error output when version check fails instead
of falsely reporting success
Validation improvements:
- checksums.sh: Validate all 4 expected binaries exist before generating
checksums to prevent releasing incomplete builds
- build-binaries.sh: Verify binary exists and has reasonable size (>1MB)
after each build step
- update-homebrew.sh: Validate extracted checksums are non-empty and
look like valid SHA256 hashes (64 hex chars)
- update-homebrew.sh: Fix sed patterns to use URL context for updating
checksums on subsequent runs
Bug fixes:
- homebrew/archon.rb: Fix test to expect exit code 0 (success) instead
of 1 for `archon version`
- loader.ts: Log error when bundled workflow fails to parse (indicates
build-time corruption)
Test coverage:
- Add bundled-defaults.test.ts for isBinaryBuild() and content validation
- Add connection.test.ts for getDatabaseType() function
- Add binary build bundled workflow tests to loader.test.ts
- Add binary build bundled command tests to executor.test.ts
All 959 tests pass.
* feat: Runtime loading of default commands/workflows
Instead of copying default commands and workflows to target repos on
clone, load them at runtime from the app's bundled defaults directory.
Changes:
- Fix getAppArchonBasePath() to resolve to repo root (not packages/core)
- Add loadDefaultCommands and loadDefaultWorkflows config options
- Update workflow loader to search app defaults then repo (repo wins)
- Update command executor to search app defaults after repo paths
- Remove copyDefaultsToRepo() calls from /clone and GitHub adapter
- Fix lint-staged to not warn on ignored test files
Benefits:
- Defaults always up-to-date (no sync issues)
- Clean repos (no 24+ files copied per clone)
- User's local clone stays in sync with what Archon uses
Closes#322
* docs: Update documentation for runtime loading of defaults
- Update CLAUDE.md to explain runtime loading behavior
- Fix README.md example output and note about defaults
- Update docs/configuration.md with new config options
- Mark copyDefaults as deprecated in favor of loadDefaultCommands/loadDefaultWorkflows
* fix: Address PR review findings for runtime loading
- Fix silent error swallowing in loadConfig catch blocks (loader.ts, executor.ts)
- Now logs warning with context before falling back to defaults
- Users will know when their config has syntax errors
- Fix config merging bug in mergeRepoConfig
- Now includes loadDefaultCommands and loadDefaultWorkflows in merge
- Repo config opt-out now works correctly
- Add consistent empty file handling for app defaults
- Returns explicit empty_file error instead of falling through
- Add debug logging for ENOENT cases
- Helps troubleshoot when app defaults aren't found
- Add startup validation for app defaults paths
- validateAppDefaultsPaths() checks and logs verification status
- Called during server startup after logArchonPaths()
- Add comprehensive tests for app defaults command loading
- Test loading from app defaults when not in repo
- Test repo commands override app defaults
- Test loadDefaultCommands: false opt-out
- Test empty file handling
- Test graceful handling of missing paths
- Test config error fallback behavior
* fix: Use namespace imports for archonPaths to fix test mocking in CI
The loader.ts used destructured imports for getDefaultWorkflowsPath and
getWorkflowFolderSearchPaths, but the tests use spyOn which only works
with namespace imports (import * as). This caused the mocks to not work
in CI where tests run in parallel, causing 48 test failures.
* fix: Restore spyOn approach with namespace imports for loader tests
The key fix is that loader.ts uses namespace imports (import * as archonPaths)
which shares the same module instance with the test file. This allows spyOn
to work correctly without using mock.module() which pollutes other tests.
* fix: Use loadDefaultWorkflows: false to avoid app defaults in tests
Instead of mocking archon-paths (which pollutes other tests), we:
1. Only mock config-loader with loadDefaultWorkflows: false by default
2. This prevents app defaults from being loaded during tests
3. For multi-source loading tests, enable loadDefaultWorkflows: true
and use spyOn to set the path to a temp directory
* fix: Use namespace imports and spyOn for all loader dependencies
Key changes:
1. loader.ts now uses namespace imports for both archonPaths and configLoader
2. loader.test.ts uses spyOn instead of mock.module
3. This avoids polluting other test files (archon-paths.test.ts, config-loader.test.ts)
The spyOn approach works because:
- Both loader.ts and loader.test.ts import the modules as namespaces
- They share the same module instance in Bun's module cache
- spyOn modifies the shared namespace object
* fix: Use namespace imports in executor.ts for test mocking
Change executor.ts to use namespace imports for archon-paths and
config-loader, matching the fix already applied to loader.ts.
The previous fix commits (491fa94, c3a68dd) only updated loader.ts
but missed executor.ts, which has the same pattern of tests using
spyOn() that requires namespace imports to work correctly.
Changes:
- import * as archonPaths from '../utils/archon-paths'
- import * as configLoader from '../config/config-loader'
- Update all usage sites to use namespace prefix
* refactor: Prefix app defaults with archon-* and simplify override logic
Changes:
- Rename all default workflow files to archon-*.yaml
- Rename all default command files to archon-*.md
- Update workflow name: fields to match filenames
- Update command references in workflows to use archon-* names
- Simplify loader.ts to use exact filename match for overrides (not workflow name)
- Remove path mocking from tests - use real app defaults instead
- Simplify tests to be more reliable in CI
Benefits:
- No accidental collisions with user workflows/commands
- Clear intent when users override (must use exact filename)
- Simpler deduplication logic (filename-based)
- More reliable tests (no spyOn issues in CI parallel execution)
* feat: Add deprecation warning for old defaults and update docs
- Add warning in loader.ts when old non-prefixed defaults found in repo
- Update CLAUDE.md with migration instructions for old repos
- Document the archon-* prefix naming convention
- Document exact filename match override behavior
* docs: Move migration docs to docs/migration-guide.md
- Revert CLAUDE.md changes (keep it focused on development)
- Create dedicated migration guide for version upgrades
- Document runtime loading defaults migration steps
- Add commands for full fresh start cleanup
* docs: Add getting started section after cleanup
* docs: Fix stale references to command loading behavior
- Update CLAUDE.md to say 'auto-detected' instead of 'loaded via /clone (auto)'
- Clarify in architecture.md that defaults are loaded at runtime, not copied
- Update GitHub webhook flow to say 'detect and register' instead of 'load commands'
* refactor: Use early return in validateAppDefaultsPaths for cleaner flow
* fix: Improve error handling for silent failure cases
- Add ENOENT check to empty catch block in loader.ts (critical)
- Distinguish between 'not found' and other errors in validateAppDefaultsPaths
- Add errorType to config load fallback logging in loader.ts and executor.ts
* feat: Phase 4 - Express to Hono migration
Replace Express with Hono in @archon/server for improved performance
and better Bun integration. This is a focused HTTP layer migration
that preserves all existing API functionality.
Changes:
- Replace express with hono dependency
- Migrate all endpoints to Hono context-based handlers
- Use Bun.serve() for native Bun server integration
- Update optional parameter syntax from Express 5 to Hono style
- Remove express.json()/express.raw() middleware (Hono handles natively)
- Change default port from 3000 to 3090
- Update log prefixes from [Express] to [Hono]
- Update CLAUDE.md documentation references
All endpoints verified working:
- GET /health, /health/db, /health/concurrency
- POST /test/message, GET /test/messages/:id
- DELETE /test/messages/:id?, PUT /test/mode
- POST /webhooks/github (signature verification)
* refactor: Simplify Hono endpoint handlers
- Remove unnecessary try/catch from /health/concurrency endpoint
(getStats() is a simple sync operation that doesn't need error handling)
- Remove outer try/catch from /test/message endpoint
(validation returns early, processing is fire-and-forget with its own error handler)
- Consolidate validation checks with clearer error messages
- Reduce nesting depth for improved readability
Total: 12 lines removed while maintaining identical functionality
* docs: Update port references from 3000 to 3090 after Hono migration
* fix: Improve error handling in Hono endpoints
- Add global app.onError() handler for consistent unhandled exception responses
- Add explicit JSON parsing error handling to /test/message endpoint (returns 400 instead of 500)
- Add explicit JSON parsing error handling to /test/mode endpoint (was completely unhandled)
- Fix CLAUDE.md worktree port example to use correct port (3637 with base 3090)
* feat: Phase 3 - Database abstraction layer and CLI isolation
Part A: Database Abstraction Layer
- Add IDatabase interface supporting PostgreSQL and SQLite
- Create PostgresAdapter wrapping pg Pool with same interface
- Create SqliteAdapter using bun:sqlite with auto-schema init
- Add SqlDialect helpers for database-specific SQL generation
- Update connection.ts with auto-detection (DATABASE_URL → Postgres, else SQLite)
- Update isolation-environments.ts to use dialect helpers
- CLI now works without DATABASE_URL (uses ~/.archon/archon.db)
Part B: CLI Isolation Integration
- Add --branch/-b flag to create/reuse worktrees for workflows
- Add --no-worktree flag to run on branch directly without isolation
- Add isolation list command to show all active worktrees
- Add isolation cleanup command to remove stale environments
- Auto-register codebase when using --branch from git repo
New git utilities:
- findRepoRoot: Find git repository root from any path
- getRemoteUrl: Get origin remote URL
- checkout: Checkout branch (creating if needed)
* docs: Update documentation for Phase 3 - SQLite support and CLI isolation
* fix: Address all PR review issues for database abstraction
Critical fixes:
- Use dialect helpers (now(), jsonMerge, jsonArrayContains) in all DB operations
- Replace hardcoded PostgreSQL NOW(), ::jsonb, and JSON operators
- Add rowCount validation to updateStatus() and updateMetadata()
- Improve PostgreSQL pool error logging with structured context
Important fixes:
- Add explicit null check in getDialect() instead of non-null assertion
- Add warning for unsupported UPDATE/DELETE RETURNING in SQLite
- Throw error in extractTableName() on parse failure instead of empty string
- Track codebaseLookupError to provide clearer errors when --branch fails
- Couple IDatabase with SqlDialect via readonly sql property
Code simplifications:
- Extract loadWorkflows() helper to DRY duplicate error handling
- Fix N+1 query in getCodebases() by including repository_url in JOIN
- Cache sql.toUpperCase() to avoid redundant calls
All changes verified with:
- Type-check passes
- All 1082 tests pass
- CLI commands tested with both SQLite and PostgreSQL
* docs: Add SQLite support to getting-started, configuration, and architecture guides
* refactor: Simplify Phase 3 code for clarity and maintainability
- sqlite.ts: Remove unused UPDATE branch from extractTableName, consolidate
RETURNING clause handling into single condition
- isolation.ts: Extract CodebaseInfo interface to reduce type duplication
- workflow.ts: Extract actualBranchName variable for clearer intent
- isolation-environments.ts: Rename variables for semantic clarity
(staleActivityThreshold/staleCreationThreshold vs nowMinusDays1/2)
* fix: Address all remaining PR review issues
- SQLite: Throw error for UPDATE/DELETE RETURNING instead of warning
- SQLite: Replace deprecated db.exec() with db.run()
- Worktree: Throw for fatal errors (permission denied, not a git repo)
- Types: Add import type for type-only imports in 4 db modules
- Codebases: Add null check validation to createCodebase return
- WorkflowRunOptions: Add JSDoc documenting constraint behavior
- QueryResult: Add comment noting fields should be treated as readonly
- Connection: Improve getDialect() error message with actionable details
* fix: Complete type safety improvements for Phase 3
- QueryResult: Make rows and rowCount readonly to prevent mutation
- WorkflowRunOptions: Use discriminated union to prevent invalid states
(noWorktree can only be set when branchName is provided)
- Update all database functions to return readonly arrays
- Fix CLI call site to properly construct options object
* fix: Add getDialect mock to database tests
Tests were failing because they expected hardcoded PostgreSQL SQL
(NOW(), metadata || $1::jsonb) but the code now uses dialect helpers.
- Add mockPostgresDialect to test/mocks/database.ts
- Update all db test files to mock getDialect() returning PostgreSQL dialect
- Tests now properly verify the SQL generated by dialect helpers
* Investigate issue #233: Workflow state management visibility
* feat: Add workflow status visibility to /status and /workflow status (#233)
Users had no visibility into running workflows - they could only see "already running"
errors when attempting to start new workflows. This made it impossible to know what
was running, how long it had been active, or whether it was stuck.
Changes:
- Add workflow info to /status command (name, step, duration, activity)
- Add /workflow status subcommand for detailed workflow state
- Show staleness warnings (>5 min) and stale indicators (>15 min)
- Update help text to document new command
Fixes#233
* Archive investigation for issue #233
* docs: Add /workflow status command to documentation
* refactor: Improve workflow status error handling and code quality
- Extract calculateWorkflowTiming() helper to eliminate code duplication
- Add try-catch around workflow DB queries for graceful degradation
- Define WORKFLOW_SLOW_THRESHOLD_MS and WORKFLOW_STALE_THRESHOLD_MS constants
- Handle invalid date data gracefully (shows "timing unavailable")
- Prevent negative durations with Math.max(0, ...)
- Remove unnecessary String() wrappers in template literals
- Add tests for database error handling and invalid date scenarios
- Add test for /workflow help text including status subcommand
* fix: Add Codex sandbox/network settings and progress logging (#288)
The Codex provider was missing critical configuration options, causing it to:
- Run in read-only sandbox mode (couldn't write files)
- Have no network access (couldn't run gh commands)
- Show no progress during execution (appeared to hang)
This commit adds:
- sandboxMode: 'workspace-write' to allow file operations
- networkAccessEnabled: true to allow network calls (gh, curl)
- approvalPolicy: 'never' to auto-approve operations (like Claude's bypassPermissions)
- Progress logging for item.started and item.completed events
Applied to all three thread creation points:
- resumeThread (line 50-56)
- fallback startThread in catch block (line 63-69)
- new startThread (line 74-80)
Fixes#288
* fix: Address PR review feedback for Codex sandbox/network settings
- Remove stale README warning about Codex read-only mode (issue #288 is now fixed)
- Extract thread options to shared helper function (DRY violation fix)
- Add user notification when session resume fails (no longer silent fallback)
- Consolidate item.completed logging with context (command details included)
- Improve comments to be self-contained (remove unverified default claims)
- Strengthen test assertions for fallback path and progress logging
Codex currently runs in read-only sandbox mode due to missing
sandboxMode and networkAccessEnabled settings in the client.
Until #288 is fixed, Codex can only analyze code but cannot
write files or make network calls.
References #288
* Investigate issue #285: stale workspace causes outdated worktrees
Analyzed root cause and created implementation plan for fixing the
workspace sync issue where new worktrees are created from outdated code
after PRs are merged.
* Fix stale workspace: sync before worktree creation
When a PR is merged, subsequent worktrees were created from outdated
code because the workspace was never synced after the initial clone.
Changes:
- Add syncWorkspace() and getDefaultBranch() helpers in git.ts
- Call syncWorkspaceBeforeCreate() in WorktreeProvider before creating
new worktrees
- Make sync non-fatal to handle offline/permission edge cases gracefully
The sync happens at the natural boundary of starting new work, ensuring
new issues/PRs always start from the latest code without disrupting
existing in-progress worktrees.
Fixes#285
* Address PR review feedback: data safety and test coverage
- Add uncommitted changes check in syncWorkspace() before git reset --hard
to prevent accidental data loss (returns false if changes detected)
- Add logging to getDefaultBranch() fallback paths for better debugging
when symbolic-ref fails and fallback to main/master is used
- Add integration tests verifying sync is called during worktree creation
- Add tests for sync failure scenarios (non-fatal behavior)
- Add test for checkout failure in syncWorkspace()
- Update worktree.ts to handle new boolean return from syncWorkspace()
* simplify: flatten getDefaultBranch fallback logic
Remove verbose logging in getDefaultBranch function. The fallback from
symbolic-ref to checking origin/main to defaulting to master is expected
behavior that doesn't need logging at the info level. Flatten nested
try-catch into sequential blocks for better readability.
* docs: document workspace sync behavior before worktree creation
* Address PR review feedback: error handling and test coverage
- Add logging to empty catch blocks in getDefaultBranch() (critical)
- Add operation context to syncWorkspace() error messages
- Differentiate error severity in syncWorkspaceBeforeCreate():
- Permission errors and corruption logged at ERROR level
- Network/timeout errors logged at WARN level
- Update syncWorkspace JSDoc with reset --hard warning
- Remove redundant inline comment before sync call
- Add tests for:
- Non-standard branch names (develop, trunk)
- Timeout parameter verification
- Operation context in error messages
- Sync skipped when adopting existing worktree
* feat: Use config-based provider selection for workflows
- Workflow executor now uses config.assistant as fallback instead of
hardcoded 'claude' when workflow doesn't specify provider
- Remove provider: claude from all default workflow files so they
inherit from config
- Add assistant: codex to repo config for testing
- Add implementation plan for model validation feature (#281)
This allows users to switch default provider via config without
modifying workflow files. Workflows can still override by specifying
provider explicitly.
* feat: Add logging for resolved provider and model at workflow execution
Log which provider and model is being used at:
- Each workflow step execution
- Each loop workflow iteration
This helps debug config-based provider selection and verify the
correct provider/model combination is being used.
Related to #281
* docs: Document config-based workflow provider inheritance
* refactor: Hoist config loading outside of loops in workflow executor
- Load config once at workflow start instead of on each step/iteration
- Pass resolvedProvider and resolvedModel as parameters to internal functions
- Remove now-unused workflow parameter from executeStepInternal and executeParallelBlock
- Eliminates redundant filesystem reads during workflow execution
* fix: Add provider source tracking and enhanced error context
- Add source tracking to provider log messages (shows "from workflow
definition" vs "from config") for easier debugging
- Wrap getAssistantClient calls with try-catch that provides actionable
error messages pointing users to check their workflow YAML or
.archon/config.yaml assistant setting
Addresses review feedback from PR #283
* Investigate issue #152: GitHub UX - Show repo identifier instead of filesystem path
* Fix: Show repo identifier instead of server filesystem path (#152)
Commands were exposing server's internal filesystem paths (e.g.,
/Users/rasmus/.archon/workspaces/owner/repo) to users, which is a security
concern and provides no value. Users need to know what repo and branch they're
working in, not the server's internal directory structure.
Changes:
- Added formatRepoContext() helper to show "owner/repo @ branch" format
- Updated /status to display "Repository: owner/repo @ branch (worktree)"
- Updated /getcwd to show repo context instead of filesystem path
- Updated /setcwd response to show repo context with fallback to path
- Updated /clone response to remove "Path:" line entirely
- Updated tests to match new output format
Fixes#152
* Archive investigation for issue #152
* Simplify formatRepoContext by extracting getCurrentBranch helper
- Extract git branch lookup into standalone getCurrentBranch() function
- Remove mutable variables (branchName, isWorktree)
- Simplify control flow with early returns
- Reduce JSDoc verbosity (function signature is self-documenting)
- Comment now explains WHY git failures fallback to 'main'
All 84 tests pass. No functional changes.
* docs: Update command output examples to show repo identifier instead of filesystem paths
* Address PR review feedback: improve error handling and simplify code
- Fix duplicate "Repository:" label in /status - now shows "URL:" for repo URL
- Add error logging to getCurrentBranch() when git fails
- Handle detached HEAD state explicitly (shows "detached HEAD" not "HEAD")
- Add try-catch around DB call in formatRepoContext() with logging
- Remove unnecessary isolationDb parameter (uses already-imported module)
- Fix /setcwd fallback to show folder name only, not full filesystem path
- Update tests to match new output format
* Add warning log for orphaned isolation envs and improve test coverage
- Add console.warn() when isolation_env_id exists but DB record not found
- Document no-throw guarantees in getCurrentBranch() and formatRepoContext()
- Add tests for worktree branch lookup and orphaned isolation env fallback
* fix: Auto-detect Claude auth when CLAUDE_USE_GLOBAL_AUTH not set
Previously, if CLAUDE_USE_GLOBAL_AUTH was not explicitly set, the code
defaulted to filtering out auth tokens. This broke backwards compatibility
for users who had explicit tokens in their .env files.
New behavior:
- CLAUDE_USE_GLOBAL_AUTH=true: Filter tokens, use global auth
- CLAUDE_USE_GLOBAL_AUTH=false: Use explicit tokens from env
- Not set: Auto-detect - if tokens exist in env, use them
This ensures existing deployments with tokens in .env continue to work
without requiring configuration changes.
* docs: Document auto-detect behavior for Claude authentication
Updated documentation to reflect the new three-way authentication behavior:
- CLAUDE_USE_GLOBAL_AUTH=true: Use global auth from claude /login
- CLAUDE_USE_GLOBAL_AUTH=false: Use explicit tokens from env
- Not set: Auto-detect (use tokens if present, otherwise global auth)
This ensures users understand the backwards-compatible auto-detect feature
that prevents breaking existing deployments with explicit tokens.
* fix: Add comprehensive logging for Claude auth detection
- Log confirmation for explicit CLAUDE_USE_GLOBAL_AUTH=true/false settings
- Log when auto-detect falls back to global auth (no tokens found)
- Warn about empty string token values (common misconfiguration)
- Warn about unrecognized boolean values (e.g., 'yes', '1')
This makes debugging auth issues straightforward by logging every path.
---------
Co-authored-by: Rasmus Widing <rasmus.widing@gmail.com>
* feat: Auto-copy default commands/workflows on clone
Automatically copy bundled default commands and workflows to newly cloned
repositories. The defaults are stored in `.archon/commands/defaults/` and
`.archon/workflows/defaults/` within the app repository.
These defaults serve dual purpose:
1. They're loaded and usable by this repo itself (recursive loading)
2. They get copied to target repos on `/clone` (flat, not nested)
Key changes:
- Move existing commands/workflows to defaults/ subdirectories
- Add getDefaultCommandsPath/getDefaultWorkflowsPath to archon-paths.ts
- Add defaults.copyDefaults config option (opt-out via config.yaml)
- Create defaults-copy.ts utility for copying files
- Update /clone handler to copy defaults before loading commands
- Update GitHub adapter to copy defaults for new codebases
- Add unit tests for defaults-copy.ts
To opt out: Set `defaults.copyDefaults: false` in target's .archon/config.yaml
Closes#241
* docs: Update documentation for default commands feature
* refactor: Simplify defaults-copy.ts by extracting common copy logic
- Extract duplicated code from copyDefaultCommands and copyDefaultWorkflows
into a single generic copyFiles helper function
- Add directoryExists helper to replace try/catch for access checks
- Define CopyFilesOptions interface for cleaner parameter passing
- Reduce code from 156 to 137 lines while preserving all functionality
* fix: Improve error handling and test coverage for defaults copy
- Add commandsFailed/workflowsFailed to CopyDefaultsResult interface
- Make copyDefaultsToRepo non-fatal in both command-handler and github adapter
- Surface partial failures to users (warning messages)
- Handle mkdir and readdir errors gracefully
- Use specific ENOENT check instead of catching all errors
- Fix template literal number warnings with String()
- Add tests for mkdir failure, combined copy, and empty directory case
* style: Fix ESLint quote errors in defaults-copy.ts
- Reorganize Available Commands into logical categories matching /help output
- Add missing commands: /repo, /repo-remove, /reset-context, /init
- Add complete Worktree commands section (/worktree create/list/remove/cleanup/orphans)
- Add Workflow commands section (/workflow list/reload/cancel)
- Add Global Templates commands (/templates, /template-add, /template-delete)
- Add Workflows documentation in Advanced Configuration
- Update architecture diagram to show Workflow Executor
- Update database schema to include workflow_runs table (6 tables total)
- Update Key Design Patterns to mention workflow engine and worktree isolation
- Update example workflow to be accurate (no commands auto-loaded unless repo has them)
- Change example paths from .claude/commands to .archon/commands (primary location)
- Add note explaining commands are only auto-loaded if repo has .archon/commands/
* fix: Remove Claude credentials from .env.example
Claude Code uses global auth from `claude /login`, not project .env
files. Having tokens in .env.example caused Bun to auto-load them
in worktrees, overriding valid user credentials and causing auth failures.
- Comment out CLAUDE_CODE_OAUTH_TOKEN placeholder
- Comment out CLAUDE_API_KEY placeholder
- Add note explaining why these should not be set
* fix: Add CLAUDE_USE_GLOBAL_AUTH for SDK built-in authentication
Bun auto-loads .env files from the working directory, which caused
issues when worktrees contained CLAUDE_CODE_OAUTH_TOKEN - the invalid
token would override the user's valid global auth from `claude /login`.
Changes:
- Add CLAUDE_USE_GLOBAL_AUTH=true option to bypass credential check
- Update .env.example to use global auth by default (recommended)
- Remove explicit Claude tokens from .env.example template
This allows the Claude Code SDK to use its built-in OAuth authentication
instead of requiring explicit tokens in environment variables.
For Docker/VPS deployments, users can still set CLAUDE_CODE_OAUTH_TOKEN
or ANTHROPIC_API_KEY explicitly via environment variables at runtime.
Related: #227
* chore: Upgrade Claude Agent SDK to 0.2.7
Fixes hanging issue when running Claude Code in worktrees with
settingSources: ["project"]. The previous version (0.1.57/0.1.69)
would hang indefinitely when loading project settings.
* docs: Add CLAUDE_USE_GLOBAL_AUTH to documentation
Update CLAUDE.md and README.md to document the new recommended
authentication method using global auth from `claude /login`.
- CLAUDE.md: Updated Environment Variables section
- README.md: Restructured Claude Code section with 3 options
This addresses the documentation gaps identified in PR review.
* Fix outdated command loading documentation
* feat: Add Ralph-style autonomous iteration loops to workflow engine
Enable workflows to iterate autonomously until a completion signal is
detected (e.g., `<promise>COMPLETE</promise>`) or max iterations reached.
Changes:
- Add LoopConfig type with until signal, max_iterations, fresh_context
- Extend WorkflowDefinition to support loop + prompt (mutually exclusive with steps)
- Add executeLoopWorkflow function with completion signal detection
- Update loader to parse and validate loop configuration
- Add ralph.yaml example workflow demonstrating PRD implementation pattern
- Add 22 new tests covering loop execution and parsing
Loop workflows allow developers to run long-running tasks (like PRD
implementation) without manual phase transitions, following the pattern
popularized by Geoffrey Huntley.
* Add test-loop workflow for Ralph loop testing
* feat: Update worktree config to copy .archon files
- Include all .archon files in worktree copy (not just .archon/ralph)
- Update ralph.yaml with dynamic path detection for feature directories
- Add PR creation step at completion
- Use {prd-dir} variable for flexible path handling
* feat: Add ralph-prd command for generating PRD files
Creates structured PRD files for Ralph autonomous loops:
- Outputs to .archon/ralph/{feature-slug}/ directory
- Generates prd.md (full context) and prd.json (story tracking)
- Feature-based naming to avoid conflicts between projects
- Guides user through requirements gathering phases
* feat: Add ralph-fresh workflow with fresh_context: true
Fresh context mode for Ralph loops where each iteration:
- Starts with a clean slate (no memory of previous iterations)
- Re-reads progress.txt, prd.json, prd.md to understand current state
- Relies on progress.txt "Codebase Patterns" section for learnings
- Better for long loops and avoiding context confusion
* refactor: Rename ralph workflows with explicit descriptions
- Rename ralph.yaml → ralph-stateful.yaml (persistent memory mode)
- Update ralph-fresh.yaml description for clarity
- Both workflows now require explicit invocation
- Clear INVOKE WITH / NOT FOR / HOW IT WORKS / TRADE-OFFS sections
- Neither is "default" - user must choose explicitly
* chore: Set max_iterations to 10 on ralph workflows
* fix: Address PR review feedback for loop workflow
- Wrap database metadata update in try-catch to prevent misleading errors
- Add dropped message tracking and user warning in loop workflow
- Make plain signal detection more restrictive (end of output or own line)
- Add context (line number, preview) to YAML parse errors
- Make max iterations error message actionable with suggestions
- Remove unnecessary type assertions after discriminated union refactor
* chore: Remove unrelated plan files from branch
* Fix: Copy git-ignored files to worktrees (#100)
Worktrees created via the orchestrator now copy git-ignored files (like
.env) based on configuration in .archon/config.yaml. This addresses the
issue where applications fail when running in worktrees due to missing
environment configuration.
Changes:
- Add copyFiles option to RepoConfig.worktree in config-types.ts
- Create worktree-copy.ts utility for parsing config and copying files
- Integrate file copying into WorktreeProvider.createWorktree()
- Add comprehensive tests for new functionality
Configuration example:
```yaml
worktree:
copyFiles:
- .env.example -> .env # Copy and rename
- .env # Copy as-is if exists
- data/fixtures/ # Copy entire directory
```
Fixes#100
* Archive investigation for issue #100
* Fix: Add path traversal protection and improve error handling
- Add isPathWithinRoot() to block path traversal attacks (works on Unix/Windows)
- Add input validation to parseCopyFileEntry() for empty/invalid entries
- Improve error logging with structured data and error codes
- Separate config loading errors from file copy errors
- Use console.error for unexpected errors, console.log for expected skips
- Add 34 new tests for security, validation, and error handling
- 100% test coverage for worktree-copy.ts
* Add worktree copyFiles config for .env files
* Update bot mention from @remote-agent to @Archon
- Update default botMention in GitHubAdapter to 'Archon'
- Update all docs to use @Archon consistently
- Update test cases to use @Archon variations
- The default botName in config is 'Archon', so this aligns the adapter
* Docs: Add worktree app testing instructions to CLAUDE.md
* Add Archon distribution config and directory structure
- Create centralized path resolution in src/utils/archon-paths.ts
- Add YAML configuration system (src/config/) with layered loading
- Update Dockerfile and docker-compose for /.archon/ directory
- Add GHCR publish workflow for multi-arch Docker builds
- Create deploy/ directory with end-user docker-compose
- Add /init command to create .archon structure in repos
- Add docs/configuration.md reference guide
- Update README with Quick Start section
- Add bun run validate script
- Update tests for new path defaults (~/.archon/)
Directory structure:
- Local: ~/.archon/{workspaces,worktrees,config.yaml}
- Docker: /.archon/{workspaces,worktrees}
- Repo: .archon/{commands,workflows,config.yaml}
Legacy WORKSPACE_PATH and WORKTREE_BASE env vars still supported.
* Complete Archon distribution config implementation
- Wire up config system in src/index.ts (Task 3.5)
- Remove legacy WORKSPACE_PATH and WORKTREE_BASE support
- Add logConfig() function to config-loader.ts
- Update docker-compose.yml to use ARCHON_DOCKER env var
- Remove legacy env vars from .env.example
- Update all documentation to reference ARCHON_HOME
- Create scripts/validate-setup.sh for setup validation
- Add setup:check script to package.json
- Create docs/getting-started.md guide
- Create docs/archon-architecture.md technical docs
- Update tests to use ARCHON_HOME instead of legacy vars
- Fix validate.md command template for new paths
All plan phases now complete:
- Phase 1: Archon Directory Structure
- Phase 2: Docker Distribution
- Phase 3: YAML Configuration System
- Phase 4: Developer Experience
- Phase 5: Documentation
* Migrate from Node.js/npm/Jest to Bun runtime
- Replace npm with bun for package management (bun.lock)
- Replace Jest with bun:test for testing
- Update tsconfig for Bun (ESNext module, bundler resolution)
- Update Dockerfile to use oven/bun:1-slim
- Update CI workflow to use oven-sh/setup-bun@v2
- Remove dynamic import hack from codex.ts (direct ESM imports)
- Fix test mocking for Bun (export execFileAsync, use spyOn)
- Update all documentation (CLAUDE.md, README.md, CONTRIBUTING.md)
All 395 tests pass, type-check passes, E2E validated with curl.
* ci: retrigger CI build
* fix: make execFileAsync a function for better Bun mockability
* fix: ensure execFileAsync returns string not Buffer
* fix: rename _execFileAsync to comply with naming convention
* fix: make mkdirAsync mockable for Bun tests
* fix: update engines to bun>=1.0.0 and add mkdirAsync mock
* fix: pin Bun to 1.3.4 in CI to fix mock.module test failures
Newer Bun versions have different mock.module() behavior that causes
cross-test module pollution, resulting in 71 test failures in CI while
tests pass locally. Pinning to 1.3.4 ensures consistent behavior.
* fix: run orchestrator tests last to avoid mock.module pollution
Bun's mock.module() pollutes the global module cache, causing tests to
fail when orchestrator.test.ts (which mocks command-handler and factory)
runs before those modules' own test files.
Fix by running tests in two batches:
1. All tests except orchestrator
2. Orchestrator tests last
This ensures orchestrator's mocks don't affect other test files.
- Add SlackAdapter using @slack/bolt with Socket Mode (no HTTP endpoints needed)
- Implement thread handling mirroring Discord pattern (channel:thread_ts conversation IDs)
- Add Slack URL normalization to strip <url> formatting from messages
- Add user whitelist authorization (SLACK_ALLOWED_USER_IDS)
- Support @mention activation in channels and direct DMs
- Add comprehensive setup guide and update README with Slack section
Updated documentation and configuration to recommend external paths
for WORKSPACE_PATH, preventing repo-inside-repo confusion when
working on this project's issues.
Changes:
- Updated .env.example default to /tmp/remote-agent-workspace
- Added detailed WORKSPACE_PATH guidance to README with warning section
- Updated cloud deployment docs with recommended external path
- Added startup warning when WORKSPACE_PATH is inside project directory
The warning helps developers avoid nested repository issues where
clones end up at paths like:
/remote-coding-agent/workspace/remote-coding-agent
This caused path confusion, git worktree conflicts, and disk duplication.
Fixes#37🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
- Update startup commands to use --profile external-db or --profile with-db
- Add Option C for local development without Docker
- Update troubleshooting section with profile-aware commands
- Document app vs app-with-db service names