Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
47baf27
feat: Added login method
kevinwang5658 Jul 16, 2025
78d5dd6
feat: Added connect integration with codify-dashboard
kevinwang5658 Jul 27, 2025
45cb8ca
feat: switched to hono server and added cors support
kevinwang5658 Jul 27, 2025
83bc13f
feat: switched to express
kevinwang5658 Jul 28, 2025
7cb3972
chore: refactored apply flow to use express
kevinwang5658 Jul 29, 2025
4c2759e
Added login helper and trying out parser abstraction
kevinwang5658 Sep 2, 2025
5630319
Added ability to load, apply and plan cloud files
kevinwang5658 Sep 3, 2025
38b2414
Moved login init to base command. Fixes
kevinwang5658 Sep 5, 2025
b73f126
Added new codify file resolution logic. WIP default document endpoint…
kevinwang5658 Sep 5, 2025
aa23381
Added path as an arg to apply and plan
kevinwang5658 Sep 5, 2025
487159f
Added path as an arg to validate
kevinwang5658 Sep 5, 2025
5976346
Fixed import logic to support cloud files
kevinwang5658 Sep 6, 2025
69f8ae1
Fixed login bugs.
kevinwang5658 Sep 12, 2025
f5eddbc
Fixed codify apply via connect to supply tmpFile path. Added helpful …
kevinwang5658 Sep 12, 2025
5289fd3
Switched to socketIO
kevinwang5658 Sep 15, 2025
7faf88f
Switched back to websockets instead of socket io
kevinwang5658 Sep 15, 2025
5984c56
Prevent multiple pty instances from being created
kevinwang5658 Sep 16, 2025
2cf0b95
Improved the command handler to support more variations
kevinwang5658 Sep 16, 2025
e031dfd
Fixed build bugs. Moved uuid to dependency. Fixed entry points that w…
kevinwang5658 Sep 16, 2025
ef61320
Improved session ending logic.
kevinwang5658 Sep 17, 2025
421e152
Added missing import flag
kevinwang5658 Sep 24, 2025
dae7277
Changed connect commands to use rootCommand that way it updates with …
kevinwang5658 Sep 24, 2025
add4147
Refactored how commands are handled. Allows for greater flexibility.
kevinwang5658 Sep 25, 2025
ddf8ba3
Added import handler
kevinwang5658 Sep 25, 2025
90b9578
Added concept of clientId. Added import writer
kevinwang5658 Sep 25, 2025
3643c4a
Re-worked login to get email, userId, claims directly from token. Swi…
kevinwang5658 Oct 1, 2025
ad81e8f
Removed extraneous logs. Added message for codify edit
kevinwang5658 Oct 1, 2025
441d624
Added install beta script. Fixed urls to point to dashboard.codifycli…
kevinwang5658 Oct 2, 2025
904ac3f
Fixed login behavior for connect and edit. Added log out command
kevinwang5658 Oct 2, 2025
aad8e5a
Add new refresh command
kevinwang5658 Oct 21, 2025
26ba958
Changed the parameterless import to mimic init (auto import everything)
kevinwang5658 Oct 21, 2025
a76a640
Added refresh method to connect and fixed bugs
kevinwang5658 Oct 21, 2025
b24f2a9
Fixed API calls to parse error messages as non-json
kevinwang5658 Oct 21, 2025
92bf7b3
Fixed bugs:
kevinwang5658 Oct 22, 2025
cbe9334
Added --updateExisting flag for import command. Made refresh orchestr…
kevinwang5658 Oct 22, 2025
f40e04c
Fixed file modification calculator handling of an empty file '[]'. Ad…
kevinwang5658 Oct 22, 2025
c186cd0
Fixed file modification calculator handling of an empty file '[]'. Ad…
kevinwang5658 Oct 22, 2025
2b5e4fa
fix: Fixed bugs with refresh and import
kevinwang5658 Oct 25, 2025
7604bf2
feat: Added support for Codify remote files
kevinwang5658 Oct 27, 2025
a681d7f
fix: Bug fix for files that don't currently exist. Import confirmatio…
kevinwang5658 Oct 27, 2025
821bef6
fix: Bug fix for MacOS oclif installer bug. It doesn't clear the ocli…
kevinwang5658 Nov 16, 2025
432614a
feat: Added auto complete, additional version flags, additional help …
kevinwang5658 Nov 17, 2025
028766a
fix: Added init command
kevinwang5658 Nov 20, 2025
989cad3
Added new finish event to unify sending the remote result back to the…
kevinwang5658 Nov 21, 2025
2ecee5e
Added the useful ability to kill the previous codify connect so you d…
kevinwang5658 Nov 21, 2025
f48c6ef
fix: Moved kill port to dependencies
kevinwang5658 Nov 22, 2025
5fb7d70
feat: Added connection start time and connection termination
kevinwang5658 Dec 3, 2025
46b3259
feat: Refactored the initialization process to return a resource defi…
kevinwang5658 Dec 13, 2025
6c96b0a
feat: Added sensitive parameter filtering to import and init. Added s…
kevinwang5658 Dec 13, 2025
5d9b8be
feat: Added improvements to import and init saving of results
kevinwang5658 Dec 13, 2025
780ad3e
feat: Improved init experience (always new project for init)
kevinwang5658 Dec 13, 2025
130402a
feat: Fixed build issues and improved help
kevinwang5658 Dec 13, 2025
950c4dd
fix: Fixed existing tests
kevinwang5658 Dec 14, 2025
a2280ee
feat: Added CLI logins without the browser
kevinwang5658 Dec 14, 2025
5584367
feat: Added test for connect + improvements and fixes
kevinwang5658 Dec 14, 2025
5d311dc
feat: Added test for connect commands (apply, plan, import, etc) + im…
kevinwang5658 Dec 14, 2025
4b37f78
feat: Added additional tests for edit, login and refresh
kevinwang5658 Dec 14, 2025
f2bf0e7
feat: Add readme and license
kevinwang5658 Dec 14, 2025
441ab31
feat: Upgrade to node 22
kevinwang5658 Dec 14, 2025
1871937
fix: Test and type fixes
kevinwang5658 Dec 14, 2025
acdeb77
fix: Temp disable socket-server tests
kevinwang5658 Dec 14, 2025
40eae06
fix: Enable one of the disabled tests
kevinwang5658 Dec 14, 2025
93339f3
kevin/fix-tests (#50)
kevinwang5658 Dec 15, 2025
9e4e7cc
Fix: Bug fixes for help, and init using dev-dependency. Added extra c…
kevinwang5658 Dec 19, 2025
1bc02e7
feat: Added new spawn code using node-pty. Root and stdin are both su…
kevinwang5658 Dec 23, 2025
aeb6219
feat: Removed the spinner powered by log messages (caused pointer iss…
kevinwang5658 Dec 23, 2025
26cfda2
feat: Added codify test command that can spawn a tart vm to test codi…
kevinwang5658 Jan 3, 2026
f91cffa
feat: Improved the display for test. Added linux support on a macOS h…
kevinwang5658 Jan 3, 2026
c56b4d7
feat: Added support for validating by OS and distro. Added improved i…
kevinwang5658 Jan 22, 2026
d31a9df
feat: Allow beta plugins to be auto-magically be added when codify ve…
kevinwang5658 Jan 25, 2026
b55db9b
feat: Reverted commenting out xz
kevinwang5658 Jan 25, 2026
50c2d76
feat: Added os filtering for codify init command
kevinwang5658 Jan 30, 2026
749265c
feat: Updated github urls and description
kevinwang5658 Feb 10, 2026
6ece30e
feat: Force arch to be arm64. Added linux to uplaod script.
kevinwang5658 Feb 15, 2026
4ff8152
fix: Fixed sudo, reporters, os filtering, and others (mainly linux re…
kevinwang5658 Feb 22, 2026
b69734e
fix: Connect commands not working on other shells
kevinwang5658 Feb 24, 2026
a68b0ec
fix: Fixed running sudo commands on linux and commands with quotes
kevinwang5658 Feb 24, 2026
bb604b1
chore: switch to public npm @codifycli/ink-form package
kevinwang5658 Feb 24, 2026
2c57de7
fix: Fixed environment variables not carried over to sudo. Fixed bash…
kevinwang5658 Feb 26, 2026
b4cc362
fix: Fixed warnings on linux install. Bumped oclif version.
kevinwang5658 Feb 27, 2026
05f94cb
feat: Updated ink. Switched to dots instead of half circles. Move sle…
kevinwang5658 Mar 3, 2026
2758c84
fix: Fixed weird memory problem with using spinner and status message…
kevinwang5658 Mar 3, 2026
1b085df
feat: Improved coloring for progress display
kevinwang5658 Mar 3, 2026
4508491
fix: Fixed tests
kevinwang5658 Mar 4, 2026
2b4b2d6
chore: commit package-lock.json
kevinwang5658 Mar 4, 2026
cfe7fa6
fix: Linux tests and build errors
kevinwang5658 Mar 4, 2026
920fb9f
feat: Allow CI builds to run on both macOS and linux
kevinwang5658 Mar 4, 2026
6ae774b
feat: Improved test command and added file syncing (#56)
kevinwang5658 Mar 6, 2026
03320ad
feat: Added test to list of remote commands
kevinwang5658 Mar 7, 2026
8decc0a
chore: Updated packages. Switched to @codifycli/schemas
kevinwang5658 Mar 7, 2026
9da6120
chore: Updated package-lock.json
kevinwang5658 Mar 7, 2026
6cadec4
feat: removed login requirement for connect command
kevinwang5658 Mar 7, 2026
fa69e91
fix: Remove github token code in github actions
kevinwang5658 Mar 8, 2026
54c6ef6
chore: Update to @codifycli/plugin-core and update version of @codify…
kevinwang5658 Mar 8, 2026
b3beab5
feat: Updated README
kevinwang5658 Mar 8, 2026
b7f97c9
chore: new package-lock.json
kevinwang5658 Mar 8, 2026
7c26073
feat: Add CLAUDE.md and updated the README.md
kevinwang5658 Mar 8, 2026
90b8e93
fix: Fix bugs with the test command
kevinwang5658 Mar 8, 2026
0a5eb91
chore: update version to 1.0.0
kevinwang5658 Mar 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"unicorn/no-array-for-each": "off",
"unicorn/prefer-object-from-entries": "off",
"unicorn/prefer-type-error": "off",
"unicorn/no-static-only-class": "off",
"@typescript-eslint/no-duplicate-enum-values": "off",
"quotes": [
"error",
"single"
Expand Down
13 changes: 8 additions & 5 deletions .github/workflows/run-unit-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@ on: ['push']

jobs:
build-and-test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest, macos-latest]

steps:
- uses: actions/checkout@v4
- run: echo -e "\n//npm.pkg.github.com/:_authToken=${{ secrets.PACKAGES_PAT_GITHUB }}" >> ./.npmrc
- name: Use Node.js 20
- name: Use Node.js 22
uses: actions/setup-node@v4
with:
node-version: '20.x'
node-version: '22.x'
cache: 'npm'
- run: npm ci
- run: npm test
- run: npm run test
1 change: 0 additions & 1 deletion .npmrc

This file was deleted.

187 changes: 187 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Codify is a configuration-as-code CLI tool that brings Infrastructure-as-Code principles to local development environments. It allows developers to declaratively define their development setup (packages, tools, system settings) in configuration files and apply them in a reproducible way. Think "Terraform for your local machine."

## Development Commands

### Building
```bash
npm run build # Build TypeScript to dist/
npm run lint # Type-check with tsc
```

### Testing
```bash
npm test # Run all tests with Vitest
npm test -- path/to/test # Run specific test file
npm run posttest # Runs lint after tests
```

### Running Locally
```bash
./bin/dev.js <command> # Run CLI in development mode
./bin/dev.js apply # Example: run apply command
```

### Test Command (VM Testing)
The `test` command spins up a Tart VM to test Codify configs in isolation:
```bash
./bin/dev.js test --vm-os darwin # Test on macOS VM
./bin/dev.js test --vm-os linux # Test on Linux VM
```

## High-Level Architecture

### Core Architectural Patterns

1. **Command-Orchestrator Pattern**: Commands (`src/commands/`) are thin oclif wrappers. Orchestrators (`src/orchestrators/`) contain all business logic and workflow coordination. This separation enables reusability.

2. **Multi-Process Plugin System**: The most unique architectural decision is running plugins as separate Node.js child processes communicating via IPC:
- **Why**: Isolation (crashes don't crash CLI), security (parent controls sudo), flexibility
- **Plugin Process** (`src/plugins/plugin-process.ts`): Spawns plugins using `fork()`
- **IPC Protocol** (`src/plugins/plugin-message.ts`): Type-safe message passing
- **Security**: Plugins run isolated; parent process controls all sudo operations
- When plugins need sudo, they send `COMMAND_REQUEST` events back to parent

3. **Event-Driven Architecture**: Central event bus (`src/events/context.ts`) using EventEmitter:
- Tracks process/subprocess lifecycle (PLAN, APPLY, INITIALIZE_PLUGINS, etc.)
- Enables plugin-to-CLI communication (sudo prompts, login credentials, etc.)
- Powers progress tracking for UI

4. **Reporter Pattern**: Abstract `Reporter` interface with multiple implementations selected via `--output` flag:
- `DefaultReporter`: Rich Ink-based TUI with React components
- `PlainReporter`: Simple text output
- `JsonReporter`: Machine-readable JSON
- `DebugReporter`: Verbose logging
- `StubReporter`: No-op for testing

5. **Resource Lifecycle State Machine**:
```
Parse Config → Validate → Resolve Dependencies → Plan → Apply
```
- **ResourceConfig**: Desired state from config file
- **Plan**: Computed difference between desired and current state
- **ResourcePlan**: Per-resource operations (CREATE, UPDATE, DELETE, NOOP)
- **Project**: Container with dependency graph

6. **Dependency Resolution**:
- Explicit: `dependsOn` field in config
- Implicit: Extracted from parameter references (e.g., `${other-resource.param}`)
- Plugin-level: Plugins declare type dependencies (e.g., xcode-tools on macOS)
- Topological sort ensures correct evaluation order (`src/utils/dependency-graph-resolver.ts`)

### Key Directory Structure

- **`/src/orchestrators/`**: Business logic layer - each file implements one CLI command's workflow
- `plan.ts`: Parse → Validate → Resolve deps → Generate plan
- `apply.ts`: Execute plan after user confirmation
- `import.ts`: Import existing resources into config
- `test.ts`: VM-based testing with live config sync via file watcher

- **`/src/plugins/`**: Plugin infrastructure
- `plugin-manager.ts`: Registry routing operations to plugins
- `plugin-process.ts`: Child process lifecycle and IPC
- `plugin.ts`: High-level plugin API

- **`/src/entities/`**: Domain models with rich behavior
- `Project`: Container with dependency resolution
- `ResourceConfig`: Mutable config with dependency tracking
- `Plan`: Immutable plan with sorting/filtering

- **`/src/parser/`**: Multi-format config parsing (JSON, JSONC, JSON5, YAML)
- All parsers maintain source maps for error messages
- Cloud parser fetches from Dashboard API via UUID

- **`/src/ui/`**: User interface layer
- `/reporters/`: Output strategy implementations
- `/components/`: React components for Ink TUI
- `/store/`: Jotai state management for UI

- **`/src/connect/`**: Dashboard integration
- WebSocket server for persistent connection
- OAuth flow handling
- JWT credential management

- **`/src/generators/`**: Config file writers
- Computes diffs for updating existing configs
- Writes to local files or cloud (via Dashboard API)

### Important Data Flows

**Apply Command Flow:**
```
ApplyOrchestrator.run()
→ PlanOrchestrator.run()
→ PluginInitOrchestrator.run()
→ Parse configs → Project
→ PluginManager.initialize() → ResourceDefinitions
→ Project.resolveDependencies()
→ PluginManager.plan() → Plan
→ Reporter.promptConfirmation()
→ PluginManager.apply()
→ For each resource (topologically sorted):
→ Plugin.apply() [IPC to child process]
```

**Plugin Communication Flow:**
```
Parent Process Plugin Process
|-- initialize() -------->|
|<-- resourceDefinitions -|
|-- plan(resource) ------>|
| [Plugin needs sudo]
|<-- COMMAND_REQUEST -----|
|-- prompt user |
|-- COMMAND_GRANTED ----->|
|<-- PlanResponse --------|
```

### Key Architectural Decisions

1. **Single file Projects**: Projects only currently support one file
2. **Cloud-First**: UUIDs are valid "file paths" - enables seamless local/cloud switching
3. **XCode Tools Injection**: On macOS, `xcode-tools` automatically prepended (most resources depend on it)
4. **Test VM Strategy**: Uses Tart VMs with bind mounts (not copying) + file watcher for live config editing
5. **OS Filtering**: Resources specify `os: ["Darwin", "Linux"]` for conditional inclusion
6. **Secure Mode**: `--secure` flag forces sudo prompt for every command (no password caching)

### Common Implementation Patterns

1. **Plugin Resolution**: Local plugins use file paths (`.ts`/`.js`), network plugins use semver versions
2. **Source Maps**: Preserved through entire parse → validate → plan flow for accurate error messages
3. **Event Timing**: Events fire synchronously; use `ctx.once()` carefully to avoid race conditions
4. **Process Cleanup**: Plugins must be killed on exit via `registerKillListeners`
5. **Reporter Lifecycle**: Call `reporter.hide()` before synchronous output to prevent UI corruption

### Testing Patterns

- **Ink Component Tests**: Must polyfill `console.Console` for test environment:
```typescript
import { Console } from 'node:console';
if (!console.Console) {
console.Console = Console;
}
```
- **Plugin Tests**: Use `StubReporter` to avoid UI initialization
- **VM Tests**: `test` command uses Tart VMs with bind mounts for integration testing

## Build & Distribution

- **Framework**: oclif CLI framework with manifest generation
- **Module System**: ES modules with NodeNext resolution
- **Packaging**: `oclif pack tarballs` for multi-platform binaries
- **Updates**: Self-updating via S3 (`@oclif/plugin-update`)
- **Code Signing**: macOS notarization via `scripts/notarize.sh`

## Common Gotchas

1. **Import Paths**: Use `.js` extensions in imports even though files are `.ts` (ES module resolution)
2. **Schema Validation**: Config changes require updating schemas in `@codifycli/schemas` package
3. **Plugin IPC**: Plugins cannot directly read stdin (security isolation)
4. **Sudo Caching**: Password cached in memory during session unless `--secure` flag used
5. **File Watcher**: Use `persistent: false` option to prevent hanging processes
6. **Linting**: ESLint enforces single quotes, specific import ordering, and strict type safety
Loading