makima-cli 0.2.0__tar.gz → 0.2.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.
- makima_cli-0.2.1/LICENSE +21 -0
- makima_cli-0.2.1/PKG-INFO +80 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/config.py +19 -19
- makima_cli-0.2.1/makima/core/agent.py +157 -0
- makima_cli-0.2.1/makima/core/config_manager.py +125 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/setup.py +50 -3
- makima_cli-0.2.1/makima/tools/shell_tools.py +20 -0
- makima_cli-0.2.1/makima_cli.egg-info/PKG-INFO +80 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima_cli.egg-info/SOURCES.txt +2 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima_cli.egg-info/requires.txt +1 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/pyproject.toml +2 -1
- makima_cli-0.2.0/PKG-INFO +0 -55
- makima_cli-0.2.0/makima/core/agent.py +0 -133
- makima_cli-0.2.0/makima/tools/shell_tools.py +0 -20
- makima_cli-0.2.0/makima_cli.egg-info/PKG-INFO +0 -55
- {makima_cli-0.2.0 → makima_cli-0.2.1}/README.md +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/__init__.py +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/core/__init__.py +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/core/context.py +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/core/memory.py +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/main.py +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/providers/base.py +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/providers/groq_provider.py +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/tools/__init__.py +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/tools/file_tools.py +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima/tools/registry.py +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima_cli.egg-info/dependency_links.txt +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima_cli.egg-info/entry_points.txt +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/makima_cli.egg-info/top_level.txt +0 -0
- {makima_cli-0.2.0 → makima_cli-0.2.1}/setup.cfg +0 -0
makima_cli-0.2.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kanhaiya kumar
|
|
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.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: makima-cli
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: AI coding assistant for your terminal
|
|
5
|
+
Author: Kanhaiya
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Kanhaiya kumar
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: groq
|
|
32
|
+
Requires-Dist: python-dotenv
|
|
33
|
+
Requires-Dist: gitpython
|
|
34
|
+
Requires-Dist: rich
|
|
35
|
+
Requires-Dist: pyfiglet
|
|
36
|
+
Requires-Dist: questionary
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# Makima CLI 🤖
|
|
40
|
+
|
|
41
|
+
An AI-powered coding assistant that runs in your terminal. Point it at any codebase and ask questions, make edits, and run commands — all from a clean CLI interface.
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
- Understands your entire codebase
|
|
46
|
+
- Answers questions about your code
|
|
47
|
+
- Edits files with auto git backup before changes
|
|
48
|
+
- Creates new files
|
|
49
|
+
- Runs terminal commands with confirmation
|
|
50
|
+
- Works on any project
|
|
51
|
+
- Clean terminal UI with syntax highlighting
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
git clone https://github.com/yourusername/makima-cli.git
|
|
56
|
+
cd makima-cli
|
|
57
|
+
pip install -r requirements.txt
|
|
58
|
+
|
|
59
|
+
## Setup
|
|
60
|
+
|
|
61
|
+
Create a .env file in the project root:
|
|
62
|
+
GROQ_API_KEY=your_key_here
|
|
63
|
+
|
|
64
|
+
Get a free API key at https://console.groq.com
|
|
65
|
+
|
|
66
|
+
## Usage
|
|
67
|
+
|
|
68
|
+
Point it at any project:
|
|
69
|
+
python main.py /path/to/your/project
|
|
70
|
+
|
|
71
|
+
Or run from inside a project folder:
|
|
72
|
+
cd your-project
|
|
73
|
+
python /path/to/makima-cli/main.py
|
|
74
|
+
|
|
75
|
+
## Built With
|
|
76
|
+
|
|
77
|
+
- Python
|
|
78
|
+
- Groq API
|
|
79
|
+
- Rich
|
|
80
|
+
- GitPython
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import sys
|
|
3
|
-
from makima.setup import setup_api_key
|
|
4
|
-
from dotenv import load_dotenv
|
|
5
|
-
load_dotenv()
|
|
6
|
-
|
|
7
|
-
GROQ_API_KEY = setup_api_key()
|
|
8
|
-
# GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
|
9
|
-
MODEL_NAME =
|
|
10
|
-
TOKEN_LIMIT = 10000
|
|
11
|
-
# PROJECT_ROOT = os.getcwd()
|
|
12
|
-
PROJECT_ROOT = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()
|
|
13
|
-
|
|
14
|
-
if not GROQ_API_KEY:
|
|
15
|
-
print("Error: GROQ_API_KEY not set.")
|
|
16
|
-
print("Run this command first:")
|
|
17
|
-
print(' Windows: setx GROQ_API_KEY "your-key-here"')
|
|
18
|
-
print(' Linux/Mac: export GROQ_API_KEY="your-key-here"')
|
|
19
|
-
print("Get a free key at: https://console.groq.com")
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from makima.setup import setup_api_key,setup_model
|
|
4
|
+
from dotenv import load_dotenv
|
|
5
|
+
load_dotenv()
|
|
6
|
+
|
|
7
|
+
GROQ_API_KEY = setup_api_key()
|
|
8
|
+
# GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
|
9
|
+
MODEL_NAME = setup_model()
|
|
10
|
+
TOKEN_LIMIT = 10000
|
|
11
|
+
# PROJECT_ROOT = os.getcwd()
|
|
12
|
+
PROJECT_ROOT = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()
|
|
13
|
+
|
|
14
|
+
if not GROQ_API_KEY:
|
|
15
|
+
print("Error: GROQ_API_KEY not set.")
|
|
16
|
+
print("Run this command first:")
|
|
17
|
+
print(' Windows: setx GROQ_API_KEY "your-key-here"')
|
|
18
|
+
print(' Linux/Mac: export GROQ_API_KEY="your-key-here"')
|
|
19
|
+
print("Get a free key at: https://console.groq.com")
|
|
20
20
|
sys.exit(1)
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from makima.config import PROJECT_ROOT,MODEL_NAME
|
|
3
|
+
from makima.core.context import ContextManager
|
|
4
|
+
from makima.core.memory import Memory
|
|
5
|
+
from makima.tools import TOOL_REGISTRY
|
|
6
|
+
from makima.tools.registry import TOOL_SCHEMAS
|
|
7
|
+
from makima.providers.groq_provider import GroqProvider
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from makima.core.config_manager import handle_config
|
|
10
|
+
|
|
11
|
+
console = Console()
|
|
12
|
+
|
|
13
|
+
ctx = ContextManager()
|
|
14
|
+
context = ctx.build_context()
|
|
15
|
+
|
|
16
|
+
SYSTEM_PROMPT = f"""
|
|
17
|
+
You are a coding assistant. The project is at: {PROJECT_ROOT}
|
|
18
|
+
|
|
19
|
+
Rules:
|
|
20
|
+
- Always use list_files first to find exact paths
|
|
21
|
+
- Always use read_file before editing any file
|
|
22
|
+
- Use full absolute paths always
|
|
23
|
+
- Be concise and direct
|
|
24
|
+
- old_str must be an exact match of multiple lines from the file
|
|
25
|
+
- Never explain what you are about to do. Never say "Let me..." or "I'll first...".
|
|
26
|
+
- Just call the tool immediately and silently.
|
|
27
|
+
- Only speak in plain text when you have a FINAL answer for the user.
|
|
28
|
+
- Call only ONE tool per response. Wait for the tool result before calling the next tool.
|
|
29
|
+
- Never output multiple tool calls in one response.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
import pyfiglet
|
|
33
|
+
from rich.panel import Panel
|
|
34
|
+
from rich.text import Text
|
|
35
|
+
from rich.rule import Rule
|
|
36
|
+
from rich.markdown import Markdown
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def run_agent():
|
|
40
|
+
provider = GroqProvider()
|
|
41
|
+
memory = Memory(system_prompt=SYSTEM_PROMPT)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
ascii_art = pyfiglet.figlet_format("Makima", font="big")
|
|
45
|
+
console.print(f"[bold #FF6B35]{ascii_art}[/]")
|
|
46
|
+
|
|
47
|
+
# info line underneath, no box
|
|
48
|
+
console.print(f"[dim] Your AI Coding Assistant[/]")
|
|
49
|
+
console.print(f"[green] Project :[/] {PROJECT_ROOT}")
|
|
50
|
+
console.print(f"[green] Files :[/] {len(ctx.files)} files loaded")
|
|
51
|
+
console.print(f"[green] Model :[/] {MODEL_NAME}")
|
|
52
|
+
console.print(f"[dim] Type 'exit' to quit[/]")
|
|
53
|
+
console.print(Rule(style="#FF6B35")) # clean horizontal line separator
|
|
54
|
+
console.print()
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
|
|
58
|
+
while True:
|
|
59
|
+
user_input = console.input("[bold blue]You:[/] ")
|
|
60
|
+
if user_input.strip() == "exit":
|
|
61
|
+
break
|
|
62
|
+
|
|
63
|
+
if user_input.strip() == "/config":
|
|
64
|
+
handle_config()
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
memory.add_user(user_input)
|
|
68
|
+
|
|
69
|
+
while True:
|
|
70
|
+
try:
|
|
71
|
+
with console.status("[yellow]thinking...[/]"):
|
|
72
|
+
stream = provider.stream_chat(
|
|
73
|
+
messages=memory.get(),
|
|
74
|
+
tools=TOOL_SCHEMAS
|
|
75
|
+
)
|
|
76
|
+
chunks = list(stream)
|
|
77
|
+
except Exception as e:
|
|
78
|
+
console.print(f"[red]Error: {e}[/]")
|
|
79
|
+
break
|
|
80
|
+
|
|
81
|
+
#variables to collect the response
|
|
82
|
+
text_buffer = ""
|
|
83
|
+
tool_name = ""
|
|
84
|
+
tool_args = ""
|
|
85
|
+
tool_call_id = ""
|
|
86
|
+
is_tool_call = False
|
|
87
|
+
|
|
88
|
+
# console.print("[bold green]Agent:[/] ", end="")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
for chunk in chunks:
|
|
92
|
+
delta = chunk.choices[0].delta
|
|
93
|
+
|
|
94
|
+
#text chunk
|
|
95
|
+
if delta.content:
|
|
96
|
+
# print(delta.content, end="", flush=True)
|
|
97
|
+
text_buffer += delta.content
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# tool call chunk
|
|
101
|
+
if delta.tool_calls:
|
|
102
|
+
is_tool_call = True
|
|
103
|
+
tc = delta.tool_calls[0]
|
|
104
|
+
if tc.id:
|
|
105
|
+
tool_call_id = tc.id
|
|
106
|
+
if tc.function.name:
|
|
107
|
+
tool_name += tc.function.name
|
|
108
|
+
if tc.function.arguments:
|
|
109
|
+
tool_args += tc.function.arguments
|
|
110
|
+
|
|
111
|
+
# print()
|
|
112
|
+
|
|
113
|
+
if is_tool_call:
|
|
114
|
+
console.print(f"[dim]⚡ {tool_name}[/]")
|
|
115
|
+
args = json.loads(tool_args)
|
|
116
|
+
|
|
117
|
+
# confirmation for run_command only
|
|
118
|
+
if tool_name == "run_command":
|
|
119
|
+
console.print(f"[yellow]Command: {args.get('cmd')}[/]")
|
|
120
|
+
confirm = console.input("[bold]Run this? (y/n):[/] ").strip().lower()
|
|
121
|
+
if confirm != "y":
|
|
122
|
+
memory.add_raw({
|
|
123
|
+
"role": "assistant",
|
|
124
|
+
"tool_calls": [{
|
|
125
|
+
"id": tool_call_id,
|
|
126
|
+
"type": "function",
|
|
127
|
+
"function": {
|
|
128
|
+
"name": tool_name,
|
|
129
|
+
"arguments": tool_args
|
|
130
|
+
}
|
|
131
|
+
}]
|
|
132
|
+
})
|
|
133
|
+
memory.add_tool_result(tool_call_id, "Command cancelled by user")
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
tool_fn = TOOL_REGISTRY.get(tool_name)
|
|
137
|
+
with console.status(f"[yellow]calling {tool_name}...[/]"):
|
|
138
|
+
result = tool_fn(**args) if tool_fn else "Unknown tool"
|
|
139
|
+
memory.add_raw({
|
|
140
|
+
"role": "assistant",
|
|
141
|
+
"tool_calls": [{
|
|
142
|
+
"id": tool_call_id,
|
|
143
|
+
"type": "function",
|
|
144
|
+
"function": {
|
|
145
|
+
"name": tool_name,
|
|
146
|
+
"arguments": tool_args
|
|
147
|
+
}
|
|
148
|
+
}]
|
|
149
|
+
})
|
|
150
|
+
memory.add_tool_result(tool_call_id, str(result))
|
|
151
|
+
else:
|
|
152
|
+
console.print("[bold green]Agent:[/]")
|
|
153
|
+
console.print(Markdown(text_buffer))
|
|
154
|
+
memory.add_assistant(text_buffer)
|
|
155
|
+
break
|
|
156
|
+
except KeyboardInterrupt:
|
|
157
|
+
console.print("\n[dim]Goodbye![/]")
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import json
|
|
3
|
+
from makima.setup import validate_key
|
|
4
|
+
import questionary
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
console = Console()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def show_config():
|
|
10
|
+
config_dir = Path.home() / ".makima"
|
|
11
|
+
config_file = config_dir / "config.json"
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
with open(config_file,"r") as f:
|
|
15
|
+
data = json.load(f)
|
|
16
|
+
model = data.get("model")
|
|
17
|
+
key = data.get("groq_api_key")
|
|
18
|
+
console.print("Current setting:")
|
|
19
|
+
console.print(f"Model: {model}")
|
|
20
|
+
console.print(f"Key: {key[:8]}****")
|
|
21
|
+
# console.print("What do you want to change?")
|
|
22
|
+
# options = questionary.select(
|
|
23
|
+
# "What do you want to change?",
|
|
24
|
+
# choices = [
|
|
25
|
+
# "Change Model",
|
|
26
|
+
# "Change API key",
|
|
27
|
+
# "Cancel"
|
|
28
|
+
# ]
|
|
29
|
+
# )
|
|
30
|
+
|
|
31
|
+
except Exception as e:
|
|
32
|
+
return f"Somthing went wrong! {e}"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def change_model():
|
|
36
|
+
config_dir = Path.home() / ".makima"
|
|
37
|
+
config_file = config_dir / "config.json"
|
|
38
|
+
|
|
39
|
+
if config_file.exists():
|
|
40
|
+
with open(config_file,"r") as f:
|
|
41
|
+
data = json.load(f)
|
|
42
|
+
model = data.get("model")
|
|
43
|
+
if model:
|
|
44
|
+
console.print(f"Selected Model: {model}")
|
|
45
|
+
|
|
46
|
+
model = questionary.select(
|
|
47
|
+
"Select a model: ",
|
|
48
|
+
choices = [
|
|
49
|
+
"llama-3.3-70b",
|
|
50
|
+
"qwen/qwen3.6-27b",
|
|
51
|
+
"gemma2-9b"
|
|
52
|
+
]
|
|
53
|
+
).ask()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
existing = {}
|
|
57
|
+
if config_file.exists():
|
|
58
|
+
with open(config_file,"r") as f:
|
|
59
|
+
existing = json.load(f)
|
|
60
|
+
|
|
61
|
+
existing["model"] = model
|
|
62
|
+
|
|
63
|
+
with open(config_file,"w") as f:
|
|
64
|
+
json.dump(existing,f)
|
|
65
|
+
|
|
66
|
+
console.print(f"[bold green]✓ Model changed to: {model}[/]")
|
|
67
|
+
return model
|
|
68
|
+
|
|
69
|
+
# if model:
|
|
70
|
+
# console.print(f"[bold green]✓ Model Selected: {model} [/]")
|
|
71
|
+
# config_dir.mkdir(exist_ok=True)
|
|
72
|
+
# with open(config_file,"w") as f:
|
|
73
|
+
# json.dump({"model":model}, f)
|
|
74
|
+
# return model
|
|
75
|
+
# else:
|
|
76
|
+
# console.print("[bold red]✗ Please Select in Given models.[/]")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def change_api_key():
|
|
81
|
+
config_dir = Path.home() / ".makima"
|
|
82
|
+
config_file = config_dir / "config.json"
|
|
83
|
+
|
|
84
|
+
if config_file.exists():
|
|
85
|
+
with open(config_file,"r") as f:
|
|
86
|
+
data = json.load(f)
|
|
87
|
+
key = data.get("groq_api_key")
|
|
88
|
+
if key:
|
|
89
|
+
console.print(f"Already Setted API key: {key}")
|
|
90
|
+
|
|
91
|
+
while True:
|
|
92
|
+
|
|
93
|
+
key = console.input("[bold yellow]Enter your Groq API key:[/] ").strip()
|
|
94
|
+
|
|
95
|
+
with console.status("[yellow]Authenticating...[/]"):
|
|
96
|
+
valid = validate_key(key)
|
|
97
|
+
|
|
98
|
+
if valid:
|
|
99
|
+
console.print("[bold green]✓ Connected to Groq[/]")
|
|
100
|
+
config_dir.mkdir(exist_ok=True)
|
|
101
|
+
existing = {}
|
|
102
|
+
if config_file.exists():
|
|
103
|
+
with open(config_file, "r") as f:
|
|
104
|
+
existing = json.load(f)
|
|
105
|
+
existing["groq_api_key"] = key
|
|
106
|
+
with open(config_file, "w") as f:
|
|
107
|
+
json.dump(existing, f)
|
|
108
|
+
return key
|
|
109
|
+
else:
|
|
110
|
+
console.print("[bold red]✗ Invalid key. Try again.[/]")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def handle_config():
|
|
115
|
+
show_config()
|
|
116
|
+
|
|
117
|
+
choice = questionary.select(
|
|
118
|
+
"What do you want to change?",
|
|
119
|
+
choices=["Change model", "Change API key", "Cancel"]
|
|
120
|
+
).ask()
|
|
121
|
+
|
|
122
|
+
if choice == "Change model":
|
|
123
|
+
change_model()
|
|
124
|
+
elif choice == "Change API key":
|
|
125
|
+
change_api_key()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from groq import Groq
|
|
3
3
|
import json
|
|
4
|
+
import questionary
|
|
4
5
|
from rich.console import Console
|
|
5
6
|
console = Console()
|
|
6
7
|
|
|
@@ -26,8 +27,9 @@ def setup_api_key():
|
|
|
26
27
|
if config_file.exists():
|
|
27
28
|
with open(config_file, "r") as f:
|
|
28
29
|
data = json.load(f)
|
|
29
|
-
key = data
|
|
30
|
-
|
|
30
|
+
key = data.get("groq_api_key")
|
|
31
|
+
if key:
|
|
32
|
+
return key
|
|
31
33
|
|
|
32
34
|
import os
|
|
33
35
|
env_key = os.getenv("GROQ_API_KEY")
|
|
@@ -50,4 +52,49 @@ def setup_api_key():
|
|
|
50
52
|
json.dump({"groq_api_key": key}, f)
|
|
51
53
|
return key
|
|
52
54
|
else:
|
|
53
|
-
console.print("[bold red]✗ Invalid key. Try again.[/]")
|
|
55
|
+
console.print("[bold red]✗ Invalid key. Try again.[/]")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def setup_model():
|
|
60
|
+
config_dir = Path.home() / ".makima"
|
|
61
|
+
config_file = config_dir / "config.json"
|
|
62
|
+
|
|
63
|
+
if config_file.exists():
|
|
64
|
+
with open(config_file,"r") as f:
|
|
65
|
+
data = json.load(f)
|
|
66
|
+
model = data.get("model")
|
|
67
|
+
if model:
|
|
68
|
+
return model
|
|
69
|
+
|
|
70
|
+
model = questionary.select(
|
|
71
|
+
"Select a model: ",
|
|
72
|
+
choices = [
|
|
73
|
+
"llama-3.3-70b",
|
|
74
|
+
"qwen/qwen3.6-27b",
|
|
75
|
+
"gemma2-9b"
|
|
76
|
+
]
|
|
77
|
+
).ask()
|
|
78
|
+
|
|
79
|
+
existing = {}
|
|
80
|
+
if config_file.exists():
|
|
81
|
+
with open(config_file,"r") as f:
|
|
82
|
+
existing = json.load(f)
|
|
83
|
+
|
|
84
|
+
existing["model"] = model
|
|
85
|
+
|
|
86
|
+
with open(config_file,"w") as f:
|
|
87
|
+
json.dump(existing,f)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
if model:
|
|
91
|
+
console.print(f"[bold green]✓ Model Selected: {model} [/]")
|
|
92
|
+
config_dir.mkdir(exist_ok=True)
|
|
93
|
+
with open(config_file,"w") as f:
|
|
94
|
+
json.dump({"model":model}, f)
|
|
95
|
+
return model
|
|
96
|
+
else:
|
|
97
|
+
console.print("[bold red]✗ Please Select in Given models.[/]")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def run_command(cmd):
|
|
5
|
+
# print(f"Commands going to Run: {cmd}")
|
|
6
|
+
# User_answer = input("Run This? (Y/N): ")
|
|
7
|
+
# User_answer = User_answer.lower()
|
|
8
|
+
|
|
9
|
+
# if User_answer != "y":
|
|
10
|
+
# return "Command cancelled"
|
|
11
|
+
|
|
12
|
+
result = subprocess.run(
|
|
13
|
+
cmd,
|
|
14
|
+
shell=True,
|
|
15
|
+
capture_output=True,
|
|
16
|
+
text=True,
|
|
17
|
+
timeout=30
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
return result.stdout + result.stderr
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: makima-cli
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: AI coding assistant for your terminal
|
|
5
|
+
Author: Kanhaiya
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Kanhaiya kumar
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: groq
|
|
32
|
+
Requires-Dist: python-dotenv
|
|
33
|
+
Requires-Dist: gitpython
|
|
34
|
+
Requires-Dist: rich
|
|
35
|
+
Requires-Dist: pyfiglet
|
|
36
|
+
Requires-Dist: questionary
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# Makima CLI 🤖
|
|
40
|
+
|
|
41
|
+
An AI-powered coding assistant that runs in your terminal. Point it at any codebase and ask questions, make edits, and run commands — all from a clean CLI interface.
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
- Understands your entire codebase
|
|
46
|
+
- Answers questions about your code
|
|
47
|
+
- Edits files with auto git backup before changes
|
|
48
|
+
- Creates new files
|
|
49
|
+
- Runs terminal commands with confirmation
|
|
50
|
+
- Works on any project
|
|
51
|
+
- Clean terminal UI with syntax highlighting
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
git clone https://github.com/yourusername/makima-cli.git
|
|
56
|
+
cd makima-cli
|
|
57
|
+
pip install -r requirements.txt
|
|
58
|
+
|
|
59
|
+
## Setup
|
|
60
|
+
|
|
61
|
+
Create a .env file in the project root:
|
|
62
|
+
GROQ_API_KEY=your_key_here
|
|
63
|
+
|
|
64
|
+
Get a free API key at https://console.groq.com
|
|
65
|
+
|
|
66
|
+
## Usage
|
|
67
|
+
|
|
68
|
+
Point it at any project:
|
|
69
|
+
python main.py /path/to/your/project
|
|
70
|
+
|
|
71
|
+
Or run from inside a project folder:
|
|
72
|
+
cd your-project
|
|
73
|
+
python /path/to/makima-cli/main.py
|
|
74
|
+
|
|
75
|
+
## Built With
|
|
76
|
+
|
|
77
|
+
- Python
|
|
78
|
+
- Groq API
|
|
79
|
+
- Rich
|
|
80
|
+
- GitPython
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
LICENSE
|
|
1
2
|
README.md
|
|
2
3
|
pyproject.toml
|
|
3
4
|
makima/__init__.py
|
|
@@ -6,6 +7,7 @@ makima/main.py
|
|
|
6
7
|
makima/setup.py
|
|
7
8
|
makima/core/__init__.py
|
|
8
9
|
makima/core/agent.py
|
|
10
|
+
makima/core/config_manager.py
|
|
9
11
|
makima/core/context.py
|
|
10
12
|
makima/core/memory.py
|
|
11
13
|
makima/providers/base.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "makima-cli"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "AI coding assistant for your terminal"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {file = "LICENSE"}
|
|
@@ -18,6 +18,7 @@ dependencies = [
|
|
|
18
18
|
"gitpython",
|
|
19
19
|
"rich",
|
|
20
20
|
"pyfiglet",
|
|
21
|
+
"questionary",
|
|
21
22
|
]
|
|
22
23
|
|
|
23
24
|
[project.scripts]
|
makima_cli-0.2.0/PKG-INFO
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: makima-cli
|
|
3
|
-
Version: 0.2.0
|
|
4
|
-
Summary: AI coding assistant for your terminal
|
|
5
|
-
Author: Kanhaiya
|
|
6
|
-
Requires-Python: >=3.10
|
|
7
|
-
Description-Content-Type: text/markdown
|
|
8
|
-
Requires-Dist: groq
|
|
9
|
-
Requires-Dist: python-dotenv
|
|
10
|
-
Requires-Dist: gitpython
|
|
11
|
-
Requires-Dist: rich
|
|
12
|
-
Requires-Dist: pyfiglet
|
|
13
|
-
|
|
14
|
-
# Makima CLI 🤖
|
|
15
|
-
|
|
16
|
-
An AI-powered coding assistant that runs in your terminal. Point it at any codebase and ask questions, make edits, and run commands — all from a clean CLI interface.
|
|
17
|
-
|
|
18
|
-
## Features
|
|
19
|
-
|
|
20
|
-
- Understands your entire codebase
|
|
21
|
-
- Answers questions about your code
|
|
22
|
-
- Edits files with auto git backup before changes
|
|
23
|
-
- Creates new files
|
|
24
|
-
- Runs terminal commands with confirmation
|
|
25
|
-
- Works on any project
|
|
26
|
-
- Clean terminal UI with syntax highlighting
|
|
27
|
-
|
|
28
|
-
## Install
|
|
29
|
-
|
|
30
|
-
git clone https://github.com/yourusername/makima-cli.git
|
|
31
|
-
cd makima-cli
|
|
32
|
-
pip install -r requirements.txt
|
|
33
|
-
|
|
34
|
-
## Setup
|
|
35
|
-
|
|
36
|
-
Create a .env file in the project root:
|
|
37
|
-
GROQ_API_KEY=your_key_here
|
|
38
|
-
|
|
39
|
-
Get a free API key at https://console.groq.com
|
|
40
|
-
|
|
41
|
-
## Usage
|
|
42
|
-
|
|
43
|
-
Point it at any project:
|
|
44
|
-
python main.py /path/to/your/project
|
|
45
|
-
|
|
46
|
-
Or run from inside a project folder:
|
|
47
|
-
cd your-project
|
|
48
|
-
python /path/to/makima-cli/main.py
|
|
49
|
-
|
|
50
|
-
## Built With
|
|
51
|
-
|
|
52
|
-
- Python
|
|
53
|
-
- Groq API
|
|
54
|
-
- Rich
|
|
55
|
-
- GitPython
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from makima.config import PROJECT_ROOT,MODEL_NAME
|
|
3
|
-
from makima.core.context import ContextManager
|
|
4
|
-
from makima.core.memory import Memory
|
|
5
|
-
from makima.tools import TOOL_REGISTRY
|
|
6
|
-
from makima.tools.registry import TOOL_SCHEMAS
|
|
7
|
-
from makima.providers.groq_provider import GroqProvider
|
|
8
|
-
from rich.console import Console
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
console = Console()
|
|
12
|
-
|
|
13
|
-
ctx = ContextManager()
|
|
14
|
-
context = ctx.build_context()
|
|
15
|
-
|
|
16
|
-
SYSTEM_PROMPT = f"""
|
|
17
|
-
You are a coding assistant. The project is at: {PROJECT_ROOT}
|
|
18
|
-
|
|
19
|
-
Rules:
|
|
20
|
-
- Always use list_files first to find exact paths
|
|
21
|
-
- Always use read_file before editing any file
|
|
22
|
-
- Use full absolute paths always
|
|
23
|
-
- Be concise and direct
|
|
24
|
-
- old_str must be an exact match of multiple lines from the file
|
|
25
|
-
- Never explain what you are about to do. Never say "Let me..." or "I'll first...".
|
|
26
|
-
- Just call the tool immediately and silently.
|
|
27
|
-
- Only speak in plain text when you have a FINAL answer for the user.
|
|
28
|
-
- Call only ONE tool per response. Wait for the tool result before calling the next tool.
|
|
29
|
-
- Never output multiple tool calls in one response.
|
|
30
|
-
"""
|
|
31
|
-
|
|
32
|
-
import pyfiglet
|
|
33
|
-
from rich.panel import Panel
|
|
34
|
-
from rich.text import Text
|
|
35
|
-
from rich.rule import Rule
|
|
36
|
-
from rich.markdown import Markdown
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def run_agent():
|
|
40
|
-
provider = GroqProvider()
|
|
41
|
-
memory = Memory(system_prompt=SYSTEM_PROMPT)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
ascii_art = pyfiglet.figlet_format("Makima", font="big")
|
|
45
|
-
console.print(f"[bold #FF6B35]{ascii_art}[/]")
|
|
46
|
-
|
|
47
|
-
# info line underneath, no box
|
|
48
|
-
console.print(f"[dim] Your AI Coding Assistant[/]")
|
|
49
|
-
console.print(f"[green] Project :[/] {PROJECT_ROOT}")
|
|
50
|
-
console.print(f"[green] Files :[/] {len(ctx.files)} files loaded")
|
|
51
|
-
console.print(f"[green] Model :[/] {MODEL_NAME}")
|
|
52
|
-
console.print(f"[dim] Type 'exit' to quit[/]")
|
|
53
|
-
console.print(Rule(style="#FF6B35")) # clean horizontal line separator
|
|
54
|
-
console.print()
|
|
55
|
-
|
|
56
|
-
while True:
|
|
57
|
-
user_input = console.input("[bold blue]You:[/] ")
|
|
58
|
-
if user_input.strip() == "exit":
|
|
59
|
-
break
|
|
60
|
-
|
|
61
|
-
memory.add_user(user_input)
|
|
62
|
-
|
|
63
|
-
while True:
|
|
64
|
-
try:
|
|
65
|
-
with console.status("[yellow]thinking...[/]"):
|
|
66
|
-
stream = provider.stream_chat(
|
|
67
|
-
messages=memory.get(),
|
|
68
|
-
tools=TOOL_SCHEMAS
|
|
69
|
-
)
|
|
70
|
-
chunks = list(stream)
|
|
71
|
-
except Exception as e:
|
|
72
|
-
console.print(f"[red]Error: {e}[/]")
|
|
73
|
-
break
|
|
74
|
-
|
|
75
|
-
#variables to collect the response
|
|
76
|
-
text_buffer = ""
|
|
77
|
-
tool_name = ""
|
|
78
|
-
tool_args = ""
|
|
79
|
-
tool_call_id = ""
|
|
80
|
-
is_tool_call = False
|
|
81
|
-
|
|
82
|
-
# console.print("[bold green]Agent:[/] ", end="")
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
for chunk in chunks:
|
|
86
|
-
delta = chunk.choices[0].delta
|
|
87
|
-
|
|
88
|
-
#text chunk
|
|
89
|
-
if delta.content:
|
|
90
|
-
# print(delta.content, end="", flush=True)
|
|
91
|
-
text_buffer += delta.content
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
# tool call chunk
|
|
95
|
-
if delta.tool_calls:
|
|
96
|
-
is_tool_call = True
|
|
97
|
-
tc = delta.tool_calls[0]
|
|
98
|
-
if tc.id:
|
|
99
|
-
tool_call_id = tc.id
|
|
100
|
-
if tc.function.name:
|
|
101
|
-
tool_name += tc.function.name
|
|
102
|
-
if tc.function.arguments:
|
|
103
|
-
tool_args += tc.function.arguments
|
|
104
|
-
|
|
105
|
-
# print()
|
|
106
|
-
|
|
107
|
-
if is_tool_call:
|
|
108
|
-
console.print(f"[dim]⚡ {tool_name}[/]")
|
|
109
|
-
|
|
110
|
-
with console.status(f"[yellow]calling {tool_name}...[/]"):
|
|
111
|
-
args = json.loads(tool_args)
|
|
112
|
-
tool_fn = TOOL_REGISTRY.get(tool_name)
|
|
113
|
-
result = tool_fn(**args) if tool_fn else "Unknown tool"
|
|
114
|
-
|
|
115
|
-
# build the assistant message manually for memory
|
|
116
|
-
memory.add_raw({
|
|
117
|
-
"role": "assistant",
|
|
118
|
-
"tool_calls": [{
|
|
119
|
-
"id": tool_call_id,
|
|
120
|
-
"type": "function",
|
|
121
|
-
"function": {
|
|
122
|
-
"name": tool_name,
|
|
123
|
-
"arguments": tool_args
|
|
124
|
-
}
|
|
125
|
-
}]
|
|
126
|
-
})
|
|
127
|
-
memory.add_tool_result(tool_call_id, str(result))
|
|
128
|
-
|
|
129
|
-
else:
|
|
130
|
-
console.print("[bold green]Agent:[/]")
|
|
131
|
-
console.print(Markdown(text_buffer))
|
|
132
|
-
memory.add_assistant(text_buffer)
|
|
133
|
-
break
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import subprocess
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def run_command(cmd):
|
|
5
|
-
print(f"Commands going to Run: {cmd}")
|
|
6
|
-
User_answer = input("Run This? (Y/N): ")
|
|
7
|
-
User_answer = User_answer.lower()
|
|
8
|
-
|
|
9
|
-
if User_answer != "y":
|
|
10
|
-
return "Command cancelled"
|
|
11
|
-
|
|
12
|
-
result = subprocess.run(
|
|
13
|
-
cmd,
|
|
14
|
-
shell=True,
|
|
15
|
-
capture_output=True,
|
|
16
|
-
text=True,
|
|
17
|
-
timeout=30
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
return result.stdout + result.stderr
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: makima-cli
|
|
3
|
-
Version: 0.2.0
|
|
4
|
-
Summary: AI coding assistant for your terminal
|
|
5
|
-
Author: Kanhaiya
|
|
6
|
-
Requires-Python: >=3.10
|
|
7
|
-
Description-Content-Type: text/markdown
|
|
8
|
-
Requires-Dist: groq
|
|
9
|
-
Requires-Dist: python-dotenv
|
|
10
|
-
Requires-Dist: gitpython
|
|
11
|
-
Requires-Dist: rich
|
|
12
|
-
Requires-Dist: pyfiglet
|
|
13
|
-
|
|
14
|
-
# Makima CLI 🤖
|
|
15
|
-
|
|
16
|
-
An AI-powered coding assistant that runs in your terminal. Point it at any codebase and ask questions, make edits, and run commands — all from a clean CLI interface.
|
|
17
|
-
|
|
18
|
-
## Features
|
|
19
|
-
|
|
20
|
-
- Understands your entire codebase
|
|
21
|
-
- Answers questions about your code
|
|
22
|
-
- Edits files with auto git backup before changes
|
|
23
|
-
- Creates new files
|
|
24
|
-
- Runs terminal commands with confirmation
|
|
25
|
-
- Works on any project
|
|
26
|
-
- Clean terminal UI with syntax highlighting
|
|
27
|
-
|
|
28
|
-
## Install
|
|
29
|
-
|
|
30
|
-
git clone https://github.com/yourusername/makima-cli.git
|
|
31
|
-
cd makima-cli
|
|
32
|
-
pip install -r requirements.txt
|
|
33
|
-
|
|
34
|
-
## Setup
|
|
35
|
-
|
|
36
|
-
Create a .env file in the project root:
|
|
37
|
-
GROQ_API_KEY=your_key_here
|
|
38
|
-
|
|
39
|
-
Get a free API key at https://console.groq.com
|
|
40
|
-
|
|
41
|
-
## Usage
|
|
42
|
-
|
|
43
|
-
Point it at any project:
|
|
44
|
-
python main.py /path/to/your/project
|
|
45
|
-
|
|
46
|
-
Or run from inside a project folder:
|
|
47
|
-
cd your-project
|
|
48
|
-
python /path/to/makima-cli/main.py
|
|
49
|
-
|
|
50
|
-
## Built With
|
|
51
|
-
|
|
52
|
-
- Python
|
|
53
|
-
- Groq API
|
|
54
|
-
- Rich
|
|
55
|
-
- GitPython
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|