loom-code 0.1.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.
Files changed (101) hide show
  1. loom_code-0.1.1/LICENSE +21 -0
  2. loom_code-0.1.1/PKG-INFO +224 -0
  3. loom_code-0.1.1/README.md +170 -0
  4. loom_code-0.1.1/loom_code/__init__.py +22 -0
  5. loom_code-0.1.1/loom_code/_post_commit.py +119 -0
  6. loom_code-0.1.1/loom_code/agent.py +544 -0
  7. loom_code-0.1.1/loom_code/approval.py +616 -0
  8. loom_code-0.1.1/loom_code/browse/__init__.py +291 -0
  9. loom_code-0.1.1/loom_code/browse/act.py +467 -0
  10. loom_code-0.1.1/loom_code/browse/observe.py +249 -0
  11. loom_code-0.1.1/loom_code/browse/session.py +96 -0
  12. loom_code-0.1.1/loom_code/browse/verify.py +194 -0
  13. loom_code-0.1.1/loom_code/checkpoint.py +283 -0
  14. loom_code-0.1.1/loom_code/cli.py +495 -0
  15. loom_code-0.1.1/loom_code/code_index.py +703 -0
  16. loom_code-0.1.1/loom_code/compact.py +143 -0
  17. loom_code-0.1.1/loom_code/consent.py +47 -0
  18. loom_code-0.1.1/loom_code/credentials.py +527 -0
  19. loom_code-0.1.1/loom_code/edit_tool.py +635 -0
  20. loom_code-0.1.1/loom_code/extensions.py +522 -0
  21. loom_code-0.1.1/loom_code/file_history.py +322 -0
  22. loom_code-0.1.1/loom_code/file_tools.py +93 -0
  23. loom_code-0.1.1/loom_code/git_hook.py +200 -0
  24. loom_code-0.1.1/loom_code/grep_tool.py +430 -0
  25. loom_code-0.1.1/loom_code/hooks.py +297 -0
  26. loom_code-0.1.1/loom_code/loominit/__init__.py +23 -0
  27. loom_code-0.1.1/loom_code/loominit/_ast_walk.py +429 -0
  28. loom_code-0.1.1/loom_code/loominit/_files.py +284 -0
  29. loom_code-0.1.1/loom_code/loominit/_graph.py +141 -0
  30. loom_code-0.1.1/loom_code/loominit/_resolve.py +392 -0
  31. loom_code-0.1.1/loom_code/loominit/_tests_map.py +108 -0
  32. loom_code-0.1.1/loom_code/loominit/extractor.py +332 -0
  33. loom_code-0.1.1/loom_code/loominit/repomap.py +225 -0
  34. loom_code-0.1.1/loom_code/loominit/schema.py +242 -0
  35. loom_code-0.1.1/loom_code/lsp_tools.py +396 -0
  36. loom_code-0.1.1/loom_code/mcp_host.py +79 -0
  37. loom_code-0.1.1/loom_code/operator.py +449 -0
  38. loom_code-0.1.1/loom_code/paste.py +97 -0
  39. loom_code-0.1.1/loom_code/paths.py +52 -0
  40. loom_code-0.1.1/loom_code/permissions.py +177 -0
  41. loom_code-0.1.1/loom_code/project.py +104 -0
  42. loom_code-0.1.1/loom_code/prompts.py +451 -0
  43. loom_code-0.1.1/loom_code/render.py +783 -0
  44. loom_code-0.1.1/loom_code/repl.py +4080 -0
  45. loom_code-0.1.1/loom_code/rules.py +267 -0
  46. loom_code-0.1.1/loom_code/sandboxed_bash.py +176 -0
  47. loom_code-0.1.1/loom_code/scribe.py +88 -0
  48. loom_code-0.1.1/loom_code/skills/__init__.py +16 -0
  49. loom_code-0.1.1/loom_code/skills/graphify/SKILL.md +97 -0
  50. loom_code-0.1.1/loom_code/skills/graphify/tools.py +570 -0
  51. loom_code-0.1.1/loom_code/trust.py +216 -0
  52. loom_code-0.1.1/loom_code/turn.py +169 -0
  53. loom_code-0.1.1/loom_code/web_fetch.py +370 -0
  54. loom_code-0.1.1/loom_code/workers.py +758 -0
  55. loom_code-0.1.1/loom_code/worktree.py +134 -0
  56. loom_code-0.1.1/loom_code.egg-info/PKG-INFO +224 -0
  57. loom_code-0.1.1/loom_code.egg-info/SOURCES.txt +99 -0
  58. loom_code-0.1.1/loom_code.egg-info/dependency_links.txt +1 -0
  59. loom_code-0.1.1/loom_code.egg-info/entry_points.txt +2 -0
  60. loom_code-0.1.1/loom_code.egg-info/requires.txt +12 -0
  61. loom_code-0.1.1/loom_code.egg-info/top_level.txt +1 -0
  62. loom_code-0.1.1/pyproject.toml +150 -0
  63. loom_code-0.1.1/setup.cfg +4 -0
  64. loom_code-0.1.1/tests/test_agent.py +215 -0
  65. loom_code-0.1.1/tests/test_antipoison_gate.py +159 -0
  66. loom_code-0.1.1/tests/test_approval.py +72 -0
  67. loom_code-0.1.1/tests/test_approval_danger.py +75 -0
  68. loom_code-0.1.1/tests/test_approval_integration.py +177 -0
  69. loom_code-0.1.1/tests/test_checkpoint.py +157 -0
  70. loom_code-0.1.1/tests/test_code_index.py +190 -0
  71. loom_code-0.1.1/tests/test_compact.py +68 -0
  72. loom_code-0.1.1/tests/test_credentials.py +232 -0
  73. loom_code-0.1.1/tests/test_edit_tool.py +529 -0
  74. loom_code-0.1.1/tests/test_extensions.py +400 -0
  75. loom_code-0.1.1/tests/test_file_boundary.py +141 -0
  76. loom_code-0.1.1/tests/test_file_history.py +184 -0
  77. loom_code-0.1.1/tests/test_git_hook.py +198 -0
  78. loom_code-0.1.1/tests/test_graphify_file_discovery.py +152 -0
  79. loom_code-0.1.1/tests/test_graphify_query_tiers.py +187 -0
  80. loom_code-0.1.1/tests/test_graphify_wiring.py +78 -0
  81. loom_code-0.1.1/tests/test_grep_tool.py +308 -0
  82. loom_code-0.1.1/tests/test_learned_notes.py +123 -0
  83. loom_code-0.1.1/tests/test_loom_hooks.py +368 -0
  84. loom_code-0.1.1/tests/test_lsp_tools.py +100 -0
  85. loom_code-0.1.1/tests/test_mcp.py +218 -0
  86. loom_code-0.1.1/tests/test_paste.py +98 -0
  87. loom_code-0.1.1/tests/test_permissions.py +220 -0
  88. loom_code-0.1.1/tests/test_pricing.py +57 -0
  89. loom_code-0.1.1/tests/test_project.py +67 -0
  90. loom_code-0.1.1/tests/test_prompts.py +120 -0
  91. loom_code-0.1.1/tests/test_render.py +285 -0
  92. loom_code-0.1.1/tests/test_repl_guards.py +99 -0
  93. loom_code-0.1.1/tests/test_resume_migration.py +264 -0
  94. loom_code-0.1.1/tests/test_resume_preview.py +249 -0
  95. loom_code-0.1.1/tests/test_routing.py +194 -0
  96. loom_code-0.1.1/tests/test_rules.py +90 -0
  97. loom_code-0.1.1/tests/test_sandboxed_bash.py +153 -0
  98. loom_code-0.1.1/tests/test_stream_liveness.py +159 -0
  99. loom_code-0.1.1/tests/test_turn_economy.py +116 -0
  100. loom_code-0.1.1/tests/test_web_fetch.py +298 -0
  101. loom_code-0.1.1/tests/test_workers.py +73 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anupam Nautiyal
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,224 @@
1
+ Metadata-Version: 2.4
2
+ Name: loom-code
3
+ Version: 0.1.1
4
+ Summary: loom-code — a loomflow-native terminal coding agent
5
+ Author: Anupam Nautiyal
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Anupam Nautiyal
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
+ Project-URL: Homepage, https://github.com/Anurich/loomflow-cli
29
+ Project-URL: Repository, https://github.com/Anurich/loomflow-cli
30
+ Project-URL: Issues, https://github.com/Anurich/loomflow-cli/issues
31
+ Keywords: ai,agent,cli,coding-assistant,llm,loomflow
32
+ Classifier: Development Status :: 4 - Beta
33
+ Classifier: Environment :: Console
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Programming Language :: Python :: 3.11
36
+ Classifier: Programming Language :: Python :: 3.12
37
+ Classifier: Programming Language :: Python :: 3.13
38
+ Classifier: Topic :: Software Development :: Code Generators
39
+ Requires-Python: >=3.11
40
+ Description-Content-Type: text/markdown
41
+ License-File: LICENSE
42
+ Requires-Dist: loomflow[litellm,mcp,web]<0.11,>=0.10.23
43
+ Requires-Dist: rich>=13
44
+ Requires-Dist: prompt-toolkit>=3.0
45
+ Requires-Dist: anthropic
46
+ Requires-Dist: openai
47
+ Requires-Dist: graphifyy<0.9,>=0.8.11
48
+ Requires-Dist: jedi>=0.19
49
+ Provides-Extra: dev
50
+ Requires-Dist: pytest; extra == "dev"
51
+ Requires-Dist: ruff; extra == "dev"
52
+ Requires-Dist: bump-my-version>=0.30; extra == "dev"
53
+ Dynamic: license-file
54
+
55
+ # loom-code
56
+
57
+ **A terminal coding agent built on [loomflow](https://github.com/Anurich/LoomFlow).**
58
+ Plans before it codes, asks before it breaks things, works with any model —
59
+ including free ones.
60
+
61
+ ```
62
+ › add a retry decorator to the http client
63
+
64
+ ● loom
65
+ Added `retry(max_attempts=3, backoff=2.0)` to http/client.py and wired it
66
+ onto get() and post(). Tests pass (14/14).
67
+ ───────────────────────────────────────────── 12,431 in · 217 out · $0.0043
68
+ ```
69
+
70
+ loom-code is a thin terminal shell — the brain is loomflow. The CLI detects
71
+ your project, builds a loomflow `Agent`, streams the run to your terminal,
72
+ and gates destructive tool calls behind an approval prompt. Everything
73
+ load-bearing — the agent loop, tools, planning, memory — is loomflow.
74
+
75
+ ## Highlights
76
+
77
+ - **Plans before it codes.** Every task gets a living plan
78
+ (TodoWrite-style), visible as it progresses, hard to drift from.
79
+ - **Any model, including free ones.** OpenAI, Anthropic, NVIDIA's free
80
+ NIM tier, local Ollama, or anything LiteLLM routes (Groq, Together,
81
+ Azure, Bedrock, Vertex…). `/set_model` walks you through provider →
82
+ API key → model with arrow-key menus.
83
+ - **Claude-Code-style permissions.** Reads are lenient, writes are
84
+ strict. Every write/edit/shell command routes through an approval
85
+ gate with a unified-diff preview. Allow/ask/deny rules, approval
86
+ modes (`default` / `accept-edits` / `plan` / `yolo`), and an
87
+ optional OS-level bash sandbox (`--sandbox`).
88
+ - **Specialist sub-agents on demand.** The main loop can call
89
+ `explore` (read-only investigation) and `review` (independent
90
+ verification) as tools — one coherent thread, specialists when they
91
+ earn their keep.
92
+ - **Session isolation.** `/isolate` runs the session in its own git
93
+ worktree; `/review` shows the diff, `/merge` or `/discard` ends it.
94
+ Auto-checkpoints before every edit; `/undo` restores.
95
+ - **Gets sharper at your repo.** A per-project notebook plus episode
96
+ memory (`.loom/`) — notes the agent used get credited when a turn
97
+ goes well, so future runs surface what worked. `/good` and `/bad`
98
+ train it.
99
+ - **Cost you can see.** Every response closes with that turn's tokens
100
+ and dollar cost (`free` on free tiers). `/cost` has session totals.
101
+ - **MCP out of the box.** Connect Linear, Sentry, Postgres,
102
+ Playwright, or any MCP server; `/mcp` lists what's live.
103
+ - **Goal mode.** `/goal make all tests pass` keeps working until the
104
+ condition is verifiably met.
105
+
106
+ ## Install
107
+
108
+ ```bash
109
+ pipx install git+https://github.com/Anurich/loomflow-cli
110
+ ```
111
+
112
+ (`pip install` works too; `pipx` keeps CLI tools in their own venvs.
113
+ No pipx? `brew install pipx` or `python -m pip install --user pipx`.)
114
+
115
+ Requires Python 3.11+. To update: `pipx upgrade loom-code`.
116
+
117
+ ## Quickstart
118
+
119
+ ```bash
120
+ cd ~/your-project
121
+ loom-code
122
+ ```
123
+
124
+ First run: type `/set_model`, pick a provider with the arrow keys,
125
+ paste your API key once (it's saved for future sessions), pick a
126
+ model. **No paid key?** Pick NVIDIA — free at
127
+ [build.nvidia.com](https://build.nvidia.com).
128
+
129
+ Then just type what you want:
130
+
131
+ ```
132
+ › fix the failing test in tests/test_auth.py
133
+ › add a /users endpoint with pagination
134
+ › why is startup slow? profile it
135
+ ```
136
+
137
+ One-shot mode (does the task, prints a summary, exits):
138
+
139
+ ```bash
140
+ loom-code "add a retry decorator to the http client"
141
+ loom-code --yes "scaffold a FastAPI backend" # skip approval prompts
142
+ ```
143
+
144
+ Works on existing code and empty directories alike — scaffolding new
145
+ projects is a first-class path.
146
+
147
+ ## Models
148
+
149
+ | model string | provider | env key |
150
+ |---|---|---|
151
+ | `claude-opus-4-8`, `claude-sonnet-4-6`, … | Anthropic | `ANTHROPIC_API_KEY` |
152
+ | `gpt-4.1`, `gpt-4.1-mini`, `o4-mini`, … | OpenAI | `OPENAI_API_KEY` |
153
+ | `nvidia/…` (Nemotron, Llama, DeepSeek) | NVIDIA NIM — **free tier** | `NVIDIA_NIM_API_KEY` |
154
+ | `ollama/llama3`, `ollama/qwen2.5-coder`, … | local [Ollama](https://ollama.com) — free, offline | — |
155
+ | `litellm/<provider>/<model>` | anything LiteLLM routes | provider's own |
156
+
157
+ Switch anytime with `/model <name>` or the guided `/set_model`.
158
+ Reasoning models support `/effort low|medium|high`.
159
+
160
+ > Tip: tool-heavy agent work needs a model with solid function
161
+ > calling. On the free NVIDIA tier, `deepseek-v4-pro` and
162
+ > `nemotron-super-49b` hold up well; tiny models fumble tool calls.
163
+
164
+ ## Safety & permissions
165
+
166
+ The permission layer is the boundary, not the working directory:
167
+
168
+ - **Reads** anywhere are allowed; **writes outside the project** are
169
+ only possible for files *you* referenced, and always show a diff
170
+ prompt — in every mode, even `--yes`.
171
+ - **Approval modes** (`/mode`): `default` asks for writes and shell;
172
+ `accept-edits` auto-approves in-project edits; `plan` is read-only;
173
+ `yolo` approves everything except your deny rules.
174
+ - **Rules** live in `.loom/settings.toml` — glob-based
175
+ `allow` / `ask` / `deny` per tool (e.g. `deny = ["edit(*.env)"]`).
176
+ Deny always wins, even in yolo.
177
+ - **Sandbox**: `--sandbox` runs bash under OS-level isolation
178
+ (writes limited to the repo, network off unless
179
+ `--sandbox-allow-network`).
180
+ - Irreversible commands (`git push --force`, `rm -rf`, …) always
181
+ get an explicit prompt.
182
+
183
+ ## Commands
184
+
185
+ Type `/` in the REPL — the menu autocompletes. Highlights:
186
+
187
+ | | |
188
+ |---|---|
189
+ | `/plan` | show or start the living plan |
190
+ | `/goal <condition>` | work until the condition is met |
191
+ | `/undo` · `/checkpoints` | restore / list auto-checkpoints |
192
+ | `/isolate` · `/review` · `/merge` · `/discard` | worktree-isolated sessions |
193
+ | `/model` · `/set_model` · `/effort` · `/mode` | model + approval setup |
194
+ | `/set_web` | web search (Serper / DuckDuckGo) |
195
+ | `/mcp` | list connected MCP servers |
196
+ | `/cost` · `/compact` · `/export` | session accounting + history |
197
+ | `/resume` | pick up the last session for this project |
198
+ | `/good` · `/bad` | credit / debit the agent's notes |
199
+
200
+ ## Project context
201
+
202
+ loom-code reads `LOOM.md` / `CLAUDE.md` / `AGENTS.md` /
203
+ `.loom/context.md` at the project root and treats it as binding house
204
+ rules. `/init-loom` creates a starter file.
205
+
206
+ ## Development
207
+
208
+ ```bash
209
+ git clone https://github.com/Anurich/loomflow-cli
210
+ cd loomflow-cli
211
+ python -m venv .venv && source .venv/bin/activate
212
+ pip install -e ".[dev]"
213
+ pytest -q # 465 tests
214
+ ruff check .
215
+ ```
216
+
217
+ Architecture in one line: **loom-code is deliberately thin** — if a
218
+ capability belongs in the agent loop, it goes in
219
+ [loomflow](https://github.com/Anurich/LoomFlow), not here. See
220
+ `DESIGN.md` for the boundary.
221
+
222
+ ## License
223
+
224
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,170 @@
1
+ # loom-code
2
+
3
+ **A terminal coding agent built on [loomflow](https://github.com/Anurich/LoomFlow).**
4
+ Plans before it codes, asks before it breaks things, works with any model —
5
+ including free ones.
6
+
7
+ ```
8
+ › add a retry decorator to the http client
9
+
10
+ ● loom
11
+ Added `retry(max_attempts=3, backoff=2.0)` to http/client.py and wired it
12
+ onto get() and post(). Tests pass (14/14).
13
+ ───────────────────────────────────────────── 12,431 in · 217 out · $0.0043
14
+ ```
15
+
16
+ loom-code is a thin terminal shell — the brain is loomflow. The CLI detects
17
+ your project, builds a loomflow `Agent`, streams the run to your terminal,
18
+ and gates destructive tool calls behind an approval prompt. Everything
19
+ load-bearing — the agent loop, tools, planning, memory — is loomflow.
20
+
21
+ ## Highlights
22
+
23
+ - **Plans before it codes.** Every task gets a living plan
24
+ (TodoWrite-style), visible as it progresses, hard to drift from.
25
+ - **Any model, including free ones.** OpenAI, Anthropic, NVIDIA's free
26
+ NIM tier, local Ollama, or anything LiteLLM routes (Groq, Together,
27
+ Azure, Bedrock, Vertex…). `/set_model` walks you through provider →
28
+ API key → model with arrow-key menus.
29
+ - **Claude-Code-style permissions.** Reads are lenient, writes are
30
+ strict. Every write/edit/shell command routes through an approval
31
+ gate with a unified-diff preview. Allow/ask/deny rules, approval
32
+ modes (`default` / `accept-edits` / `plan` / `yolo`), and an
33
+ optional OS-level bash sandbox (`--sandbox`).
34
+ - **Specialist sub-agents on demand.** The main loop can call
35
+ `explore` (read-only investigation) and `review` (independent
36
+ verification) as tools — one coherent thread, specialists when they
37
+ earn their keep.
38
+ - **Session isolation.** `/isolate` runs the session in its own git
39
+ worktree; `/review` shows the diff, `/merge` or `/discard` ends it.
40
+ Auto-checkpoints before every edit; `/undo` restores.
41
+ - **Gets sharper at your repo.** A per-project notebook plus episode
42
+ memory (`.loom/`) — notes the agent used get credited when a turn
43
+ goes well, so future runs surface what worked. `/good` and `/bad`
44
+ train it.
45
+ - **Cost you can see.** Every response closes with that turn's tokens
46
+ and dollar cost (`free` on free tiers). `/cost` has session totals.
47
+ - **MCP out of the box.** Connect Linear, Sentry, Postgres,
48
+ Playwright, or any MCP server; `/mcp` lists what's live.
49
+ - **Goal mode.** `/goal make all tests pass` keeps working until the
50
+ condition is verifiably met.
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ pipx install git+https://github.com/Anurich/loomflow-cli
56
+ ```
57
+
58
+ (`pip install` works too; `pipx` keeps CLI tools in their own venvs.
59
+ No pipx? `brew install pipx` or `python -m pip install --user pipx`.)
60
+
61
+ Requires Python 3.11+. To update: `pipx upgrade loom-code`.
62
+
63
+ ## Quickstart
64
+
65
+ ```bash
66
+ cd ~/your-project
67
+ loom-code
68
+ ```
69
+
70
+ First run: type `/set_model`, pick a provider with the arrow keys,
71
+ paste your API key once (it's saved for future sessions), pick a
72
+ model. **No paid key?** Pick NVIDIA — free at
73
+ [build.nvidia.com](https://build.nvidia.com).
74
+
75
+ Then just type what you want:
76
+
77
+ ```
78
+ › fix the failing test in tests/test_auth.py
79
+ › add a /users endpoint with pagination
80
+ › why is startup slow? profile it
81
+ ```
82
+
83
+ One-shot mode (does the task, prints a summary, exits):
84
+
85
+ ```bash
86
+ loom-code "add a retry decorator to the http client"
87
+ loom-code --yes "scaffold a FastAPI backend" # skip approval prompts
88
+ ```
89
+
90
+ Works on existing code and empty directories alike — scaffolding new
91
+ projects is a first-class path.
92
+
93
+ ## Models
94
+
95
+ | model string | provider | env key |
96
+ |---|---|---|
97
+ | `claude-opus-4-8`, `claude-sonnet-4-6`, … | Anthropic | `ANTHROPIC_API_KEY` |
98
+ | `gpt-4.1`, `gpt-4.1-mini`, `o4-mini`, … | OpenAI | `OPENAI_API_KEY` |
99
+ | `nvidia/…` (Nemotron, Llama, DeepSeek) | NVIDIA NIM — **free tier** | `NVIDIA_NIM_API_KEY` |
100
+ | `ollama/llama3`, `ollama/qwen2.5-coder`, … | local [Ollama](https://ollama.com) — free, offline | — |
101
+ | `litellm/<provider>/<model>` | anything LiteLLM routes | provider's own |
102
+
103
+ Switch anytime with `/model <name>` or the guided `/set_model`.
104
+ Reasoning models support `/effort low|medium|high`.
105
+
106
+ > Tip: tool-heavy agent work needs a model with solid function
107
+ > calling. On the free NVIDIA tier, `deepseek-v4-pro` and
108
+ > `nemotron-super-49b` hold up well; tiny models fumble tool calls.
109
+
110
+ ## Safety & permissions
111
+
112
+ The permission layer is the boundary, not the working directory:
113
+
114
+ - **Reads** anywhere are allowed; **writes outside the project** are
115
+ only possible for files *you* referenced, and always show a diff
116
+ prompt — in every mode, even `--yes`.
117
+ - **Approval modes** (`/mode`): `default` asks for writes and shell;
118
+ `accept-edits` auto-approves in-project edits; `plan` is read-only;
119
+ `yolo` approves everything except your deny rules.
120
+ - **Rules** live in `.loom/settings.toml` — glob-based
121
+ `allow` / `ask` / `deny` per tool (e.g. `deny = ["edit(*.env)"]`).
122
+ Deny always wins, even in yolo.
123
+ - **Sandbox**: `--sandbox` runs bash under OS-level isolation
124
+ (writes limited to the repo, network off unless
125
+ `--sandbox-allow-network`).
126
+ - Irreversible commands (`git push --force`, `rm -rf`, …) always
127
+ get an explicit prompt.
128
+
129
+ ## Commands
130
+
131
+ Type `/` in the REPL — the menu autocompletes. Highlights:
132
+
133
+ | | |
134
+ |---|---|
135
+ | `/plan` | show or start the living plan |
136
+ | `/goal <condition>` | work until the condition is met |
137
+ | `/undo` · `/checkpoints` | restore / list auto-checkpoints |
138
+ | `/isolate` · `/review` · `/merge` · `/discard` | worktree-isolated sessions |
139
+ | `/model` · `/set_model` · `/effort` · `/mode` | model + approval setup |
140
+ | `/set_web` | web search (Serper / DuckDuckGo) |
141
+ | `/mcp` | list connected MCP servers |
142
+ | `/cost` · `/compact` · `/export` | session accounting + history |
143
+ | `/resume` | pick up the last session for this project |
144
+ | `/good` · `/bad` | credit / debit the agent's notes |
145
+
146
+ ## Project context
147
+
148
+ loom-code reads `LOOM.md` / `CLAUDE.md` / `AGENTS.md` /
149
+ `.loom/context.md` at the project root and treats it as binding house
150
+ rules. `/init-loom` creates a starter file.
151
+
152
+ ## Development
153
+
154
+ ```bash
155
+ git clone https://github.com/Anurich/loomflow-cli
156
+ cd loomflow-cli
157
+ python -m venv .venv && source .venv/bin/activate
158
+ pip install -e ".[dev]"
159
+ pytest -q # 465 tests
160
+ ruff check .
161
+ ```
162
+
163
+ Architecture in one line: **loom-code is deliberately thin** — if a
164
+ capability belongs in the agent loop, it goes in
165
+ [loomflow](https://github.com/Anurich/LoomFlow), not here. See
166
+ `DESIGN.md` for the boundary.
167
+
168
+ ## License
169
+
170
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,22 @@
1
+ """loom-code — a loomflow-native terminal coding agent.
2
+
3
+ The entire agent brain is loomflow:
4
+
5
+ * ``Agent`` + ``ReAct`` — the agent loop
6
+ * ``living_plan=True`` — the task tracker (Claude Code's TodoWrite)
7
+ * ``LocalDiskWorkspace`` — per-project memory + the self-improvement
8
+ loop (citation tracking + relevance-aware recall)
9
+ * ``read`` / ``write`` / ``edit`` / ``bash`` / ``grep`` / ``find``
10
+ / ``ls`` builtin tools — the file-and-shell kernel
11
+ * ``StandardPermissions`` + ``approval_handler`` — the safety gate
12
+ * ``Agent.stream()`` — streaming output
13
+
14
+ This package is ONLY the terminal shell: REPL, ``rich`` rendering,
15
+ slash commands, project detection, the diff-approval prompt. If
16
+ agent-loop / memory / tool-dispatch logic ever shows up here, that
17
+ is a bug — it means loomflow is missing something and the fix
18
+ belongs in the framework, not here. loom-code is the dogfood test
19
+ that keeps loomflow honest.
20
+ """
21
+
22
+ __version__ = "0.1.1"
@@ -0,0 +1,119 @@
1
+ """Post-commit hook runner — debounced indexer refresh.
2
+
3
+ Invoked by ``.git/hooks/post-commit`` (installed by
4
+ ``loom_code.git_hook.install``). Counts commits since the last
5
+ refresh per indexer; when the threshold is hit (5 by default),
6
+ runs the indexer's incremental update.
7
+
8
+ Designed to FAIL SILENT. A git hook crashing has the same UX
9
+ cost as a broken commit — we'd rather skip a refresh than make
10
+ ``git commit`` look broken. All exception handling is broad and
11
+ mute; the worst case is "graph stayed stale one more commit."
12
+
13
+ Why debounce: graphify rebuilds + loominit structural rebuilds
14
+ are fast (5-15s on typical projects) but not free. Running them
15
+ on every single commit during a heavy dev session (10+ commits/
16
+ hour) is wasteful. Every-5-commits keeps the indexes "close
17
+ enough" without burning cycles.
18
+
19
+ Invoked as::
20
+
21
+ python -m loom_code._post_commit <project_root>
22
+
23
+ Backgrounded by the shell hook so it doesn't delay the commit.
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import sys
29
+ from collections.abc import Callable
30
+ from pathlib import Path
31
+
32
+ # Refresh threshold — commits since last refresh before triggering
33
+ # the indexer's incremental rebuild. Empirically tuned: every
34
+ # commit is wasteful, every 20 is too stale to be useful, 5 sits
35
+ # in the goldilocks zone for typical dev pace.
36
+ _THRESHOLD = 5
37
+
38
+
39
+ def main() -> int:
40
+ if len(sys.argv) < 2:
41
+ return 0
42
+ project_root = Path(sys.argv[1])
43
+ loom_dir = project_root / ".loom"
44
+ if not loom_dir.is_dir():
45
+ return 0
46
+
47
+ # Graphify: incremental rebuild via the package's own
48
+ # ``--update`` flag (re-extracts only changed files, merges
49
+ # into the existing graph). Only runs if graphify has been
50
+ # set up at least once for this project.
51
+ graphify_dir = loom_dir / "graphify"
52
+ if (graphify_dir / "graph.json").is_file():
53
+ _maybe_refresh(
54
+ counter_file=graphify_dir / "_commits_since_refresh.txt",
55
+ refresh_fn=lambda: _refresh_graphify(project_root, graphify_dir),
56
+ )
57
+
58
+ return 0
59
+
60
+
61
+ def _maybe_refresh(
62
+ *, counter_file: Path, refresh_fn: Callable[[], None]
63
+ ) -> None:
64
+ """Increment the counter; if it crosses the threshold, run
65
+ the refresh and reset. Errors are swallowed — better to skip
66
+ a refresh than break the commit."""
67
+ try:
68
+ count = (
69
+ int(counter_file.read_text())
70
+ if counter_file.is_file()
71
+ else 0
72
+ )
73
+ except (ValueError, OSError):
74
+ count = 0
75
+ count += 1
76
+ if count >= _THRESHOLD:
77
+ try:
78
+ refresh_fn()
79
+ counter_file.write_text("0")
80
+ except Exception: # noqa: BLE001 — never break a commit
81
+ # Leave counter at threshold; next commit will retry.
82
+ pass
83
+ else:
84
+ try:
85
+ counter_file.write_text(str(count))
86
+ except OSError:
87
+ pass
88
+
89
+
90
+ def _refresh_graphify(project_root: Path, graphify_dir: Path) -> None:
91
+ """Re-run the graphify extract → build → cluster → persist
92
+ pipeline in-process via the shared ``graphify_build_impl``
93
+ helper that the ``@tool`` wrapper + ``/loominit`` already use.
94
+
95
+ Single source of truth means three things stay in sync: the
96
+ submodule-import shim that dodges graphify's ``__getattr__``
97
+ namespace shadowing, the git-ls-files fast path that skips
98
+ walking ``.venv`` / ``node_modules``, and the exact tree-sitter
99
+ / Leiden / JSON pipeline. Bypassing it here is what caused this
100
+ function to silently fail on every commit before: it called
101
+ ``graphify.extract(files)`` (a submodule, not a function),
102
+ passed ``[extraction]`` (build_from_json wants a dict), and
103
+ dropped the ``communities`` arg to ``to_json``.
104
+
105
+ Capped via subprocess from the shell hook (5 min, see the hook
106
+ wrapper) so a hung extraction can't block git indefinitely."""
107
+ # graphify_dir kept in the signature for the caller's existing
108
+ # path math; the impl writes to the same `.loom/graphify/graph.json`
109
+ # via its own ``_graph_path`` helper, so we don't need to use it.
110
+ _ = graphify_dir
111
+ import anyio
112
+
113
+ from .skills.graphify.tools import graphify_build_impl
114
+
115
+ anyio.run(graphify_build_impl, project_root)
116
+
117
+
118
+ if __name__ == "__main__":
119
+ sys.exit(main())