
Apex Decompose
- 4 installs
- 2 repo stars
- Updated March 14, 2026
- othmanadi/apex
Analyze legacy code and extract feature behavior, contracts, and edge cases into migration-ready specification documents.
About
Decomposes features from an existing codebase into implementation-ready specification documents for migration or replatforming. A developer uses it to analyze legacy code and capture its behavior before rewriting it in a new architecture.
- Builds a dependency graph and documents inputs, outputs, and side effects
- Extracts implicit knowledge like magic values, ordering, and feature flags into a spec
Apex Decompose by the numbers
- 4 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,241 of 1,879 Documentation skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/othmanadi/apex --skill apex-decomposeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 4 |
|---|---|
| repo stars | ★ 2 |
| Last updated | March 14, 2026 |
| Repository | othmanadi/apex ↗ |
What it does
Analyze legacy code and extract feature behavior, contracts, and edge cases into migration-ready specification documents.
Files
APEX Decompose
Break down features from a source codebase into detailed, implementation-ready specifications that an agent can use to rebuild them in a new architecture.
When to Use
Use this skill when you need to understand what existing code does before rewriting it. This is the first step in any replatforming or migration workflow. The output is a specification document, not code.
Workflow
Decomposing a feature involves these steps:
1. Identify the feature scope (files, modules, entry points) 2. Analyze behavior and contracts (inputs, outputs, side effects) 3. Extract implicit knowledge (edge cases, error handling, config dependencies) 4. Generate the specification document 5. Validate the spec against the source
Step 1: Identify Feature Scope
Collect all relevant source files. Ask the user or scan the directory:
What feature or module do you want to decompose?
Provide the path(s) to the relevant source files or directories.Read every file in the scope. Build a dependency graph: which files import which, what external services are called, what state is mutated.
Run the dependency scanner to accelerate this step:
Linux/Mac:
bash "${CLAUDE_SKILL_DIR}/scripts/scan-deps.sh" <source-dir>Windows:
powershell -File "${CLAUDE_SKILL_DIR}/scripts/scan-deps.ps1" <source-dir>Step 2: Analyze Behavior and Contracts
For each function, class, or module in scope, document:
| Aspect | What to Capture |
|---|---|
| Inputs | Parameters, environment variables, config values, request shapes |
| Outputs | Return values, response shapes, files written, events emitted |
| Side effects | Database writes, API calls, cache mutations, logging |
| Error handling | Try/catch patterns, error codes, fallback behavior |
| Dependencies | Internal imports, external packages, services called |
Step 3: Extract Implicit Knowledge
This is the critical step most migrations miss. Look for:
- Magic values — hardcoded strings, numbers, or thresholds with no documentation
- Ordering dependencies — operations that must happen in a specific sequence
- Race conditions — concurrent access patterns or timing-sensitive logic
- Feature flags — conditional behavior based on config or environment
- Undocumented APIs — internal endpoints or contracts between services
Step 4: Generate the Specification
Write the spec to specs/{feature-name}.md using the template in references/spec-template.md.
Step 5: Validate the Spec
Cross-reference the spec against the source code. For each behavior documented, confirm it matches the actual implementation. Flag any ambiguities with [VERIFY] tags for human review.
Output
The final deliverable is a Markdown specification file in specs/ that another agent (or apex-replatform) can consume to implement the feature in a new architecture without needing access to the original source code.
Example output location: specs/user-authentication.md
# Feature: User Authentication
## Overview
Handles user login, session management, and token refresh for the web application.
## Behavior Contract
### Inputs
| Name | Type | Source | Required |
|------|------|--------|----------|
| email | string | request.body | yes |
| password | string | request.body | yes |
### Outputs
| Name | Type | Destination |
|------|------|-------------|
| accessToken | JWT | response.json |
| refreshToken | string | httpOnly cookie |
### Side Effects
1. Creates session record in `sessions` table
2. Emits `user.logged_in` event
## Edge Cases
1. **Invalid credentials** — Returns 401 with generic message
2. **Account locked** — Returns 403 after 5 failed attempts
## Migration Notes
- [VERIFY] Confirm bcrypt rounds (currently 12)Feature: {Feature Name}
Overview
One paragraph describing what this feature does from the user's perspective.
Source Files
path/to/file1.ts— Role in the featurepath/to/file2.ts— Role in the feature
Behavior Contract
Inputs
| Name | Type | Source | Required | Description |
|---|---|---|---|---|
| param1 | string | request.body | yes | Description |
Outputs
| Name | Type | Destination | Description |
|---|---|---|---|
| result | object | response.json | Description |
Side Effects
1. Writes to table_name in database when condition X 2. Emits event event_name on success 3. Calls external-service/endpoint with payload Y
Edge Cases
1. When input is empty — Returns 400 with message "..." 2. When service is down — Retries 3 times, then falls back to cached value 3. When concurrent requests — Uses optimistic locking on field Z
Dependencies
| Dependency | Type | Version | Purpose |
|---|---|---|---|
| package-x | npm | ^2.0.0 | Used for Y |
| service-z | API | v3 | Called during Z |
Configuration
| Key | Default | Description |
|---|---|---|
| FEATURE_FLAG_X | false | Enables experimental behavior |
| TIMEOUT_MS | 5000 | Request timeout |
Migration Notes
- [VERIFY] Confirm whether the retry logic is still needed in the new architecture
- The hardcoded value
42on line 87 of file.ts is the max batch size from a 2023 incident - Order of operations in
processQueue()is critical — step 2 must complete before step 3
# APEX Decompose — Dependency Scanner (Windows)
# Scans a source directory and outputs a dependency report.
# Usage: powershell -File scan-deps.ps1 <source-dir>
param(
[Parameter(Position=0)]
[string]$SourceDir = "."
)
$ErrorActionPreference = "Stop"
if (-not (Test-Path $SourceDir -PathType Container)) {
Write-Error "ERROR: Directory '$SourceDir' does not exist."
exit 1
}
Write-Host "=== APEX Dependency Scan ==="
Write-Host "Source: $SourceDir"
Write-Host "Date: $((Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))"
Write-Host ""
# Detect project type
Write-Host "--- Project Detection ---"
$packageJson = Join-Path $SourceDir "package.json"
$requirementsTxt = Join-Path $SourceDir "requirements.txt"
$pyprojectToml = Join-Path $SourceDir "pyproject.toml"
$goMod = Join-Path $SourceDir "go.mod"
$cargoToml = Join-Path $SourceDir "Cargo.toml"
if (Test-Path $packageJson) {
Write-Host "Type: Node.js / JavaScript / TypeScript"
$pm = if (Test-Path (Join-Path $SourceDir "pnpm-lock.yaml")) { "pnpm" }
elseif (Test-Path (Join-Path $SourceDir "yarn.lock")) { "yarn" }
else { "npm" }
Write-Host "Package Manager: $pm"
Write-Host ""
Write-Host "--- Dependencies (package.json) ---"
try {
$pkg = Get-Content $packageJson -Raw | ConvertFrom-Json
if ($pkg.dependencies) {
$pkg.dependencies.PSObject.Properties | ForEach-Object {
Write-Host " $($_.Name): $($_.Value)"
}
}
Write-Host ""
Write-Host "--- Dev Dependencies ---"
if ($pkg.devDependencies) {
$pkg.devDependencies.PSObject.Properties | ForEach-Object {
Write-Host " $($_.Name): $($_.Value)"
}
}
} catch {
Write-Host " (could not parse)"
}
} elseif ((Test-Path $requirementsTxt) -or (Test-Path $pyprojectToml)) {
Write-Host "Type: Python"
Write-Host ""
Write-Host "--- Dependencies ---"
if (Test-Path $requirementsTxt) { Get-Content $requirementsTxt }
if (Test-Path $pyprojectToml) { Get-Content $pyprojectToml }
} elseif (Test-Path $goMod) {
Write-Host "Type: Go"
Write-Host ""
Write-Host "--- Dependencies (go.mod) ---"
Get-Content $goMod
} elseif (Test-Path $cargoToml) {
Write-Host "Type: Rust"
Write-Host ""
Write-Host "--- Dependencies (Cargo.toml) ---"
Get-Content $cargoToml
} else {
Write-Host "Type: Unknown (no recognized package manifest found)"
}
Write-Host ""
Write-Host "--- File Structure ---"
Get-ChildItem -Path $SourceDir -Recurse -File |
Where-Object {
$_.FullName -notmatch "node_modules|\.git|dist|build|__pycache__|target" -and
$_.Name -notmatch "\.lock$|package-lock\.json$"
} |
Select-Object -First 200 |
Sort-Object FullName |
ForEach-Object { $_.FullName.Replace($SourceDir, ".") }
Write-Host ""
Write-Host "--- Import/Require Analysis ---"
# JavaScript/TypeScript imports
$jsFiles = Get-ChildItem -Path $SourceDir -Recurse -Include "*.ts","*.tsx","*.js","*.jsx" -File |
Where-Object { $_.FullName -notmatch "node_modules" }
foreach ($file in ($jsFiles | Select-Object -First 50)) {
$imports = Select-String -Path $file.FullName -Pattern "^import|^const.*require\(" -ErrorAction SilentlyContinue
if ($imports) { $imports | Select-Object -First 5 | ForEach-Object { Write-Host $_.ToString() } }
}
# Python imports
$pyFiles = Get-ChildItem -Path $SourceDir -Recurse -Include "*.py" -File |
Where-Object { $_.FullName -notmatch "__pycache__" }
foreach ($file in ($pyFiles | Select-Object -First 50)) {
$imports = Select-String -Path $file.FullName -Pattern "^import|^from.*import" -ErrorAction SilentlyContinue
if ($imports) { $imports | Select-Object -First 5 | ForEach-Object { Write-Host $_.ToString() } }
}
Write-Host ""
Write-Host "=== Scan Complete ==="
#!/usr/bin/env bash
# APEX Decompose — Dependency Scanner (Linux/Mac)
# Scans a source directory and outputs a dependency report.
# Usage: bash scan-deps.sh <source-dir>
set -euo pipefail
SOURCE_DIR="${1:-.}"
if [ ! -d "$SOURCE_DIR" ]; then
echo "ERROR: Directory '$SOURCE_DIR' does not exist."
exit 1
fi
echo "=== APEX Dependency Scan ==="
echo "Source: $SOURCE_DIR"
echo "Date: $(date -u +"%Y-%m-%dT%H:%M:%SZ")"
echo ""
# Detect project type
echo "--- Project Detection ---"
if [ -f "$SOURCE_DIR/package.json" ]; then
echo "Type: Node.js / JavaScript / TypeScript"
echo "Package Manager: $([ -f "$SOURCE_DIR/pnpm-lock.yaml" ] && echo "pnpm" || ([ -f "$SOURCE_DIR/yarn.lock" ] && echo "yarn" || echo "npm"))"
echo ""
echo "--- Dependencies (package.json) ---"
if command -v jq &>/dev/null; then
jq -r '.dependencies // {} | to_entries[] | " \(.key): \(.value)"' "$SOURCE_DIR/package.json" 2>/dev/null || echo " (could not parse)"
echo ""
echo "--- Dev Dependencies ---"
jq -r '.devDependencies // {} | to_entries[] | " \(.key): \(.value)"' "$SOURCE_DIR/package.json" 2>/dev/null || echo " (could not parse)"
else
cat "$SOURCE_DIR/package.json"
fi
elif [ -f "$SOURCE_DIR/requirements.txt" ] || [ -f "$SOURCE_DIR/pyproject.toml" ]; then
echo "Type: Python"
echo ""
echo "--- Dependencies ---"
[ -f "$SOURCE_DIR/requirements.txt" ] && cat "$SOURCE_DIR/requirements.txt"
[ -f "$SOURCE_DIR/pyproject.toml" ] && grep -A 50 '\[project.dependencies\]' "$SOURCE_DIR/pyproject.toml" 2>/dev/null || true
elif [ -f "$SOURCE_DIR/go.mod" ]; then
echo "Type: Go"
echo ""
echo "--- Dependencies (go.mod) ---"
cat "$SOURCE_DIR/go.mod"
elif [ -f "$SOURCE_DIR/Cargo.toml" ]; then
echo "Type: Rust"
echo ""
echo "--- Dependencies (Cargo.toml) ---"
grep -A 100 '\[dependencies\]' "$SOURCE_DIR/Cargo.toml" 2>/dev/null || cat "$SOURCE_DIR/Cargo.toml"
else
echo "Type: Unknown (no recognized package manifest found)"
fi
echo ""
echo "--- File Structure ---"
find "$SOURCE_DIR" -type f \
-not -path "*/node_modules/*" \
-not -path "*/.git/*" \
-not -path "*/dist/*" \
-not -path "*/build/*" \
-not -path "*/__pycache__/*" \
-not -path "*/target/*" \
-not -name "*.lock" \
-not -name "package-lock.json" \
| head -200 \
| sort
echo ""
echo "--- Import/Require Analysis ---"
# JavaScript/TypeScript imports
JS_IMPORTS=$(grep -rn "^import\|^const.*require(" "$SOURCE_DIR" \
--include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" \
2>/dev/null | grep -v node_modules | head -100)
# Python imports
PY_IMPORTS=$(grep -rn "^import\|^from.*import" "$SOURCE_DIR" \
--include="*.py" \
2>/dev/null | grep -v __pycache__ | head -100)
# Go imports
GO_IMPORTS=$(grep -rn "\".*\"" "$SOURCE_DIR" \
--include="*.go" \
2>/dev/null | grep -v vendor | head -100)
[ -n "$JS_IMPORTS" ] && echo "$JS_IMPORTS"
[ -n "$PY_IMPORTS" ] && echo "$PY_IMPORTS"
[ -n "$GO_IMPORTS" ] && echo "$GO_IMPORTS"
echo ""
echo "=== Scan Complete ==="