- 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.
10 KiB
Claude integration
This document describes how FamiliarOS Desktop integrates with Claude Code, what files are configured, how Claude reaches the desktop app, and which Claude events trigger familiar reactions or speech.
Integration surfaces
Claude support has three related surfaces:
- MCP tools — Claude gets the
familiaros_status,familiaros_react, andfamiliaros_saytools. - Claude memory instructions — Claude is told when it should use those tools.
- Claude hooks — Claude lifecycle and tool events automatically trigger FamiliarOS reactions.
The desktop setup UI for these surfaces is implemented in apps/desktop/src/agent-setup.ts and exposed to the renderer through familiaros:agent-setup-snapshot and familiaros:agent-setup-action.
This document primarily describes Desktop user/global setup. The CLI also supports project-local Claude setup; see Project-local Claude setup.
Files managed by FamiliarOS
Claude MCP entry
The MCP entry is installed into Claude Code by running a Claude command shaped like:
claude mcp add --scope user familiaros -- npx -y @familiaros/mcp
If the user selected a specific familiar in the desktop setup UI, the command includes that familiar:
claude mcp add --scope user familiaros -- npx -y @familiaros/mcp --familiar <petId>
In local development or packaged desktop mode, FamiliarOS can use node <local-or-bundled-entry> instead of npx.
Packaged and local node <entry> commands require node to be available on Claude Code's PATH. Desktop setup reports an error instead of installing a bundled command if node --version cannot run from the agent environment.
Claude memory
FamiliarOS writes two user-level Claude memory files:
~/.claude/CLAUDE.md
~/.claude/familiaros.md
~/.claude/CLAUDE.md receives a managed import block:
<!-- FAMILIAROS:IMPORT:START -->
@~/.claude/familiaros.md
<!-- FAMILIAROS:IMPORT:END -->
~/.claude/familiaros.md receives the managed instruction block:
<!-- FAMILIAROS:START -->
## FamiliarOS
FamiliarOS MCP tools may be available.
Use FamiliarOS as a short visible status channel for meaningful coding progress:
- Use `familiaros_say` when starting, completing, blocking, or needing review on non-trivial work.
- Keep messages brief, user-facing, and non-sensitive.
- Do not include code, logs, secrets, URLs, or file paths.
- Use `familiaros_react` for small visual or emotional feedback.
- Use `familiaros_status` only when checking availability or the targeted familiar.
- Do not spam every internal step.
<!-- FAMILIAROS:END -->
The memory installer is idempotent. It updates only the managed blocks, avoids symlinks and unsafe files, writes private files, and uses atomic temp-file writes.
Claude hooks
Claude hooks are installed into:
~/.claude/settings.json
FamiliarOS-managed hook commands include this marker:
--familiaros-managed
The normal published hook command is:
npx -y @familiaros/claude hook --familiaros-managed
If a familiar is selected:
npx -y @familiaros/claude hook --familiaros-managed --familiar <petId>
FamiliarOS installs the command for these Claude hook events:
UserPromptSubmit
PreToolUse
PermissionRequest
Notification
Stop
StopFailure
Each hook entry is a Claude command hook with a short timeout and async execution enabled:
{
"type": "command",
"command": "npx -y @familiaros/claude hook --familiaros-managed",
"timeout": 3,
"async": true,
"asyncRewake": false
}
FamiliarOS backs up settings.json before changing it and removes only hooks containing the --familiaros-managed marker.
Project-local Claude setup
The @familiaros/cli package can configure a project-local Claude integration from a project directory:
familiaros configure --agent claude --familiar <petId>
Project-local setup differs from Desktop user/global setup:
- It uses
claude mcp add-json familiaros ... --scope localfrom the target project directory. - It writes hooks to
<project>/.claude/settings.local.json. - Hook commands include both
--familiaros-managedand--project-local. - Project-local hook entries use
timeout: 10,async: true, andasyncRewake: false. - The MCP and hooks are always configured with a selected
--familiar <petId>.
When a global FamiliarOS Claude hook runs, it checks whether the current Claude project already has a project-local FamiliarOS hook. If it finds one, the global hook does not send a duplicate reaction. This avoids double familiar events when both global Desktop setup and project-local CLI setup exist.
Project-local files live inside the project and may be committed depending on the user's repository policy. They can contain the selected familiar id.
Runtime path
When Claude calls an FamiliarOS tool or when a Claude hook fires, the runtime path is:
Claude Code
-> @familiaros/mcp or @familiaros/claude hook
-> @familiaros/client
-> FamiliarOS desktop local IPC discovery file
-> FamiliarOS desktop IPC socket/pipe
-> default familiar controller or explicit agent familiar controller
The desktop app writes a discovery file such as:
macOS: ~/Library/Application Support/FamiliarOS/runtime/ipc.json
Windows: %APPDATA%/FamiliarOS/runtime/ipc.json
Linux: $XDG_RUNTIME_DIR/familiaros/ipc.json, or ~/.config/FamiliarOS/runtime/ipc.json fallback
That file contains the IPC endpoint and a per-run token. Clients must send that token with every request.
MCP tools
Claude sees these tools when the MCP server is configured:
| Tool | Purpose | Desktop IPC method |
|---|---|---|
familiaros_status |
Check whether FamiliarOS is reachable and which familiar is targeted. | status |
familiaros_react |
Set a short reaction on the target familiar. | familiar.react |
familiaros_say |
Show a short safe speech bubble, optionally with a reaction. | familiar.say |
familiaros_say is validated before it reaches the desktop app. Messages must be short, single-line, and must not look like code, logs, secrets, URLs, or file paths.
Familiar targeting
If the MCP server or hook command was configured without --familiar, events target the desktop default familiar.
If it was configured with --familiar <petId>, the process asks the desktop app for a lease. A valid installed non-default familiar opens as an explicit agent familiar window. Missing, invalid, broken, built-in, or default familiar requests fall back to the default familiar.
Explicit leases expire after a short TTL unless refreshed. When the last explicit lease for a familiar expires or is released, FamiliarOS clears and closes that agent familiar window.
Claude hook reaction and speech mapping
Claude hooks are decorative and best-effort. They must not block, approve, deny, or change Claude's behavior. If FamiliarOS is closed or IPC is unavailable, the hook exits successfully and silently.
| Claude event | Trigger condition | Reaction | Speech bubble |
|---|---|---|---|
UserPromptSubmit |
User submits a prompt to Claude. | thinking, throttled. |
None. |
PreToolUse |
Tool name is Edit, Write, or MultiEdit. |
editing |
None. |
PreToolUse |
Tool name is Bash and command text looks test-like. |
testing |
None. |
PreToolUse |
Tool name is Bash and command text does not look test-like. |
None. | None. |
PreToolUse |
Any other tool. | None. | None. |
PermissionRequest |
Claude asks for approval. | waiting |
Approval needed, throttled with a short cooldown. |
Notification |
Claude emits a notification hook event. | None. | None. |
Stop |
Claude finishes a response. | success, throttled. |
None. |
StopFailure |
Claude stop/finalization fails. | error |
One error-pool message, throttled. |
| Unknown event | Event is not recognized. | None | None. |
Test-like Bash detection is intentionally coarse and private. It may inspect only a bounded command string to classify the reaction. The command text is never sent to speech.
Claude hooks do not use the left/right walking animations or the running reaction. The running-right and running-left sprite rows are reserved for familiar drag/move motion, and generic Bash/shell activity is silent by default. Hook reactions use quieter phase changes instead: editing maps to the generic active-work row, thinking maps to review, waiting/testing maps to waiting, success maps to jumping, and errors map to failed.
Hook speech pools
When a hook is allowed to speak, it chooses one static local message from the matching pool:
| Category | Possible messages |
|---|---|
thinking |
Thinking it through, Let me check, On it, Working it out |
success |
Done, That worked, All set, Nice, finished |
error |
Something failed, Needs another look, Hit a snag, Not quite there |
permission |
Approval needed |
Speech is throttled by category so hooks do not spam bubbles. Current speech cooldowns are:
| Category | Cooldown |
|---|---|
permission |
3 seconds |
thinking, success, error |
20 seconds each |
Normal thinking and success hooks no longer speak, so their speech pools are retained for shared/static message support but are not used by Claude's default quiet hook policy. Reaction-only hooks are also deduped, with the same reaction suppressed for about 10 seconds.
Throttle state stores only speech-category and reaction timestamp keys, never prompts, commands, tool input, output, code, logs, or transcripts.
Safety rules
- Hook stdout stays empty so Claude does not ingest accidental context.
- Hook errors are swallowed unless debug logging is enabled.
- Hook debug logs sanitize path-like values. MCP/client-side validation separately rejects secret-looking speech.
- Speech is static and local; it does not include model-generated text.
- Tool input and command text are used only for coarse reaction classification.
- Managed setup refuses unsafe symlinks and non-regular files. Claude memory files also have an oversized-file safety limit before FamiliarOS edits them.