Integrate Long-Term Memory with Qoder via Hooks
Overview
AnalyticDB for PostgreSQLLong-Term Memory Hooks is aAnalyticDB for PostgreSQL session lifecycle hook integration solution that provides Qoder AI coding assistant with seamless, persistent memory across sessions.
Qoder Hooks is a session lifecycle hook mechanism. When users perform specific actions in Qoder (sending messages, AI calling tools, exiting sessions), Qoder automatically executes pre-registered scripts to insert custom logic at critical session checkpoints.
Each Hook receives JSON input from Qoder via stdin (containing session ID, working directory, user messages, etc.) and returns JSON output via stdout to influence Qoder's behavior (such as injecting context or blocking dangerous operations).
How It Works
AnalyticDB for PostgreSQLLong-Term Memory useshttpx (Python async HTTP client library) to directly call theLong-Term Memory service REST API.It does not depend on MCP Server. The workflow is as follows:
-
Install Hook scripts: Install via
pip installto register 3 Hook CLI entry points. -
Register with Qoder: Install via
adbpgmem-install-hookscommand to write Hook scripts into~/.qoder/settings.json. -
Automatic triggering: Qoder automatically executes the corresponding Hook scripts at events such as user message submission, before tool calls, and session exit.
-
API calls: Hook scripts call theAnalyticDB for PostgreSQLLong-Term Memory REST API via httpx to perform memory search and save operations.
All operations run silently in the background without affecting normal Qoder usage. Configuration changes take effect immediately without requiring a restart.
Three Hooks
|
Hook |
Event |
Function |
Summary |
|
|
UserPromptSubmit |
Dual-query search for historical memories on the first prompt, injected via additionalContext |
Automatically loads relevant knowledge at the first interaction of each session |
|
|
Stop |
Extracts session summary and saves to memory store |
Automatically saves new knowledge at session end |
|
|
PreToolUse |
Blocks writing to local memory files such as MEMORY.md |
Guards local files, redirects to MCP tools |
Difference from Claude Code: Qoder has stopped triggering the SessionStart event since version 1.106.x and has never supported the PreCompact event. Therefore, Qoder registers only 3 Hooks, and memory context injection uses the UserPromptSubmit event (triggered on the first prompt + session-level throttling).
All Hooks are fault-tolerant: if theLong-Term Memory service is unavailable, Qoder works normally. Sessions are never interrupted due to Hook failures.
Use Cases
Scenarios suitable for Hooks integration:
-
Seamless memory management: Memory is automatically loaded and saved in the background with no manual operations.
-
Automatic loading at session start: Historical architectural decisions and coding preferences are automatically injected with the first message when starting a new session.
-
Automatic saving at session end: Valuable knowledge from the current session is automatically extracted and saved on exit.
-
Prevent local file scattering: Blocks Qoder AI from writing memories to local files such as MEMORY.md, centralizing all memory management in theAnalyticDB for PostgreSQLLong-Term Memory service.
Install Hooks
Prerequisites
-
Qoder IDE or Qoder CLI is installed and functional.
-
Python >= 3.10.
-
Obtained theAnalyticDB for PostgreSQLLong-Term Memory service API URL and token.
-
Obtained the
adbpgmem_mcp_selfhostedproject source codeadbpgmem-mcp-server-0.2.0.tar.gz.Extract the archive to a directory named
adbpgmem_mcp_selfhosted. All paths in the following steps refer to this extracted directory.
Installation
Install the Python package viapip install to register the Hook CLI entry points:
pip install -e /path/to/adbpgmem_mcp_selfhosted
-e (editable) mode links the source code to the current environment, so changes take effect without reinstallation. Suitable for development and debugging. For production deployment, remove the-e flag for standard installation.
After installation, the following Qoder-specific CLI commands will be available:
|
Command |
Description |
|
|
Hook registration tool (multi-platform support) |
|
|
Hook uninstallation tool (multi-platform support) |
Verify installation:
which adbpgmem-qoder-stop
# Should output the installation path, e.g., /usr/local/bin/adbpgmem-qoder-stop
Configure Hooks
ConfigureLong-Term Memory service connection parameters via environment variables or configuration files. Priority from highest to lowest:
|
Priority |
Source |
Description |
|
1 |
Environment variable |
Set via |
|
2 |
|
Environment variable pointing to the configuration file directory. The program looks for |
|
3 |
|
Project-level configuration file |
|
4 |
|
Global configuration file |
Parameters
|
Parameter |
Type |
Required |
Description |
|
|
string |
Yes |
AnalyticDB for PostgreSQLAPI URL of the Long-Term Memory service |
|
|
string |
Yes |
Service authentication token (sensitive) |
|
|
string |
No |
User identifier. Defaults to the system username |
Method 1: Environment Variables
Export environment variables before starting Qoder. Hooks inherit environment variables from the parent process:
export ADBPGMEM_API_URL="https://api-longmemory-cn-chengdu.opentrust.net"
export ADBPGMEM_API_TOKEN="sk-your-token-here"
export ADBPGMEM_USER_ID="your.username"
Environment variables must be re-set each time a new terminal is opened. Add them to~/.zshrc or ~/.bashrc for persistence.
Method 2: Configuration File (Recommended)
Once written, no further action is needed. ADBPGMEM_USER_ID can be omitted (defaults to the system username).
Global configuration (recommended, applies to all projects):
mkdir -p ~/.qoder
cat > ~/.qoder/adbpgmem.conf << 'EOF'
ADBPGMEM_API_URL="https://api-longmemory-cn-chengdu.opentrust.net"
ADBPGMEM_API_TOKEN="sk-your-token-here"
ADBPGMEM_USER_ID="your.username"
EOF
Project-level configuration (applies to the current project only):
mkdir -p .qoder
cat > .qoder/adbpgmem.conf << 'EOF'
ADBPGMEM_API_URL="https://api-longmemory-cn-chengdu.opentrust.net"
ADBPGMEM_API_TOKEN="sk-your-token-here"
ADBPGMEM_USER_ID="your.username"
EOF
adbpgmem.conf contains the API token. Do not commit it to Git. We recommend adding.gitignore to.qoder/adbpgmem.conf. Hooks silently skip execution when the configuration is incomplete, without affecting normal Qoder operation.
Register Hooks
After installation and configuration, register the 3 Hook scripts to Qoder lifecycle events. The installer automatically detects the current platform (you can also specify it manually via--platform qoder).
Global Registration (Recommended)
Writes to ~/.qoder/settings.json, applying to all projects:
# (Optional) Back up existing configuration
cp ~/.qoder/settings.json ~/.qoder/settings.json.bak 2>/dev/null
# Global registration (auto-detect platform)
adbpgmem-install-hooks --global
# Or manually specify Qoder platform
adbpgmem-install-hooks --platform qoder --global
Project-Level Registration
Writes to <project>/.qoder/settings.json, applying only to the current project:
# (Optional) Back up existing configuration
cp .qoder/settings.json .qoder/settings.json.bak 2>/dev/null
# Project-level registration
adbpgmem-install-hooks
# Or manually specify
adbpgmem-install-hooks --platform qoder
Selective Registration by Type
The installer supports selective registration by Hook responsibility group:
# Install only write-type Hooks (stop + pretooluse)
adbpgmem-install-hooks --global --type write
# Install only read-type Hooks (userpromptsubmit)
adbpgmem-install-hooks --global --type read
# Install all (default)
adbpgmem-install-hooks --global --type all
Declarative semantics: Each installation first removes all adbpgmem Hooks under the Qoder platform, then writes the specified group. Switching types does not leave behind old configurations.
After registration, settings.json contains the following Hook configuration:
{
"hooks": {
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-userpromptsubmit", "timeout": 10}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-stop", "timeout": 30}
]
}
],
"PreToolUse": [
{
"matcher": "*",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-pretooluse", "timeout": 2}
]
}
]
}
}
Idempotent installation: Repeatedly running adbpgmem-install-hooks does not produce duplicate entries. It first removes all existing adbpgmem Hooks before re-writing. Immediate effect: Changes apply immediately after the configuration file is edited, without requiring a restart or new session.
Uninstall Hooks
# Auto-detect platform (recommended)
adbpgmem-uninstall-hooks --global # Global uninstall
adbpgmem-uninstall-hooks # Project-level uninstall
# Manually specify platform
adbpgmem-uninstall-hooks --platform qoder --global
# Also clean up session injection marker directory
adbpgmem-uninstall-hooks --global --remove-sessions
The uninstall command removes all adbpgmem-*-prefixed hook entries from the configuration file and cleans up empty event arrays. With the --remove-sessions flag, it also deletes the ~/.qoder/.adbpgmem-injected-sessions/ throttling marker directory.
How to Use Hooks
Verify Registration
# Check if Hooks are registered successfully
cat ~/.qoder/settings.json
# Should contain entries like adbpgmem-qoder-stop
Functional test: Send a message in Qoder and check whether the AI response includes historical memory context.
View Logs
Hook runtime logs are written to ~/.qoder/adbpgmem-hooks.log. View the latest logs for troubleshooting:
tail -50 ~/.qoder/adbpgmem-hooks.log
Invocation
Hooks run fully automatically without any manual operation. Qoder automatically triggers at the following events:
|
Trigger |
Hook Executed |
User Experience |
|
User sends the first message |
|
Qoder AI response already includes historical preferences and architectural decisions |
|
When Qoder AI writes to a file |
|
Blocks writing to local memory files such as MEMORY.md |
|
Exit session |
|
Seamless, extracts and saves session summary in the background |
Detailed Hook Behavior
adbpgmem-qoder-userpromptsubmit (UserPromptSubmit: Memory Context Injection)
Trigger: Each time a user sends a message to Qoder AI. With session-level throttling, memory injection runs only on the first message of each session. Subsequent messages are automatically skipped.
Workflow:
-
Reads JSON input from Qoder (containing
session_id,prompt,cwd, etc.). -
Loads AnalyticDB for PostgreSQLLong-Term Memory configuration.
-
Session-level throttle check: Looks for a marker file named by
~/.qoder/.adbpgmem-injected-sessions/in thesession_iddirectory. If the marker file exists, memory has already been injected in this session, and the process is skipped. -
Executes a dual-query search strategy: Query 1 uses the user's
prompttext to retrieve the most relevant historical memories; Query 2 uses{{project_name}} project architecture tech stackto retrieve project background information. -
Deduplicates the two result sets by
memory_id). -
Formats results as a numbered list and injects them into the Qoder AI session context via the
hookSpecificOutput.additionalContextfield. -
Creates a marker file to prevent duplicate injection in the same session.
Since Qoder stopped triggering the SessionStart event starting from version 1.106.x, memory injection uses the UserPromptSubmit event instead. Session-level throttling ensures injection occurs only once per session, avoiding performance overhead from repeated triggering.
Output Example:
# adbpgmem cross-session memory
1. Project uses Go 1.22 + Gin framework, ORM uses GORM v2
2. Database: PostgreSQL 15, connection pool: PgBouncer, max connections: 50
3. APIs uniformly use RESTful style, error codes follow RFC 7807
adbpgmem-qoder-stop (Stop: Session End Saving)
Trigger: When the user exits a Qoder session.
Workflow:
-
Reads JSON input from Qoder (containing
session_id,cwd,transcript_path, etc.). -
Reads the session transcript file (complete conversation record in JSONL format).
-
Intelligent summary extraction (two-pass processing): First pass collects all user/assistant messages; second pass performs intelligent filtering, keeping the user's last message, filtering out assistant transitional messages (< 100 characters), and selecting the top 5 assistant messages by length (total budget of 6000 characters).
-
If the transcript file is unavailable, falls back to extracting from the
conversation_summaryfield in the stdin JSON. -
Short session filtering: Skips saving when the summary length is < 50 characters.
-
Saves to the AnalyticDB for PostgreSQLLong-Term Memory service with
infer=falseand additional metadata:type=session_summary.
Design Purpose: Automatically saves valuable content from each session without manual user intervention. The content can be retrieved via the UserPromptSubmit Hook in the next session.
adbpgmem-qoder-pretooluse (PreToolUse: Local Memory File Guard)
Trigger: When Qoder AI calls a file writing tool. The matcher is set to * (wildcard) because Qoder supports both native naming and Claude Code-compatible naming for tools.
Workflow:
-
Reads JSON input from Qoder (containing
tool_name,tool_input, etc.). -
Determines whether it is a file writing tool (Write/Edit/SearchReplace).
-
Checks whether the target file path matches the guard pattern:
MEMORY.md,memory.md,.claude/memory/. -
If matched, returns both
decision: "block"andpermissionDecision: "deny"to block the write. -
If not matched, allows the write to proceed normally.
Design Purpose: Prevents Qoder AI from scattering memories into local files, ensuring all memories are centrally stored in adbpgmem for cross-session retrieval and management.
Typical Usage Scenarios
Scenario 1: Automatically Inherit Historical Decisions in New Sessions
You have determined the tech stack for a project and want Qoder AI to automatically know it when starting a new session.
Session 1 (memory saved via MCP tools or other methods):
You: Remember: the project uses Python 3.11 + FastAPI, database PostgreSQL 15, cache Redis 7
Session 2 (new session started days later):
You: Help me add a new API endpoint
← adbpgmem-qoder-userpromptsubmit triggered automatically (first prompt)
← Dual-query searches user prompt and "project_name project architecture tech stack"
← Injects matched memories into additionalContext
← Creates session marker file, subsequent messages no longer trigger
Qoder AI: Based on the project's FastAPI + PostgreSQL 15 tech stack, I'll create the new endpoint...
[Automatically uses the correct framework and database version]
No need to manually inform Qoder AI about the tech stack. Historical memories are automatically injected with the first message.
Scenario 2: Prevent Memory from Scattering to Local Files
Qoder AI attempts to write memories to the local MEMORY.md file during a conversation.
Qoder AI: [Attempts to call the Write tool to write to MEMORY.md]
"Let me record this architectural decision in MEMORY.md..."
← adbpgmem-qoder-pretooluse triggered automatically
← Detected target path matches "MEMORY.md" guard pattern
← Returns decision: "block" + permissionDecision: "deny"
← reason: "Memories should be stored in adbpgmem via the add_memory MCP tool"
Qoder AI: [Received block signal, switches to using add_memory MCP tool]
Architectural decision saved to the adbpgmem memory store.
All memories are centrally stored in adbpgmem, avoiding scattering across local files that would prevent cross-session retrieval.
Scenario 3: Combined MCP + Hooks (Most Complete Solution)
Combine MCP tools and Hooks for the most complete memory capability.
Configuration Steps:
# 1. Install the Python package (required for Hooks)
pip install -e /path/to/adbpgmem_mcp_selfhosted
# 2. Register MCP Server (edit ~/.qoder/settings.json, add mcpServers configuration)
# 3. Register Hooks
adbpgmem-install-hooks --platform qoder --global
# 4. Configure AGENTS.md (guide Qoder AI to proactively use MCP tools)
cat >> AGENTS.md << 'EOF'
# MCP Servers
- **adbpgmem**: Persistent memory service. At the start of each session, use search_memories
to search for relevant context. Use add_memory to save architectural decisions,
debugging experience, and coding patterns. Better to save too much than to miss something.
EOF
Complete ~/.qoder/settings.json example (MCP + Hooks coexistence):
{
"mcpServers": {
"adbpgmem": {
"command": "uvx",
"args": ["--from", "/path/to/adbpgmem_mcp_selfhosted", "adbpgmem-mcp-server"],
"env": {
"ADBPGMEM_API_URL": "https://api-longmemory-cn-chengdu.opentrust.net",
"ADBPGMEM_API_TOKEN": "sk-your-token-here",
"ADBPGMEM_USER_ID": "your.username"
}
}
},
"hooks": {
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-userpromptsubmit", "timeout": 10}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-stop", "timeout": 30}
]
}
],
"PreToolUse": [
{
"matcher": "*",
"hooks": [
{"type": "command", "command": "adbpgmem-qoder-pretooluse", "timeout": 2}
]
}
]
}
}
Combined Usage Benefits:
|
Capability |
Source |
Description |
|
Automatically loads memory on the first message |
Hooks (UserPromptSubmit) |
Automatically injects historical context in the background (session-level throttling) |
|
Automatically saves memory at session end |
Hooks (Stop) |
Automatically extracts and saves session content in the background |
|
Guards local memory files |
Hooks (PreToolUse) |
Blocks writing to MEMORY.md, centralizes management |
|
Manually save precise knowledge |
MCP (add_memory) |
Proactively record important decisions during conversations |
|
Search historical memories on demand |
MCP (search_memories) |
Precisely retrieve historical experience when needed |
|
Memory CRUD management |
MCP (update/delete/list) |
Update, delete, and browse memories |