auto-context-cli 1.0.0__tar.gz → 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/PKG-INFO +34 -10
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/README.md +33 -9
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/pyproject.toml +1 -1
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/__init__.py +1 -1
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/commands/init_cmd.py +41 -0
- auto_context_cli-1.0.1/src/auto_context/commands/memory.py +320 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/main.py +2 -1
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/AGENTS.template.md +7 -4
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/GEMINI.template.md +7 -4
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/maintain_context.template.md +4 -4
- auto_context_cli-1.0.0/src/auto_context/commands/memory.py +0 -236
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/.gitignore +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/LICENSE +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/commands/__init__.py +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/commands/import_cmd.py +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/commands/mcp.py +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/commands/share.py +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/config.py +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/security.py +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/context.local.template.md +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/context.template.md +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/mcp_config.template.json +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/profile.template.md +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/rule.template.md +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/rules/code-standards.md +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/rules/security-boundaries.md +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/skill.template.md +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/skills/browser-testing/SKILL.md +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/skills/docker-ops/SKILL.md +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/skills/git-workflow/SKILL.md +0 -0
- {auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/skills/server-diagnostics/SKILL.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: auto-context-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.1
|
|
4
4
|
Summary: Autonomous context & instruction manager for AI coding assistants
|
|
5
5
|
Author: Arghya Biswas
|
|
6
6
|
License: MIT
|
|
@@ -18,10 +18,12 @@ Description-Content-Type: text/markdown
|
|
|
18
18
|
|
|
19
19
|
**Autonomous Context & Instruction Management Protocol for AI Coding Assistants**
|
|
20
20
|
|
|
21
|
+
[](https://pypi.org/project/auto-context-cli/)
|
|
22
|
+
[](https://pypi.org/project/auto-context-cli/)
|
|
23
|
+
[](https://github.com/Cyber-arghya/auto-context/releases/tag/v1.0.1)
|
|
21
24
|
[](https://opensource.org/licenses/MIT)
|
|
22
|
-
[](#-quick-one-line-install)
|
|
23
26
|
[](#-supported-ai-assistants)
|
|
24
|
-
[](https://github.com/Cyber-arghya/auto-context/pulls)
|
|
25
27
|
|
|
26
28
|
*Never lose context, forgotten architecture decisions, or unlogged bug fixes again.*
|
|
27
29
|
|
|
@@ -33,19 +35,26 @@ Description-Content-Type: text/markdown
|
|
|
33
35
|
|
|
34
36
|
## ⚡ Quick One-Line Install
|
|
35
37
|
|
|
36
|
-
No manual
|
|
38
|
+
No manual git clones or complex PATH configurations required. Install directly via PyPI or using our 1-click installer:
|
|
37
39
|
|
|
38
|
-
### 📦
|
|
40
|
+
### 📦 Direct via PyPI (Universal - Windows, macOS, Linux, WSL2):
|
|
39
41
|
```bash
|
|
40
|
-
uv
|
|
42
|
+
# Recommended via uv (fast & isolated):
|
|
43
|
+
uv tool install auto-context-cli
|
|
44
|
+
|
|
45
|
+
# Or via standard pip:
|
|
46
|
+
pip install auto-context-cli
|
|
47
|
+
|
|
48
|
+
# Or via pipx:
|
|
49
|
+
pipx install auto-context-cli
|
|
41
50
|
```
|
|
42
51
|
|
|
43
|
-
### 🪟 Windows (PowerShell / `pwsh` 1-Click):
|
|
52
|
+
### 🪟 Windows (PowerShell / `pwsh` 1-Click Installer):
|
|
44
53
|
```powershell
|
|
45
54
|
irm https://raw.githubusercontent.com/Cyber-arghya/auto-context/main/install.ps1 | iex
|
|
46
55
|
```
|
|
47
56
|
|
|
48
|
-
### 🐧 Linux / WSL2 / macOS (Bash / Zsh 1-Click):
|
|
57
|
+
### 🐧 Linux / WSL2 / macOS (Bash / Zsh 1-Click Installer):
|
|
49
58
|
```bash
|
|
50
59
|
curl -sSL https://raw.githubusercontent.com/Cyber-arghya/auto-context/main/install.sh | bash
|
|
51
60
|
```
|
|
@@ -184,6 +193,11 @@ You can easily teach your AI assistants new abilities (**Skills**) or enforce cu
|
|
|
184
193
|
| **Rule** | Behavioral constraints, coding standards, security boundaries, or test requirements. | Always active (`trigger: always_on`) or context-triggered. | `.agents/rules/<name>.md` or `GEMINI.md` |
|
|
185
194
|
| **Skill** | Step-by-step procedures, deployment runbooks, debugging steps, or CLI tool guides. | Activated on-demand when relevant task is requested. | `.agents/skills/<name>/SKILL.md` |
|
|
186
195
|
|
|
196
|
+
> [!IMPORTANT]
|
|
197
|
+
> **Core Directives for AI Coding Agents:**
|
|
198
|
+
> - **Zero Token Waste:** DO NOT burn tokens manually searching directories or reading files to check for existing rules. Directly run `init-context -r <name> [-g]` — the CLI has instant built-in duplicate detection and collision guards.
|
|
199
|
+
> - **Mandatory Global Scope:** When the user mentions "for future", "always", or defines a reusable standard, **MANDATORY: Always pass `--global` (`-g`)** and immediately follow with `init-context memory push`.
|
|
200
|
+
|
|
187
201
|
---
|
|
188
202
|
|
|
189
203
|
### 1️⃣ How to Add a New Rule
|
|
@@ -454,11 +468,17 @@ To prevent **Prompt Injection Leaks** and keep production secrets safe:
|
|
|
454
468
|
3. **পাসওয়ার্ড ও পোর্ট ভল্ট:** সার্ভারের স্ট্যাটিক আইপি, ক্লাউডফ্লেয়ার টানেল আইডি বা ডাটাবেজ পোর্ট সবসময় এক ফাইলে নিখুঁতভাবে থাকবে।
|
|
455
469
|
|
|
456
470
|
### ইনস্টলেশন ও ব্যবহার:
|
|
457
|
-
*
|
|
471
|
+
* **PyPI থেকে সরাসরি ইনস্টল করতে (সবার জন্য সহজ):**
|
|
472
|
+
```bash
|
|
473
|
+
pip install auto-context-cli
|
|
474
|
+
# অথবা uv দিয়ে:
|
|
475
|
+
uv tool install auto-context-cli
|
|
476
|
+
```
|
|
477
|
+
* **উইন্ডোজ পাওয়ারশেল (1-Click Installer):**
|
|
458
478
|
```powershell
|
|
459
479
|
irm https://raw.githubusercontent.com/Cyber-arghya/auto-context/main/install.ps1 | iex
|
|
460
480
|
```
|
|
461
|
-
* **লিনাক্স / WSL2
|
|
481
|
+
* **লিনাক্স / WSL2 / macOS (1-Click Installer):**
|
|
462
482
|
```bash
|
|
463
483
|
curl -sSL https://raw.githubusercontent.com/Cyber-arghya/auto-context/main/install.sh | bash
|
|
464
484
|
```
|
|
@@ -470,6 +490,10 @@ To prevent **Prompt Injection Leaks** and keep production secrets safe:
|
|
|
470
490
|
ব্যস! আপনার প্রজেক্টে স্বয়ংক্রিয় কনটেক্সট ট্র্যাকিং চালু হয়ে যাবে।
|
|
471
491
|
|
|
472
492
|
### নতুন স্কিল বা রুল তৈরি করার নিয়ম:
|
|
493
|
+
> [!IMPORTANT]
|
|
494
|
+
> **এআই কোডিং এজেন্টের জন্য বাধ্যতামূলক নির্দেশিকা:**
|
|
495
|
+
> - **জিরো টোকেন অপচয় (Zero Token Waste):** কোনো রুল বা স্কিল আগে থেকে আছে কিনা তা চেক করতে ম্যানুয়ালি ফাইল খোঁজা বা পড়ার কোনো প্রয়োজন নেই। সরাসরি `init-context -r <name> [-g]` রান করুন — সিএলআই স্বয়ংক্রিয়ভাবে ডুপ্লিকেট শনাক্ত ও কলিশন গার্ড দিয়ে প্রোটেক্ট করে।
|
|
496
|
+
> - **বাধ্যতামূলক গ্লোবাল স্কোপ (Mandatory Global Scope):** ইউজার যখন "for future", "always" বা ভবিষ্যতের জন্য কোনো সাধারণ নিয়ম সেভ করতে বলবে, তখন অবশ্যই `--global` (`-g`) ব্যবহার করতে হবে এবং সাথে সাথে `init-context memory push` রান করে সেন্ট্রাল মেমরিতে সিঙ্ক করতে হবে।
|
|
473
497
|
* **নতুন রুল (Rule) তৈরি করতে:**
|
|
474
498
|
```bash
|
|
475
499
|
init-context -r my-rule-name # বর্তমান প্রজেক্টের জন্য
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
**Autonomous Context & Instruction Management Protocol for AI Coding Assistants**
|
|
6
6
|
|
|
7
|
+
[](https://pypi.org/project/auto-context-cli/)
|
|
8
|
+
[](https://pypi.org/project/auto-context-cli/)
|
|
9
|
+
[](https://github.com/Cyber-arghya/auto-context/releases/tag/v1.0.1)
|
|
7
10
|
[](https://opensource.org/licenses/MIT)
|
|
8
|
-
[](#-quick-one-line-install)
|
|
9
12
|
[](#-supported-ai-assistants)
|
|
10
|
-
[](https://github.com/Cyber-arghya/auto-context/pulls)
|
|
11
13
|
|
|
12
14
|
*Never lose context, forgotten architecture decisions, or unlogged bug fixes again.*
|
|
13
15
|
|
|
@@ -19,19 +21,26 @@
|
|
|
19
21
|
|
|
20
22
|
## ⚡ Quick One-Line Install
|
|
21
23
|
|
|
22
|
-
No manual
|
|
24
|
+
No manual git clones or complex PATH configurations required. Install directly via PyPI or using our 1-click installer:
|
|
23
25
|
|
|
24
|
-
### 📦
|
|
26
|
+
### 📦 Direct via PyPI (Universal - Windows, macOS, Linux, WSL2):
|
|
25
27
|
```bash
|
|
26
|
-
uv
|
|
28
|
+
# Recommended via uv (fast & isolated):
|
|
29
|
+
uv tool install auto-context-cli
|
|
30
|
+
|
|
31
|
+
# Or via standard pip:
|
|
32
|
+
pip install auto-context-cli
|
|
33
|
+
|
|
34
|
+
# Or via pipx:
|
|
35
|
+
pipx install auto-context-cli
|
|
27
36
|
```
|
|
28
37
|
|
|
29
|
-
### 🪟 Windows (PowerShell / `pwsh` 1-Click):
|
|
38
|
+
### 🪟 Windows (PowerShell / `pwsh` 1-Click Installer):
|
|
30
39
|
```powershell
|
|
31
40
|
irm https://raw.githubusercontent.com/Cyber-arghya/auto-context/main/install.ps1 | iex
|
|
32
41
|
```
|
|
33
42
|
|
|
34
|
-
### 🐧 Linux / WSL2 / macOS (Bash / Zsh 1-Click):
|
|
43
|
+
### 🐧 Linux / WSL2 / macOS (Bash / Zsh 1-Click Installer):
|
|
35
44
|
```bash
|
|
36
45
|
curl -sSL https://raw.githubusercontent.com/Cyber-arghya/auto-context/main/install.sh | bash
|
|
37
46
|
```
|
|
@@ -170,6 +179,11 @@ You can easily teach your AI assistants new abilities (**Skills**) or enforce cu
|
|
|
170
179
|
| **Rule** | Behavioral constraints, coding standards, security boundaries, or test requirements. | Always active (`trigger: always_on`) or context-triggered. | `.agents/rules/<name>.md` or `GEMINI.md` |
|
|
171
180
|
| **Skill** | Step-by-step procedures, deployment runbooks, debugging steps, or CLI tool guides. | Activated on-demand when relevant task is requested. | `.agents/skills/<name>/SKILL.md` |
|
|
172
181
|
|
|
182
|
+
> [!IMPORTANT]
|
|
183
|
+
> **Core Directives for AI Coding Agents:**
|
|
184
|
+
> - **Zero Token Waste:** DO NOT burn tokens manually searching directories or reading files to check for existing rules. Directly run `init-context -r <name> [-g]` — the CLI has instant built-in duplicate detection and collision guards.
|
|
185
|
+
> - **Mandatory Global Scope:** When the user mentions "for future", "always", or defines a reusable standard, **MANDATORY: Always pass `--global` (`-g`)** and immediately follow with `init-context memory push`.
|
|
186
|
+
|
|
173
187
|
---
|
|
174
188
|
|
|
175
189
|
### 1️⃣ How to Add a New Rule
|
|
@@ -440,11 +454,17 @@ To prevent **Prompt Injection Leaks** and keep production secrets safe:
|
|
|
440
454
|
3. **পাসওয়ার্ড ও পোর্ট ভল্ট:** সার্ভারের স্ট্যাটিক আইপি, ক্লাউডফ্লেয়ার টানেল আইডি বা ডাটাবেজ পোর্ট সবসময় এক ফাইলে নিখুঁতভাবে থাকবে।
|
|
441
455
|
|
|
442
456
|
### ইনস্টলেশন ও ব্যবহার:
|
|
443
|
-
*
|
|
457
|
+
* **PyPI থেকে সরাসরি ইনস্টল করতে (সবার জন্য সহজ):**
|
|
458
|
+
```bash
|
|
459
|
+
pip install auto-context-cli
|
|
460
|
+
# অথবা uv দিয়ে:
|
|
461
|
+
uv tool install auto-context-cli
|
|
462
|
+
```
|
|
463
|
+
* **উইন্ডোজ পাওয়ারশেল (1-Click Installer):**
|
|
444
464
|
```powershell
|
|
445
465
|
irm https://raw.githubusercontent.com/Cyber-arghya/auto-context/main/install.ps1 | iex
|
|
446
466
|
```
|
|
447
|
-
* **লিনাক্স / WSL2
|
|
467
|
+
* **লিনাক্স / WSL2 / macOS (1-Click Installer):**
|
|
448
468
|
```bash
|
|
449
469
|
curl -sSL https://raw.githubusercontent.com/Cyber-arghya/auto-context/main/install.sh | bash
|
|
450
470
|
```
|
|
@@ -456,6 +476,10 @@ To prevent **Prompt Injection Leaks** and keep production secrets safe:
|
|
|
456
476
|
ব্যস! আপনার প্রজেক্টে স্বয়ংক্রিয় কনটেক্সট ট্র্যাকিং চালু হয়ে যাবে।
|
|
457
477
|
|
|
458
478
|
### নতুন স্কিল বা রুল তৈরি করার নিয়ম:
|
|
479
|
+
> [!IMPORTANT]
|
|
480
|
+
> **এআই কোডিং এজেন্টের জন্য বাধ্যতামূলক নির্দেশিকা:**
|
|
481
|
+
> - **জিরো টোকেন অপচয় (Zero Token Waste):** কোনো রুল বা স্কিল আগে থেকে আছে কিনা তা চেক করতে ম্যানুয়ালি ফাইল খোঁজা বা পড়ার কোনো প্রয়োজন নেই। সরাসরি `init-context -r <name> [-g]` রান করুন — সিএলআই স্বয়ংক্রিয়ভাবে ডুপ্লিকেট শনাক্ত ও কলিশন গার্ড দিয়ে প্রোটেক্ট করে।
|
|
482
|
+
> - **বাধ্যতামূলক গ্লোবাল স্কোপ (Mandatory Global Scope):** ইউজার যখন "for future", "always" বা ভবিষ্যতের জন্য কোনো সাধারণ নিয়ম সেভ করতে বলবে, তখন অবশ্যই `--global` (`-g`) ব্যবহার করতে হবে এবং সাথে সাথে `init-context memory push` রান করে সেন্ট্রাল মেমরিতে সিঙ্ক করতে হবে।
|
|
459
483
|
* **নতুন রুল (Rule) তৈরি করতে:**
|
|
460
484
|
```bash
|
|
461
485
|
init-context -r my-rule-name # বর্তমান প্রজেক্টের জন্য
|
|
@@ -307,3 +307,44 @@ def new_skill(
|
|
|
307
307
|
f"[green] File: [/] {dest_file}",
|
|
308
308
|
border_style="cyan",
|
|
309
309
|
))
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
# ── promote command ───────────────────────────────────────────────────────────
|
|
313
|
+
|
|
314
|
+
def promote(
|
|
315
|
+
name: Annotated[str, typer.Argument(help="Rule or skill name to promote to Central Memory.")],
|
|
316
|
+
target: Annotated[Optional[Path], typer.Option("--target", "-t")] = None,
|
|
317
|
+
) -> None:
|
|
318
|
+
"""Promote a local workspace rule or skill to Central Memory and global scope."""
|
|
319
|
+
project_dir = (target or Path.cwd()).resolve()
|
|
320
|
+
clean_name = name.lower().replace(" ", "-").replace("_", "-").removesuffix(".md")
|
|
321
|
+
|
|
322
|
+
local_rule = project_dir / AGENTS_SUBDIR / "rules" / f"{clean_name}.md"
|
|
323
|
+
local_skill = project_dir / AGENTS_SUBDIR / "skills" / clean_name / "SKILL.md"
|
|
324
|
+
|
|
325
|
+
promoted = False
|
|
326
|
+
if local_rule.exists():
|
|
327
|
+
content = local_rule.read_text(encoding="utf-8")
|
|
328
|
+
(config.GLOBAL_PLUGIN_DIR / "rules").mkdir(parents=True, exist_ok=True)
|
|
329
|
+
(config.GLOBAL_PLUGIN_DIR / "rules" / f"{clean_name}.md").write_text(content, encoding="utf-8")
|
|
330
|
+
if config.MEMORY_DIR.exists():
|
|
331
|
+
(config.MEMORY_DIR / "rules").mkdir(parents=True, exist_ok=True)
|
|
332
|
+
(config.MEMORY_DIR / "rules" / f"{clean_name}.md").write_text(content, encoding="utf-8")
|
|
333
|
+
console.print(f"[bold green][✓] Promoted local rule '{clean_name}' to Global Plugin and Central Memory![/]")
|
|
334
|
+
promoted = True
|
|
335
|
+
|
|
336
|
+
if local_skill.exists():
|
|
337
|
+
content = local_skill.read_text(encoding="utf-8")
|
|
338
|
+
(config.GLOBAL_PLUGIN_DIR / "skills" / clean_name).mkdir(parents=True, exist_ok=True)
|
|
339
|
+
(config.GLOBAL_PLUGIN_DIR / "skills" / clean_name / "SKILL.md").write_text(content, encoding="utf-8")
|
|
340
|
+
if config.MEMORY_DIR.exists():
|
|
341
|
+
(config.MEMORY_DIR / "skills" / clean_name).mkdir(parents=True, exist_ok=True)
|
|
342
|
+
(config.MEMORY_DIR / "skills" / clean_name / "SKILL.md").write_text(content, encoding="utf-8")
|
|
343
|
+
console.print(f"[bold green][✓] Promoted local skill '{clean_name}' to Global Plugin and Central Memory![/]")
|
|
344
|
+
promoted = True
|
|
345
|
+
|
|
346
|
+
if not promoted:
|
|
347
|
+
console.print(f"[red][✗] Rule or skill '{clean_name}' not found in local workspace ({project_dir}).[/]")
|
|
348
|
+
raise typer.Exit(1)
|
|
349
|
+
|
|
350
|
+
console.print(" [cyan]💡 Run 'init-context memory push' to push changes to your private GitHub repo.[/]\n")
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"""
|
|
2
|
+
commands/memory.py — Central memory brain management.
|
|
3
|
+
|
|
4
|
+
Wraps git CLI via subprocess.run. Runs security.audit_path()
|
|
5
|
+
before every commit or push — zero-bypass hard-block.
|
|
6
|
+
|
|
7
|
+
Subcommands: init, push, pull, status
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import shutil
|
|
12
|
+
import subprocess
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Annotated, Optional
|
|
16
|
+
|
|
17
|
+
import typer
|
|
18
|
+
from rich.console import Console
|
|
19
|
+
from rich.panel import Panel
|
|
20
|
+
|
|
21
|
+
from auto_context import config, security
|
|
22
|
+
|
|
23
|
+
app = typer.Typer(help="Central memory brain management.")
|
|
24
|
+
console = Console()
|
|
25
|
+
|
|
26
|
+
MEMORY_DIR = config.MEMORY_DIR
|
|
27
|
+
|
|
28
|
+
_GITIGNORE_ENTRIES = """\
|
|
29
|
+
# Security: Prohibit credentials and environment files from central memory
|
|
30
|
+
.env
|
|
31
|
+
.env.*
|
|
32
|
+
*.local.md
|
|
33
|
+
context.local.md
|
|
34
|
+
*.key
|
|
35
|
+
*.pem
|
|
36
|
+
*.p12
|
|
37
|
+
*.pfx
|
|
38
|
+
*.kdbx
|
|
39
|
+
id_rsa*
|
|
40
|
+
id_ed25519*
|
|
41
|
+
id_ecdsa*
|
|
42
|
+
id_dsa*
|
|
43
|
+
authorized_keys
|
|
44
|
+
known_hosts
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _git(cwd: Path, *args: str, check: bool = True) -> subprocess.CompletedProcess:
|
|
49
|
+
"""Run a git command in *cwd*, capturing output."""
|
|
50
|
+
return subprocess.run(
|
|
51
|
+
["git", "-C", str(cwd), *args],
|
|
52
|
+
capture_output=True,
|
|
53
|
+
text=True,
|
|
54
|
+
check=check,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _has_gh() -> bool:
|
|
59
|
+
return shutil.which("gh") is not None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# ── init ──────────────────────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
@app.command("init")
|
|
65
|
+
def memory_init(
|
|
66
|
+
repo_name: Annotated[str, typer.Argument(help="GitHub repo name.")] = "auto-context-memory",
|
|
67
|
+
) -> None:
|
|
68
|
+
"""Initialize a private central memory brain repository."""
|
|
69
|
+
console.print(Panel(
|
|
70
|
+
f"[bold green]🧠 Initializing Private Central Memory Brain[/]\n"
|
|
71
|
+
f"[yellow] Directory:[/] {MEMORY_DIR}\n"
|
|
72
|
+
f"[cyan] Repo: [/] {repo_name} (Strictly Private)",
|
|
73
|
+
border_style="cyan",
|
|
74
|
+
))
|
|
75
|
+
|
|
76
|
+
(MEMORY_DIR / "rules").mkdir(parents=True, exist_ok=True)
|
|
77
|
+
(MEMORY_DIR / "skills").mkdir(parents=True, exist_ok=True)
|
|
78
|
+
|
|
79
|
+
# Init git repo
|
|
80
|
+
if not (MEMORY_DIR / ".git").exists():
|
|
81
|
+
_git(MEMORY_DIR, "init")
|
|
82
|
+
console.print(" [green][✓] Initialized Git repository[/]")
|
|
83
|
+
|
|
84
|
+
# Hardened .gitignore
|
|
85
|
+
(MEMORY_DIR / ".gitignore").write_text(_GITIGNORE_ENTRIES, encoding="utf-8")
|
|
86
|
+
console.print(" [green][✓] Hardened .gitignore written[/]")
|
|
87
|
+
|
|
88
|
+
# profile.md
|
|
89
|
+
_write_profile(repo_name)
|
|
90
|
+
|
|
91
|
+
# Security audit before first commit
|
|
92
|
+
console.print(" [cyan][*] Running pre-commit security audit...[/]")
|
|
93
|
+
violations = security.audit_path(MEMORY_DIR)
|
|
94
|
+
security.abort_if_violations(violations)
|
|
95
|
+
|
|
96
|
+
_git(MEMORY_DIR, "add", "-A", check=False)
|
|
97
|
+
_git(MEMORY_DIR, "commit", "-m", config.GIT_COMMIT_INIT, check=False)
|
|
98
|
+
_git(MEMORY_DIR, "branch", "-M", "main", check=False)
|
|
99
|
+
|
|
100
|
+
if _has_gh():
|
|
101
|
+
console.print(" [cyan][*] Creating strictly private GitHub repository via gh...[/]")
|
|
102
|
+
result = subprocess.run(
|
|
103
|
+
["gh", "repo", "create", repo_name,
|
|
104
|
+
"--private", f"--source={MEMORY_DIR}", "--remote=origin", "--push"],
|
|
105
|
+
capture_output=True, text=True,
|
|
106
|
+
)
|
|
107
|
+
if result.returncode == 0:
|
|
108
|
+
console.print(" [green][✓] Private GitHub memory repository created and pushed![/]")
|
|
109
|
+
else:
|
|
110
|
+
_print_manual_push(repo_name)
|
|
111
|
+
else:
|
|
112
|
+
console.print(" [yellow][!] GitHub CLI ('gh') not found. Install it or connect manually:[/]")
|
|
113
|
+
_print_manual_push(repo_name)
|
|
114
|
+
|
|
115
|
+
console.print(f"\n[bold green]🎉 Central Memory Initialized![/]")
|
|
116
|
+
console.print(f" [yellow]Local Brain:[/] {MEMORY_DIR}")
|
|
117
|
+
console.print(f" [green]Sync Command:[/] init-context memory push\n")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _print_manual_push(repo_name: str) -> None:
|
|
121
|
+
console.print(f" [dim]git -C \"{MEMORY_DIR}\" remote add origin git@github.com:<username>/{repo_name}.git[/]")
|
|
122
|
+
console.print(f" [dim]git -C \"{MEMORY_DIR}\" push -u origin main[/]")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _write_profile(repo_name: str) -> None:
|
|
126
|
+
profile = MEMORY_DIR / "profile.md"
|
|
127
|
+
if profile.exists():
|
|
128
|
+
return
|
|
129
|
+
import getpass
|
|
130
|
+
username = getpass.getuser()
|
|
131
|
+
date_now = datetime.now().strftime("%Y-%m-%d")
|
|
132
|
+
profile.write_text(
|
|
133
|
+
f"# Agent Memory & Developer Profile\n\n"
|
|
134
|
+
f"> **Owner:** {username} \n"
|
|
135
|
+
f"> **Initialized:** {date_now} \n"
|
|
136
|
+
f"> **Repository:** {repo_name} \n"
|
|
137
|
+
f"> **Visibility:** Private Central Agent Brain \n\n---\n\n"
|
|
138
|
+
f"## 1. Developer Preferences\n- Edit this file to personalise agent behaviour.\n\n"
|
|
139
|
+
f"## 2. Central Knowledge Base Index\n"
|
|
140
|
+
f"- **Global Rules:** `rules/`\n"
|
|
141
|
+
f"- **Reusable Skills:** `skills/`\n",
|
|
142
|
+
encoding="utf-8",
|
|
143
|
+
)
|
|
144
|
+
console.print(" [green][✓] Generated Developer Profile: profile.md[/]")
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# ── local harvester ─────────────────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
def _sync_local_to_memory(project_dir: Path) -> int:
|
|
150
|
+
"""Harvest newly created local project rules & skills into central memory."""
|
|
151
|
+
harvested = 0
|
|
152
|
+
try:
|
|
153
|
+
local_rules = project_dir / config.AGENTS_SUBDIR / "rules"
|
|
154
|
+
if local_rules.exists():
|
|
155
|
+
(MEMORY_DIR / "rules").mkdir(parents=True, exist_ok=True)
|
|
156
|
+
for rfile in local_rules.glob("*.md"):
|
|
157
|
+
# Skip standard default boilerplates from polluting memory if already synced
|
|
158
|
+
dest = MEMORY_DIR / "rules" / rfile.name
|
|
159
|
+
if not dest.exists():
|
|
160
|
+
shutil.copy2(rfile, dest)
|
|
161
|
+
harvested += 1
|
|
162
|
+
console.print(f" [green][✓] Harvested local rule to Central Memory:[/] {rfile.name}")
|
|
163
|
+
elif rfile.stat().st_mtime > dest.stat().st_mtime:
|
|
164
|
+
shutil.copy2(rfile, dest)
|
|
165
|
+
harvested += 1
|
|
166
|
+
console.print(f" [green][✓] Updated local rule in Central Memory:[/] {rfile.name}")
|
|
167
|
+
|
|
168
|
+
local_skills = project_dir / config.AGENTS_SUBDIR / "skills"
|
|
169
|
+
if local_skills.exists():
|
|
170
|
+
(MEMORY_DIR / "skills").mkdir(parents=True, exist_ok=True)
|
|
171
|
+
for sdir in local_skills.iterdir():
|
|
172
|
+
if sdir.is_dir() and (sdir / "SKILL.md").exists():
|
|
173
|
+
dest_dir = MEMORY_DIR / "skills" / sdir.name
|
|
174
|
+
dest_file = dest_dir / "SKILL.md"
|
|
175
|
+
src_file = sdir / "SKILL.md"
|
|
176
|
+
if not dest_file.exists() or src_file.stat().st_mtime > dest_file.stat().st_mtime:
|
|
177
|
+
dest_dir.mkdir(parents=True, exist_ok=True)
|
|
178
|
+
shutil.copy2(src_file, dest_file)
|
|
179
|
+
harvested += 1
|
|
180
|
+
console.print(f" [green][✓] Harvested local skill to Central Memory:[/] {sdir.name}")
|
|
181
|
+
except OSError:
|
|
182
|
+
pass
|
|
183
|
+
return harvested
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
# ── push ──────────────────────────────────────────────────────────────────────
|
|
187
|
+
|
|
188
|
+
@app.command("push")
|
|
189
|
+
def memory_push(
|
|
190
|
+
harvest: Annotated[bool, typer.Option("--harvest/--no-harvest", "-h/-n", help="Auto-harvest local workspace rules/skills into central memory.")] = True,
|
|
191
|
+
) -> None:
|
|
192
|
+
"""Audit secrets and push memory brain to private GitHub repo."""
|
|
193
|
+
console.print(Panel(
|
|
194
|
+
"[bold green]🧠 Synchronizing Central Memory Brain[/]\n"
|
|
195
|
+
f"[yellow] Location:[/] {MEMORY_DIR}",
|
|
196
|
+
border_style="cyan",
|
|
197
|
+
))
|
|
198
|
+
|
|
199
|
+
try:
|
|
200
|
+
if not MEMORY_DIR.exists():
|
|
201
|
+
console.print(f"[red][✗] Memory directory not found:[/] {MEMORY_DIR}")
|
|
202
|
+
console.print(" Run: [cyan]init-context memory init[/]")
|
|
203
|
+
raise typer.Exit(1)
|
|
204
|
+
|
|
205
|
+
# Harvest local rules/skills if in a project directory
|
|
206
|
+
if harvest:
|
|
207
|
+
_sync_local_to_memory(Path.cwd().resolve())
|
|
208
|
+
|
|
209
|
+
console.print(" [cyan][*] Running Zero-Bypass Security Auditor...[/]")
|
|
210
|
+
violations = security.audit_path(MEMORY_DIR)
|
|
211
|
+
security.abort_if_violations(violations)
|
|
212
|
+
|
|
213
|
+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
|
|
214
|
+
_git(MEMORY_DIR, "add", "-A", check=False)
|
|
215
|
+
_git(MEMORY_DIR, "commit", "-m", f"{config.GIT_COMMIT_SYNC} [{timestamp}]", check=False)
|
|
216
|
+
|
|
217
|
+
remote = _git(MEMORY_DIR, "remote", "get-url", "origin", check=False).stdout.strip()
|
|
218
|
+
if remote:
|
|
219
|
+
console.print(" [cyan][*] Pushing to private remote repository...[/]")
|
|
220
|
+
result = _git(MEMORY_DIR, "push", "origin", "main", check=False)
|
|
221
|
+
if result.returncode == 0:
|
|
222
|
+
console.print(" [green][✓] Memory brain pushed successfully![/]")
|
|
223
|
+
else:
|
|
224
|
+
console.print(f" [red][✗] Push failed:[/] {result.stderr.strip()}")
|
|
225
|
+
else:
|
|
226
|
+
console.print(" [yellow][!] No remote 'origin' configured. Run memory init first.[/]")
|
|
227
|
+
|
|
228
|
+
console.print("\n[bold green]✨ Memory synchronization complete![/]\n")
|
|
229
|
+
|
|
230
|
+
except PermissionError as pe:
|
|
231
|
+
console.print(Panel(
|
|
232
|
+
f"[bold red][✗] Permission Denied Accessing Central Memory[/]\n"
|
|
233
|
+
f"[yellow] Path:[/] {MEMORY_DIR}\n\n"
|
|
234
|
+
f"[white] Cause:[/] Running inside a restricted sandbox without host filesystem access.\n"
|
|
235
|
+
f"[cyan] Fix:[/] Run this command in your external terminal (PowerShell / Bash), or enable unsandboxed mode.",
|
|
236
|
+
border_style="red",
|
|
237
|
+
))
|
|
238
|
+
raise typer.Exit(1)
|
|
239
|
+
except OSError as err:
|
|
240
|
+
console.print(f"[red][✗] Central memory error:[/] {err}")
|
|
241
|
+
raise typer.Exit(1)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# ── pull ──────────────────────────────────────────────────────────────────────
|
|
245
|
+
|
|
246
|
+
@app.command("pull")
|
|
247
|
+
def memory_pull(
|
|
248
|
+
repo_url: Annotated[Optional[str], typer.Argument(help="Remote repo URL (required for first pull).")] = None,
|
|
249
|
+
) -> None:
|
|
250
|
+
"""Pull and sync the central memory brain from remote."""
|
|
251
|
+
console.print(Panel(
|
|
252
|
+
"[bold green]🧠 Pulling Central Memory Brain[/]",
|
|
253
|
+
border_style="cyan",
|
|
254
|
+
))
|
|
255
|
+
|
|
256
|
+
try:
|
|
257
|
+
if not MEMORY_DIR.exists():
|
|
258
|
+
if not repo_url:
|
|
259
|
+
console.print("[red][✗] Memory directory not found. Provide a repo URL:[/]")
|
|
260
|
+
console.print(" [cyan]init-context memory pull <url>[/]")
|
|
261
|
+
raise typer.Exit(1)
|
|
262
|
+
subprocess.run(["git", "clone", repo_url, str(MEMORY_DIR)], check=True)
|
|
263
|
+
else:
|
|
264
|
+
_git(MEMORY_DIR, "pull", "origin", "main")
|
|
265
|
+
|
|
266
|
+
console.print(" [cyan][*] Running post-pull security audit...[/]")
|
|
267
|
+
violations = security.audit_path(MEMORY_DIR)
|
|
268
|
+
security.abort_if_violations(violations)
|
|
269
|
+
console.print("\n[bold green]✨ Central memory updated successfully![/]\n")
|
|
270
|
+
|
|
271
|
+
except PermissionError as pe:
|
|
272
|
+
console.print(Panel(
|
|
273
|
+
f"[bold red][✗] Permission Denied Accessing Central Memory[/]\n"
|
|
274
|
+
f"[yellow] Path:[/] {MEMORY_DIR}\n\n"
|
|
275
|
+
f"[white] Fix:[/] Run in external terminal or enable unsandboxed execution mode.",
|
|
276
|
+
border_style="red",
|
|
277
|
+
))
|
|
278
|
+
raise typer.Exit(1)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
# ── status ────────────────────────────────────────────────────────────────────
|
|
282
|
+
|
|
283
|
+
@app.command("status")
|
|
284
|
+
def memory_status() -> None:
|
|
285
|
+
"""Show status of the central memory brain."""
|
|
286
|
+
console.print(Panel(
|
|
287
|
+
"[bold green]🧠 Central Memory Status[/]",
|
|
288
|
+
border_style="cyan",
|
|
289
|
+
))
|
|
290
|
+
|
|
291
|
+
try:
|
|
292
|
+
if not MEMORY_DIR.exists():
|
|
293
|
+
console.print(" [yellow][!] Central memory not initialized.[/]")
|
|
294
|
+
console.print(" Run: [cyan]init-context memory init[/]")
|
|
295
|
+
return
|
|
296
|
+
|
|
297
|
+
remote = _git(MEMORY_DIR, "remote", "get-url", "origin", check=False).stdout.strip()
|
|
298
|
+
rules_path = MEMORY_DIR / "rules"
|
|
299
|
+
skills_path = MEMORY_DIR / "skills"
|
|
300
|
+
|
|
301
|
+
rules_count = len(list(rules_path.glob("*.md"))) if rules_path.exists() else 0
|
|
302
|
+
skills_count = len([d for d in skills_path.iterdir() if d.is_dir()]) if skills_path.exists() else 0
|
|
303
|
+
|
|
304
|
+
console.print(f" [yellow]Location:[/] {MEMORY_DIR}")
|
|
305
|
+
console.print(f" [cyan]Remote: [/] {remote or '(none)'}")
|
|
306
|
+
console.print(f" [green]Rules: [/] {rules_count} registered")
|
|
307
|
+
console.print(f" [green]Skills: [/] {skills_count} registered")
|
|
308
|
+
console.print()
|
|
309
|
+
|
|
310
|
+
except PermissionError:
|
|
311
|
+
console.print(Panel(
|
|
312
|
+
f"[bold red][✗] Permission Denied Accessing Central Memory[/]\n"
|
|
313
|
+
f"[yellow] Path:[/] {MEMORY_DIR}\n\n"
|
|
314
|
+
f"[white] Cause:[/] Sandboxed IDE terminal lacks access to host directory ~/.auto-context.\n"
|
|
315
|
+
f"[cyan] Fix:[/] Run 'init-context memory status' in your host terminal (PowerShell / Bash), or grant filesystem access.",
|
|
316
|
+
border_style="red",
|
|
317
|
+
))
|
|
318
|
+
except OSError as err:
|
|
319
|
+
console.print(f" [yellow][!] Central memory status warning:[/] {err}")
|
|
320
|
+
|
|
@@ -29,6 +29,7 @@ app.add_typer(mcp.app, name="mcp", help="MCP tool registry management.")
|
|
|
29
29
|
app.command("init")(init_cmd.init)
|
|
30
30
|
app.command("rule")(init_cmd.new_rule)
|
|
31
31
|
app.command("skill")(init_cmd.new_skill)
|
|
32
|
+
app.command("promote")(init_cmd.promote)
|
|
32
33
|
app.command("share")(share.share)
|
|
33
34
|
app.command("import")(import_cmd.import_item)
|
|
34
35
|
|
|
@@ -65,7 +66,7 @@ def root(
|
|
|
65
66
|
try:
|
|
66
67
|
v = pkg_version("auto-context")
|
|
67
68
|
except Exception:
|
|
68
|
-
v = "1.0.
|
|
69
|
+
v = "1.0.1"
|
|
69
70
|
console.print(f"init-context v{v}")
|
|
70
71
|
raise typer.Exit()
|
|
71
72
|
|
{auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/AGENTS.template.md
RENAMED
|
@@ -17,10 +17,12 @@ Whenever you learn a new pattern, receive a correction, observe a coding prefere
|
|
|
17
17
|
1. **Identify the Type:**
|
|
18
18
|
- **Rule:** If it is a constraint, coding standard, safety boundary, or architectural preference -> Create a Rule (`init-context -r <name>`).
|
|
19
19
|
- **Skill:** If it is a multi-step procedure, deployment workflow, diagnosis runbook, or CLI sequence -> Create a Skill (`init-context -s <name>`).
|
|
20
|
-
2. **
|
|
21
|
-
- **
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
2. **Zero Token Waste:**
|
|
21
|
+
- **DO NOT burn tokens manually searching directories or reading files to check for existing rules.** Directly run `init-context -r <name> [-g]` — the CLI has instant built-in duplicate detection and collision guards.
|
|
22
|
+
3. **Mandatory Global Scope:**
|
|
23
|
+
- When the user mentions "for future", "always", or defines a reusable standard, **MANDATORY: Always pass `--global` (`-g`)** and immediately follow with `init-context memory push`.
|
|
24
|
+
- **Project-Specific:** Only omit `-g` if strictly confined to this specific project repository.
|
|
25
|
+
4. **Execution:**
|
|
24
26
|
- Use the `init-context` CLI tool to scaffold the file.
|
|
25
27
|
- Populate it with clear objectives, constraints, or step-by-step instructions.
|
|
26
28
|
- Inform the user of the new rule or skill codified.
|
|
@@ -30,6 +32,7 @@ You have native access to run `init-context` via terminal commands:
|
|
|
30
32
|
- `init-context`: Scaffolds or repairs project context.
|
|
31
33
|
- `init-context -r <rule-name> [-g]`: Creates a new rule with frontmatter.
|
|
32
34
|
- `init-context -s <skill-name> [-g]`: Creates a new skill with frontmatter.
|
|
35
|
+
- `init-context memory push`: Synchronizes central brain memory to private Git repository.
|
|
33
36
|
|
|
34
37
|
### 4. Required Content & Structure in `context.md`
|
|
35
38
|
1. **Master Credentials & Configuration Vault (Section 1):** Keep all ports, IPs, secrets, tokens, and endpoints synchronized.
|
{auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/GEMINI.template.md
RENAMED
|
@@ -17,10 +17,12 @@ Whenever you learn a new pattern, receive a correction, observe a coding prefere
|
|
|
17
17
|
1. **Identify the Type:**
|
|
18
18
|
- **Rule:** If it is a constraint, coding standard, safety boundary, or architectural preference -> Create a Rule (`init-context -r <name>`).
|
|
19
19
|
- **Skill:** If it is a multi-step procedure, deployment workflow, diagnosis runbook, or CLI sequence -> Create a Skill (`init-context -s <name>`).
|
|
20
|
-
2. **
|
|
21
|
-
- **
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
2. **Zero Token Waste:**
|
|
21
|
+
- **DO NOT burn tokens manually searching directories or reading files to check for existing rules.** Directly run `init-context -r <name> [-g]` — the CLI has instant built-in duplicate detection and collision guards.
|
|
22
|
+
3. **Mandatory Global Scope:**
|
|
23
|
+
- When the user mentions "for future", "always", or defines a reusable standard, **MANDATORY: Always pass `--global` (`-g`)** and immediately follow with `init-context memory push`.
|
|
24
|
+
- **Project-Specific:** Only omit `-g` if strictly confined to this specific project repository.
|
|
25
|
+
4. **Execution:**
|
|
24
26
|
- Use the `init-context` CLI tool to scaffold the file.
|
|
25
27
|
- Populate it with clear objectives, constraints, or step-by-step instructions.
|
|
26
28
|
- Inform the user of the new rule or skill codified.
|
|
@@ -30,6 +32,7 @@ You have native access to run `init-context` via terminal commands:
|
|
|
30
32
|
- `init-context`: Scaffolds or repairs project context.
|
|
31
33
|
- `init-context -r <rule-name> [-g]`: Creates a new rule with frontmatter.
|
|
32
34
|
- `init-context -s <skill-name> [-g]`: Creates a new skill with frontmatter.
|
|
35
|
+
- `init-context memory push`: Synchronizes central brain memory to private Git repository.
|
|
33
36
|
|
|
34
37
|
### 4. Required Content & Structure in `context.md`
|
|
35
38
|
1. **Master Credentials & Configuration Vault (Section 1):** Keep all ports, IPs, secrets, tokens, and endpoints synchronized.
|
|
@@ -13,16 +13,16 @@ trigger: always_on
|
|
|
13
13
|
- Architectural decisions or operational runbooks.
|
|
14
14
|
|
|
15
15
|
2. **Autonomous Learning & Skill Crystallization**:
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- Populates the file with clear instructions and notifies the user.
|
|
16
|
+
- **Zero Token Waste:** DO NOT burn tokens manually searching directories or reading files to check for existing rules. Directly run `init-context -r <name> [-g]` — the CLI has instant built-in duplicate detection and collision guards.
|
|
17
|
+
- **Mandatory Global Scope:** When the user mentions "for future", "always", or defines a reusable standard, **MANDATORY: Always pass `--global` (`-g`)** and immediately follow with `init-context memory push`.
|
|
18
|
+
- Populates the file with clear instructions and notifies the user.
|
|
20
19
|
|
|
21
20
|
3. **CLI Tool Availability**:
|
|
22
21
|
- The agent has full access to run `init-context` directly via terminal:
|
|
23
22
|
- `init-context`: Initialize/repair context.
|
|
24
23
|
- `init-context -r <name> [-g]`: Create rule.
|
|
25
24
|
- `init-context -s <name> [-g]`: Create skill.
|
|
25
|
+
- `init-context memory push`: Push updates to central memory.
|
|
26
26
|
|
|
27
27
|
4. **No User Reminder Needed**: The user must never need to ask the agent to update `context.md` or learn rules. This is a strict automated post-condition for all actions.
|
|
28
28
|
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
commands/memory.py — Central memory brain management.
|
|
3
|
-
|
|
4
|
-
Wraps git CLI via subprocess.run. Runs security.audit_path()
|
|
5
|
-
before every commit or push — zero-bypass hard-block.
|
|
6
|
-
|
|
7
|
-
Subcommands: init, push, pull, status
|
|
8
|
-
"""
|
|
9
|
-
from __future__ import annotations
|
|
10
|
-
|
|
11
|
-
import shutil
|
|
12
|
-
import subprocess
|
|
13
|
-
from datetime import datetime
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
from typing import Annotated, Optional
|
|
16
|
-
|
|
17
|
-
import typer
|
|
18
|
-
from rich.console import Console
|
|
19
|
-
from rich.panel import Panel
|
|
20
|
-
|
|
21
|
-
from auto_context import config, security
|
|
22
|
-
|
|
23
|
-
app = typer.Typer(help="Central memory brain management.")
|
|
24
|
-
console = Console()
|
|
25
|
-
|
|
26
|
-
MEMORY_DIR = config.MEMORY_DIR
|
|
27
|
-
|
|
28
|
-
_GITIGNORE_ENTRIES = """\
|
|
29
|
-
# Security: Prohibit credentials and environment files from central memory
|
|
30
|
-
.env
|
|
31
|
-
.env.*
|
|
32
|
-
*.local.md
|
|
33
|
-
context.local.md
|
|
34
|
-
*.key
|
|
35
|
-
*.pem
|
|
36
|
-
*.p12
|
|
37
|
-
*.pfx
|
|
38
|
-
*.kdbx
|
|
39
|
-
id_rsa*
|
|
40
|
-
id_ed25519*
|
|
41
|
-
id_ecdsa*
|
|
42
|
-
id_dsa*
|
|
43
|
-
authorized_keys
|
|
44
|
-
known_hosts
|
|
45
|
-
"""
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def _git(cwd: Path, *args: str, check: bool = True) -> subprocess.CompletedProcess:
|
|
49
|
-
"""Run a git command in *cwd*, capturing output."""
|
|
50
|
-
return subprocess.run(
|
|
51
|
-
["git", "-C", str(cwd), *args],
|
|
52
|
-
capture_output=True,
|
|
53
|
-
text=True,
|
|
54
|
-
check=check,
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def _has_gh() -> bool:
|
|
59
|
-
return shutil.which("gh") is not None
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
# ── init ──────────────────────────────────────────────────────────────────────
|
|
63
|
-
|
|
64
|
-
@app.command("init")
|
|
65
|
-
def memory_init(
|
|
66
|
-
repo_name: Annotated[str, typer.Argument(help="GitHub repo name.")] = "auto-context-memory",
|
|
67
|
-
) -> None:
|
|
68
|
-
"""Initialize a private central memory brain repository."""
|
|
69
|
-
console.print(Panel(
|
|
70
|
-
f"[bold green]🧠 Initializing Private Central Memory Brain[/]\n"
|
|
71
|
-
f"[yellow] Directory:[/] {MEMORY_DIR}\n"
|
|
72
|
-
f"[cyan] Repo: [/] {repo_name} (Strictly Private)",
|
|
73
|
-
border_style="cyan",
|
|
74
|
-
))
|
|
75
|
-
|
|
76
|
-
(MEMORY_DIR / "rules").mkdir(parents=True, exist_ok=True)
|
|
77
|
-
(MEMORY_DIR / "skills").mkdir(parents=True, exist_ok=True)
|
|
78
|
-
|
|
79
|
-
# Init git repo
|
|
80
|
-
if not (MEMORY_DIR / ".git").exists():
|
|
81
|
-
_git(MEMORY_DIR, "init")
|
|
82
|
-
console.print(" [green][✓] Initialized Git repository[/]")
|
|
83
|
-
|
|
84
|
-
# Hardened .gitignore
|
|
85
|
-
(MEMORY_DIR / ".gitignore").write_text(_GITIGNORE_ENTRIES, encoding="utf-8")
|
|
86
|
-
console.print(" [green][✓] Hardened .gitignore written[/]")
|
|
87
|
-
|
|
88
|
-
# profile.md
|
|
89
|
-
_write_profile(repo_name)
|
|
90
|
-
|
|
91
|
-
# Security audit before first commit
|
|
92
|
-
console.print(" [cyan][*] Running pre-commit security audit...[/]")
|
|
93
|
-
violations = security.audit_path(MEMORY_DIR)
|
|
94
|
-
security.abort_if_violations(violations)
|
|
95
|
-
|
|
96
|
-
_git(MEMORY_DIR, "add", "-A", check=False)
|
|
97
|
-
_git(MEMORY_DIR, "commit", "-m", config.GIT_COMMIT_INIT, check=False)
|
|
98
|
-
_git(MEMORY_DIR, "branch", "-M", "main", check=False)
|
|
99
|
-
|
|
100
|
-
if _has_gh():
|
|
101
|
-
console.print(" [cyan][*] Creating strictly private GitHub repository via gh...[/]")
|
|
102
|
-
result = subprocess.run(
|
|
103
|
-
["gh", "repo", "create", repo_name,
|
|
104
|
-
"--private", f"--source={MEMORY_DIR}", "--remote=origin", "--push"],
|
|
105
|
-
capture_output=True, text=True,
|
|
106
|
-
)
|
|
107
|
-
if result.returncode == 0:
|
|
108
|
-
console.print(" [green][✓] Private GitHub memory repository created and pushed![/]")
|
|
109
|
-
else:
|
|
110
|
-
_print_manual_push(repo_name)
|
|
111
|
-
else:
|
|
112
|
-
console.print(" [yellow][!] GitHub CLI ('gh') not found. Install it or connect manually:[/]")
|
|
113
|
-
_print_manual_push(repo_name)
|
|
114
|
-
|
|
115
|
-
console.print(f"\n[bold green]🎉 Central Memory Initialized![/]")
|
|
116
|
-
console.print(f" [yellow]Local Brain:[/] {MEMORY_DIR}")
|
|
117
|
-
console.print(f" [green]Sync Command:[/] init-context memory push\n")
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def _print_manual_push(repo_name: str) -> None:
|
|
121
|
-
console.print(f" [dim]git -C \"{MEMORY_DIR}\" remote add origin git@github.com:<username>/{repo_name}.git[/]")
|
|
122
|
-
console.print(f" [dim]git -C \"{MEMORY_DIR}\" push -u origin main[/]")
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def _write_profile(repo_name: str) -> None:
|
|
126
|
-
profile = MEMORY_DIR / "profile.md"
|
|
127
|
-
if profile.exists():
|
|
128
|
-
return
|
|
129
|
-
import getpass
|
|
130
|
-
username = getpass.getuser()
|
|
131
|
-
date_now = datetime.now().strftime("%Y-%m-%d")
|
|
132
|
-
profile.write_text(
|
|
133
|
-
f"# Agent Memory & Developer Profile\n\n"
|
|
134
|
-
f"> **Owner:** {username} \n"
|
|
135
|
-
f"> **Initialized:** {date_now} \n"
|
|
136
|
-
f"> **Repository:** {repo_name} \n"
|
|
137
|
-
f"> **Visibility:** Private Central Agent Brain \n\n---\n\n"
|
|
138
|
-
f"## 1. Developer Preferences\n- Edit this file to personalise agent behaviour.\n\n"
|
|
139
|
-
f"## 2. Central Knowledge Base Index\n"
|
|
140
|
-
f"- **Global Rules:** `rules/`\n"
|
|
141
|
-
f"- **Reusable Skills:** `skills/`\n",
|
|
142
|
-
encoding="utf-8",
|
|
143
|
-
)
|
|
144
|
-
console.print(" [green][✓] Generated Developer Profile: profile.md[/]")
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
# ── push ──────────────────────────────────────────────────────────────────────
|
|
148
|
-
|
|
149
|
-
@app.command("push")
|
|
150
|
-
def memory_push() -> None:
|
|
151
|
-
"""Audit secrets and push memory brain to private GitHub repo."""
|
|
152
|
-
console.print(Panel(
|
|
153
|
-
"[bold green]🧠 Synchronizing Central Memory Brain[/]\n"
|
|
154
|
-
f"[yellow] Location:[/] {MEMORY_DIR}",
|
|
155
|
-
border_style="cyan",
|
|
156
|
-
))
|
|
157
|
-
|
|
158
|
-
if not MEMORY_DIR.exists():
|
|
159
|
-
console.print(f"[red][✗] Memory directory not found:[/] {MEMORY_DIR}")
|
|
160
|
-
console.print(" Run: [cyan]init-context memory init[/]")
|
|
161
|
-
raise typer.Exit(1)
|
|
162
|
-
|
|
163
|
-
console.print(" [cyan][*] Running Zero-Bypass Security Auditor...[/]")
|
|
164
|
-
violations = security.audit_path(MEMORY_DIR)
|
|
165
|
-
security.abort_if_violations(violations)
|
|
166
|
-
|
|
167
|
-
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
|
|
168
|
-
_git(MEMORY_DIR, "add", "-A", check=False)
|
|
169
|
-
_git(MEMORY_DIR, "commit", "-m", f"{config.GIT_COMMIT_SYNC} [{timestamp}]", check=False)
|
|
170
|
-
|
|
171
|
-
remote = _git(MEMORY_DIR, "remote", "get-url", "origin", check=False).stdout.strip()
|
|
172
|
-
if remote:
|
|
173
|
-
console.print(" [cyan][*] Pushing to private remote repository...[/]")
|
|
174
|
-
result = _git(MEMORY_DIR, "push", "origin", "main", check=False)
|
|
175
|
-
if result.returncode == 0:
|
|
176
|
-
console.print(" [green][✓] Memory brain pushed successfully![/]")
|
|
177
|
-
else:
|
|
178
|
-
console.print(f" [red][✗] Push failed:[/] {result.stderr.strip()}")
|
|
179
|
-
else:
|
|
180
|
-
console.print(" [yellow][!] No remote 'origin' configured. Run memory init first.[/]")
|
|
181
|
-
|
|
182
|
-
console.print("\n[bold green]✨ Memory synchronization complete![/]\n")
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
# ── pull ──────────────────────────────────────────────────────────────────────
|
|
186
|
-
|
|
187
|
-
@app.command("pull")
|
|
188
|
-
def memory_pull(
|
|
189
|
-
repo_url: Annotated[Optional[str], typer.Argument(help="Remote repo URL (required for first pull).")] = None,
|
|
190
|
-
) -> None:
|
|
191
|
-
"""Pull and sync the central memory brain from remote."""
|
|
192
|
-
console.print(Panel(
|
|
193
|
-
"[bold green]🧠 Pulling Central Memory Brain[/]",
|
|
194
|
-
border_style="cyan",
|
|
195
|
-
))
|
|
196
|
-
|
|
197
|
-
if not MEMORY_DIR.exists():
|
|
198
|
-
if not repo_url:
|
|
199
|
-
console.print("[red][✗] Memory directory not found. Provide a repo URL:[/]")
|
|
200
|
-
console.print(" [cyan]init-context memory pull <url>[/]")
|
|
201
|
-
raise typer.Exit(1)
|
|
202
|
-
subprocess.run(["git", "clone", repo_url, str(MEMORY_DIR)], check=True)
|
|
203
|
-
else:
|
|
204
|
-
_git(MEMORY_DIR, "pull", "origin", "main")
|
|
205
|
-
|
|
206
|
-
console.print(" [cyan][*] Running post-pull security audit...[/]")
|
|
207
|
-
violations = security.audit_path(MEMORY_DIR)
|
|
208
|
-
security.abort_if_violations(violations)
|
|
209
|
-
console.print("\n[bold green]✨ Central memory updated successfully![/]\n")
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
# ── status ────────────────────────────────────────────────────────────────────
|
|
213
|
-
|
|
214
|
-
@app.command("status")
|
|
215
|
-
def memory_status() -> None:
|
|
216
|
-
"""Show status of the central memory brain."""
|
|
217
|
-
console.print(Panel(
|
|
218
|
-
"[bold green]🧠 Central Memory Status[/]",
|
|
219
|
-
border_style="cyan",
|
|
220
|
-
))
|
|
221
|
-
|
|
222
|
-
if not MEMORY_DIR.exists():
|
|
223
|
-
console.print(" [yellow][!] Central memory not initialized.[/]")
|
|
224
|
-
console.print(" Run: [cyan]init-context memory init[/]")
|
|
225
|
-
return
|
|
226
|
-
|
|
227
|
-
remote = _git(MEMORY_DIR, "remote", "get-url", "origin", check=False).stdout.strip()
|
|
228
|
-
rules_count = len(list((MEMORY_DIR / "rules").glob("*.md"))) if (MEMORY_DIR / "rules").exists() else 0
|
|
229
|
-
skills_count = len([d for d in (MEMORY_DIR / "skills").iterdir() if d.is_dir()]) if (MEMORY_DIR / "skills").exists() else 0
|
|
230
|
-
|
|
231
|
-
console.print(f" [yellow]Location:[/] {MEMORY_DIR}")
|
|
232
|
-
console.print(f" [cyan]Remote: [/] {remote or '(none)'}")
|
|
233
|
-
console.print(f" [green]Rules: [/] {rules_count} registered")
|
|
234
|
-
console.print(f" [green]Skills: [/] {skills_count} registered")
|
|
235
|
-
console.print()
|
|
236
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/context.template.md
RENAMED
|
File without changes
|
|
File without changes
|
{auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/profile.template.md
RENAMED
|
File without changes
|
{auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/rule.template.md
RENAMED
|
File without changes
|
{auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/rules/code-standards.md
RENAMED
|
File without changes
|
|
File without changes
|
{auto_context_cli-1.0.0 → auto_context_cli-1.0.1}/src/auto_context/templates/skill.template.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|