librarian-code 0.1.0__py3-none-any.whl

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.
Files changed (45) hide show
  1. librarian/__init__.py +3 -0
  2. librarian/__main__.py +3 -0
  3. librarian/actions/__init__.py +0 -0
  4. librarian/actions/file_ops.py +47 -0
  5. librarian/actions/safety.py +29 -0
  6. librarian/actions/shell_ops.py +49 -0
  7. librarian/adapter/__init__.py +0 -0
  8. librarian/adapter/base.py +11 -0
  9. librarian/adapter/groq_adapter.py +40 -0
  10. librarian/adapter/openrouter_adapter.py +58 -0
  11. librarian/cli.py +26 -0
  12. librarian/commands/__init__.py +0 -0
  13. librarian/commands/ask.py +46 -0
  14. librarian/commands/do.py +232 -0
  15. librarian/commands/init.py +96 -0
  16. librarian/commands/status.py +71 -0
  17. librarian/commands/undo.py +85 -0
  18. librarian/commands/why.py +47 -0
  19. librarian/exceptions.py +22 -0
  20. librarian/memory/__init__.py +0 -0
  21. librarian/memory/capsule.py +94 -0
  22. librarian/memory/chunker.py +183 -0
  23. librarian/memory/decision_log.py +36 -0
  24. librarian/memory/indexer.py +96 -0
  25. librarian/memory/retriever.py +62 -0
  26. librarian/orchestrator/__init__.py +0 -0
  27. librarian/orchestrator/core.py +47 -0
  28. librarian/orchestrator/router.py +17 -0
  29. librarian/skills/__init__.py +0 -0
  30. librarian/skills/bundled/__init__.py +0 -0
  31. librarian/skills/bundled/api-design/conventions.md +93 -0
  32. librarian/skills/bundled/python/conventions.md +59 -0
  33. librarian/skills/bundled/react/conventions.md +83 -0
  34. librarian/skills/bundled/web-dev/conventions.md +54 -0
  35. librarian/skills/loader.py +109 -0
  36. librarian/utils/__init__.py +0 -0
  37. librarian/utils/config.py +15 -0
  38. librarian/utils/logger.py +32 -0
  39. librarian/utils/token_tracker.py +16 -0
  40. librarian/utils/ui.py +97 -0
  41. librarian_code-0.1.0.dist-info/METADATA +180 -0
  42. librarian_code-0.1.0.dist-info/RECORD +45 -0
  43. librarian_code-0.1.0.dist-info/WHEEL +4 -0
  44. librarian_code-0.1.0.dist-info/entry_points.txt +2 -0
  45. librarian_code-0.1.0.dist-info/licenses/LICENSE.md +21 -0
librarian/utils/ui.py ADDED
@@ -0,0 +1,97 @@
1
+ import sys
2
+ import io
3
+ import pyfiglet
4
+ from rich.console import Console
5
+ from rich.panel import Panel
6
+ from rich.table import Table
7
+ from rich.progress import Progress, SpinnerColumn, TextColumn
8
+ from rich.prompt import Confirm
9
+ from rich.columns import Columns
10
+ from rich.text import Text
11
+
12
+ sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
13
+ console = Console(force_terminal=True)
14
+
15
+ INDIGO = "#6366F1"
16
+ VIOLET = "#8B5CF6"
17
+ MUTED = "#6B7280"
18
+ SUCCESS = "#10B981"
19
+ WARNING = "#F59E0B"
20
+ ERROR = "#EF4444"
21
+ CYAN = "#06B6D4"
22
+ PINK = "#EC4899"
23
+
24
+
25
+ def print_banner():
26
+ ascii_art = pyfiglet.figlet_format("librarian", font="larry3d")
27
+ styled_art = Text(ascii_art, style="bold white")
28
+ tagline = Text("\n a CLI coding agent with persistent project memory", style=f"italic {MUTED}")
29
+
30
+ commands = Table(show_header=False, box=None, padding=(0, 2))
31
+ commands.add_column(style=f"bold {CYAN}")
32
+ commands.add_column(style=MUTED)
33
+ commands.add_row("init", "index your project")
34
+ commands.add_row("ask", "question your codebase")
35
+ commands.add_row("do", "execute a task")
36
+ commands.add_row("why", "see decision history")
37
+ commands.add_row("undo", "revert last action")
38
+ commands.add_row("status", "project overview")
39
+
40
+ banner_content = Text()
41
+ banner_content.append_text(styled_art)
42
+ banner_content.append_text(tagline)
43
+
44
+ panel = Panel(
45
+ banner_content,
46
+ border_style=INDIGO,
47
+ padding=(1, 3),
48
+ )
49
+ console.print()
50
+ console.print(panel)
51
+
52
+ cmd_panel = Panel(
53
+ commands,
54
+ title=f"[bold {VIOLET}]commands[/bold {VIOLET}]",
55
+ border_style=VIOLET,
56
+ padding=(0, 1),
57
+ )
58
+ console.print(cmd_panel)
59
+ console.print()
60
+
61
+
62
+ def print_header(title: str):
63
+ console.print(f"\n[bold {INDIGO}]>[/bold {INDIGO}] [bold]{title}[/bold]")
64
+ console.rule(style=INDIGO)
65
+
66
+
67
+ def print_success(msg: str):
68
+ console.print(f"[bold {SUCCESS}]checkmark[/bold {SUCCESS}] {msg}")
69
+
70
+
71
+ def print_warning(msg: str):
72
+ console.print(f"[bold {WARNING}]![/bold {WARNING}] {msg}")
73
+
74
+
75
+ def print_error(msg: str):
76
+ console.print(f"[bold {ERROR}]x[/bold {ERROR}] {msg}")
77
+
78
+
79
+ def print_muted(msg: str):
80
+ console.print(f"[{MUTED}]{msg}[/{MUTED}]")
81
+
82
+
83
+ def print_panel(content: str, title: str = "", style: str = INDIGO):
84
+ console.print(Panel(content, title=title, border_style=style, padding=(1, 2)))
85
+
86
+
87
+ def confirm_action(description: str) -> bool:
88
+ console.print(f"\n[bold {WARNING}]safety check[/bold {WARNING}]")
89
+ return Confirm.ask(f" [{WARNING}]{description}[/{WARNING}]")
90
+
91
+
92
+ def spinner(description: str):
93
+ return Progress(
94
+ SpinnerColumn(style=INDIGO),
95
+ TextColumn(f"[{MUTED}]{description}[/{MUTED}]"),
96
+ transient=True,
97
+ )
@@ -0,0 +1,180 @@
1
+ Metadata-Version: 2.4
2
+ Name: librarian-code
3
+ Version: 0.1.0
4
+ Summary: A local-first CLI coding agent with persistent project memory
5
+ Project-URL: Homepage, https://github.com/Humble-Librarian/Librarian-Code
6
+ Project-URL: Repository, https://github.com/Humble-Librarian/Librarian-Code
7
+ Project-URL: Issues, https://github.com/Humble-Librarian/Librarian-Code/issues
8
+ Author: Neel Sorathiya
9
+ License-Expression: MIT
10
+ License-File: LICENSE.md
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development :: Code Generators
18
+ Classifier: Topic :: Software Development :: Libraries
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: chromadb>=0.5.0
21
+ Requires-Dist: gitpython>=3.1.0
22
+ Requires-Dist: groq>=0.11.0
23
+ Requires-Dist: httpx>=0.27.0
24
+ Requires-Dist: pyfiglet>=1.0.0
25
+ Requires-Dist: python-dotenv>=1.0.0
26
+ Requires-Dist: rich>=13.0.0
27
+ Requires-Dist: sentence-transformers>=3.0.0
28
+ Requires-Dist: typer>=0.12.0
29
+ Description-Content-Type: text/markdown
30
+
31
+ # librarian
32
+
33
+ > a CLI coding agent that remembers your project
34
+
35
+ ## what it does differently
36
+
37
+ Librarian is a local-first CLI coding agent with persistent project memory. Unlike tools that call an LLM on every request regardless of confidence, Librarian builds a capsule-based memory of your project's decisions — remembering why edits were made, adjusting confidence over time, and routing between Groq and OpenRouter intelligently when rate limits hit.
38
+
39
+ Built without LangChain — pure Python, owned stack. Every file operation, every LLM call, every decision is transparent and logged.
40
+
41
+ ## install
42
+
43
+ ```bash
44
+ pip install -g librarian-code
45
+ ```
46
+
47
+ ## setup
48
+
49
+ You need at least one free API key:
50
+
51
+ | Provider | Get Key | Cost |
52
+ |----------|---------|------|
53
+ | **Groq** | https://console.groq.com | Free tier available |
54
+ | **OpenRouter** | https://openrouter.ai | Free models available |
55
+
56
+ Create `.env` in your project root:
57
+
58
+ ```bash
59
+ # option 1: groq (fast)
60
+ echo "GROQ_API_KEY=gsk_..." > .env
61
+
62
+ # option 2: openrouter
63
+ echo "OPENROUTER_API_KEY=sk-or-..." > .env
64
+
65
+ # or both (openrouter used as fallback)
66
+ ```
67
+
68
+ ## quick start
69
+
70
+ ```bash
71
+ librarian init # index your project
72
+ librarian ask "what does this project do?"
73
+ librarian do "add input validation to login()"
74
+ librarian why # see decision history
75
+ librarian undo # revert last action
76
+ librarian status # project overview
77
+ ```
78
+
79
+ ## commands
80
+
81
+ | command | what it does |
82
+ |---------|-------------|
83
+ | `librarian init` | indexes project files, generates LIBRARIAN.md conventions |
84
+ | `librarian ask` | asks a question about your codebase, returns answer with sources |
85
+ | `librarian do` | gives librarian a task, shows plan preview, executes with your approval |
86
+ | `librarian why` | shows last decisions with reasoning |
87
+ | `librarian undo` | reverts the last agent action |
88
+ | `librarian status` | shows project info, memory stats, token usage |
89
+
90
+ ## how memory works
91
+
92
+ Librarian uses a **capsule-based memory system**:
93
+
94
+ - Every action creates a **capsule** with a confidence score (starts at 0.5)
95
+ - When you approve an action: confidence × 1.15
96
+ - When you undo an action: confidence × 0.6
97
+ - Unused capsules decay: × 0.98 per day
98
+ - Capsules below 0.4 confidence are archived
99
+
100
+ This means Librarian learns from your feedback over time — actions you approve become more confident, actions you undo become less likely to be repeated.
101
+
102
+ ## skills
103
+
104
+ Librarian auto-detects your project type and loads relevant conventions:
105
+
106
+ - **python**: pyproject.toml, setup.py, requirements.txt
107
+ - **react**: next.config.*, .tsx/.jsx files
108
+ - **web-dev**: .html files, CSS/SCSS
109
+ - **api-design**: routes.py, models.py, schemas.py
110
+
111
+ Skills provide domain-specific best practices that are injected into the LLM context for more relevant suggestions.
112
+
113
+ ## architecture
114
+
115
+ ```
116
+ librarian/
117
+ ├── adapter/ # LLM adapters (Groq primary, OpenRouter fallback)
118
+ │ ├── base.py # abstract adapter interface
119
+ │ ├── groq_adapter.py
120
+ │ └── openrouter_adapter.py
121
+ ├── orchestrator/ # routing and system prompt building
122
+ │ ├── router.py # Groq → OpenRouter fallback
123
+ │ └── core.py # prompt construction
124
+ ├── memory/ # persistent project memory
125
+ │ ├── chunker.py # AST-based code splitting
126
+ │ ├── indexer.py # ChromaDB + sentence-transformers
127
+ │ ├── retriever.py # semantic search (cached model)
128
+ │ ├── capsule.py # decision memory with confidence
129
+ │ └── decision_log.py # append-only action log
130
+ ├── skills/ # auto-detected project conventions
131
+ │ ├── loader.py # project type detection with caching
132
+ │ └── bundled/ # skill convention files
133
+ ├── actions/ # file and shell operations
134
+ │ ├── file_ops.py # read, write, edit files
135
+ │ ├── shell_ops.py # git and shell commands (shell=False)
136
+ │ └── safety.py # risk classification
137
+ ├── commands/ # CLI commands
138
+ │ ├── init.py
139
+ │ ├── ask.py
140
+ │ ├── do.py
141
+ │ ├── why.py
142
+ │ ├── undo.py
143
+ │ └── status.py
144
+ ├── utils/ # shared utilities
145
+ │ ├── config.py # env var loading
146
+ │ ├── ui.py # Terminal Luxury output
147
+ │ ├── logger.py # structured logging
148
+ │ └── token_tracker.py
149
+ ├── cli.py # typer entry point
150
+ └── exceptions.py # custom exception types
151
+ ```
152
+
153
+ ## providers
154
+
155
+ - **Groq** (primary): `llama-3.3-70b-versatile`, fast inference
156
+ - **OpenRouter** (fallback): `qwen/qwen3-coder:free`, automatic on rate limit
157
+
158
+ ## security
159
+
160
+ - Shell commands use `shell=False` with argument lists to prevent injection
161
+ - File operations use proper context managers to prevent handle leaks
162
+ - API responses validated before access
163
+ - LLM-generated delete operations require confirmation
164
+
165
+ ## performance
166
+
167
+ - SentenceTransformer model cached as singleton (~2-3s saved per invocation)
168
+ - ChromaDB client reused across calls
169
+ - Project type detection cached with `@lru_cache`
170
+ - Heavy dependencies lazy-loaded at function call time
171
+
172
+ ## testing
173
+
174
+ ```bash
175
+ python -m pytest tests/ -v
176
+ ```
177
+
178
+ ## license
179
+
180
+ MIT
@@ -0,0 +1,45 @@
1
+ librarian/__init__.py,sha256=ZGVQ7mPZNTCf6su8JgJUBC0H_fG-3WehU8TkW-PXPT4,94
2
+ librarian/__main__.py,sha256=FzsJRHMKtP-Ufam5f9WmwuLgLEjT9EGS8E_wpXg1DrE,37
3
+ librarian/cli.py,sha256=w1tCtBw6OkhsBG0ifwyQFRBfEm5RXvISqUfCPq6FDFI,665
4
+ librarian/exceptions.py,sha256=6vvJHuZqhrZrgYZGUo8Y2jQ_4O2QeMK279jG5NDyHbc,318
5
+ librarian/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ librarian/actions/file_ops.py,sha256=RtdNERT4x0l7IY_Hml6F_0RnxRjByzNke3hiFFxxQ78,1417
7
+ librarian/actions/safety.py,sha256=MXtdmXE632A2vWzCEETcrTcxoEA8RXBd31CqKprZEOg,584
8
+ librarian/actions/shell_ops.py,sha256=P6TL6tBoPX70p7G4yOPIS2N6QfK2BFXvSwq_PXxlDAI,1302
9
+ librarian/adapter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ librarian/adapter/base.py,sha256=KJCnHZEdKu6S3wW4oxHgdABlPRiuGwQNUFokvWat0tU,221
11
+ librarian/adapter/groq_adapter.py,sha256=xT_GZdJfxXTyTk2HQ5rnzg_VxvQ1L9QbTpbwBgL8pcI,1489
12
+ librarian/adapter/openrouter_adapter.py,sha256=0iz1ZhzGpZqdtbi5bsl_Tf-Y3Ljp6EriqXzumjm-_Zg,2307
13
+ librarian/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ librarian/commands/ask.py,sha256=2PaRre15bMPIEavw37LvBaM8SPzxE5U6nlCoUdmlMmQ,1633
15
+ librarian/commands/do.py,sha256=tt117T4CSMz7XAB9oRx_etaDuh1zTRmYJRTbYnmwjsQ,8743
16
+ librarian/commands/init.py,sha256=9bN6X_I8K0gG80hTKEHtLKrWZ0t7LGyxJxzHdHeC2dE,2894
17
+ librarian/commands/status.py,sha256=-_SG7ftxdrSDEt1N6TFDAtz3Tt2t0YWTccDQYPJU-Yk,2706
18
+ librarian/commands/undo.py,sha256=M_4NjfVB5TebpBG77r3VNdSpW6YFyuvZAfcKtYo95BI,2574
19
+ librarian/commands/why.py,sha256=pgLM2cYnUxV4DaQTmOoGlXuv97c5oQtMt2nXZfWr_p8,1667
20
+ librarian/memory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ librarian/memory/capsule.py,sha256=KcnZI0zKcMnpMPEhLv7dh0-EqR00_PTFSPwgIWAkqWk,2518
22
+ librarian/memory/chunker.py,sha256=uBZyWRv75AAVaAM_FWiP0BUmGQXYaG_0pnkizWRwEUQ,6285
23
+ librarian/memory/decision_log.py,sha256=TmakVFnx_ifQp7IuMUxhbh5UsOV5AkxvuIeH78VPX0w,1048
24
+ librarian/memory/indexer.py,sha256=FoONgVMN5qax_VKg9_qrtOZ2qfIcEp9qVMyXToITRyc,3043
25
+ librarian/memory/retriever.py,sha256=gFbM8fjER4-QJrAnWR6swjXOTlnPTPIVwyseUdw6jzM,1564
26
+ librarian/orchestrator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ librarian/orchestrator/core.py,sha256=RLWL5MEi09ztxVuqi3PLzr8oF9L5G0kz49LxGzrWe_E,1730
28
+ librarian/orchestrator/router.py,sha256=sSLCiXh3g0j_vnbr6gHgayQHHmnUmoVqsmSZ1--_6Gg,720
29
+ librarian/skills/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ librarian/skills/loader.py,sha256=rv8bMVL9I0HC1Pxzq5ypmIol9GGfiycJv16f90M5s0k,3729
31
+ librarian/skills/bundled/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ librarian/skills/bundled/api-design/conventions.md,sha256=DWK6lumDKGTjBwC0ZyJLDUd87ZVfRzduZmC2TaG50tY,3209
33
+ librarian/skills/bundled/python/conventions.md,sha256=4bcZOVVzk5zDToYGEsh2HVVdibrxCk2TiqE-WvGk-vM,2316
34
+ librarian/skills/bundled/react/conventions.md,sha256=52YgVygWmPJLZOecBDpwzrHFfqV1LGSNm9XfEowb_Kc,3062
35
+ librarian/skills/bundled/web-dev/conventions.md,sha256=PY4Tll-4APkmAPMB7p1-gtCOb1rBssB4xlSDsWKeC3c,2253
36
+ librarian/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
+ librarian/utils/config.py,sha256=bHzj3qFDJY7BZc37vKgpQe3LRPi36-QQCfcBXhVAFfI,546
38
+ librarian/utils/logger.py,sha256=n1COiHWzXLWm0J6I5PuBKkMhXbb6nRPBFU8S3FNf6SM,605
39
+ librarian/utils/token_tracker.py,sha256=5xch5JWNWnM5Z-3XkC-uf8a_HatlFIkkZAwoaXyLOP4,487
40
+ librarian/utils/ui.py,sha256=oGDS7pAtf8PMoN5vHdtAHUC2O92fp42em3SCkJaLYxg,2721
41
+ librarian_code-0.1.0.dist-info/METADATA,sha256=7yPmU4GRYR-gPB0dMrZnl3WOT-572qfj5i_jlt7Ft1U,6472
42
+ librarian_code-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
43
+ librarian_code-0.1.0.dist-info/entry_points.txt,sha256=oE3mm9INPgmDXlTLTKPfdd10ocDwa2xIb0o3gzgw5Q8,48
44
+ librarian_code-0.1.0.dist-info/licenses/LICENSE.md,sha256=SE4TZDsWWMYoMePRurMmCCqsRGahPc5uzghX8s8EqJY,1071
45
+ librarian_code-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ librarian = librarian.cli:app
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Neel Sorathiya
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.