Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions plugins/persistent-identity/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "persistent-identity",
"version": "1.0.0",
"description": "Gives Claude Code a persistent name and per-project memory that carries across sessions",
"author": {
"name": "Hrishikesh S",
"email": "hrish2006@gmail.com"
}
}
54 changes: 54 additions & 0 deletions plugins/persistent-identity/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Persistent Identity Plugin

Gives your Claude Code instance a persistent name and per-project memory that carries across sessions.

## Features

- **Persistent Name**: Auto-generated on first run (e.g., "swift-fox", "keen-owl"), consistent across all projects
- **Per-Project Memory**: Claude remembers important context, decisions, and preferences for each project between sessions
- **Natural Identity**: Claude uses its name naturally in conversation without being repetitive

## How It Works

On every session start, the plugin:
1. Reads (or creates) your instance's identity from `~/.claude/persistent-identity/identity.md`
2. Loads per-project memory from `~/.claude/persistent-identity/projects/<hash>/memory.md`
3. Injects identity and memory into the session context

Claude will naturally maintain its memory file by writing important observations as it works with you.

## Commands

### `/name [new-name]`

View or change your Claude instance's name.

- `/name` -- show current name
- `/name marvin` -- rename to "marvin"

Name requirements: 2-30 characters, letters/numbers/hyphens, must start with a letter.

## Data Storage

All data lives in `~/.claude/persistent-identity/`:

```
~/.claude/persistent-identity/
├── identity.md # Your instance's name
└── projects/
└── <project-hash>/
├── project-info.txt # Maps hash to project path
└── memory.md # Per-project memory
```

## Uninstallation

1. Remove the plugin from your Claude Code configuration
2. Optionally delete `~/.claude/persistent-identity/` to remove all identity and memory data

## Notes

- Memory files are markdown and can be manually edited
- The plugin adds ~400-600 tokens of context per session (plus the size of your memory file)
- Names are auto-generated from 1,600 adjective-noun combinations
- The identity is global (same name across all projects); memory is per-project
16 changes: 16 additions & 0 deletions plugins/persistent-identity/commands/name.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
description: View or change your Claude Code instance's name
argument-hint: [new-name]
allowed-tools:
- Bash
---

Run the rename script with the provided arguments:

```bash
bash "${CLAUDE_PLUGIN_ROOT}/scripts/rename-identity.sh" $ARGUMENTS
```

After running:
- If the user provided a name, confirm the rename and note it takes effect next session
- If no name was provided, show them their current identity
25 changes: 25 additions & 0 deletions plugins/persistent-identity/data/wordlists.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Word lists for identity name generation
# Names are generated as adjective-noun pairs (e.g., "swift-fox", "keen-owl")

ADJECTIVES=(
swift keen bold calm bright
quick sharp clear steady warm
agile lucid vivid prime sage
nimble astute deft adept brisk
noble gentle fierce ardent grand
witty clever subtle poised stoic
serene fluid lithe vibrant crisp
staunch placid earnest candid apt
)

NOUNS=(
fox owl hawk bear wolf
lynx heron crane raven falcon
otter cedar birch willow oak
aspen maple spruce cypress elm
lark finch wren robin dove
pike flint ridge brook vale
summit harbor reef crest glade
beacon forge nexus pulse spark
)
112 changes: 112 additions & 0 deletions plugins/persistent-identity/hooks-handlers/session-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/usr/bin/env bash
set -euo pipefail

# --- Configuration ---
IDENTITY_DIR="$HOME/.claude/persistent-identity"
IDENTITY_FILE="$IDENTITY_DIR/identity.md"
PROJECTS_DIR="$IDENTITY_DIR/projects"

# --- Source word lists ---
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_ROOT="$(dirname "$SCRIPT_DIR")"
source "$PLUGIN_ROOT/data/wordlists.sh"

# --- Ensure directory structure exists ---
mkdir -p "$IDENTITY_DIR"

# --- Read or create identity ---
if [[ -f "$IDENTITY_FILE" ]]; then
IDENTITY_NAME=$(head -1 "$IDENTITY_FILE" | sed 's/^# //')
else
# Generate random adjective-noun name
ADJ_INDEX=$((RANDOM % ${#ADJECTIVES[@]}))
NOUN_INDEX=$((RANDOM % ${#NOUNS[@]}))
IDENTITY_NAME="${ADJECTIVES[$ADJ_INDEX]}-${NOUNS[$NOUN_INDEX]}"

cat > "$IDENTITY_FILE" << EOF
# ${IDENTITY_NAME}

Created: $(date -u +%Y-%m-%dT%H:%M:%SZ)

This is the persistent identity for this Claude Code installation.
Use /name to change your name.
EOF
fi

# --- Determine project and load memory ---
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"

if command -v shasum &>/dev/null; then
PROJECT_HASH=$(echo -n "$PROJECT_DIR" | shasum -a 256 | cut -c1-16)
else
PROJECT_HASH=$(echo -n "$PROJECT_DIR" | sha256sum | cut -c1-16)
fi

PROJECT_MEMORY_DIR="$PROJECTS_DIR/$PROJECT_HASH"
MEMORY_FILE="$PROJECT_MEMORY_DIR/memory.md"

mkdir -p "$PROJECT_MEMORY_DIR"

# Write project info for reverse lookup
echo "$PROJECT_DIR" > "$PROJECT_MEMORY_DIR/project-info.txt"

# --- Read memory if it exists ---
MEMORY_CONTENT=""
if [[ -f "$MEMORY_FILE" ]] && [[ -s "$MEMORY_FILE" ]]; then
MEMORY_CONTENT=$(cat "$MEMORY_FILE")
fi

# --- Build additionalContext ---
if [[ -n "$MEMORY_CONTENT" ]]; then
MEMORY_SECTION="## Your Memory for This Project

The following are your notes from previous sessions in this project. Use them to maintain continuity.

${MEMORY_CONTENT}

---"
else
MEMORY_SECTION="## Your Memory for This Project

You have no saved memories for this project yet. As you work, save important observations, decisions, and context to your memory file."
fi

CONTEXT="## Your Identity

You are **${IDENTITY_NAME}**. This is your persistent name across all sessions and projects. When greeting the user or referring to yourself, use this name naturally -- for example in your initial greeting or when asked who you are. Do not announce your name on every message.

${MEMORY_SECTION}

## Memory Management

You have a persistent memory file for this project at:
\`${MEMORY_FILE}\`

Write to this file when you learn something important that should persist across sessions:
- Key architectural decisions and their rationale
- User preferences for this project (coding style, conventions, preferred tools)
- Important context about the codebase that took effort to discover
- Recurring issues or patterns
- Your relationship with the user -- things they've shared, how they like to work

Keep your memory file organized with markdown headers. Update it incrementally -- append new sections or update existing ones. Keep entries concise and actionable.

Only write to your memory file when you have genuinely useful information to persist. Quality over quantity."

# --- JSON-escape and output ---
if command -v jq &>/dev/null; then
ESCAPED_CONTEXT=$(echo "$CONTEXT" | jq -Rs .)
else
ESCAPED_CONTEXT=$(echo "$CONTEXT" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
fi

cat << EOF
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": ${ESCAPED_CONTEXT}
}
}
EOF

exit 0
16 changes: 16 additions & 0 deletions plugins/persistent-identity/hooks/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"description": "Persistent identity and memory injection at session start",
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks-handlers/session-start.sh",
"timeout": 10
}
]
}
]
}
}
62 changes: 62 additions & 0 deletions plugins/persistent-identity/scripts/rename-identity.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail

IDENTITY_DIR="$HOME/.claude/persistent-identity"
IDENTITY_FILE="$IDENTITY_DIR/identity.md"

# --- No argument: show current name ---
if [[ $# -eq 0 ]] || [[ -z "${1:-}" ]]; then
if [[ -f "$IDENTITY_FILE" ]]; then
CURRENT_NAME=$(head -1 "$IDENTITY_FILE" | sed 's/^# //')
echo "Current identity: ${CURRENT_NAME}"
echo ""
echo "To rename, use: /name <new-name>"
echo "Example: /name swift-fox"
else
echo "No identity set yet. Start a new session to auto-generate one,"
echo "or use: /name <new-name>"
fi
exit 0
fi

NEW_NAME="$1"

# --- Validate name format ---
if [[ ! "$NEW_NAME" =~ ^[a-zA-Z][a-zA-Z0-9-]*[a-zA-Z0-9]$ ]] || [[ ${#NEW_NAME} -lt 2 ]] || [[ ${#NEW_NAME} -gt 30 ]]; then
echo "Error: Invalid name '${NEW_NAME}'" >&2
echo "" >&2
echo "Name requirements:" >&2
echo " - 2-30 characters" >&2
echo " - Letters, numbers, and hyphens only" >&2
echo " - Must start with a letter" >&2
echo " - Must not end with a hyphen" >&2
exit 1
fi

# --- Read old name ---
OLD_NAME=""
if [[ -f "$IDENTITY_FILE" ]]; then
OLD_NAME=$(head -1 "$IDENTITY_FILE" | sed 's/^# //')
fi

# --- Update identity file ---
mkdir -p "$IDENTITY_DIR"

cat > "$IDENTITY_FILE" << EOF
# ${NEW_NAME}

Created: $(date -u +%Y-%m-%dT%H:%M:%SZ)
Renamed from: ${OLD_NAME:-"(first name)"}

This is the persistent identity for this Claude Code installation.
Use /name to change your name.
EOF

# --- Report ---
if [[ -n "$OLD_NAME" ]]; then
echo "Renamed from '${OLD_NAME}' to '${NEW_NAME}'"
else
echo "Identity set to '${NEW_NAME}'"
fi
echo ""
echo "The new name will appear in your greeting on the next session."