Metadata-Version: 2.4
Name: memocode
Version: 0.8.15
Summary: Personal AI coding agent with memory, tool execution, and safety controls
Author: AssassinCHN
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: openai>=1.0
Requires-Dist: rich>=13.0
Requires-Dist: prompt_toolkit>=3.0
Requires-Dist: certifi>=2024.0
Requires-Dist: httpx>=0.24
Requires-Dist: pdfplumber>=0.10
Requires-Dist: pdfminer.six>=20221105
Requires-Dist: readability-lxml>=0.8
Dynamic: license-file

```
  __  __               _
 |  \/  | ___ ___   __| | ___
 | |\/| |/ __/ _ \ / _` |/ _ \
 | |  | | (_| (_) | (_| |  __/
 |_|  |_|\___\___/ \__,_|\___|
 ──────────────────────────────────────────────────────────────────────
  Mcode  —  Your local AI coding agent
  › /help for commands
  › Project: default  —  /project rename <name> to name this session
  › Model:   minimax  (MiniMax-M2.7)  —  /model to switch
 ──────────────────────────────────────────────────────────────────────
```

<div align="center">

[![PyPI](https://img.shields.io/pypi/v/memocode?color=blue&label=PyPI)](https://pypi.org/project/memocode/)
[![Python](https://img.shields.io/pypi/pyversions/memocode)](https://pypi.org/project/memocode/)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
[![Language](https://img.shields.io/github/languages/top/hankwangcn/mcode?color=3572A5)](https://github.com/hankwangcn/mcode)

**Personal AI coding agent CLI — persistent memory, tool execution, and safety controls.**

</div>

---

## Features

| | |
|---|---|
| **Agentic loop** | Native function calling, stuck detection, fully autonomous auto mode |
| **Memory** | 4-layer cross-session memory with compression, recall, Ebbinghaus forgetting, behavioral learning, and quantitative prompt analysis |
| **Browser automation** | Playwright-based browser control with click state verification, deferred/lazy validation error detection, auto-detection (Edge → Chrome → Chromium), authenticated file downloads, and auto-distilled recipe reuse (auto-execute with 5s countdown) |
| **Projects** | Multiple projects, each with isolated memory DB, task store, and working directory |
| **Resource registry** | Index local files by topic; reference them with `@name` in any message |
| **Image support** | Attach images via `@path` for multimodal turns with vision-capable models |
| **Safety** | Human / Auto / Bypass modes with zone checks, whitelists, and file backups |
| **Extensible** | Drop `.py` files into `~/.mcode/tools/` to add custom tools |

---

## Installation

```bash
pip install memocode
```

**Optional dependencies**

| Feature | Package |
|---------|---------|
| JS-heavy pages (`playwright=true`) | `pip install playwright` (uses system Chrome/Edge — no browser download needed) |
| Word documents | `pip install python-docx` |
| Excel files | `pip install openpyxl` |

On first run, `~/.mcode/agent.json` is created. Add your model:

```json
{
  "active_model": "gpt4o",
  "models": {
    "gpt4o": {
      "provider": "openai",
      "model": "gpt-4o",
      "api_key_env": "OPENAI_API_KEY",
      "context_window": 128000
    }
  }
}
```

```bash
export OPENAI_API_KEY=your_key_here
mcode
```

Any OpenAI-compatible endpoint works — OpenAI, Anthropic, DeepSeek, local models via vLLM/Ollama, etc. Multiple models can be defined and switched with `/model`.

---

## Quick Start

```bash
mcode                      # Start (auto-resumes last project)
mcode --project myapp      # Start with a specific project
```

Type naturally. Use `/help` to see all commands.

---

## Slash Commands

**Session**

| Command | Description |
|---------|-------------|
| `/help` | Show all commands |
| `/status` | Show current settings |
| `/end` | End session and save to memory |
| `/quit` / `/exit` | Exit |

**Conversation**

| Command | Description |
|---------|-------------|
| `/btw <question>` | Quick one-shot question — no memory, no tools |
| `/rewind` | Interactive rewind — select turn, then choose conversation/files/both; `/rewind del N` deletes a specific turn |
| `/context [path]` | Export full context (core+project+recent memory + history) to file or stdout |
| `/history [N\|clear]` | Show last N input history entries (default 50); `clear` to wipe |

**Auto mode**

| Command | Description |
|---------|-------------|
| `/auto [on\|off]` | Toggle autonomous mode |
| `/auto whitelist [list\|add\|remove\|reset]` | Manage whitelisted shell commands |
| `/template [example]` | Show recommended task prompt template |

**Projects**

| Command | Description |
|---------|-------------|
| `/project new [name]` | Create a new project |
| `/project switch <name>` | Switch to another project |
| `/project list` | List all projects |
| `/project workdir [path]` | Set working directory |
| `/project rename [<old>] <new>` | Rename a project |
| `/project delete <name>` | Delete a project |

**Memory & Tasks**

| Command | Description |
|---------|-------------|
| `/memory` | Show core memory, project memory, and open tasks |
| `/memory compact` | Condense bloated memory entries via LLM |
| `/memory set <key> <value>` | Write a core memory entry |
| `/memory set <key> <value> --dim <dim>` | Write to a specific core memory dimension |
| `/memory set <key> <value> --project` | Write a project memory entry (key = dimension name) |
| `/memory del <key>` | Delete a core memory entry |
| `/memory del <key> --project` | Delete a project memory entry |
| `/memory pin <key>` | Pin an entry (never forgets) |
| `/tasks` | List plan+open tasks |
| `/tasks plan\|open\|done\|cancelled\|all` | Filter by status |
| `/tasks done <id>` | Mark task as done |
| `/tasks start <id>` | Move plan → open (coding started) |
| `/tasks cancel <id>` | Cancel a task |
| `/tasks del <id>` | Hard-delete a task |
| `/tasks export <file>` | Export all tasks to a file |

**Resources**

| Command | Description |
|---------|-------------|
| `/resource add [-r] <path\|dir>` | Register a file or directory (recursive with `-r`) |
| `/resource search <query>` | Search registered resources |
| `/resource list` | List all resources |
| `/resource tree` | Directory tree view of all resources |
| `/resource sync [name]` | Re-classify changed files |
| `/resource rescan [filter]` | Re-classify resources with empty descriptions |
| `/resource edit <idx\|query>` | Edit resource name/description/tags |
| `/resource del <idx\|range\|query>` | Delete resource(s) by index, range, or keyword |
| `/resource watch [-r] <dir>` | Watch a directory for new files |
| `/resource unwatch <dir>` | Stop watching a directory |

**Other**

| Command | Description |
|---------|-------------|
| `/model [name]` | Show or switch LLM model |
| `/tools` | List all loaded tools |
| `/usage` | Show token consumption (session + all-time + per-model) |
| `/safety [on\|off]` | Toggle safety bypass (DANGEROUS, session-only) |
| `/email [--since <days>] [--tasks] [file]` | Summarise unread Outlook emails (Windows only) |
| `!<command>` | Run a shell command directly (safety-checked) |
| `@<path or name>` | Attach a file or registered resource inline |
| `@*<query>` | Inject all resources matching a search query |
| `@<dir>/` | Inject a directory file listing |
| `@<N>` | Reference resource by global index number |

---

## Memory System

mcode maintains four memory layers across sessions:

| Layer | Scope | Contents |
|-------|-------|----------|
| **Core memory** | Global | User traits: interaction style, delegation, tool preference, error handling |
| **Project memory** | Per-project | Architecture, decisions, norms, context, constraints |
| **Behavior stats** | Global | Per-turn quantitative prompt metrics (specificity, ambiguity, info density) |
| **Recent memory** | Per-project | Compressed summaries of past sessions |
| **Session history** | Per-project | Current session verbatim; older turns compressed in-place |

**Recall** — Recent summaries are injected every turn (newest-first, 4k token cap) with timestamps. `memory_query` is called automatically when context is missing. Core and project memory are always in the system prefix (prompt-cache eligible).

**Compression** — When context reaches 50% of `context_window`, old turns are summarised with explicit markers (`Rejected X — reason`, `Changed from X to Y — reason`) so negations and reversals remain retrievable. Mode is auto-detected: **plan mode** for conversations without code (preserves process sequences), **code mode** for code-heavy sessions (excludes code snippets and file paths). Both modes preserve dates, names, specific values, and identifiers.

**Forgetting** — Core memory decays via the Ebbinghaus curve. Frequently confirmed traits resist forgetting; entries never reinforced eventually fade below threshold and are dropped. Project memory does not decay.

**Behavioral learning** — User corrections are detected via keyword matching and fed to the core memory judge as highest-priority signals. Tool call success rates and file path patterns are collected per session and injected into the judge for `delegation` habit extraction. Recipes auto-prune based on reject/fail counts and 30-day staleness.

---

## Resource Registry

Register local files once; reference them by name from any message.

```
/resource add ~/Documents/specs      # register a directory (also auto-watches for new files)
/resource add -r ~/Documents         # recursive
/resource search kubernetes          # find by keyword
```

After searching, reference a result directly in your message:

```
@API设计规范 根据规范帮我 review 这段代码
```

The file content is injected automatically — no copy-paste needed. New files added to a watched directory are auto-registered on the next startup.

---

## Auto Mode

Auto mode runs the agent fully autonomously — no confirmation prompts, hard sandbox boundaries (whitelist-only shell commands, writes restricted to `work_dir`).

Enable with `/auto on`, then use `/template` for the recommended task structure:

```
Task: <one-line goal>
Context: work_dir, language/framework, entry point
Acceptance criteria: 1) ... 2) ... 3) ...
Constraints: do NOT modify <files>
Verify by running: <test command>
```

---

## Safety Modes

| Mode | Behavior |
|------|----------|
| **Human** (default) | Prompts before risky ops; backs up files before destructive edits |
| **Auto** (`/auto on`) | No prompts; blocks non-whitelisted commands and out-of-`work_dir` writes |
| **Bypass** (`/safety off`) | Skips all checks; session-only; requires typing `yes` to confirm |

---

## Built-in Tools

| Tool | Description |
|------|-------------|
| `shell_exec` | Run shell commands with streaming output |
| `file_read` | Read file with optional pagination |
| `file_write` | Write or append to a file |
| `file_edit` | Targeted string replacement |
| `glob` | Find files by pattern (`**/*.py`) |
| `grep` | Search file content by regex |
| `web_fetch` | Fetch a URL — GET/POST/PUT/PATCH/DELETE, custom headers, JSON body; HTML converted to readable text via Mozilla Readability; `playwright=true` renders JS-heavy pages |
| `web_search` | Search the web via DuckDuckGo — no API key required |
| `edge_browser` | Browser automation — navigate, click, type, select, scroll, hover, wait, back/forward/refresh, upload, download; click state verification; error detection; auto-detects Edge/Chrome/Chromium |
| `pdf_read` | Extract text, tables and images from PDF files |
| `docx_read` | Extract text, tables and images from Word (.docx) files |
| `excel_read` | Read Excel / CSV files as formatted table |
| `excel_write` | Write data to Excel / CSV files |
| `calc` | Safe arithmetic evaluator |
| `date_calc` | Convert relative date expressions to absolute YYYY-MM-DD |
| `memory_query` | Memory search with automatic routing — semantic (BM25), temporal (activity log), or mixed |
| `project_query` | Read structured project memory |
| `task_add/list/start/done/update/cancel` | Task store operations |
| `resource_find/scan/register/list/delete` | Resource registry operations |

---

## Custom Tools

Drop a `.py` file in `~/.mcode/tools/`:

```python
from tools.registry import Tool, ToolSchema

def _my_tool(param: str) -> str:
    return f"result: {param}"

MY_TOOL = Tool(
    schema=ToolSchema(
        name="my_tool",
        description="Description shown to the model",
        parameters={
            "type": "object",
            "properties": {"param": {"type": "string"}},
            "required": ["param"],
        },
    ),
    fn=_my_tool,
)
```

---

## Configuration Reference

### `~/.mcode/agent.json` — Global Settings

```jsonc
{
  // ── Agent behavior ──
  "auto_mode": false,               // start in auto mode (default: false)
  "parallel_tasks": true,           // allow parallel tool execution
  "llm_timeout": 120,               // LLM request timeout in seconds (default: 30)
  "max_tool_iter": 500,             // max tool iterations per turn — human mode
  "auto_max_tool_iter": 200,        // max tool iterations per turn — auto mode
  "max_tool_output": 20000,         // max chars returned per tool call
  "max_response_tokens": 16000,     // max tokens for LLM response
  "require_confirm_on_irreversible": true,  // prompt before destructive ops
  "web_search_max_results": 15,     // max results per web search

  // ── Model selection ──
  "active_model": "gpt4o",          // key from "models" to use on startup
  "models": {
    "gpt4o": {
      // Required
      "provider": "openai",         // "openai" (any OpenAI-compatible) | "anthropic"
      "model": "gpt-4o",            // model name sent to API
      "api_key_env": "OPENAI_API_KEY",  // env var holding the API key

      // Optional
      "base_url": null,             // API endpoint (null = provider default)
      "context_window": 128000,     // context window size in tokens
      "compress_model": null,       // separate model for compression (default: same as model)
      "vision": false,              // enable image/vision support
      "thinking": false,            // enable thinking/reasoning mode
      "thinking_budget": 8000,      // max tokens for thinking (Anthropic extended thinking)
      "ssl_verify": true,           // set false for corporate proxies with custom CA
      "extra_body": null,           // provider-specific params, e.g. {"thinking": {"type": "disabled"}}
      "excluded_params": null,      // params to drop from requests, e.g. ["temperature"]
      "auth": null                  // enterprise auth config (internal use)
    }
  }
}
```

Only `provider`, `model`, and `api_key_env` are required per model. All other fields have sensible defaults and can be omitted.

### `~/.mcode/chatmem.json` — Memory & Compression Settings

This file is auto-managed — the `llm` section is synced from `agent.json` on startup. Normally you only edit `dimensions` and `compression_mode` here.

```jsonc
{
  // ── LLM (auto-synced from agent.json — do not edit manually) ──
  "llm": { ... },

  // ── Compression ──
  "compression_mode": "auto",       // "auto" | "code" | "plan"
                                     //   auto: detect from conversation content
                                     //   code: focus on decisions and rationale
                                     //   plan: preserve dates, values, identifiers

  // ── Core memory dimensions ──
  // Each dimension tracks a behavioral trait extracted from conversations.
  // stability = Ebbinghaus decay half-life in days (higher = slower to forget)
  "dimensions": {
    "interaction_style": { "label": "Expression style, language preference, tone, detail level",                                                                                           "stability": 45.0 },
    "delegation":        { "label": "Delegation level + cross-project working habits: autonomy (executes/options/validates), coding standards, error handling, tool usage patterns", "stability": 40.0 }
  }
}
```

### `~/.mcode/project_memory.json` — Project Memory Dimensions

Per-project structured knowledge, extracted by a dedicated judge at compression and session end. Unlike core memory, project memory does **not** decay (no Ebbinghaus forgetting).

```jsonc
{
  "dimensions": {
    "context":       { "label": "Permanent project identity: purpose, long-term constraints",       "stability": 90.0 },
    "constraints":   { "label": "Deadlines, ownership boundaries, external dependencies",           "stability": 30.0 },
    "norms":         { "label": "Development standards, workflow rules, quality requirements",       "stability": 35.0 },
    "architecture":  { "label": "Tech stack, modules, structure (WHAT is built)",                    "stability": 40.0 },
    "decisions":     { "label": "Confirmed design decisions and rationale (WHY it was chosen)",      "stability": 35.0 }
  }
}
```

Dimensions can be customized: edit `label` to change what the judge extracts, adjust `stability` to control update frequency. Dimension keys can be renamed or extended — the judge prompt is built dynamically from whatever dimensions are defined.

---

## Project Structure

```
mcode/
├── run.py                       # CLI entry point (~1070 lines)
├── cmds/                        # Slash command handlers
│   ├── memory.py                # /memory
│   ├── tasks.py                 # /tasks
│   ├── rewind.py                # /rewind, /context, /history
│   ├── email.py                 # /email (Windows only)
│   ├── project.py               # /project
│   ├── resource.py              # /resource
│   ├── usage.py                 # /usage
│   ├── at_expand.py             # @mention expansion
│   └── _utils.py                # shared utilities
├── control/
│   ├── brain.py                 # Agent loop, tool dispatch, safety
│   ├── llm.py                   # LLM adapter (OpenAI-compatible + Anthropic)
│   ├── fmt.py                   # Terminal formatting helpers
│   ├── recipe.py                # Auto-distilled browser recipe system
│   ├── tasks.py                 # Task store (per-project SQLite)
│   ├── project_manager.py       # Project registry
│   ├── mcp_client.py            # MCP tool integration
│   ├── audit.py                 # Audit log
│   ├── resources/               # Local resource registry
│   │   ├── manager.py           # ResourceManager
│   │   ├── db.py                # SQLite storage + BM25 search
│   │   └── scanner.py           # File content extraction
│   └── chatmem/                 # Memory system
│       ├── context_manager.py   # History, compression, injection
│       ├── compressor.py        # LLM-based summarization
│       ├── config.py            # ContextConfig, LLMConfig, DimensionConfig
│       ├── token_counter.py     # Character-based token estimation
│       └── memory/
│           ├── core_memory.py   # User traits (global, Ebbinghaus forgetting)
│           ├── recent_memory.py # Cross-session summaries (BM25 + co-occurrence)
│           ├── activity_log.py  # Exact timestamp activity log
│           ├── tool_stats.py    # Per-tool success rate tracking
│           ├── consolidation.py      # Pattern extraction → core memory
│           ├── behavior_analyzer.py # Quantitative prompt metrics
│           └── forgetting.py        # Ebbinghaus decay engine
├── tools/
│   ├── file.py                  # file_read/write/edit, glob, grep
│   ├── shell.py                 # shell_exec
│   ├── web.py                   # web_fetch, web_search
│   ├── browser.py               # edge_browser (Playwright-based)
│   ├── pdf.py                   # pdf_read (pdfplumber)
│   ├── docx.py                  # docx_read (python-docx)
│   ├── excel.py                 # excel_read, excel_write (openpyxl)
│   ├── calc.py                  # safe arithmetic evaluator
│   ├── date.py                  # date_calc (relative → absolute)
│   ├── task.py                  # task_add/list/start/done/update/cancel
│   ├── resource.py              # resource_find/scan/register/list/delete
│   ├── outlook.py               # Outlook email + calendar (Windows)
│   ├── loader.py                # Auto-discovery for tools/*.py + ~/.mcode/tools/
│   └── registry.py              # Tool/ToolSchema/ToolRegistry
└── safety/
    ├── safety.py                # Zone checks, auto mode rules
    ├── backup.py                # File backup before edits
    └── policy.py                # Persistent always-allow policies
```

---

## Data Storage

All data is stored locally under `~/.mcode/`:

| Path | Contents |
|------|----------|
| `agent.json` | Model configuration, global settings |
| `chatmem.json` | Core memory dimensions, compression mode |
| `project_memory.json` | Project memory dimensions |
| `projects/` | Per-project memory DB, history, task store |
| `resources/index.db` | Resource registry index |
| `recipes/` | Auto-distilled browser operation templates |
| `tools/` | User custom tools |
| `autobackup/` | File backup before destructive edits |
| `history` | Input history (prompt_toolkit format) |

---

## License

Apache License 2.0 — see [LICENSE](LICENSE).
