Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
86 changes: 86 additions & 0 deletions iflow-cli/.iflow/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"$schema": "https://platform.iflow.cn/schemas/settings.json",
"mcpServers": {
"claude-mem": {
"command": "node",
"args": ["~/.iflow/mcp/mcp-server.cjs"],
"env": {
"CLAUDE_MEM_DATA_DIR": "~/.claude-mem/data"
}
}
},
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "node ~/.iflow/hooks/claude-mem/bun-runner.cjs ~/.iflow/hooks/claude-mem/worker-service.cjs start",
"timeout": 60
},
{
"type": "command",
"command": "node ~/.iflow/hooks/claude-mem/bun-runner.cjs ~/.iflow/hooks/claude-mem/worker-service.cjs hook iflow-cli context",
"timeout": 60
}
]
},
{
"matcher": "clear|compact",
"hooks": [
{
"type": "command",
"command": "node ~/.iflow/hooks/claude-mem/bun-runner.cjs ~/.iflow/hooks/claude-mem/worker-service.cjs start",
"timeout": 60
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "node ~/.iflow/hooks/claude-mem/bun-runner.cjs ~/.iflow/hooks/claude-mem/worker-service.cjs hook iflow-cli session-init",
"timeout": 30
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|MultiEdit|Write|write_file|replace|run_shell_command",
"hooks": [
{
"type": "command",
"command": "node ~/.iflow/hooks/claude-mem/bun-runner.cjs ~/.iflow/hooks/claude-mem/worker-service.cjs hook iflow-cli observation",
"timeout": 60
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "node ~/.iflow/hooks/claude-mem/bun-runner.cjs ~/.iflow/hooks/claude-mem/worker-service.cjs hook iflow-cli summarize",
"timeout": 120
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "node ~/.iflow/hooks/claude-mem/bun-runner.cjs ~/.iflow/hooks/claude-mem/worker-service.cjs hook iflow-cli session-complete",
"timeout": 30
}
]
}
]
}
}
10 changes: 10 additions & 0 deletions iflow-cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Claude-Mem iFlow CLI Integration

## 安装

```bash
curl -fsSL https://raw.githubusercontent.com/thedotmack/claude-mem/main/iflow-cli/install.sh | bash
iflow
```

与 Claude Code 版本共享 worker 和数据。
252 changes: 252 additions & 0 deletions iflow-cli/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
#!/bin/bash
#
# Claude-Mem iFlow CLI Installation Script
# Integrates claude-mem into iFlow CLI
#

set -e

# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Default configuration
IFLOW_CONFIG_DIR="${HOME}/.iflow"
CLAUDE_MEM_ROOT="${HOME}/.claude-mem"
WORKER_PORT="${CLAUDE_MEM_WORKER_PORT:-37777}"

echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Claude-Mem for iFlow CLI Installer ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""

# Check dependencies
check_dependencies() {
echo -e "${YELLOW}Checking dependencies...${NC}"

if ! command -v node &> /dev/null; then
echo -e "${RED}Error: Node.js is not installed${NC}"
echo "Please install Node.js 18+ from https://nodejs.org"
exit 1
fi
echo -e "${GREEN}✓ Node.js: $(node --version)${NC}"

if command -v bun &> /dev/null; then
echo -e "${GREEN}✓ Bun: $(bun --version)${NC}"
else
echo -e "${YELLOW}⚠ Bun not installed (optional, needed for worker)${NC}"
fi
Comment on lines +38 to +67

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require Bun before reporting install success

The dependency check treats Bun as optional, but install_iflow_integration writes hook commands that always execute bun-runner (for example the commands added in this same script), so environments without Bun will complete installation and then fail every hook invocation, effectively disabling memory capture. This should fail fast (or install Bun) instead of proceeding as a successful setup.

Useful? React with 👍 / 👎.

}

# Check/clone claude-mem
setup_claude_mem() {
echo ""
echo -e "${YELLOW}Setting up claude-mem...${NC}"

if [ -d "${CLAUDE_MEM_ROOT}" ]; then
echo -e "${GREEN}✓ claude-mem already exists at ${CLAUDE_MEM_ROOT}${NC}"
read -p "Update existing installation? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
cd "${CLAUDE_MEM_ROOT}"
git pull
npm install
npm run build
fi
else
echo "Cloning claude-mem..."
git clone https://github.com/thedotmack/claude-mem.git "${CLAUDE_MEM_ROOT}"
cd "${CLAUDE_MEM_ROOT}"
npm install
npm run build
fi
}

# Install iFlow CLI integration files using symlinks
install_iflow_integration() {
echo ""
echo -e "${YELLOW}Installing iFlow CLI integration...${NC}"

# Create directories
mkdir -p "${IFLOW_CONFIG_DIR}/hooks/claude-mem"
mkdir -p "${IFLOW_CONFIG_DIR}/skills"
mkdir -p "${IFLOW_CONFIG_DIR}/mcp"

# Create symlinks for worker scripts (needed by hooks)
ln -sf "${CLAUDE_MEM_ROOT}/plugin/scripts/bun-runner.js" "${IFLOW_CONFIG_DIR}/hooks/claude-mem/bun-runner.cjs"
ln -sf "${CLAUDE_MEM_ROOT}/plugin/scripts/worker-service.cjs" "${IFLOW_CONFIG_DIR}/hooks/claude-mem/worker-service.cjs"
echo -e "${GREEN}✓ Created symlinks for worker scripts${NC}"

# Create symlinks for MCP server
ln -sf "${CLAUDE_MEM_ROOT}/plugin/scripts/mcp-server.cjs" "${IFLOW_CONFIG_DIR}/mcp/mcp-server.cjs"
echo -e "${GREEN}✓ Created symlinks for MCP server${NC}"

# Create symlinks for skills (link to main plugin skills)
for skill in mem-search smart-explore; do
rm -rf "${IFLOW_CONFIG_DIR}/skills/${skill}" 2>/dev/null || true
ln -s "${CLAUDE_MEM_ROOT}/plugin/skills/${skill}" "${IFLOW_CONFIG_DIR}/skills/${skill}"
done
echo -e "${GREEN}✓ Created symlinks for skills${NC}"

# Update settings.json
IFLOW_SETTINGS="${IFLOW_CONFIG_DIR}/settings.json"

if [ ! -f "${IFLOW_SETTINGS}" ]; then
mkdir -p "${IFLOW_CONFIG_DIR}"
echo '{}' > "${IFLOW_SETTINGS}"
fi

# Use node to merge JSON configuration
node -e "
const fs = require('fs');
const settings = JSON.parse(fs.readFileSync('${IFLOW_SETTINGS}', 'utf8'));

// Add hooks configuration
settings.hooks = settings.hooks || {};
settings.hooks.SessionStart = settings.hooks.SessionStart || [];
settings.hooks.UserPromptSubmit = settings.hooks.UserPromptSubmit || [];
settings.hooks.PostToolUse = settings.hooks.PostToolUse || [];
settings.hooks.Stop = settings.hooks.Stop || [];
settings.hooks.SessionEnd = settings.hooks.SessionEnd || [];

const hooksDir = '${IFLOW_CONFIG_DIR}/hooks/claude-mem';

// Check if claude-mem hooks already exist
const hasClaudeMemHooks = settings.hooks.SessionStart.some(h =>
JSON.stringify(h).includes('claude-mem') || JSON.stringify(h).includes('worker-service')
);

if (!hasClaudeMemHooks) {
// SessionStart: startup - start worker + inject context
settings.hooks.SessionStart.push({
matcher: 'startup',
hooks: [
{ type: 'command', command: 'node ' + hooksDir + '/bun-runner.cjs ' + hooksDir + '/worker-service.cjs start', timeout: 60 },
{ type: 'command', command: 'node ' + hooksDir + '/bun-runner.cjs ' + hooksDir + '/worker-service.cjs hook iflow-cli context', timeout: 60 }
]
});

// SessionStart: clear/compact - start worker only
settings.hooks.SessionStart.push({
matcher: 'clear|compact',
hooks: [
{ type: 'command', command: 'node ' + hooksDir + '/bun-runner.cjs ' + hooksDir + '/worker-service.cjs start', timeout: 60 }
]
});

// UserPromptSubmit: session init
settings.hooks.UserPromptSubmit.push({
hooks: [
{ type: 'command', command: 'node ' + hooksDir + '/bun-runner.cjs ' + hooksDir + '/worker-service.cjs hook iflow-cli session-init', timeout: 30 }
]
});

// PostToolUse: observation capture
settings.hooks.PostToolUse.push({
matcher: 'Edit|MultiEdit|Write|write_file|replace|run_shell_command',
hooks: [
{ type: 'command', command: 'node ' + hooksDir + '/bun-runner.cjs ' + hooksDir + '/worker-service.cjs hook iflow-cli observation', timeout: 60 }
]
});

// Stop: summarize
settings.hooks.Stop.push({
hooks: [
{ type: 'command', command: 'node ' + hooksDir + '/bun-runner.cjs ' + hooksDir + '/worker-service.cjs hook iflow-cli summarize', timeout: 120 }
]
});

// SessionEnd: cleanup
settings.hooks.SessionEnd.push({
hooks: [
{ type: 'command', command: 'node ' + hooksDir + '/bun-runner.cjs ' + hooksDir + '/worker-service.cjs hook iflow-cli session-complete', timeout: 30 }
]
});
}

// Add MCP server
settings.mcpServers = settings.mcpServers || {};
settings.mcpServers['claude-mem'] = {
command: 'node',
args: ['${IFLOW_CONFIG_DIR}/mcp/mcp-server.cjs'],
env: { CLAUDE_MEM_DATA_DIR: '${HOME}/.claude-mem/data' }
};

fs.writeFileSync('${IFLOW_SETTINGS}', JSON.stringify(settings, null, 2));
console.log('✓ Updated settings.json');
"

echo -e "${GREEN}✓ Installed iFlow CLI integration${NC}"
}

# Start worker
start_worker() {
echo ""
echo -e "${YELLOW}Starting claude-mem worker...${NC}"

cd "${CLAUDE_MEM_ROOT}"

# Check if worker is already running
if curl -s "http://localhost:${WORKER_PORT}/api/health" > /dev/null 2>&1; then
echo -e "${GREEN}✓ Worker already running on port ${WORKER_PORT}${NC}"
else
# Start worker (background)
nohup node plugin/scripts/worker-service.cjs start > /dev/null 2>&1 &

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Launch worker via bun-runner instead of node

In the auto-start path, the installer launches the worker with node plugin/scripts/worker-service.cjs start, but this worker script depends on Bun runtime modules, so the command exits immediately and the installer can never actually start the worker when it is not already running. Reusing the bun-runner invocation used by the hook configuration would make the startup step functional.

Useful? React with 👍 / 👎.

sleep 2

if curl -s "http://localhost:${WORKER_PORT}/api/health" > /dev/null 2>&1; then
echo -e "${GREEN}✓ Worker started on port ${WORKER_PORT}${NC}"
else
echo -e "${YELLOW}⚠ Worker may need manual start${NC}"
echo " Run: cd ${CLAUDE_MEM_ROOT} && npm run worker:start"
fi
fi
}

# Display completion information
show_completion() {
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ Installation Complete! ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════╝${NC}"
echo ""
echo "Claude-mem is now integrated with iFlow CLI!"
echo ""
echo -e "${BLUE}Features enabled:${NC}"
echo " ✓ Context injection on session start"
echo " ✓ Session tracking initialization"
echo " ✓ Automatic observation capture"
echo " ✓ Session summarization"
echo " ✓ Session state saving"
echo ""
echo -e "${BLUE}Available skills:${NC}"
echo " @mem-search <query> - Search historical memories"
echo " @smart-explore - Smart code exploration"
echo ""
echo -e "${BLUE}Next steps:${NC}"
echo " 1. Restart iFlow CLI: iflow"
echo " 2. Start working - memories will be captured automatically"
echo " 3. Use @mem-search to find past work"
echo ""
echo -e "${BLUE}Configuration:${NC}"
echo " Settings: ${IFLOW_CONFIG_DIR}/settings.json"
echo " Hooks: ${IFLOW_CONFIG_DIR}/hooks/claude-mem/"
echo " Skills: ${IFLOW_CONFIG_DIR}/skills/"
echo " Data: ${HOME}/.claude-mem/data/"
echo " Web UI: http://localhost:${WORKER_PORT}"
echo ""
}

# Main flow
main() {
check_dependencies
setup_claude_mem
install_iflow_integration
start_worker
show_completion
}

main "$@"