ctxl-cli 0.1.0__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.
- ctxl_cli-0.1.0/LICENSE +21 -0
- ctxl_cli-0.1.0/PKG-INFO +175 -0
- ctxl_cli-0.1.0/README.md +136 -0
- ctxl_cli-0.1.0/ctxl/__init__.py +3 -0
- ctxl_cli-0.1.0/ctxl/checkpoint.py +130 -0
- ctxl_cli-0.1.0/ctxl/cli.py +272 -0
- ctxl_cli-0.1.0/ctxl/init.py +92 -0
- ctxl_cli-0.1.0/ctxl/mapper.py +439 -0
- ctxl_cli-0.1.0/ctxl_cli.egg-info/PKG-INFO +175 -0
- ctxl_cli-0.1.0/ctxl_cli.egg-info/SOURCES.txt +14 -0
- ctxl_cli-0.1.0/ctxl_cli.egg-info/dependency_links.txt +1 -0
- ctxl_cli-0.1.0/ctxl_cli.egg-info/entry_points.txt +2 -0
- ctxl_cli-0.1.0/ctxl_cli.egg-info/requires.txt +15 -0
- ctxl_cli-0.1.0/ctxl_cli.egg-info/top_level.txt +1 -0
- ctxl_cli-0.1.0/pyproject.toml +56 -0
- ctxl_cli-0.1.0/setup.cfg +4 -0
ctxl_cli-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Prashanth Reddy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
ctxl_cli-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ctxl-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Context Engineering CLI — Reduce AI agent token waste with compressed codebase skeletons, task-focused instructions, and session checkpoints. Zero AI, pure parsing.
|
|
5
|
+
Author: Prashanth Reddy
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/prashanthreddy/ctxl
|
|
8
|
+
Project-URL: Repository, https://github.com/prashanthreddy/ctxl
|
|
9
|
+
Project-URL: Issues, https://github.com/prashanthreddy/ctxl/issues
|
|
10
|
+
Keywords: context-engineering,llm,ai-agents,token-optimization,copilot,tree-sitter,codebase-map,developer-tools
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: click>=8.1
|
|
26
|
+
Requires-Dist: tree-sitter>=0.24
|
|
27
|
+
Requires-Dist: tree-sitter-python>=0.23
|
|
28
|
+
Requires-Dist: tree-sitter-javascript>=0.23
|
|
29
|
+
Requires-Dist: tree-sitter-java>=0.23
|
|
30
|
+
Requires-Dist: tree-sitter-typescript>=0.23
|
|
31
|
+
Requires-Dist: rich>=13.0
|
|
32
|
+
Provides-Extra: clipboard
|
|
33
|
+
Requires-Dist: pyperclip>=1.8; extra == "clipboard"
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
36
|
+
Requires-Dist: build; extra == "dev"
|
|
37
|
+
Requires-Dist: twine; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# ctxl — Context Engineering CLI for AI Agents
|
|
41
|
+
|
|
42
|
+
**Reduce token waste. Prevent hallucination. Zero AI used.**
|
|
43
|
+
|
|
44
|
+
`ctxl` (pronounced "contextual") is a developer CLI tool that helps you manage the context window of AI coding agents (GitHub Copilot, Cursor, Claude, etc.) by generating compressed codebase skeletons, task-focused instructions, and session checkpoints — all using deterministic parsing, not AI.
|
|
45
|
+
|
|
46
|
+
## The Problem
|
|
47
|
+
|
|
48
|
+
AI coding agents (Copilot, Cursor, etc.) read your entire codebase to build context. A 3,000-line PySpark file burns ~750 tokens every time the agent references it. Over a session, your context window fills with noise, leading to:
|
|
49
|
+
|
|
50
|
+
- 🔴 **Hallucination** — the model starts making things up
|
|
51
|
+
- 🔴 **Token waste** — you pay for irrelevant context
|
|
52
|
+
- 🔴 **Lost focus** — the agent forgets your actual task
|
|
53
|
+
|
|
54
|
+
## The Solution
|
|
55
|
+
|
|
56
|
+
`ctxl` gives you three commands that prepare your environment *before* the AI agent reads it:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
ctxl map # Generate a compressed codebase skeleton (~95% token reduction)
|
|
60
|
+
ctxl init # Generate task-focused Copilot instructions
|
|
61
|
+
ctxl checkpoint # Save session state for safe /clear workflows
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Zero AI models. Zero API calls. Zero tokens burned by this tool.**
|
|
65
|
+
|
|
66
|
+
## Installation
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pip install ctxl-cli
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Quick Start
|
|
73
|
+
|
|
74
|
+
### `ctxl map` — Codebase Skeleton
|
|
75
|
+
|
|
76
|
+
Generate a compressed structural map of your codebase with line numbers:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
ctxl map # Map current directory
|
|
80
|
+
ctxl map ./src # Map a specific directory
|
|
81
|
+
ctxl map -e .py # Only Python files
|
|
82
|
+
ctxl map -o codebase.md # Save to file
|
|
83
|
+
ctxl map --clipboard # Copy to clipboard for pasting into AI chat
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Before (raw file, ~750 tokens):**
|
|
87
|
+
```python
|
|
88
|
+
class DataPipeline:
|
|
89
|
+
def __init__(self, spark, config):
|
|
90
|
+
self.spark = spark
|
|
91
|
+
self.config = config
|
|
92
|
+
self.source_path = config.get("source_path", "/data/raw")
|
|
93
|
+
# ... 60 more lines of implementation
|
|
94
|
+
|
|
95
|
+
def clean_data(self, df, drop_nulls=True):
|
|
96
|
+
string_cols = [f.name for f in df.schema.fields ...]
|
|
97
|
+
# ... 20 more lines
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**After (`ctxl map` output, ~50 tokens):**
|
|
101
|
+
```
|
|
102
|
+
L22: class DataPipeline:
|
|
103
|
+
L25: def __init__(self, spark: SparkSession, config: Dict)
|
|
104
|
+
L33: def load_data(self, table_name: str, filters: Optional[Dict] = None) -> DataFrame
|
|
105
|
+
L42: def clean_data(self, df: DataFrame, drop_nulls: bool = True) -> DataFrame
|
|
106
|
+
L52: def transform(self, df: DataFrame, rules: List[Dict]) -> DataFrame
|
|
107
|
+
L66: def validate(self, df: DataFrame) -> bool
|
|
108
|
+
L75: def save(self, df: DataFrame, partition_cols: List[str] = None) -> str
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Line numbers (`L22:`, `L42:`) let the AI agent navigate directly to the right location.
|
|
112
|
+
|
|
113
|
+
### `ctxl init` — Copilot Instructions
|
|
114
|
+
|
|
115
|
+
Generate a `.github/copilot-instructions.md` file that GitHub Copilot reads natively:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
ctxl init "Fix the data pipeline ETL bug"
|
|
119
|
+
ctxl init "Add authentication" -f auth.py -f models.py
|
|
120
|
+
ctxl init "Refactor tests" --no-map
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `ctxl checkpoint` — Session State
|
|
124
|
+
|
|
125
|
+
Save your progress before running `/clear` in Copilot Chat:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
ctxl checkpoint save \
|
|
129
|
+
-t "Fix ETL pipeline" \
|
|
130
|
+
--done "Found the bug in clean_data()" \
|
|
131
|
+
--state "Pipeline runs but output has wrong column order" \
|
|
132
|
+
--next "Fix column ordering in transform()" \
|
|
133
|
+
--file "data_pipeline.py"
|
|
134
|
+
|
|
135
|
+
ctxl checkpoint list # List all checkpoints
|
|
136
|
+
ctxl checkpoint show # Show latest checkpoint
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Supported Languages
|
|
140
|
+
|
|
141
|
+
`ctxl map` uses [Tree-sitter](https://tree-sitter.github.io/) for parsing and supports:
|
|
142
|
+
|
|
143
|
+
| Language | Extensions |
|
|
144
|
+
|----------|-----------|
|
|
145
|
+
| Python | `.py` |
|
|
146
|
+
| JavaScript | `.js`, `.jsx` |
|
|
147
|
+
| TypeScript | `.ts`, `.tsx` |
|
|
148
|
+
| Java | `.java` |
|
|
149
|
+
|
|
150
|
+
More languages can be added easily via Tree-sitter grammars.
|
|
151
|
+
|
|
152
|
+
## How It Works
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
Your Codebase (10,000+ tokens)
|
|
156
|
+
│
|
|
157
|
+
▼
|
|
158
|
+
Tree-sitter Parser (deterministic, local, free)
|
|
159
|
+
│
|
|
160
|
+
▼
|
|
161
|
+
AST → Extract signatures + line numbers
|
|
162
|
+
│
|
|
163
|
+
▼
|
|
164
|
+
Compressed Skeleton (~500 tokens)
|
|
165
|
+
│
|
|
166
|
+
▼
|
|
167
|
+
AI Agent reads skeleton instead of raw code
|
|
168
|
+
│
|
|
169
|
+
▼
|
|
170
|
+
90-95% fewer tokens burned 🎉
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
MIT
|
ctxl_cli-0.1.0/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# ctxl — Context Engineering CLI for AI Agents
|
|
2
|
+
|
|
3
|
+
**Reduce token waste. Prevent hallucination. Zero AI used.**
|
|
4
|
+
|
|
5
|
+
`ctxl` (pronounced "contextual") is a developer CLI tool that helps you manage the context window of AI coding agents (GitHub Copilot, Cursor, Claude, etc.) by generating compressed codebase skeletons, task-focused instructions, and session checkpoints — all using deterministic parsing, not AI.
|
|
6
|
+
|
|
7
|
+
## The Problem
|
|
8
|
+
|
|
9
|
+
AI coding agents (Copilot, Cursor, etc.) read your entire codebase to build context. A 3,000-line PySpark file burns ~750 tokens every time the agent references it. Over a session, your context window fills with noise, leading to:
|
|
10
|
+
|
|
11
|
+
- 🔴 **Hallucination** — the model starts making things up
|
|
12
|
+
- 🔴 **Token waste** — you pay for irrelevant context
|
|
13
|
+
- 🔴 **Lost focus** — the agent forgets your actual task
|
|
14
|
+
|
|
15
|
+
## The Solution
|
|
16
|
+
|
|
17
|
+
`ctxl` gives you three commands that prepare your environment *before* the AI agent reads it:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
ctxl map # Generate a compressed codebase skeleton (~95% token reduction)
|
|
21
|
+
ctxl init # Generate task-focused Copilot instructions
|
|
22
|
+
ctxl checkpoint # Save session state for safe /clear workflows
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Zero AI models. Zero API calls. Zero tokens burned by this tool.**
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install ctxl-cli
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### `ctxl map` — Codebase Skeleton
|
|
36
|
+
|
|
37
|
+
Generate a compressed structural map of your codebase with line numbers:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
ctxl map # Map current directory
|
|
41
|
+
ctxl map ./src # Map a specific directory
|
|
42
|
+
ctxl map -e .py # Only Python files
|
|
43
|
+
ctxl map -o codebase.md # Save to file
|
|
44
|
+
ctxl map --clipboard # Copy to clipboard for pasting into AI chat
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Before (raw file, ~750 tokens):**
|
|
48
|
+
```python
|
|
49
|
+
class DataPipeline:
|
|
50
|
+
def __init__(self, spark, config):
|
|
51
|
+
self.spark = spark
|
|
52
|
+
self.config = config
|
|
53
|
+
self.source_path = config.get("source_path", "/data/raw")
|
|
54
|
+
# ... 60 more lines of implementation
|
|
55
|
+
|
|
56
|
+
def clean_data(self, df, drop_nulls=True):
|
|
57
|
+
string_cols = [f.name for f in df.schema.fields ...]
|
|
58
|
+
# ... 20 more lines
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**After (`ctxl map` output, ~50 tokens):**
|
|
62
|
+
```
|
|
63
|
+
L22: class DataPipeline:
|
|
64
|
+
L25: def __init__(self, spark: SparkSession, config: Dict)
|
|
65
|
+
L33: def load_data(self, table_name: str, filters: Optional[Dict] = None) -> DataFrame
|
|
66
|
+
L42: def clean_data(self, df: DataFrame, drop_nulls: bool = True) -> DataFrame
|
|
67
|
+
L52: def transform(self, df: DataFrame, rules: List[Dict]) -> DataFrame
|
|
68
|
+
L66: def validate(self, df: DataFrame) -> bool
|
|
69
|
+
L75: def save(self, df: DataFrame, partition_cols: List[str] = None) -> str
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Line numbers (`L22:`, `L42:`) let the AI agent navigate directly to the right location.
|
|
73
|
+
|
|
74
|
+
### `ctxl init` — Copilot Instructions
|
|
75
|
+
|
|
76
|
+
Generate a `.github/copilot-instructions.md` file that GitHub Copilot reads natively:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
ctxl init "Fix the data pipeline ETL bug"
|
|
80
|
+
ctxl init "Add authentication" -f auth.py -f models.py
|
|
81
|
+
ctxl init "Refactor tests" --no-map
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### `ctxl checkpoint` — Session State
|
|
85
|
+
|
|
86
|
+
Save your progress before running `/clear` in Copilot Chat:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
ctxl checkpoint save \
|
|
90
|
+
-t "Fix ETL pipeline" \
|
|
91
|
+
--done "Found the bug in clean_data()" \
|
|
92
|
+
--state "Pipeline runs but output has wrong column order" \
|
|
93
|
+
--next "Fix column ordering in transform()" \
|
|
94
|
+
--file "data_pipeline.py"
|
|
95
|
+
|
|
96
|
+
ctxl checkpoint list # List all checkpoints
|
|
97
|
+
ctxl checkpoint show # Show latest checkpoint
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Supported Languages
|
|
101
|
+
|
|
102
|
+
`ctxl map` uses [Tree-sitter](https://tree-sitter.github.io/) for parsing and supports:
|
|
103
|
+
|
|
104
|
+
| Language | Extensions |
|
|
105
|
+
|----------|-----------|
|
|
106
|
+
| Python | `.py` |
|
|
107
|
+
| JavaScript | `.js`, `.jsx` |
|
|
108
|
+
| TypeScript | `.ts`, `.tsx` |
|
|
109
|
+
| Java | `.java` |
|
|
110
|
+
|
|
111
|
+
More languages can be added easily via Tree-sitter grammars.
|
|
112
|
+
|
|
113
|
+
## How It Works
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
Your Codebase (10,000+ tokens)
|
|
117
|
+
│
|
|
118
|
+
▼
|
|
119
|
+
Tree-sitter Parser (deterministic, local, free)
|
|
120
|
+
│
|
|
121
|
+
▼
|
|
122
|
+
AST → Extract signatures + line numbers
|
|
123
|
+
│
|
|
124
|
+
▼
|
|
125
|
+
Compressed Skeleton (~500 tokens)
|
|
126
|
+
│
|
|
127
|
+
▼
|
|
128
|
+
AI Agent reads skeleton instead of raw code
|
|
129
|
+
│
|
|
130
|
+
▼
|
|
131
|
+
90-95% fewer tokens burned 🎉
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
MIT
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ctx checkpoint — Session state manager.
|
|
3
|
+
|
|
4
|
+
Tracks what the AI agent has learned during a session (files edited,
|
|
5
|
+
schemas discovered, errors resolved) and saves a compressed checkpoint.
|
|
6
|
+
This allows you to safely run /clear in Copilot Chat without losing context.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Dict, List, Optional
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
CHECKPOINT_DIR = ".ctx_checkpoints"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _ensure_dir(project_root: str) -> Path:
|
|
19
|
+
"""Ensure the checkpoint directory exists."""
|
|
20
|
+
path = Path(project_root).resolve() / CHECKPOINT_DIR
|
|
21
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
22
|
+
return path
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def create_checkpoint(
|
|
26
|
+
project_root: str,
|
|
27
|
+
task: str,
|
|
28
|
+
completed_steps: List[str],
|
|
29
|
+
current_state: str,
|
|
30
|
+
next_steps: List[str],
|
|
31
|
+
files_modified: Optional[List[str]] = None,
|
|
32
|
+
key_discoveries: Optional[List[str]] = None,
|
|
33
|
+
errors_resolved: Optional[List[str]] = None,
|
|
34
|
+
) -> str:
|
|
35
|
+
"""
|
|
36
|
+
Create a checkpoint file capturing the current session state.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
project_root: Path to the project root directory.
|
|
40
|
+
task: The high-level task description.
|
|
41
|
+
completed_steps: List of steps already completed.
|
|
42
|
+
current_state: Brief description of where things stand right now.
|
|
43
|
+
next_steps: List of planned next steps.
|
|
44
|
+
files_modified: List of files that were modified.
|
|
45
|
+
key_discoveries: Key things learned (schemas, configs, etc.).
|
|
46
|
+
errors_resolved: Errors that were encountered and resolved.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Path to the created checkpoint file.
|
|
50
|
+
"""
|
|
51
|
+
checkpoint_dir = _ensure_dir(project_root)
|
|
52
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
53
|
+
filename = f"checkpoint_{timestamp}.md"
|
|
54
|
+
filepath = checkpoint_dir / filename
|
|
55
|
+
|
|
56
|
+
lines = []
|
|
57
|
+
lines.append(f"# Session Checkpoint")
|
|
58
|
+
lines.append(f"_Saved at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}_\n")
|
|
59
|
+
|
|
60
|
+
lines.append(f"## Task")
|
|
61
|
+
lines.append(f"{task}\n")
|
|
62
|
+
|
|
63
|
+
lines.append(f"## Current State")
|
|
64
|
+
lines.append(f"{current_state}\n")
|
|
65
|
+
|
|
66
|
+
if completed_steps:
|
|
67
|
+
lines.append("## Completed Steps")
|
|
68
|
+
for step in completed_steps:
|
|
69
|
+
lines.append(f"- [x] {step}")
|
|
70
|
+
lines.append("")
|
|
71
|
+
|
|
72
|
+
if next_steps:
|
|
73
|
+
lines.append("## Next Steps")
|
|
74
|
+
for step in next_steps:
|
|
75
|
+
lines.append(f"- [ ] {step}")
|
|
76
|
+
lines.append("")
|
|
77
|
+
|
|
78
|
+
if files_modified:
|
|
79
|
+
lines.append("## Files Modified")
|
|
80
|
+
for f in files_modified:
|
|
81
|
+
lines.append(f"- `{f}`")
|
|
82
|
+
lines.append("")
|
|
83
|
+
|
|
84
|
+
if key_discoveries:
|
|
85
|
+
lines.append("## Key Discoveries")
|
|
86
|
+
for d in key_discoveries:
|
|
87
|
+
lines.append(f"- {d}")
|
|
88
|
+
lines.append("")
|
|
89
|
+
|
|
90
|
+
if errors_resolved:
|
|
91
|
+
lines.append("## Errors Resolved")
|
|
92
|
+
for e in errors_resolved:
|
|
93
|
+
lines.append(f"- {e}")
|
|
94
|
+
lines.append("")
|
|
95
|
+
|
|
96
|
+
lines.append("---")
|
|
97
|
+
lines.append("_Paste this into your active file or Copilot Chat after running `/clear`._")
|
|
98
|
+
|
|
99
|
+
content = "\n".join(lines)
|
|
100
|
+
filepath.write_text(content, encoding="utf-8")
|
|
101
|
+
|
|
102
|
+
return str(filepath)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def list_checkpoints(project_root: str) -> List[Dict]:
|
|
106
|
+
"""List all checkpoints in the project, newest first."""
|
|
107
|
+
checkpoint_dir = Path(project_root).resolve() / CHECKPOINT_DIR
|
|
108
|
+
if not checkpoint_dir.exists():
|
|
109
|
+
return []
|
|
110
|
+
|
|
111
|
+
checkpoints = []
|
|
112
|
+
for f in sorted(checkpoint_dir.glob("checkpoint_*.md"), reverse=True):
|
|
113
|
+
stat = f.stat()
|
|
114
|
+
checkpoints.append({
|
|
115
|
+
"filename": f.name,
|
|
116
|
+
"path": str(f),
|
|
117
|
+
"created": datetime.fromtimestamp(stat.st_mtime).strftime("%Y-%m-%d %H:%M:%S"),
|
|
118
|
+
"size_bytes": stat.st_size,
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
return checkpoints
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def get_latest_checkpoint(project_root: str) -> Optional[str]:
|
|
125
|
+
"""Read the content of the most recent checkpoint."""
|
|
126
|
+
checkpoints = list_checkpoints(project_root)
|
|
127
|
+
if not checkpoints:
|
|
128
|
+
return None
|
|
129
|
+
latest_path = checkpoints[0]["path"]
|
|
130
|
+
return Path(latest_path).read_text(encoding="utf-8")
|