kopipasta 0.2.0__tar.gz → 0.3.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.

Potentially problematic release.


This version of kopipasta might be problematic. Click here for more details.

@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.1
2
+ Name: kopipasta
3
+ Version: 0.3.0
4
+ Summary: A CLI tool to generate prompts with project structure and file contents
5
+ Home-page: https://github.com/mkorpela/kopipasta
6
+ Author: Mikko Korpela
7
+ Author-email: mikko.korpela@gmail.com
8
+ License: MIT
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.8
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
+ Requires-Python: >=3.8
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: pyperclip==1.9.0
23
+
24
+ # kopipasta
25
+
26
+ A CLI tool to generate prompts with project structure, file contents, and web content, while handling environment variables securely and offering snippets for large files.
27
+
28
+ <img src="kopipasta.jpg" alt="kopipasta" width="300">
29
+
30
+ ## Installation
31
+
32
+ You can install kopipasta using pipx (or pip):
33
+
34
+ ```
35
+ pipx install kopipasta
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ To use kopipasta, run the following command in your terminal:
41
+
42
+ ```
43
+ kopipasta [files_or_directories_or_urls]
44
+ ```
45
+
46
+ Replace `[files_or_directories_or_urls]` with the paths to the files or directories you want to include in the prompt, as well as any web URLs you want to fetch content from.
47
+
48
+ Example:
49
+ ```
50
+ kopipasta src/ config.json https://example.com/api-docs
51
+ ```
52
+
53
+ This will generate a prompt including:
54
+ - The project structure
55
+ - Contents of the specified files and directories (with snippet options for large files)
56
+ - Content fetched from the provided URLs (with snippet options for large content)
57
+ - Handling of environment variables found in a `.env` file (if present)
58
+
59
+ Files and directories typically excluded in version control (based on common .gitignore patterns) are ignored.
60
+
61
+ The generated prompt will be displayed in the console and automatically copied to your clipboard.
62
+
63
+ ## Features
64
+
65
+ - Generates a structured prompt with project overview, file contents, web content, and task instructions
66
+ - Offers snippet options for large files (>100 KB) and web content (>10,000 characters)
67
+ - Fetches and includes content from web URLs
68
+ - Detects and securely handles environment variables from a `.env` file
69
+ - Ignores files and directories based on common .gitignore patterns
70
+ - Allows interactive selection of files to include
71
+ - Automatically copies the generated prompt to the clipboard
72
+
73
+ ## Environment Variable Handling
74
+
75
+ If a `.env` file is present in the current directory, kopipasta will:
76
+ 1. Read and store the environment variables
77
+ 2. Detect these variables in file contents and web content
78
+ 3. Prompt you to choose how to handle each detected variable:
79
+ - (m)ask: Replace the value with asterisks
80
+ - (s)kip: Replace the value with "[REDACTED]"
81
+ - (k)eep: Leave the value as-is
82
+
83
+ This ensures sensitive information is handled securely in the generated prompt.
84
+
85
+ ## Snippet Functionality
86
+
87
+ For large files (>100 KB) and web content (>10,000 characters), kopipasta offers a snippet option:
88
+
89
+ - For files: The first 50 lines or 4 KB (4,096 bytes), whichever comes first
90
+ - For web content: The first 1,000 characters
91
+
92
+ This helps manage the overall prompt size while still providing useful information about the content structure.
93
+
94
+ ## Example output
95
+
96
+ ```bash
97
+ ❯ kopipasta . https://example.com/api-docs
98
+
99
+ Directory: .
100
+ Files:
101
+ - __init__.py
102
+ - main.py (120 KB, ~120000 chars, ~30000 tokens)
103
+ - large_data.csv (5 MB, ~5000000 chars, ~1250000 tokens)
104
+ - .env
105
+
106
+ (y)es add all / (n)o ignore all / (s)elect individually / (q)uit? y
107
+ main.py is large. Use (f)ull content or (s)nippet? s
108
+ large_data.csv is large. Use (f)ull content or (s)nippet? s
109
+ Added all files from .
110
+ Added web content from: https://example.com/api-docs
111
+
112
+ File and web content selection complete.
113
+ Current prompt size: 10500 characters (~ 2625 tokens)
114
+ Summary: Added 3 files from 1 directory and 1 web source.
115
+
116
+ Detected environment variables:
117
+ - API_KEY=12345abcde
118
+
119
+ How would you like to handle API_KEY? (m)ask / (k)eep: m
120
+
121
+ Enter the task instructions: Implement new API endpoint
122
+
123
+ Generated prompt:
124
+ # Project Overview
125
+
126
+ ## Project Structure
127
+
128
+ ```
129
+ |-- ./
130
+ |-- __init__.py
131
+ |-- main.py
132
+ |-- large_data.csv
133
+ |-- .env
134
+ ```
135
+
136
+ ## File Contents
137
+
138
+ ### __init__.py
139
+
140
+ ```python
141
+ # Initialize package
142
+ ```
143
+
144
+ ### main.py (snippet)
145
+
146
+ ```python
147
+ import os
148
+ import pandas as pd
149
+
150
+ API_KEY = os.getenv('API_KEY')
151
+
152
+ def process_data(file_path):
153
+ df = pd.read_csv(file_path)
154
+ # Rest of the function...
155
+
156
+ # More code...
157
+ ```
158
+
159
+ ### large_data.csv (snippet)
160
+
161
+ ```
162
+ id,name,value
163
+ 1,John,100
164
+ 2,Jane,200
165
+ 3,Bob,150
166
+ 4,Alice,300
167
+ # ... (first 50 lines or 4 KB)
168
+ ```
169
+
170
+ ## Web Content
171
+
172
+ ### https://example.com/api-docs (snippet)
173
+
174
+ ```
175
+ API Documentation
176
+ Endpoint: /api/v1/data
177
+ Method: GET
178
+ Authorization: Bearer **********
179
+ ...
180
+ ```
181
+
182
+ ## Task Instructions
183
+
184
+ Implement new API endpoint
185
+
186
+ ## Task Analysis and Planning
187
+
188
+ Before starting, explain the task back to me in your own words. Ask for any clarifications if needed. Once you're clear, ask to proceed.
189
+
190
+ Then, outline a plan for the task. Finally, use your plan to complete the task.
191
+
192
+ Prompt has been copied to clipboard. Final size: 1500 characters (~ 375 tokens)
193
+ ```
194
+
195
+ ## License
196
+
197
+ This project is licensed under the MIT License.
@@ -0,0 +1,174 @@
1
+ # kopipasta
2
+
3
+ A CLI tool to generate prompts with project structure, file contents, and web content, while handling environment variables securely and offering snippets for large files.
4
+
5
+ <img src="kopipasta.jpg" alt="kopipasta" width="300">
6
+
7
+ ## Installation
8
+
9
+ You can install kopipasta using pipx (or pip):
10
+
11
+ ```
12
+ pipx install kopipasta
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ To use kopipasta, run the following command in your terminal:
18
+
19
+ ```
20
+ kopipasta [files_or_directories_or_urls]
21
+ ```
22
+
23
+ Replace `[files_or_directories_or_urls]` with the paths to the files or directories you want to include in the prompt, as well as any web URLs you want to fetch content from.
24
+
25
+ Example:
26
+ ```
27
+ kopipasta src/ config.json https://example.com/api-docs
28
+ ```
29
+
30
+ This will generate a prompt including:
31
+ - The project structure
32
+ - Contents of the specified files and directories (with snippet options for large files)
33
+ - Content fetched from the provided URLs (with snippet options for large content)
34
+ - Handling of environment variables found in a `.env` file (if present)
35
+
36
+ Files and directories typically excluded in version control (based on common .gitignore patterns) are ignored.
37
+
38
+ The generated prompt will be displayed in the console and automatically copied to your clipboard.
39
+
40
+ ## Features
41
+
42
+ - Generates a structured prompt with project overview, file contents, web content, and task instructions
43
+ - Offers snippet options for large files (>100 KB) and web content (>10,000 characters)
44
+ - Fetches and includes content from web URLs
45
+ - Detects and securely handles environment variables from a `.env` file
46
+ - Ignores files and directories based on common .gitignore patterns
47
+ - Allows interactive selection of files to include
48
+ - Automatically copies the generated prompt to the clipboard
49
+
50
+ ## Environment Variable Handling
51
+
52
+ If a `.env` file is present in the current directory, kopipasta will:
53
+ 1. Read and store the environment variables
54
+ 2. Detect these variables in file contents and web content
55
+ 3. Prompt you to choose how to handle each detected variable:
56
+ - (m)ask: Replace the value with asterisks
57
+ - (s)kip: Replace the value with "[REDACTED]"
58
+ - (k)eep: Leave the value as-is
59
+
60
+ This ensures sensitive information is handled securely in the generated prompt.
61
+
62
+ ## Snippet Functionality
63
+
64
+ For large files (>100 KB) and web content (>10,000 characters), kopipasta offers a snippet option:
65
+
66
+ - For files: The first 50 lines or 4 KB (4,096 bytes), whichever comes first
67
+ - For web content: The first 1,000 characters
68
+
69
+ This helps manage the overall prompt size while still providing useful information about the content structure.
70
+
71
+ ## Example output
72
+
73
+ ```bash
74
+ ❯ kopipasta . https://example.com/api-docs
75
+
76
+ Directory: .
77
+ Files:
78
+ - __init__.py
79
+ - main.py (120 KB, ~120000 chars, ~30000 tokens)
80
+ - large_data.csv (5 MB, ~5000000 chars, ~1250000 tokens)
81
+ - .env
82
+
83
+ (y)es add all / (n)o ignore all / (s)elect individually / (q)uit? y
84
+ main.py is large. Use (f)ull content or (s)nippet? s
85
+ large_data.csv is large. Use (f)ull content or (s)nippet? s
86
+ Added all files from .
87
+ Added web content from: https://example.com/api-docs
88
+
89
+ File and web content selection complete.
90
+ Current prompt size: 10500 characters (~ 2625 tokens)
91
+ Summary: Added 3 files from 1 directory and 1 web source.
92
+
93
+ Detected environment variables:
94
+ - API_KEY=12345abcde
95
+
96
+ How would you like to handle API_KEY? (m)ask / (k)eep: m
97
+
98
+ Enter the task instructions: Implement new API endpoint
99
+
100
+ Generated prompt:
101
+ # Project Overview
102
+
103
+ ## Project Structure
104
+
105
+ ```
106
+ |-- ./
107
+ |-- __init__.py
108
+ |-- main.py
109
+ |-- large_data.csv
110
+ |-- .env
111
+ ```
112
+
113
+ ## File Contents
114
+
115
+ ### __init__.py
116
+
117
+ ```python
118
+ # Initialize package
119
+ ```
120
+
121
+ ### main.py (snippet)
122
+
123
+ ```python
124
+ import os
125
+ import pandas as pd
126
+
127
+ API_KEY = os.getenv('API_KEY')
128
+
129
+ def process_data(file_path):
130
+ df = pd.read_csv(file_path)
131
+ # Rest of the function...
132
+
133
+ # More code...
134
+ ```
135
+
136
+ ### large_data.csv (snippet)
137
+
138
+ ```
139
+ id,name,value
140
+ 1,John,100
141
+ 2,Jane,200
142
+ 3,Bob,150
143
+ 4,Alice,300
144
+ # ... (first 50 lines or 4 KB)
145
+ ```
146
+
147
+ ## Web Content
148
+
149
+ ### https://example.com/api-docs (snippet)
150
+
151
+ ```
152
+ API Documentation
153
+ Endpoint: /api/v1/data
154
+ Method: GET
155
+ Authorization: Bearer **********
156
+ ...
157
+ ```
158
+
159
+ ## Task Instructions
160
+
161
+ Implement new API endpoint
162
+
163
+ ## Task Analysis and Planning
164
+
165
+ Before starting, explain the task back to me in your own words. Ask for any clarifications if needed. Once you're clear, ask to proceed.
166
+
167
+ Then, outline a plan for the task. Finally, use your plan to complete the task.
168
+
169
+ Prompt has been copied to clipboard. Final size: 1500 characters (~ 375 tokens)
170
+ ```
171
+
172
+ ## License
173
+
174
+ This project is licensed under the MIT License.
@@ -1,9 +1,12 @@
1
1
  #!/usr/bin/env python3
2
2
  import os
3
3
  import argparse
4
+ import re
4
5
  import pyperclip
5
6
  import fnmatch
6
7
 
8
+ import requests
9
+
7
10
  def read_gitignore():
8
11
  default_ignore_patterns = [
9
12
  '.git', 'node_modules', 'venv', '.venv', 'dist', '.idea', '__pycache__',
@@ -49,6 +52,9 @@ def get_human_readable_size(size):
49
52
  return f"{size:.2f} {unit}"
50
53
  size /= 1024.0
51
54
 
55
+ def is_large_file(file_path, threshold=102400): # 100 KB threshold
56
+ return os.path.getsize(file_path) > threshold
57
+
52
58
  def get_project_structure(ignore_patterns):
53
59
  tree = []
54
60
  for root, dirs, files in os.walk('.'):
@@ -94,6 +100,17 @@ def get_language_for_file(file_path):
94
100
  }
95
101
  return language_map.get(extension, '')
96
102
 
103
+ def get_file_snippet(file_path, max_lines=50, max_bytes=4096):
104
+ snippet = ""
105
+ byte_count = 0
106
+ with open(file_path, 'r') as file:
107
+ for i, line in enumerate(file):
108
+ if i >= max_lines or byte_count >= max_bytes:
109
+ break
110
+ snippet += line
111
+ byte_count += len(line.encode('utf-8'))
112
+ return snippet
113
+
97
114
  def select_files_in_directory(directory, ignore_patterns, current_char_count=0):
98
115
  files = [f for f in os.listdir(directory)
99
116
  if os.path.isfile(os.path.join(directory, f)) and not is_ignored(os.path.join(directory, f), ignore_patterns) and not is_binary(os.path.join(directory, f))]
@@ -115,10 +132,26 @@ def select_files_in_directory(directory, ignore_patterns, current_char_count=0):
115
132
  print_char_count(current_char_count)
116
133
  choice = input("(y)es add all / (n)o ignore all / (s)elect individually / (q)uit? ").lower()
117
134
  if choice == 'y':
135
+ selected_files = []
118
136
  for file in files:
119
- current_char_count += os.path.getsize(os.path.join(directory, file))
137
+ file_path = os.path.join(directory, file)
138
+ if is_large_file(file_path):
139
+ while True:
140
+ snippet_choice = input(f"{file} is large. Use (f)ull content or (s)nippet? ").lower()
141
+ if snippet_choice in ['f', 's']:
142
+ break
143
+ print("Invalid choice. Please enter 'f' or 's'.")
144
+ if snippet_choice == 's':
145
+ selected_files.append((file, True))
146
+ current_char_count += len(get_file_snippet(file_path))
147
+ else:
148
+ selected_files.append((file, False))
149
+ current_char_count += os.path.getsize(file_path)
150
+ else:
151
+ selected_files.append((file, False))
152
+ current_char_count += os.path.getsize(file_path)
120
153
  print(f"Added all files from {directory}")
121
- return files, current_char_count
154
+ return selected_files, current_char_count
122
155
  elif choice == 'n':
123
156
  print(f"Ignored all files from {directory}")
124
157
  return [], current_char_count
@@ -135,8 +168,21 @@ def select_files_in_directory(directory, ignore_patterns, current_char_count=0):
135
168
  print_char_count(current_char_count)
136
169
  file_choice = input(f"{file} ({file_size_readable}, ~{file_char_estimate} chars, ~{file_token_estimate} tokens) (y/n/q)? ").lower()
137
170
  if file_choice == 'y':
138
- selected_files.append(file)
139
- current_char_count += file_char_estimate
171
+ if is_large_file(file_path):
172
+ while True:
173
+ snippet_choice = input(f"{file} is large. Use (f)ull content or (s)nippet? ").lower()
174
+ if snippet_choice in ['f', 's']:
175
+ break
176
+ print("Invalid choice. Please enter 'f' or 's'.")
177
+ if snippet_choice == 's':
178
+ selected_files.append((file, True))
179
+ current_char_count += len(get_file_snippet(file_path))
180
+ else:
181
+ selected_files.append((file, False))
182
+ current_char_count += file_char_estimate
183
+ else:
184
+ selected_files.append((file, False))
185
+ current_char_count += file_char_estimate
140
186
  break
141
187
  elif file_choice == 'n':
142
188
  break
@@ -165,24 +211,89 @@ def process_directory(directory, ignore_patterns, current_char_count=0):
165
211
  continue
166
212
 
167
213
  selected_files, current_char_count = select_files_in_directory(root, ignore_patterns, current_char_count)
168
- full_paths = [os.path.join(root, f) for f in selected_files]
214
+ full_paths = [(os.path.join(root, f), use_snippet) for f, use_snippet in selected_files]
169
215
  files_to_include.extend(full_paths)
170
216
  processed_dirs.add(root)
171
217
 
172
218
  return files_to_include, processed_dirs, current_char_count
173
219
 
174
- def generate_prompt(files_to_include, ignore_patterns):
220
+ def fetch_web_content(url):
221
+ try:
222
+ response = requests.get(url)
223
+ response.raise_for_status()
224
+ full_content = response.text
225
+ snippet = full_content[:1000] if len(full_content) > 10000 else full_content
226
+ return full_content, snippet
227
+ except requests.RequestException as e:
228
+ print(f"Error fetching content from {url}: {e}")
229
+ return None, None
230
+
231
+ def read_env_file():
232
+ env_vars = {}
233
+ if os.path.exists('.env'):
234
+ with open('.env', 'r') as env_file:
235
+ for line in env_file:
236
+ line = line.strip()
237
+ if line and not line.startswith('#'):
238
+ key, value = line.split('=', 1)
239
+ env_vars[key.strip()] = value.strip()
240
+ return env_vars
241
+
242
+ def detect_env_variables(content, env_vars):
243
+ detected_vars = []
244
+ for key, value in env_vars.items():
245
+ if value in content:
246
+ detected_vars.append((key, value))
247
+ return detected_vars
248
+
249
+ def handle_env_variables(content, env_vars):
250
+ detected_vars = detect_env_variables(content, env_vars)
251
+ if not detected_vars:
252
+ return content
253
+
254
+ print("Detected environment variables:")
255
+ for key, value in detected_vars:
256
+ print(f"- {key}={value}")
257
+
258
+ for key, value in detected_vars:
259
+ while True:
260
+ choice = input(f"How would you like to handle {key}? (m)ask / (s)kip / (k)eep: ").lower()
261
+ if choice in ['m', 's', 'k']:
262
+ break
263
+ print("Invalid choice. Please enter 'm', 's', or 'k'.")
264
+
265
+ if choice == 'm':
266
+ content = content.replace(value, '*' * len(value))
267
+ elif choice == 's':
268
+ content = content.replace(value, "[REDACTED]")
269
+ # If 'k', we don't modify the content
270
+
271
+ return content
272
+
273
+ def generate_prompt(files_to_include, ignore_patterns, web_contents, env_vars):
175
274
  prompt = "# Project Overview\n\n"
176
275
  prompt += "## Project Structure\n\n"
177
276
  prompt += "```\n"
178
277
  prompt += get_project_structure(ignore_patterns)
179
278
  prompt += "\n```\n\n"
180
279
  prompt += "## File Contents\n\n"
181
- for file in files_to_include:
280
+ for file, use_snippet in files_to_include:
182
281
  relative_path = get_relative_path(file)
183
282
  language = get_language_for_file(file)
184
- file_content = f"### {relative_path}\n\n```{language}\n{read_file_contents(file)}\n```\n\n"
185
- prompt += file_content
283
+ if use_snippet:
284
+ file_content = get_file_snippet(file)
285
+ prompt += f"### {relative_path} (snippet)\n\n```{language}\n{file_content}\n```\n\n"
286
+ else:
287
+ file_content = read_file_contents(file)
288
+ file_content = handle_env_variables(file_content, env_vars)
289
+ prompt += f"### {relative_path}\n\n```{language}\n{file_content}\n```\n\n"
290
+
291
+ if web_contents:
292
+ prompt += "## Web Content\n\n"
293
+ for url, (full_content, snippet) in web_contents.items():
294
+ content = handle_env_variables(snippet if len(full_content) > 10000 else full_content, env_vars)
295
+ prompt += f"### {url}{' (snippet)' if len(full_content) > 10000 else ''}\n\n```\n{content}\n```\n\n"
296
+
186
297
  prompt += "## Task Instructions\n\n"
187
298
  task_instructions = input("Enter the task instructions: ")
188
299
  prompt += f"{task_instructions}\n\n"
@@ -200,21 +311,34 @@ def print_char_count(count):
200
311
  print(f"\rCurrent prompt size: {count} characters (~ {token_estimate} tokens)", flush=True)
201
312
 
202
313
  def main():
203
- parser = argparse.ArgumentParser(description="Generate a prompt with project structure and file contents.")
204
- parser.add_argument('inputs', nargs='+', help='Files or directories to include in the prompt')
314
+ parser = argparse.ArgumentParser(description="Generate a prompt with project structure, file contents, and web content.")
315
+ parser.add_argument('inputs', nargs='+', help='Files, directories, or URLs to include in the prompt')
205
316
  args = parser.parse_args()
206
317
 
207
318
  ignore_patterns = read_gitignore()
319
+ env_vars = read_env_file()
208
320
 
209
321
  files_to_include = []
210
322
  processed_dirs = set()
323
+ web_contents = {}
211
324
  current_char_count = 0
212
325
 
213
326
  for input_path in args.inputs:
214
- if os.path.isfile(input_path):
327
+ if input_path.startswith(('http://', 'https://')):
328
+ full_content, snippet = fetch_web_content(input_path)
329
+ if full_content:
330
+ web_contents[input_path] = (full_content, snippet)
331
+ current_char_count += len(snippet if len(full_content) > 10000 else full_content)
332
+ print(f"Added web content from: {input_path}")
333
+ elif os.path.isfile(input_path):
215
334
  if not is_ignored(input_path, ignore_patterns) and not is_binary(input_path):
216
- files_to_include.append(input_path)
217
- print(f"Added file: {input_path}")
335
+ use_snippet = is_large_file(input_path)
336
+ files_to_include.append((input_path, use_snippet))
337
+ if use_snippet:
338
+ current_char_count += len(get_file_snippet(input_path))
339
+ else:
340
+ current_char_count += os.path.getsize(input_path)
341
+ print(f"Added file: {input_path}{' (snippet)' if use_snippet else ''}")
218
342
  else:
219
343
  print(f"Ignored file: {input_path}")
220
344
  elif os.path.isdir(input_path):
@@ -222,17 +346,17 @@ def main():
222
346
  files_to_include.extend(dir_files)
223
347
  processed_dirs.update(dir_processed)
224
348
  else:
225
- print(f"Warning: {input_path} is not a valid file or directory. Skipping.")
349
+ print(f"Warning: {input_path} is not a valid file, directory, or URL. Skipping.")
226
350
 
227
- if not files_to_include:
228
- print("No files were selected. Exiting.")
351
+ if not files_to_include and not web_contents:
352
+ print("No files or web content were selected. Exiting.")
229
353
  return
230
354
 
231
- print("\nFile selection complete.")
355
+ print("\nFile and web content selection complete.")
232
356
  print_char_count(current_char_count)
233
- print(f"Summary: Added {len(files_to_include)} files from {len(processed_dirs)} directories.")
357
+ print(f"Summary: Added {len(files_to_include)} files from {len(processed_dirs)} directories and {len(web_contents)} web sources.")
234
358
 
235
- prompt = generate_prompt(files_to_include, ignore_patterns)
359
+ prompt = generate_prompt(files_to_include, ignore_patterns, web_contents, env_vars)
236
360
  print("\n\nGenerated prompt:")
237
361
  print(prompt)
238
362
 
@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.1
2
+ Name: kopipasta
3
+ Version: 0.3.0
4
+ Summary: A CLI tool to generate prompts with project structure and file contents
5
+ Home-page: https://github.com/mkorpela/kopipasta
6
+ Author: Mikko Korpela
7
+ Author-email: mikko.korpela@gmail.com
8
+ License: MIT
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.8
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
+ Requires-Python: >=3.8
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: pyperclip==1.9.0
23
+
24
+ # kopipasta
25
+
26
+ A CLI tool to generate prompts with project structure, file contents, and web content, while handling environment variables securely and offering snippets for large files.
27
+
28
+ <img src="kopipasta.jpg" alt="kopipasta" width="300">
29
+
30
+ ## Installation
31
+
32
+ You can install kopipasta using pipx (or pip):
33
+
34
+ ```
35
+ pipx install kopipasta
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ To use kopipasta, run the following command in your terminal:
41
+
42
+ ```
43
+ kopipasta [files_or_directories_or_urls]
44
+ ```
45
+
46
+ Replace `[files_or_directories_or_urls]` with the paths to the files or directories you want to include in the prompt, as well as any web URLs you want to fetch content from.
47
+
48
+ Example:
49
+ ```
50
+ kopipasta src/ config.json https://example.com/api-docs
51
+ ```
52
+
53
+ This will generate a prompt including:
54
+ - The project structure
55
+ - Contents of the specified files and directories (with snippet options for large files)
56
+ - Content fetched from the provided URLs (with snippet options for large content)
57
+ - Handling of environment variables found in a `.env` file (if present)
58
+
59
+ Files and directories typically excluded in version control (based on common .gitignore patterns) are ignored.
60
+
61
+ The generated prompt will be displayed in the console and automatically copied to your clipboard.
62
+
63
+ ## Features
64
+
65
+ - Generates a structured prompt with project overview, file contents, web content, and task instructions
66
+ - Offers snippet options for large files (>100 KB) and web content (>10,000 characters)
67
+ - Fetches and includes content from web URLs
68
+ - Detects and securely handles environment variables from a `.env` file
69
+ - Ignores files and directories based on common .gitignore patterns
70
+ - Allows interactive selection of files to include
71
+ - Automatically copies the generated prompt to the clipboard
72
+
73
+ ## Environment Variable Handling
74
+
75
+ If a `.env` file is present in the current directory, kopipasta will:
76
+ 1. Read and store the environment variables
77
+ 2. Detect these variables in file contents and web content
78
+ 3. Prompt you to choose how to handle each detected variable:
79
+ - (m)ask: Replace the value with asterisks
80
+ - (s)kip: Replace the value with "[REDACTED]"
81
+ - (k)eep: Leave the value as-is
82
+
83
+ This ensures sensitive information is handled securely in the generated prompt.
84
+
85
+ ## Snippet Functionality
86
+
87
+ For large files (>100 KB) and web content (>10,000 characters), kopipasta offers a snippet option:
88
+
89
+ - For files: The first 50 lines or 4 KB (4,096 bytes), whichever comes first
90
+ - For web content: The first 1,000 characters
91
+
92
+ This helps manage the overall prompt size while still providing useful information about the content structure.
93
+
94
+ ## Example output
95
+
96
+ ```bash
97
+ ❯ kopipasta . https://example.com/api-docs
98
+
99
+ Directory: .
100
+ Files:
101
+ - __init__.py
102
+ - main.py (120 KB, ~120000 chars, ~30000 tokens)
103
+ - large_data.csv (5 MB, ~5000000 chars, ~1250000 tokens)
104
+ - .env
105
+
106
+ (y)es add all / (n)o ignore all / (s)elect individually / (q)uit? y
107
+ main.py is large. Use (f)ull content or (s)nippet? s
108
+ large_data.csv is large. Use (f)ull content or (s)nippet? s
109
+ Added all files from .
110
+ Added web content from: https://example.com/api-docs
111
+
112
+ File and web content selection complete.
113
+ Current prompt size: 10500 characters (~ 2625 tokens)
114
+ Summary: Added 3 files from 1 directory and 1 web source.
115
+
116
+ Detected environment variables:
117
+ - API_KEY=12345abcde
118
+
119
+ How would you like to handle API_KEY? (m)ask / (k)eep: m
120
+
121
+ Enter the task instructions: Implement new API endpoint
122
+
123
+ Generated prompt:
124
+ # Project Overview
125
+
126
+ ## Project Structure
127
+
128
+ ```
129
+ |-- ./
130
+ |-- __init__.py
131
+ |-- main.py
132
+ |-- large_data.csv
133
+ |-- .env
134
+ ```
135
+
136
+ ## File Contents
137
+
138
+ ### __init__.py
139
+
140
+ ```python
141
+ # Initialize package
142
+ ```
143
+
144
+ ### main.py (snippet)
145
+
146
+ ```python
147
+ import os
148
+ import pandas as pd
149
+
150
+ API_KEY = os.getenv('API_KEY')
151
+
152
+ def process_data(file_path):
153
+ df = pd.read_csv(file_path)
154
+ # Rest of the function...
155
+
156
+ # More code...
157
+ ```
158
+
159
+ ### large_data.csv (snippet)
160
+
161
+ ```
162
+ id,name,value
163
+ 1,John,100
164
+ 2,Jane,200
165
+ 3,Bob,150
166
+ 4,Alice,300
167
+ # ... (first 50 lines or 4 KB)
168
+ ```
169
+
170
+ ## Web Content
171
+
172
+ ### https://example.com/api-docs (snippet)
173
+
174
+ ```
175
+ API Documentation
176
+ Endpoint: /api/v1/data
177
+ Method: GET
178
+ Authorization: Bearer **********
179
+ ...
180
+ ```
181
+
182
+ ## Task Instructions
183
+
184
+ Implement new API endpoint
185
+
186
+ ## Task Analysis and Planning
187
+
188
+ Before starting, explain the task back to me in your own words. Ask for any clarifications if needed. Once you're clear, ask to proceed.
189
+
190
+ Then, outline a plan for the task. Finally, use your plan to complete the task.
191
+
192
+ Prompt has been copied to clipboard. Final size: 1500 characters (~ 375 tokens)
193
+ ```
194
+
195
+ ## License
196
+
197
+ This project is licensed under the MIT License.
@@ -1 +1,2 @@
1
1
  pyperclip==1.9.0
2
+ requests==2.32.3
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setup(
7
7
  name="kopipasta",
8
- version="0.2.0",
8
+ version="0.3.0",
9
9
  author="Mikko Korpela",
10
10
  author_email="mikko.korpela@gmail.com",
11
11
  description="A CLI tool to generate prompts with project structure and file contents",
@@ -35,4 +35,4 @@ setup(
35
35
  "kopipasta=kopipasta.main:main",
36
36
  ],
37
37
  },
38
- )
38
+ )
kopipasta-0.2.0/PKG-INFO DELETED
@@ -1,122 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: kopipasta
3
- Version: 0.2.0
4
- Summary: A CLI tool to generate prompts with project structure and file contents
5
- Home-page: https://github.com/mkorpela/kopipasta
6
- Author: Mikko Korpela
7
- Author-email: mikko.korpela@gmail.com
8
- License: MIT
9
- Classifier: Development Status :: 3 - Alpha
10
- Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Operating System :: OS Independent
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.8
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
- Requires-Python: >=3.8
20
- Description-Content-Type: text/markdown
21
- License-File: LICENSE
22
- Requires-Dist: pyperclip==1.9.0
23
-
24
-
25
- # kopipasta
26
-
27
- A CLI tool to generate prompts with project structure and file contents.
28
-
29
- <img src="kopipasta.jpg" alt="kopipasta" width="300">
30
-
31
- ## Installation
32
-
33
- You can install kopipasta using pipx (or pip):
34
-
35
- ```
36
- pipx install kopipasta
37
- ```
38
-
39
- ## Usage
40
-
41
- To use kopipasta, run the following command in your terminal:
42
-
43
- ```
44
- kopipasta [files_or_directories]
45
- ```
46
-
47
- Replace `[files_or_directories]` with the paths to the files or directories you want to include in the prompt.
48
-
49
- Example:
50
- ```
51
- kopipasta src/ config.json
52
- ```
53
-
54
- This will generate a prompt including the project structure and contents of the specified files and directories, ignoring files and directories typically excluded in version control (based on common .gitignore patterns).
55
-
56
- The generated prompt will be displayed in the console and automatically copied to your clipboard.
57
-
58
- ## Features
59
-
60
- - Generates a structured prompt with project overview, file contents, and task instructions
61
- - Ignores files and directories based on common .gitignore patterns
62
- - Allows interactive selection of files to include
63
- - Automatically copies the generated prompt to the clipboard
64
-
65
- ## Example output
66
-
67
- ```bash
68
- ❯ kopipasta .
69
-
70
- Directory: .
71
- Files:
72
- - __init__.py
73
- - main.py
74
-
75
- (y)es add all / (n)o ignore all / (s)elect individually / (q)uit? s
76
- __init__.py (y/n/q)? y
77
- main.py (y/n/q)? n
78
- Added 1 files from .
79
-
80
- File selection complete.
81
- Summary: Added 1 files from 1 directories.
82
- Enter the task instructions: Do my work
83
-
84
- Generated prompt:
85
- # Project Overview
86
-
87
- ## Summary of Included Files
88
-
89
- - __init__.py
90
-
91
- ## Project Structure
92
-
93
- ```
94
- |-- ./
95
- |-- __init__.py
96
- |-- main.py
97
- ```
98
-
99
- ## File Contents
100
-
101
- ### __init__.py
102
-
103
- ```python
104
-
105
- ```
106
-
107
- ## Task Instructions
108
-
109
- Do my work
110
-
111
- ## Task Analysis and Planning
112
-
113
- Before starting, explain the task back to me in your own words. Ask for any clarifications if needed. Once you're clear, ask to proceed.
114
-
115
- Then, outline a plan for the task. Finally, use your plan to complete the task.
116
-
117
- Prompt has been copied to clipboard.
118
- ```
119
-
120
- ## License
121
-
122
- This project is licensed under the MIT License.
kopipasta-0.2.0/README.md DELETED
@@ -1,99 +0,0 @@
1
-
2
- # kopipasta
3
-
4
- A CLI tool to generate prompts with project structure and file contents.
5
-
6
- <img src="kopipasta.jpg" alt="kopipasta" width="300">
7
-
8
- ## Installation
9
-
10
- You can install kopipasta using pipx (or pip):
11
-
12
- ```
13
- pipx install kopipasta
14
- ```
15
-
16
- ## Usage
17
-
18
- To use kopipasta, run the following command in your terminal:
19
-
20
- ```
21
- kopipasta [files_or_directories]
22
- ```
23
-
24
- Replace `[files_or_directories]` with the paths to the files or directories you want to include in the prompt.
25
-
26
- Example:
27
- ```
28
- kopipasta src/ config.json
29
- ```
30
-
31
- This will generate a prompt including the project structure and contents of the specified files and directories, ignoring files and directories typically excluded in version control (based on common .gitignore patterns).
32
-
33
- The generated prompt will be displayed in the console and automatically copied to your clipboard.
34
-
35
- ## Features
36
-
37
- - Generates a structured prompt with project overview, file contents, and task instructions
38
- - Ignores files and directories based on common .gitignore patterns
39
- - Allows interactive selection of files to include
40
- - Automatically copies the generated prompt to the clipboard
41
-
42
- ## Example output
43
-
44
- ```bash
45
- ❯ kopipasta .
46
-
47
- Directory: .
48
- Files:
49
- - __init__.py
50
- - main.py
51
-
52
- (y)es add all / (n)o ignore all / (s)elect individually / (q)uit? s
53
- __init__.py (y/n/q)? y
54
- main.py (y/n/q)? n
55
- Added 1 files from .
56
-
57
- File selection complete.
58
- Summary: Added 1 files from 1 directories.
59
- Enter the task instructions: Do my work
60
-
61
- Generated prompt:
62
- # Project Overview
63
-
64
- ## Summary of Included Files
65
-
66
- - __init__.py
67
-
68
- ## Project Structure
69
-
70
- ```
71
- |-- ./
72
- |-- __init__.py
73
- |-- main.py
74
- ```
75
-
76
- ## File Contents
77
-
78
- ### __init__.py
79
-
80
- ```python
81
-
82
- ```
83
-
84
- ## Task Instructions
85
-
86
- Do my work
87
-
88
- ## Task Analysis and Planning
89
-
90
- Before starting, explain the task back to me in your own words. Ask for any clarifications if needed. Once you're clear, ask to proceed.
91
-
92
- Then, outline a plan for the task. Finally, use your plan to complete the task.
93
-
94
- Prompt has been copied to clipboard.
95
- ```
96
-
97
- ## License
98
-
99
- This project is licensed under the MIT License.
@@ -1,122 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: kopipasta
3
- Version: 0.2.0
4
- Summary: A CLI tool to generate prompts with project structure and file contents
5
- Home-page: https://github.com/mkorpela/kopipasta
6
- Author: Mikko Korpela
7
- Author-email: mikko.korpela@gmail.com
8
- License: MIT
9
- Classifier: Development Status :: 3 - Alpha
10
- Classifier: Intended Audience :: Developers
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Operating System :: OS Independent
13
- Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.8
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
- Requires-Python: >=3.8
20
- Description-Content-Type: text/markdown
21
- License-File: LICENSE
22
- Requires-Dist: pyperclip==1.9.0
23
-
24
-
25
- # kopipasta
26
-
27
- A CLI tool to generate prompts with project structure and file contents.
28
-
29
- <img src="kopipasta.jpg" alt="kopipasta" width="300">
30
-
31
- ## Installation
32
-
33
- You can install kopipasta using pipx (or pip):
34
-
35
- ```
36
- pipx install kopipasta
37
- ```
38
-
39
- ## Usage
40
-
41
- To use kopipasta, run the following command in your terminal:
42
-
43
- ```
44
- kopipasta [files_or_directories]
45
- ```
46
-
47
- Replace `[files_or_directories]` with the paths to the files or directories you want to include in the prompt.
48
-
49
- Example:
50
- ```
51
- kopipasta src/ config.json
52
- ```
53
-
54
- This will generate a prompt including the project structure and contents of the specified files and directories, ignoring files and directories typically excluded in version control (based on common .gitignore patterns).
55
-
56
- The generated prompt will be displayed in the console and automatically copied to your clipboard.
57
-
58
- ## Features
59
-
60
- - Generates a structured prompt with project overview, file contents, and task instructions
61
- - Ignores files and directories based on common .gitignore patterns
62
- - Allows interactive selection of files to include
63
- - Automatically copies the generated prompt to the clipboard
64
-
65
- ## Example output
66
-
67
- ```bash
68
- ❯ kopipasta .
69
-
70
- Directory: .
71
- Files:
72
- - __init__.py
73
- - main.py
74
-
75
- (y)es add all / (n)o ignore all / (s)elect individually / (q)uit? s
76
- __init__.py (y/n/q)? y
77
- main.py (y/n/q)? n
78
- Added 1 files from .
79
-
80
- File selection complete.
81
- Summary: Added 1 files from 1 directories.
82
- Enter the task instructions: Do my work
83
-
84
- Generated prompt:
85
- # Project Overview
86
-
87
- ## Summary of Included Files
88
-
89
- - __init__.py
90
-
91
- ## Project Structure
92
-
93
- ```
94
- |-- ./
95
- |-- __init__.py
96
- |-- main.py
97
- ```
98
-
99
- ## File Contents
100
-
101
- ### __init__.py
102
-
103
- ```python
104
-
105
- ```
106
-
107
- ## Task Instructions
108
-
109
- Do my work
110
-
111
- ## Task Analysis and Planning
112
-
113
- Before starting, explain the task back to me in your own words. Ask for any clarifications if needed. Once you're clear, ask to proceed.
114
-
115
- Then, outline a plan for the task. Finally, use your plan to complete the task.
116
-
117
- Prompt has been copied to clipboard.
118
- ```
119
-
120
- ## License
121
-
122
- This project is licensed under the MIT License.
File without changes
File without changes
File without changes