> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/QwenLM/qwen-code/llms.txt
> Use this file to discover all available pages before exploring further.

# Memory System

> Persistent context and facts across sessions

# Memory System

Qwen Code's memory system allows the AI to remember important facts, preferences, and context across sessions, providing personalized and context-aware assistance.

## Overview

The memory system consists of:

* **Global Memory**: User-level facts shared across all projects (`~/.qwen/QWEN.md`)
* **Project Memory**: Project-specific context (`.qwen/QWEN.md` or `QWEN.md` in project root)
* **Hierarchical Loading**: Automatic discovery from workspace root to current directory
* **Import System**: Include external files and organize memory content

## Memory Files

### File Locations

From `packages/core/src/tools/memoryTool.ts:77`:

```typescript theme={null}
export const QWEN_CONFIG_DIR = '.qwen';
export const DEFAULT_CONTEXT_FILENAME = 'QWEN.md';
export const AGENT_CONTEXT_FILENAME = 'AGENTS.md';
export const MEMORY_SECTION_HEADER = '## Qwen Added Memories';
```

**Global memory**:

```bash theme={null}
~/.qwen/QWEN.md
~/.qwen/AGENTS.md
```

**Project memory**:

```bash theme={null}
/path/to/project/QWEN.md
/path/to/project/.qwen/QWEN.md
/path/to/project/AGENTS.md
```

### File Format

Memory files are Markdown documents with optional structure:

```markdown theme={null}
# Project Context

This is a Next.js application using TypeScript and Tailwind CSS.

## Architecture

- Frontend: React components in `src/components/`
- Backend: API routes in `src/pages/api/`
- Database: PostgreSQL with Prisma ORM

## Qwen Added Memories

- User prefers functional components over class components
- Always use `const` instead of `let` when possible
- API endpoints should return JSON with snake_case keys
- Tests use Vitest instead of Jest
```

## Memory Tool

The `save_memory` tool allows Qwen Code to store facts for future reference.

### Tool Schema

From `memoryTool.ts:31`:

```typescript theme={null}
interface SaveMemoryParams {
  fact: string;                // Required: The fact to remember
  scope?: 'global' | 'project'; // Optional: Where to save
  modified_by_user?: boolean;   // Internal: User edited content
  modified_content?: string;    // Internal: Modified content
}
```

### Usage Examples

#### Save to Global Memory

```typescript theme={null}
{
  fact: "User prefers TypeScript for new projects",
  scope: "global"
}
```

This appends to `~/.qwen/QWEN.md`:

```markdown theme={null}
## Qwen Added Memories
- User prefers TypeScript for new projects
```

#### Save to Project Memory

```typescript theme={null}
{
  fact: "API uses OAuth2 with client credentials flow",
  scope: "project"
}
```

This appends to project's `QWEN.md`:

```markdown theme={null}
## Qwen Added Memories
- API uses OAuth2 with client credentials flow
```

#### Interactive Scope Selection

If `scope` is omitted, user is prompted to choose:

```typescript theme={null}
{ fact: "Database credentials in 1Password vault" }
```

User sees:

```
Choose where to save this memory:

"Database credentials in 1Password vault"

Options:
- Global: ~/.qwen/QWEN.md (shared across all projects)
- Project: /path/to/project/QWEN.md (current project only)
```

### Tool Behavior

From `memoryTool.ts:165`:

```typescript theme={null}
/**
 * Computes the new content that would result from adding a memory entry
 */
function computeNewContent(currentContent: string, fact: string): string {
  let processedText = fact.trim();
  processedText = processedText.replace(/^(-+\s*)+/, '').trim();
  const newMemoryItem = `- ${processedText}`;

  const headerIndex = currentContent.indexOf(MEMORY_SECTION_HEADER);

  if (headerIndex === -1) {
    // Header not found, append header and then the entry
    const separator = ensureNewlineSeparation(currentContent);
    return (
      currentContent +
      `${separator}${MEMORY_SECTION_HEADER}\n${newMemoryItem}\n`
    );
  } else {
    // Header found, append to section
    const startOfSectionContent = headerIndex + MEMORY_SECTION_HEADER.length;
    let endOfSectionIndex = currentContent.indexOf(
      '\n## ',
      startOfSectionContent,
    );
    if (endOfSectionIndex === -1) {
      endOfSectionIndex = currentContent.length;
    }

    const beforeSectionMarker = currentContent
      .substring(0, startOfSectionContent)
      .trimEnd();
    let sectionContent = currentContent
      .substring(startOfSectionContent, endOfSectionIndex)
      .trimEnd();
    const afterSectionMarker = currentContent.substring(endOfSectionIndex);

    sectionContent += `\n${newMemoryItem}`;
    return (
      `${beforeSectionMarker}\n${sectionContent.trimStart()}\n${afterSectionMarker}`.trimEnd() +
      '\n'
    );
  }
}
```

Key behaviors:

* Creates `## Qwen Added Memories` section if it doesn't exist
* Appends new facts as bullet points
* Strips leading dashes from fact text
* Maintains proper spacing

## Hierarchical Memory Loading

Qwen Code automatically discovers and loads memory files in a hierarchical manner.

### Discovery Process

From `packages/core/src/utils/memoryDiscovery.ts:24`:

```typescript theme={null}
async function findProjectRoot(startDir: string): Promise<string | null> {
  let currentDir = path.resolve(startDir);
  while (true) {
    const gitPath = path.join(currentDir, '.git');
    try {
      const stats = await fs.lstat(gitPath);
      if (stats.isDirectory()) {
        return currentDir;
      }
    } catch (error) {
      // Continue searching upward
    }
    const parentDir = path.dirname(currentDir);
    if (parentDir === currentDir) {
      return null; // Reached root
    }
    currentDir = parentDir;
  }
}
```

### Load Order

From `memoryDiscovery.ts:68`:

```typescript theme={null}
export async function getGeminiMdFilePathsInternal(
  currentWorkingDirectory: string,
  includeDirectoriesToReadGemini: readonly string[],
  userHomePath: string,
  fileService: FileDiscoveryService,
  extensionContextFilePaths: string[] = [],
  folderTrust: boolean,
): Promise<string[]> {
  const dirs = new Set<string>([
    ...includeDirectoriesToReadGemini,
    currentWorkingDirectory,
  ]);
  
  // Process directories in parallel with concurrency limit
  const CONCURRENT_LIMIT = 10;
  // ...
}
```

Memory files are loaded in this order:

1. **Global memory** (`~/.qwen/QWEN.md`)
2. **Project root** (found via `.git` directory)
3. **Intermediate directories** (between project root and current directory)
4. **Current directory**
5. **Extension context files** (if any)

Example for `/home/user/projects/myapp/src/components/`:

```
~/.qwen/QWEN.md                           # Global
/home/user/projects/myapp/QWEN.md         # Project root
/home/user/projects/myapp/src/QWEN.md     # Subdirectory
/home/user/projects/myapp/src/components/QWEN.md  # Current dir
```

### Content Concatenation

From `memoryDiscovery.ts:282`:

```typescript theme={null}
function concatenateInstructions(
  instructionContents: GeminiFileContent[],
  currentWorkingDirectoryForDisplay: string,
): string {
  return instructionContents
    .filter((item) => typeof item.content === 'string')
    .map((item) => {
      const trimmedContent = (item.content as string).trim();
      if (trimmedContent.length === 0) {
        return null;
      }
      const displayPath = path.isAbsolute(item.filePath)
        ? path.relative(currentWorkingDirectoryForDisplay, item.filePath)
        : item.filePath;
      return `--- Context from: ${displayPath} ---\n${trimmedContent}\n--- End of Context from: ${displayPath} ---`;
    })
    .filter((block): block is string => block !== null)
    .join('\n\n');
}
```

Final memory content:

```markdown theme={null}
--- Context from: ../.qwen/QWEN.md ---
# Global Context
- User works with TypeScript
--- End of Context from: ../.qwen/QWEN.md ---

--- Context from: QWEN.md ---
# Project Context
- Next.js application
--- End of Context from: QWEN.md ---

--- Context from: src/QWEN.md ---
# Source Directory
- Components use Tailwind
--- End of Context from: src/QWEN.md ---
```

## Import System

Memory files support importing other files.

### Import Syntax

From `packages/core/src/utils/memoryImportProcessor.ts`:

```markdown theme={null}
<!-- @import: path/to/file.md -->
<!-- @import: ../docs/api-guide.md -->
<!-- @import: ~/.config/coding-standards.md -->
```

### Import Formats

**Tree Format** (default):

```markdown theme={null}
<imported from="docs/setup.md">
# Setup Guide
...
</imported>
```

**Flat Format**:

```markdown theme={null}
# Setup Guide
...
```

Configuration:

```typescript theme={null}
import { loadServerHierarchicalMemory } from '@qwen-code/qwen-code-core';

const { memoryContent } = await loadServerHierarchicalMemory(
  cwd,
  includeDirs,
  fileService,
  extensionContextFilePaths,
  folderTrust,
  'tree'  // or 'flat'
);
```

### Recursive Imports

Imports can be nested:

```markdown theme={null}
<!-- File: QWEN.md -->
# Project Context

<!-- @import: docs/architecture.md -->

<!-- File: docs/architecture.md -->
# Architecture

<!-- @import: api/endpoints.md -->

<!-- File: api/endpoints.md -->
# API Endpoints
...
```

## Configuration

### Custom Filenames

From `memoryTool.ts:90`:

```typescript theme={null}
export function setGeminiMdFilename(newFilename: string | string[]): void {
  if (Array.isArray(newFilename)) {
    if (newFilename.length > 0) {
      currentGeminiMdFilename = newFilename.map((name) => name.trim());
    }
  } else if (newFilename && newFilename.trim() !== '') {
    currentGeminiMdFilename = newFilename.trim();
  }
}
```

Usage:

```typescript theme={null}
import { setGeminiMdFilename } from '@qwen-code/qwen-code-core';

// Single filename
setGeminiMdFilename('CONTEXT.md');

// Multiple filenames (checked in order)
setGeminiMdFilename(['QWEN.md', 'AGENTS.md', 'CONTEXT.md']);
```

### Folder Trust

Memory loading respects folder trust settings:

```typescript theme={null}
const { memoryContent } = await loadServerHierarchicalMemory(
  cwd,
  includeDirs,
  fileService,
  extensionContextFilePaths,
  folderTrust: true  // Enable workspace scanning
);
```

When `folderTrust` is `false`, only global memory and explicitly included directories are loaded.

## Best Practices

### When to Use Global vs Project Memory

**Global Memory** (`~/.qwen/QWEN.md`):

* Personal preferences and coding style
* Tool configurations
* Common patterns across all projects
* Credential locations (not the credentials themselves!)

Example:

```markdown theme={null}
## Qwen Added Memories
- User prefers functional programming style
- Always use `const` instead of `let` when possible
- Database credentials stored in 1Password
- Prefer explicit error handling over try-catch
```

**Project Memory** (project's `QWEN.md`):

* Project architecture and structure
* Technology stack and versions
* Build and deployment processes
* Team conventions
* API endpoints and schemas

Example:

```markdown theme={null}
## Project Context

Next.js 14 application with App Router.

### Architecture
- `/app`: Next.js App Router pages
- `/components`: Reusable React components
- `/lib`: Utility functions and API clients
- `/prisma`: Database schema and migrations

### Tech Stack
- TypeScript 5.3
- React 18
- Tailwind CSS 3.4
- Prisma 5.x
- PostgreSQL 16

## Qwen Added Memories
- API uses camelCase for request/response
- All components must have PropTypes
- Use React Query for data fetching
- Prefer server components over client components
```

### Memory File Organization

Structure memory files for clarity:

```markdown theme={null}
# Project Title

Brief project description.

## Architecture

High-level architecture overview.

## Technology Stack

List of technologies and versions.

## Development Workflow

Build, test, and deployment processes.

## Coding Standards

Team conventions and preferences.

## Qwen Added Memories

- Dynamic facts added by Qwen Code
- User preferences specific to this project
```

### Import Organization

Use imports to keep files manageable:

```markdown theme={null}
<!-- Main QWEN.md -->
# Project Context

<!-- @import: docs/architecture.md -->
<!-- @import: docs/api-reference.md -->
<!-- @import: docs/deployment.md -->

## Qwen Added Memories
- (Dynamic content here)
```

This keeps the main file clean while providing comprehensive context.

### Avoid Sensitive Information

Never store sensitive data in memory files:

❌ **Bad**:

```markdown theme={null}
- Database password: super_secret_123
- API key: sk-1234567890abcdef
```

✅ **Good**:

```markdown theme={null}
- Database credentials stored in 1Password vault "Production"
- API keys managed via environment variables in `.env.local`
- Secrets rotation handled by DevOps team quarterly
```

## Advanced Usage

### Programmatic Memory Access

```typescript theme={null}
import { 
  loadServerHierarchicalMemory,
  FileDiscoveryService 
} from '@qwen-code/qwen-code-core';

const fileService = new FileDiscoveryService();

const { memoryContent, fileCount } = await loadServerHierarchicalMemory(
  process.cwd(),
  ['/additional/path'],
  fileService,
  [],
  true,  // folderTrust
  'tree' // importFormat
);

console.log(`Loaded ${fileCount} memory files`);
console.log(memoryContent);
```

### Memory in Resumable Sessions

Memory content is included in session checkpoints:

```typescript theme={null}
// Memory loaded at session start
const initialMemory = await loadServerHierarchicalMemory(...);

// Included in system prompt
const systemPrompt = `
${baseInstructions}

${initialMemory.memoryContent}
`;

// Memory persists across resume
qwen --resume <session-id>
// Same memory context restored
```

### Extension Context Files

Extensions can provide additional context:

```typescript theme={null}
const extensionContextPaths = [
  '/path/to/extension/context.md',
  '/another/extension/docs.md'
];

const { memoryContent } = await loadServerHierarchicalMemory(
  cwd,
  includeDirs,
  fileService,
  extensionContextPaths,  // Added to memory
  true
);
```

## Troubleshooting

### Memory Not Loading

**Problem**: Qwen Code doesn't seem to remember context.

**Check**:

```bash theme={null}
# Verify files exist
ls -la ~/.qwen/QWEN.md
ls -la QWEN.md
ls -la .qwen/QWEN.md

# Check folder trust
qwen config get folderTrust

# Enable if disabled
qwen config set folderTrust true
```

### Import Loops

**Problem**: Circular imports cause issues.

**Solution**: Imports track visited files to prevent loops:

```typescript theme={null}
// From memoryImportProcessor.ts
const visitedFiles = new Set<string>();

if (visitedFiles.has(resolvedPath)) {
  // Skip already imported file
  continue;
}
visitedFiles.add(resolvedPath);
```

Avoid circular references:

```markdown theme={null}
<!-- A.md -->
<!-- @import: B.md -->  ❌ Don't create loops

<!-- B.md -->
<!-- @import: A.md -->  ❌ Don't create loops
```

### Large Memory Files

**Problem**: Memory files too large, wasting tokens.

**Solution**:

1. Use imports to split content
2. Keep only essential information
3. Archive outdated context

```bash theme={null}
# Move old content to archive
mkdir -p .qwen/archive
mv QWEN.md .qwen/archive/QWEN-$(date +%Y%m%d).md

# Start fresh
cat > QWEN.md << 'EOF'
# Project Context

<!-- @import: .qwen/archive/QWEN-20240315.md -->

## Current Context
(New, relevant information)
EOF
```

### Permission Issues

**Problem**: Cannot write to global memory file.

**Solution**:

```bash theme={null}
# Check permissions
ls -la ~/.qwen/

# Fix if needed
chmod 755 ~/.qwen
chmod 644 ~/.qwen/QWEN.md

# Create if missing
mkdir -p ~/.qwen
touch ~/.qwen/QWEN.md
```

## Source Code References

* Memory tool: `packages/core/src/tools/memoryTool.ts`
* Memory discovery: `packages/core/src/utils/memoryDiscovery.ts`
* Import processor: `packages/core/src/utils/memoryImportProcessor.ts`
* Configuration: `packages/core/src/config/config.ts:52`
