makima-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.
@@ -0,0 +1,54 @@
1
+ Metadata-Version: 2.4
2
+ Name: makima-cli
3
+ Version: 0.1.0
4
+ Summary: AI coding assistant for your terminal
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: groq
8
+ Requires-Dist: python-dotenv
9
+ Requires-Dist: gitpython
10
+ Requires-Dist: rich
11
+ Requires-Dist: pyfiglet
12
+
13
+ # Makima CLI 🤖
14
+
15
+ 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.
16
+
17
+ ## Features
18
+
19
+ - Understands your entire codebase
20
+ - Answers questions about your code
21
+ - Edits files with auto git backup before changes
22
+ - Creates new files
23
+ - Runs terminal commands with confirmation
24
+ - Works on any project
25
+ - Clean terminal UI with syntax highlighting
26
+
27
+ ## Install
28
+
29
+ git clone https://github.com/yourusername/makima-cli.git
30
+ cd makima-cli
31
+ pip install -r requirements.txt
32
+
33
+ ## Setup
34
+
35
+ Create a .env file in the project root:
36
+ GROQ_API_KEY=your_key_here
37
+
38
+ Get a free API key at https://console.groq.com
39
+
40
+ ## Usage
41
+
42
+ Point it at any project:
43
+ python main.py /path/to/your/project
44
+
45
+ Or run from inside a project folder:
46
+ cd your-project
47
+ python /path/to/makima-cli/main.py
48
+
49
+ ## Built With
50
+
51
+ - Python
52
+ - Groq API
53
+ - Rich
54
+ - GitPython
@@ -0,0 +1,42 @@
1
+ # Makima CLI 🤖
2
+
3
+ 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.
4
+
5
+ ## Features
6
+
7
+ - Understands your entire codebase
8
+ - Answers questions about your code
9
+ - Edits files with auto git backup before changes
10
+ - Creates new files
11
+ - Runs terminal commands with confirmation
12
+ - Works on any project
13
+ - Clean terminal UI with syntax highlighting
14
+
15
+ ## Install
16
+
17
+ git clone https://github.com/yourusername/makima-cli.git
18
+ cd makima-cli
19
+ pip install -r requirements.txt
20
+
21
+ ## Setup
22
+
23
+ Create a .env file in the project root:
24
+ GROQ_API_KEY=your_key_here
25
+
26
+ Get a free API key at https://console.groq.com
27
+
28
+ ## Usage
29
+
30
+ Point it at any project:
31
+ python main.py /path/to/your/project
32
+
33
+ Or run from inside a project folder:
34
+ cd your-project
35
+ python /path/to/makima-cli/main.py
36
+
37
+ ## Built With
38
+
39
+ - Python
40
+ - Groq API
41
+ - Rich
42
+ - GitPython
File without changes
@@ -0,0 +1,13 @@
1
+ import os
2
+ import sys
3
+ from dotenv import load_dotenv
4
+ load_dotenv()
5
+
6
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
7
+ MODEL_NAME = "qwen/qwen3.6-27b"
8
+ TOKEN_LIMIT = 10000
9
+ # PROJECT_ROOT = os.getcwd()
10
+ PROJECT_ROOT = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()
11
+
12
+ if not GROQ_API_KEY:
13
+ raise ValueError("GROQ_API_KEY not set in .env file")
File without changes
@@ -0,0 +1,133 @@
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
@@ -0,0 +1,47 @@
1
+ from makima.config import PROJECT_ROOT,TOKEN_LIMIT
2
+ from makima.tools.file_tools import read_file,list_files
3
+ import os
4
+
5
+
6
+ class ContextManager:
7
+ def __init__(self):
8
+ self.files = []
9
+ self.total_tokens = 0
10
+ self.scan_files()
11
+
12
+
13
+ def scan_files(self):
14
+ skip = {"__pycache__", ".git", "node_modules", ".env",".venv"}
15
+ skip_ext = {".pyc", ".png", ".jpg", ".jpeg", ".gif", ".ico"}
16
+ self.files = []
17
+
18
+ for folder, subfolders, files in os.walk(PROJECT_ROOT):
19
+ subfolders[:] = [f for f in subfolders if f not in skip]
20
+
21
+ for file in files:
22
+
23
+ if any(file.endswith(ext) for ext in skip_ext):
24
+ continue
25
+ file_path = os.path.join(folder,file)
26
+ self.files.append(file_path)
27
+
28
+
29
+ def count_tokens(self,text):
30
+ return len(text) // 4
31
+
32
+
33
+ def build_context(self):
34
+
35
+ context = ""
36
+
37
+ for file in self.files:
38
+ content = read_file(file)
39
+
40
+ self.total_tokens += self.count_tokens(content)
41
+
42
+ if self.total_tokens > TOKEN_LIMIT:
43
+ return "TOO LARGE CONTEXT"
44
+ else:
45
+ context += f"\n--- {file} ---\n{content}\n"
46
+
47
+ return context
@@ -0,0 +1,23 @@
1
+ class Memory:
2
+
3
+ def __init__(self, system_prompt: str):
4
+ self.messages = [{"role": "system", "content": system_prompt}]
5
+
6
+ def add_user(self, text: str):
7
+ self.messages.append({"role": "user", "content": text})
8
+
9
+ def add_assistant(self, text: str):
10
+ self.messages.append({"role": "assistant", "content": text})
11
+
12
+ def add_tool_result(self, tool_call_id: str, content: str):
13
+ self.messages.append({
14
+ "role": "tool",
15
+ "tool_call_id": tool_call_id,
16
+ "content": content
17
+ })
18
+
19
+ def add_raw(self, message):
20
+ self.messages.append(message)
21
+
22
+ def get(self) -> list:
23
+ return self.messages
@@ -0,0 +1,8 @@
1
+ from makima.core.agent import run_agent
2
+ import sys
3
+
4
+ def main():
5
+ run_agent()
6
+
7
+ if __name__ == "__main__":
8
+ main()
@@ -0,0 +1,7 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ class LLMProvider(ABC):
4
+
5
+ @abstractmethod
6
+ def chat(self, messages: list, tools: list) -> object:
7
+ pass
@@ -0,0 +1,25 @@
1
+ from groq import Groq
2
+ from makima.providers.base import LLMProvider
3
+ from makima.config import GROQ_API_KEY, MODEL_NAME
4
+
5
+ class GroqProvider(LLMProvider):
6
+
7
+ def __init__(self):
8
+ self.client = Groq(api_key=GROQ_API_KEY)
9
+
10
+ def chat(self, messages: list, tools: list) -> object:
11
+ return self.client.chat.completions.create(
12
+ model=MODEL_NAME,
13
+ messages=messages,
14
+ tools=tools,
15
+ max_tokens=1024
16
+ )
17
+
18
+ def stream_chat(self, messages: list, tools: list):
19
+ return self.client.chat.completions.create(
20
+ model=MODEL_NAME,
21
+ messages=messages,
22
+ tools=tools,
23
+ max_tokens=1024,
24
+ stream=True
25
+ )
@@ -0,0 +1,10 @@
1
+ from makima.tools.file_tools import read_file, list_files, edit_file, create_file
2
+ from makima.tools.shell_tools import run_command
3
+
4
+ TOOL_REGISTRY = {
5
+ "read_file": read_file,
6
+ "list_files": list_files,
7
+ "edit_file": edit_file,
8
+ "run_command": run_command,
9
+ "create_file": create_file,
10
+ }
@@ -0,0 +1,65 @@
1
+ from makima.config import PROJECT_ROOT
2
+ import os
3
+ import git
4
+
5
+ def read_file(path):
6
+ if not os.path.exists(path):
7
+ path = os.path.join(PROJECT_ROOT, path)
8
+ try:
9
+ with open(path, "r") as content:
10
+ return content.read()
11
+ except Exception as e:
12
+ return f"There is an Error while Reading your files. Error - {e}"
13
+
14
+
15
+ def list_files():
16
+ skip = {"__pycache__", ".git", "node_modules", ".env",".venv"}
17
+ output = []
18
+
19
+ for folder, subfolders, files in os.walk(PROJECT_ROOT):
20
+
21
+ subfolders[:] = [f for f in subfolders if f not in skip]
22
+
23
+ output.append(folder)
24
+ for file in files:
25
+ output.append(" " + file)
26
+
27
+ return "\n".join(output)
28
+
29
+
30
+ def edit_file(path, old_str, new_str):
31
+ auto_commit(path)
32
+
33
+ if not os.path.exists(path):
34
+ path = os.path.join(PROJECT_ROOT,path)
35
+
36
+ readed_content = read_file(path)
37
+ if old_str in readed_content:
38
+ new_contents = readed_content.replace(old_str,new_str,1)
39
+ else:
40
+ return f"content that i tried to change is missing"
41
+
42
+ with open(path,"w") as f:
43
+ f.write(new_contents)
44
+ return f"Done. Edited {path}"
45
+
46
+
47
+
48
+ def create_file(path, content):
49
+ if os.path.exists(path):
50
+ return f"File already exists: {path}"
51
+
52
+ os.makedirs(os.path.dirname(path), exist_ok=True)
53
+
54
+ with open(path, "w") as f:
55
+ f.write(content)
56
+ return f"Created path: {path}"
57
+
58
+
59
+ def auto_commit(path):
60
+ try:
61
+ repo = git.Repo(PROJECT_ROOT)
62
+ repo.git.add(path)
63
+ repo.index.commit(f"auto-backup before edit: {path}")
64
+ except Exception as e:
65
+ pass
@@ -0,0 +1,67 @@
1
+ TOOL_SCHEMAS = [
2
+ {
3
+ "type": "function",
4
+ "function": {
5
+ "name": "read_file",
6
+ "description": "Read a file and return its contents",
7
+ "parameters": {
8
+ "type": "object",
9
+ "properties": {
10
+ "path": {"type": "string", "description": "Full absolute path to the file"}
11
+ },
12
+ "required": ["path"]
13
+ }
14
+ }
15
+ },
16
+ {
17
+ "type": "function",
18
+ "function": {
19
+ "name": "list_files",
20
+ "description": "List all files in the project",
21
+ "parameters": {"type": "object", "properties": {}}
22
+ }
23
+ },
24
+ {
25
+ "type": "function",
26
+ "function": {
27
+ "name": "edit_file",
28
+ "description": "Edit a file by replacing old_str with new_str",
29
+ "parameters": {
30
+ "type": "object",
31
+ "properties": {
32
+ "path": {"type": "string"},
33
+ "old_str": {"type": "string"},
34
+ "new_str": {"type": "string"}
35
+ },
36
+ "required": ["path", "old_str", "new_str"]
37
+ }
38
+ }
39
+ },
40
+ {
41
+ "type": "function",
42
+ "function": {
43
+ "name": "run_command",
44
+ "description": "Run a terminal command and return output",
45
+ "parameters": {
46
+ "type": "object",
47
+ "properties": {"cmd": {"type": "string"}},
48
+ "required": ["cmd"]
49
+ }
50
+ }
51
+ },
52
+ {
53
+ "type": "function",
54
+ "function": {
55
+ "name": "create_file",
56
+ "description": "Create a new file with given content",
57
+ "parameters": {
58
+ "type": "object",
59
+ "properties": {
60
+ "path": {"type": "string"},
61
+ "content": {"type": "string"}
62
+ },
63
+ "required": ["path", "content"]
64
+ }
65
+ }
66
+ }
67
+ ]
@@ -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,54 @@
1
+ Metadata-Version: 2.4
2
+ Name: makima-cli
3
+ Version: 0.1.0
4
+ Summary: AI coding assistant for your terminal
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: groq
8
+ Requires-Dist: python-dotenv
9
+ Requires-Dist: gitpython
10
+ Requires-Dist: rich
11
+ Requires-Dist: pyfiglet
12
+
13
+ # Makima CLI 🤖
14
+
15
+ 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.
16
+
17
+ ## Features
18
+
19
+ - Understands your entire codebase
20
+ - Answers questions about your code
21
+ - Edits files with auto git backup before changes
22
+ - Creates new files
23
+ - Runs terminal commands with confirmation
24
+ - Works on any project
25
+ - Clean terminal UI with syntax highlighting
26
+
27
+ ## Install
28
+
29
+ git clone https://github.com/yourusername/makima-cli.git
30
+ cd makima-cli
31
+ pip install -r requirements.txt
32
+
33
+ ## Setup
34
+
35
+ Create a .env file in the project root:
36
+ GROQ_API_KEY=your_key_here
37
+
38
+ Get a free API key at https://console.groq.com
39
+
40
+ ## Usage
41
+
42
+ Point it at any project:
43
+ python main.py /path/to/your/project
44
+
45
+ Or run from inside a project folder:
46
+ cd your-project
47
+ python /path/to/makima-cli/main.py
48
+
49
+ ## Built With
50
+
51
+ - Python
52
+ - Groq API
53
+ - Rich
54
+ - GitPython
@@ -0,0 +1,21 @@
1
+ README.md
2
+ pyproject.toml
3
+ makima/__init__.py
4
+ makima/config.py
5
+ makima/main.py
6
+ makima/core/__init__.py
7
+ makima/core/agent.py
8
+ makima/core/context.py
9
+ makima/core/memory.py
10
+ makima/providers/base.py
11
+ makima/providers/groq_provider.py
12
+ makima/tools/__init__.py
13
+ makima/tools/file_tools.py
14
+ makima/tools/registry.py
15
+ makima/tools/shell_tools.py
16
+ makima_cli.egg-info/PKG-INFO
17
+ makima_cli.egg-info/SOURCES.txt
18
+ makima_cli.egg-info/dependency_links.txt
19
+ makima_cli.egg-info/entry_points.txt
20
+ makima_cli.egg-info/requires.txt
21
+ makima_cli.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ makima = makima.main:main
@@ -0,0 +1,5 @@
1
+ groq
2
+ python-dotenv
3
+ gitpython
4
+ rich
5
+ pyfiglet
@@ -0,0 +1 @@
1
+ makima
@@ -0,0 +1,25 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "makima-cli"
7
+ version = "0.1.0"
8
+ description = "AI coding assistant for your terminal"
9
+ readme = "README.md"
10
+ license = {file = "LICENSE"}
11
+ requires-python = ">=3.10"
12
+ dependencies = [
13
+ "groq",
14
+ "python-dotenv",
15
+ "gitpython",
16
+ "rich",
17
+ "pyfiglet",
18
+ ]
19
+
20
+ [project.scripts]
21
+ makima = "makima.main:main"
22
+
23
+ [tool.setuptools.packages.find]
24
+ where = ["."]
25
+ include = ["makima*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+