- Rename all user-facing and technical identifiers from OpenPets/Pet to FamiliarOS/Familiar. - Rename packages from @open-pets/* to @familiaros/*; rename install-pet/pet-format packages. - Rename plugin IDs and directories from openpets.* to familiaros.*. - Rename IPC namespace from openpets:* to familiaros:* and state filenames from openpets-* to familiaros-* with legacy migration. - Rename source files (pet-window, built-in-pet, default-pet-controller, etc.) to familiar equivalents. - Update locales (en, es-419, ja, ko, pt-BR, zh-Hans, zh-Hant) and tray/pet context menu strings. - Add Familiar naming feature: preference, settings input, tray menu display. - Update assets and packaging config; all desktop tests pass.
7.9 KiB
7.9 KiB
Package: @familiaros/cursor
Responsibility
Pure Node.js package for Cursor editor integration file management. Manages FamiliarOS MCP entries in Cursor's mcp.json configuration files and optional project-local Cursor rules guidance. Provides safe, atomic file operations with validation, backup, and redaction capabilities.
Design/Patterns
Config Path Resolution
- Global config:
<homeDir>/.cursor/mcp.json- user-wide MCP settings - Project config:
<projectDir>/.cursor/mcp.json- project-specific MCP settings - Rules path:
<projectDir>/.cursor/rules/familiaros.mdc- project-local Cursor rules - All APIs accept explicit
configPathfor custom locations
Safety-First File Operations
- Strict JSON only (no JSONC comments)
- Maximum config size: 256 KiB (rules: 64 KiB)
- Reject symlinks at any path level (config file, parent directories, ancestors)
- Reject non-regular files (directories, sockets, etc.)
- Validate parent directories before creating
.cursorfolders - Atomic writes using temp files and atomic rename
- Automatic backup creation before modifications
- Private file permissions (0o600) where supported
Status Classification (MCP & Rules)
missing: No config file or no FamiliarOS entry existsinstalled: Matching FamiliarOS entry present and up-to-dateneeds-update: Old version, different familiar, or content driftconflict: Non-FamiliarOS entry blocking installationinvalid: Parse error, oversized, unsafe path, malformed schemaerror: Unexpected I/O failure
MCP Entry Format
{
"type": "stdio",
"command": "npx",
"args": ["-y", "@familiaros/mcp@VERSION", "--familiar", "PET_ID"]
}
Managed Entry Detection
- Published mode:
npx -y @familiaros/mcp@SEMVER [--familiar PET] - Local mode:
node <absolute-path> [--familiar PET] - Validates semantic versioning and familiar ID format
- Rejects unpinned versions (e.g.,
@latest)
Sensitive Data Redaction
Recursive, case-insensitive redaction of:
- Keys:
env,headers,auth,authorization,token,secret,password,credentials - URL query parameters matching sensitive patterns
- String values containing
token=,api_key=,secret=,password=,auth=
Cursor Rules Management
- Exact whole-file ownership requires recognized frontmatter
- Requires exactly one ordered
FAMILIAROS:CURSOR_RULES:START/ENDmarker pair - Rejects duplicate, reversed, or missing markers
- Rejects user content before/after managed block
- Desktop uses preview/copy only; CLI writes project-local rules
Flow
MCP Installation Flow
- Read existing config via
readCursorMcpConfig(path) - Classify status via
classifyCursorMcpStatus(result, path, expected) - Plan operation via
planCursorMcpInstall(path, options, allowReplace?) - Execute write via
executeCursorMcpWrite(plan) - Atomic write creates temp file, backs up existing, renames to target
MCP Replacement Flow
- Read and classify existing config
- Verify status is
needs-update,conflict, orinstalled - Plan replace via
planCursorMcpReplace(path, options) - Execute preserves unrelated MCP servers and top-level fields
MCP Removal Flow
- Read and classify existing config
- Verify entry is managed by FamiliarOS (not conflict)
- Plan remove via
planCursorMcpRemove(path) - Execute removes only
mcpServers.familiaros, preserves other servers - Empty
mcpServerskept as{}after removal
Rules Installation Flow
- Read existing rules via
readCursorFamiliarOSRules(projectDir) - Classify status via
classifyCursorRulesStatus(result, path, expected?) - Plan via
planCursorRulesInstall(projectDir, allowReplace?) - Execute via
executeCursorRulesWrite(plan) - Managed content includes frontmatter + START/END markers
Preview/Redaction Flow
- Build preview via
buildFamiliarOSOnlyPreview(options) - Redact sensitive config via
redactCursorConfig(config) - Safe for logging and UI display
Integration
Entry Points
src/index.ts: Public API exports (re-exports all modules)src/cursor-mcp.ts: MCP entry builders and path utilitiessrc/cursor-status.ts: Status classification and config read/write operationssrc/cursor-previews.ts: Config preview and redaction helperssrc/cursor-rules.ts: Project-local Cursor rules preview/status/write/remove helperssrc/check-cursor.ts: Contract validation tests (runs vianpm test)
Exported APIs
From cursor-mcp.ts:
buildCursorMcpEntry(options): Build MCP entry objectformatCursorMcpConfig(options): Build full config with familiaros entrygetCursorGlobalMcpPath(homeDir): Get global config pathgetCursorProjectMcpPath(projectDir): Get project config pathvalidateFamiliarOSPetId(id): Validate and return familiar IDisValidPetId(id): Check if familiar ID is valid
From cursor-status.ts:
classifyCursorMcpStatus(result, path, expected): Classify config statusreadCursorMcpConfig(path): Read and validate config fileplanCursorMcpInstall(path, options, allowReplace?): Plan install operationplanCursorMcpReplace(path, options): Plan replace operationplanCursorMcpRemove(path): Plan remove operationexecuteCursorMcpWrite(plan): Execute planned write atomicallyisManagedFamiliarOSMcpEntry(value): Check if entry is FamiliarOS-managedmaxCursorConfigBytes: 256 KiB limit constant
From cursor-previews.ts:
buildFamiliarOSOnlyPreview(options): Build FamiliarOS-only previewredactCursorConfig(config): Redact sensitive fields from config
From cursor-rules.ts:
getCursorProjectRulesPath(projectDir): Get project rules pathbuildCursorFamiliarOSRule(): Build managed Cursor rules contentbuildCursorRulesPreview(): Build copyable rules previewreadCursorFamiliarOSRules(projectDir): Safely read managed rules fileclassifyCursorRulesStatus(result, path, expected?): Classify rules statusplanCursorRulesInstall(projectDir, allowReplace?): Plan project rules install/updateplanCursorRulesReplace(projectDir): Plan explicit replacementplanCursorRulesRemove(projectDir): Plan managed rules removalexecuteCursorRulesWrite(plan): Execute rules write/remove atomicallyisManagedCursorFamiliarOSRule(content): Check managed marker/frontmatter shapemaxCursorRulesBytes: 64 KiB limit constant
Package Scripts
npm test: Run contract validation tests (node dist/check-cursor.js)npm run check: Full typecheck + build + test pipelinenpm run typecheck: TypeScript type checking onlynpm run build: Compile TypeScript todist/
Downstream Consumers
- Desktop app: Uses preview/redaction APIs for UI display
- CLI tools: Uses planning/execution APIs for install/remove operations
- Both use status classification to determine available actions
Test Coverage
check-cursor.ts validates:
- Familiar ID validation (valid/invalid patterns, length limits)
- MCP entry building (published/local modes, version validation)
- Config formatting and path helpers
- All status classifications (missing, empty, installed, needs-update, conflict, invalid)
- Parse errors, oversized files, symlink rejection
- Non-object schema rejection (top-level, mcpServers, entries)
- Backup creation and atomic write behavior
- Uninstall preserves unrelated entries and top-level fields
- No writes on invalid/error status
- No conflict write without explicit replace
- Explicit replace preserves unrelated servers/fields
- Recursive and case-insensitive redaction
- URL token parameter redaction
- Symlink parent/ancestor rejection
- Empty mcpServers preservation after remove
- Cursor project rules generation and path resolution
- Rules missing/installed/needs-update/conflict classification
- Rules duplicate/reversed/missing marker handling
- Rules frontmatter conflict detection
- Rules symlink parent/file, dangling symlink, non-regular, oversized rejection
- Rules backup, atomic write, replace, remove, and no-write invalid behavior