Feature-marker platform-detection
Centralized tech-stack detection engine. Identifies iOS, Node.js, Rust, Python, Go from project files. Run once at workflow start; result is cached in platform-context.json.
git clone https://github.com/Viniciuscarvalho/Feature-marker
T=$(mktemp -d) && git clone --depth=1 https://github.com/Viniciuscarvalho/Feature-marker "$T" && mkdir -p ~/.claude/skills && cp -r "$T/feature-marker-dist/feature-marker/resources/spec-workflow/skills/platform-detection" ~/.claude/skills/viniciuscarvalho-feature-marker-platform-detection && rm -rf "$T"
feature-marker-dist/feature-marker/resources/spec-workflow/skills/platform-detection/SKILL.mdPlatform Detection Engine
Runs once at the start of any feature-marker workflow and caches the result. All subsequent phases read from the cached
platform-context.json — never re-detect.
When to run
- First time: Phase 0 (Inputs Gate) if
does not exist in state dirplatform-context.json - Skip: If
already exists — use the cached resultplatform-context.json - Force re-detect: If user passes
or deletes the file manually--redetect
Detection logic
Scan the project root for the following signals, in priority order:
🍎 iOS / Swift
Detected when ANY of:
found (up to 3 levels deep)*.xcodeproj
found (up to 3 levels deep)*.xcworkspace
found in rootPackage.swift
Subtype disambiguation:
→ CocoaPods/multi-target workspacexcworkspace
→ single Xcode projectxcodeproj
→ Swift Package Manager (Package.swift, no .xcodeproj)swift-package
iOS confirmation (vs macOS/watchOS):
in anyIPHONEOS_DEPLOYMENT_TARGET.pbxproj
in anyUIRequiredDeviceCapabilitiesInfo.plist
Test framework detection:
- Any
with*Tests.swift
→import Testingswift-testing - Only
in test files →import XCTestxctest - No test files → default to
swift-testing
Tool availability checks:
→command -v swiftlintcapabilities.swiftlint_available
exists →~/.claude/skills/xcodebuildmcp/SKILL.mdcapabilities.xcodebuildmcp_available
🟨 Node.js / TypeScript
Detected when:
package.json exists in root
Package manager detection from lockfiles:
→pnpm-lock.yamlpnpm
→yarn.lockyarn
→bun.lockbbun
or none →package-lock.jsonnpm
Subtype:
→next.config.{js,ts,mjs}nextjs
inreact-native
deps →package.jsonreact-native
→nest-cli.jsonnestjs- else →
node
Test runner:
orjest.config.{js,ts}
in"jest"
→package.jsonjest
orvitest.config.{ts,js}
in"vitest"
→package.jsonvitest- else →
{pm} test
🦀 Rust
Detected when:
Cargo.toml exists in root
🐍 Python
Detected when ANY of:
pyproject.toml, setup.py, requirements.txt
🐹 Go
Detected when:
go.mod exists in root
Multi-stack / Monorepo
If signals from 2+ platforms detected → set
is_monorepo: true.
Map each detected platform to its sub-directory when possible.
Manual override
Check
.feature-marker.json for manual platform override:
{ "platform": "ios" }
If present, use that as
primary_platform (overrides auto-detection).
Output: platform-context.json
Save to
.claude/feature-state/{slug}/platform-context.json:
{ "primary_platform": "ios", "platforms": [ { "type": "ios", "subtype": "swift-package", "path": ".", "confidence": "high", "signals": ["Package.swift found", ".swift files present (47)", "IPHONEOS_DEPLOYMENT_TARGET detected"], "test_command": "swift test --parallel", "build_command": "xcodebuild build", "lint_command": "swiftlint", "test_framework": "swift-testing", "capabilities": { "swiftlint_available": true, "xcodebuildmcp_available": true, "swift_testing_available": true } } ], "is_monorepo": false, "detected_at": "2026-03-01T12:00:00Z" }
Node.js example:
{ "primary_platform": "nodejs", "platforms": [ { "type": "nodejs", "subtype": "nextjs", "path": ".", "confidence": "high", "signals": ["package.json found", "next.config found", "pnpm-lock.yaml found"], "package_manager": "pnpm", "package_manager_lock": "pnpm-lock.yaml", "test_command": "jest --findRelatedTests", "build_command": "pnpm run build", "lint_command": "pnpm run lint" } ], "is_monorepo": false, "detected_at": "2026-03-01T12:00:00Z" }
Confidence scoring
| Score | Signals |
|---|---|
| 3+ platform-specific signals |
| 2 signals |
| 1 signal (config file only) |
User output
After detection, always display:
✅ Platform detected: iOS (Swift Package) — swift test + SwiftLint + XcodeBuildMCP
Or for Node.js:
✅ Platform detected: Node.js / Next.js (pnpm) — jest + pnpm run lint
If unknown:
⚠️ Platform not detected. No known config files found. Running without platform-specific commands. Use .feature-marker.json to override.
Usage by other phases
| Phase | What it reads |
|---|---|
| Context Gathering | to adjust file scan patterns |
| idea-explorer | to frame questions in context of stack |
| spec-writer | , for validation sections |
| TechSpec Validation | to validate import paths format |
| Per-Task Execution | , , per task |
| Test Only mode | Full platform entry to route to correct test framework |
| commit.md | + for pre-commit hooks |