Metadata-Version: 2.4
Name: memocode
Version: 0.4.7
Summary: Personal AI coding agent with memory, tool execution, and safety controls
Author: AssassinCHN
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: openai>=1.0
Requires-Dist: rich>=13.0
Requires-Dist: prompt_toolkit>=3.0
Requires-Dist: certifi>=2024.0

```
  __  __               _
 |  \/  | ___ ___   __| | ___
 | |\/| |/ __/ _ \ / _` |/ _ \
 | |  | | (_| (_) | (_| |  __/
 |_|  |_|\___\___/ \__,_|\___|
 ──────────────────────────────────────────────────────────────────────
  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/github/license/hankwangcn/mcode)](LICENSE)
[![Language](https://img.shields.io/github/languages/top/hankwangcn/mcode?color=3572A5)](https://github.com/hankwangcn/mcode)

**Personal AI coding agent CLI — memory, tools, 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, and Ebbinghaus forgetting |
| **Projects** | Multiple projects, each with isolated memory DB and working directory |
| **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
```

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

```json
{
  "active_model": "minimax",
  "models": {
    "minimax": {
      "provider": "openai",
      "model": "MiniMax-M2.7",
      "base_url": "https://api.minimaxi.com/v1",
      "api_key_env": "MINIMAX_API_KEY",
      "context_window": 128000
    }
  }
}
```

```bash
export MINIMAX_API_KEY=your_key_here
mcode
```

Any OpenAI-compatible endpoint works. Multiple models can be defined and switched with `/model`.

---

## Usage

```bash
mcode                      # Start (auto-resumes last project)
mcode --project myapp      # Start with a specific project
mcode --verbose            # Show full tracebacks on errors
```

---

## 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 |
| `/undo` | Undo last run — restore files and/or rewind conversation |
| `/rewind [N]` | Rewind to turn N (1 = start); `/rewind 0` clears conversation (optionally also clears project memory) |
| `/rollback` | Restore a specific backed-up file |
| `/history [N]` | Show audit log |

**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 |

**Safety**

| Command | Description |
|---------|-------------|
| `/safety [on\|off]` | Toggle safety bypass (DANGEROUS, session-only) |

**Projects**

| Command | Description |
|---------|-------------|
| `/project list` | List all projects |
| `/project workdir [path]` | Set working directory |
| `/project rename [<old>] <new>` | Rename a project |
| `/project delete <name>` | Delete a project (glob patterns supported) |

**Memory**

| Command | Description |
|---------|-------------|
| `/memory` | Show core memory (user profile) |
| `/memory set <key> <value>` | Write an entry |
| `/memory del <key>` | Delete an entry |
| `/memory pin <key>` | Pin an entry (never forgets) |

**Other**

| Command | Description |
|---------|-------------|
| `/model [name]` | Show or switch LLM model |
| `/tools` | List all loaded tools |
| `!<command>` | Run a shell command directly (safety-checked) |
| `@<path>` | Attach a file — text files are inlined, images sent as multimodal content |

---

## Memory System

mcode maintains four memory layers across sessions:

| Layer | Scope | Contents |
|-------|-------|----------|
| **Core memory** | Global | User traits: interaction style, delegation preference |
| **Project memory** | Per-project | Decisions, architecture, conventions, progress |
| **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 so the model can answer timeline questions
- `memory_search` is called automatically when context is missing — searches the full summary history
- Core and project memory are always in the system prefix (prompt-cache eligible)
- Project memory entries include an age marker (e.g. `14d ago`) so the model can assess data freshness

**Compression**
When context reaches 50% of `context_window`, old turns are replaced with a structured summary: topics, decisions, progress, pending items. Summaries use explicit markers (`Rejected X — reason`, `Changed from X to Y — reason`) so negations and reversals are directly retrievable. Compression mode is auto-detected per session: conversations without code use **plan mode** (preserves specific values, dates, URLs, identifiers); code-heavy conversations use **code mode** (focuses on decisions and rationale). Override via `compression_mode` in `chatmem.json` (`"auto"` / `"code"` / `"plan"`).

**Forgetting**
Core memory decays via the Ebbinghaus curve (`score = exp(-t / stability)`). Each judge reinforcement grows the entry's stability by 10% (capped at 2× the dimension default), so frequently confirmed traits resist forgetting longer. Entries never reinforced gradually fade below the 0.1 threshold and are dropped. Project memory is not subject to decay — decisions persist until explicitly overwritten or deleted.

---

## Auto Mode

Auto mode runs the agent fully autonomously — no prompts, hard 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, returns readable text (HTML stripped) |
| `web_search` | Search the web via DuckDuckGo — no API key required |
| `calc` | Safe arithmetic evaluator — any math expression, never computed mentally |
| `memory_search` | Search past session summaries for relevant context |
| `activity_log_query` | Query recent activity log — for "today / this session / past N days" questions |
| `project_query` | Read structured project memory — decisions, architecture, progress; prefer over `memory_search` for current-state questions |

---

## 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,
)
```

---

## Project Structure

```
mcode/
├── run.py                       # CLI entry point
├── control/
│   ├── brain.py                 # Agent loop, tool dispatch, safety
│   ├── llm.py                   # LLM adapter (OpenAI-compatible)
│   ├── project_manager.py       # Project registry
│   ├── audit.py                 # Audit log
│   └── chatmem/                 # Memory system
│       ├── context_manager.py   # History, compression, injection
│       ├── compressor.py        # LLM-based summarization
│       └── memory/
│           ├── core_memory.py   # User traits (global, with forgetting)
│           ├── recent_memory.py # Cross-session summaries (per-project)
│           ├── consolidation.py # Pattern extraction → core memory
│           └── forgetting.py    # Ebbinghaus decay
├── tools/
│   ├── file.py                  # file_read/write/edit, glob, grep
│   ├── shell.py                 # shell_exec
│   ├── web.py                   # web_fetch
│   ├── calc.py                  # calc — safe arithmetic evaluator
│   └── registry.py              # Tool registry + loader
└── safety/
    ├── safety.py                # Zone checks, auto mode rules
    ├── backup.py                # File backup
    └── policy.py                # Persistent always-allow policies
```
