euron-code 0.1.0__tar.gz → 0.2.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.
Files changed (62) hide show
  1. {euron_code-0.1.0 → euron_code-0.2.0}/PKG-INFO +190 -16
  2. euron_code-0.2.0/README.md +391 -0
  3. {euron_code-0.1.0 → euron_code-0.2.0}/pyproject.toml +1 -1
  4. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/__init__.py +1 -1
  5. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/agent.py +812 -595
  6. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/api.py +403 -364
  7. euron_code-0.2.0/src/euron_code/builtin_skills/explain-codebase/SKILL.md +20 -0
  8. euron_code-0.2.0/src/euron_code/builtin_skills/review/SKILL.md +22 -0
  9. euron_code-0.2.0/src/euron_code/builtin_skills/test-writer/SKILL.md +14 -0
  10. euron_code-0.2.0/src/euron_code/checkpoints.py +95 -0
  11. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/cli.py +358 -351
  12. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/config.py +2 -0
  13. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/context.py +190 -131
  14. euron_code-0.2.0/src/euron_code/frontmatter.py +119 -0
  15. euron_code-0.2.0/src/euron_code/hooks.py +221 -0
  16. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/permissions.py +2 -1
  17. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/prompts.py +121 -98
  18. euron_code-0.2.0/src/euron_code/repl.py +821 -0
  19. euron_code-0.2.0/src/euron_code/repomap.py +197 -0
  20. euron_code-0.2.0/src/euron_code/rules.py +128 -0
  21. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/sessions.py +34 -0
  22. euron_code-0.2.0/src/euron_code/skills.py +132 -0
  23. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/tools/__init__.py +2 -0
  24. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/tools/base.py +95 -19
  25. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/tools/db.py +2 -2
  26. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/tools/fs.py +14 -8
  27. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/tools/search.py +3 -3
  28. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/tools/shell.py +226 -214
  29. euron_code-0.2.0/src/euron_code/tools/skill.py +37 -0
  30. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/tools/task.py +2 -2
  31. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/tools/web.py +112 -112
  32. euron_code-0.2.0/src/euron_code/usage_view.py +240 -0
  33. {euron_code-0.1.0 → euron_code-0.2.0}/tests/mock_gateway.py +571 -508
  34. {euron_code-0.1.0 → euron_code-0.2.0}/tests/test_cli_e2e.py +1 -1
  35. euron_code-0.2.0/tests/test_powershell_exit_codes.py +54 -0
  36. euron_code-0.2.0/tests/test_v2_rules_skills_hooks.py +314 -0
  37. euron_code-0.2.0/tests/test_v2_tokens_shortcuts.py +285 -0
  38. euron_code-0.2.0/tests/test_v2_usage_headers.py +185 -0
  39. euron_code-0.1.0/README.md +0 -217
  40. euron_code-0.1.0/src/euron_code/repl.py +0 -425
  41. euron_code-0.1.0/src/euron_code/usage_view.py +0 -108
  42. {euron_code-0.1.0 → euron_code-0.2.0}/.gitignore +0 -0
  43. {euron_code-0.1.0 → euron_code-0.2.0}/LICENSE +0 -0
  44. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/__main__.py +0 -0
  45. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/auth.py +0 -0
  46. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/credentials.py +0 -0
  47. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/doctor.py +0 -0
  48. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/keys.py +0 -0
  49. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/memory.py +0 -0
  50. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/tools/ignore.py +0 -0
  51. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/tools/todo.py +0 -0
  52. {euron_code-0.1.0 → euron_code-0.2.0}/src/euron_code/ui.py +0 -0
  53. {euron_code-0.1.0 → euron_code-0.2.0}/tests/conftest.py +0 -0
  54. {euron_code-0.1.0 → euron_code-0.2.0}/tests/helpers.py +0 -0
  55. {euron_code-0.1.0 → euron_code-0.2.0}/tests/test_agent_mock.py +0 -0
  56. {euron_code-0.1.0 → euron_code-0.2.0}/tests/test_api_shell.py +0 -0
  57. {euron_code-0.1.0 → euron_code-0.2.0}/tests/test_context_memory_sessions.py +0 -0
  58. {euron_code-0.1.0 → euron_code-0.2.0}/tests/test_db.py +0 -0
  59. {euron_code-0.1.0 → euron_code-0.2.0}/tests/test_permissions.py +0 -0
  60. {euron_code-0.1.0 → euron_code-0.2.0}/tests/test_repl.py +0 -0
  61. {euron_code-0.1.0 → euron_code-0.2.0}/tests/test_search.py +0 -0
  62. {euron_code-0.1.0 → euron_code-0.2.0}/tests/test_tools_fs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: euron-code
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: Euron Code: an agentic coding assistant in your terminal for Euron Plus and Super 30 students.
5
5
  Project-URL: Homepage, https://euron.one/code-agent
6
6
  Author-email: Euron <contact@euron.one>
@@ -139,23 +139,60 @@ Press **Esc** or **Ctrl-C** to stop a reply; the session stays open. **Ctrl-D**
139
139
 
140
140
  | Command | What it does |
141
141
  |---|---|
142
- | `/help` | list commands |
143
- | `/usage` | plan, tokens used today and your daily limit, reset time, last 30 days |
144
- | `/cost` | tokens used in this session |
142
+ | `/help` | list commands, your own commands and skills, and the shortcuts |
143
+ | `/usage` | today / this week / this month with limits, reset times, sessions, tasks, cache share, last 30 days |
144
+ | `/cost` | tokens this session: sent, served from the server's cache, and saved automatically |
145
+ | `/context` | what fills the context window (system, memory, rules, skills, tools, messages, tool results) |
145
146
  | `/model [id]` | show or switch the model |
146
147
  | `/compact [focus]` | summarise the conversation to free context |
147
148
  | `/clear` | start a fresh conversation |
149
+ | `/resume [id]` | switch to a saved session |
150
+ | `/rewind` | undo the last turn's file edits and drop it from the conversation (also **Esc Esc**) |
151
+ | `/export [file]` | save the conversation as Markdown |
148
152
  | `/memory`, `/memory edit` | show or edit `EURON.md` memory |
149
- | `/init` | let Euron Code explore the repo and write `EURON.md` |
153
+ | `/init` | map the repo and write `EURON.md`; offers `.euron/` skeletons |
154
+ | `/rules`, `/rules new <name>` | list rules, create a rule file |
155
+ | `/skills`, `/skills new <name>` | list skills and commands, create a skill |
156
+ | `/hooks`, `/hooks new` | list hooks, add an example hook |
157
+ | `/review [focus]` | review your uncommitted changes (built-in skill) |
158
+ | `/plan` | toggle plan mode |
150
159
  | `/permissions` | show rules; `/permissions mode acceptEdits`, `/permissions allow "Bash(pytest:*)"` |
151
160
  | `/thinking show\|collapse\|hide` | how the model's reasoning is displayed |
152
161
  | `/todos` | the current task list |
153
162
  | `/doctor` | check your setup |
154
163
  | `/login`, `/logout`, `/exit` | |
155
- | `# some note` | save a note to memory (asks: project or user) |
164
+ | `/<skill or command> [args]` | run one of your skills or custom commands |
156
165
 
157
- The bar at the bottom shows the model, tokens used this session, how full the context is, and how
158
- many tokens you have left today.
166
+ The bar at the bottom shows the model, tokens used this session, how full the context is, how many
167
+ tokens you have left (today or this week, whichever is tighter) and the permission mode.
168
+
169
+ ### Shortcuts
170
+
171
+ | Type | What it does |
172
+ |---|---|
173
+ | `!npm test` | run a command yourself; the output goes into your next message |
174
+ | `@src/app.py` | attach a file (or a folder listing) to your message; **Tab** completes paths |
175
+ | `# note` | save a note to memory (asks: project or user) |
176
+ | **Shift+Tab** | cycle the mode: default -> acceptEdits -> plan |
177
+ | **Esc Esc** | on an empty prompt: rewind the last turn; otherwise clear the line |
178
+ | **Esc** / **Ctrl-C** | interrupt a reply |
179
+ | **Esc Enter** | new line |
180
+ | **Ctrl-L** | clear the screen |
181
+ | **Tab** | complete `/commands` and `@paths` |
182
+
183
+ ### Plan mode
184
+
185
+ In plan mode (Shift+Tab twice, `/plan`, or `euron --permission-mode plan`) Euron Code can only read
186
+ and search: edits, shell commands and database writes are refused. It explores and answers with a
187
+ numbered plan. You then choose: `a` accept edits and go, `y` go but ask before each change, or Enter to
188
+ keep planning. The model cannot leave plan mode by itself.
189
+
190
+ ### Rewind
191
+
192
+ Before Euron Code's file tools change a file, the original is kept in memory for that turn.
193
+ `/rewind` (or Esc Esc) puts the files back, removes the turn from the conversation and puts your
194
+ prompt back in the input line. Files you changed again after that turn are skipped (use
195
+ `/rewind --force`). Changes made by shell commands (`npm install`, a code generator) are not undone.
159
196
 
160
197
  ### Continue later
161
198
 
@@ -172,9 +209,17 @@ euron --resume # choose from a list
172
209
  euron usage
173
210
  ```
174
211
 
175
- shows your plan (Euron Plus / Super 30), tokens today out of your daily limit, what is left, when it
176
- resets (in your local time), all-time totals and a day-by-day table for the last 30 days. The daily
177
- allowance resets at midnight IST.
212
+ (or `/usage` inside a session) shows, like Claude's usage page:
213
+
214
+ - **Today**: a bar of tokens used against your daily limit, what is left, and when it resets.
215
+ - **This week**: the same against your weekly limit, if your plan has one.
216
+ - **This month**: tokens used since the 1st (no monthly cap).
217
+ - For each period: requests, sessions, tasks (one task = one message you sent, with all the model
218
+ calls it took) and how much of your prompt was served from the server's cache.
219
+ - A day-by-day table for the last 30 days.
220
+
221
+ Reset times are shown in your local time. The day resets at midnight IST, the week on Monday at
222
+ midnight IST. When the daily or weekly allowance is used up, Euron Code says so and when it resets.
178
223
 
179
224
  Euron Code sends one request at a time per student. When the servers are busy it waits and retries
180
225
  by itself, and tells you.
@@ -183,8 +228,125 @@ by itself, and tells you.
183
228
 
184
229
  Put project instructions in `EURON.md` at the project root (commands to build and test, conventions,
185
230
  things to avoid). Euron Code reads it at the start of every session, together with `EURON.md` files in
186
- parent folders up to the git root and your personal `~/.euron/EURON.md`. Run `/init` to have a first
187
- version written for you.
231
+ parent folders up to the git root and your personal `~/.euron/EURON.md`.
232
+
233
+ `/init` builds a map of the repository on your computer (detected stack, commands from the
234
+ manifests, top-level layout, entry points), then has the model confirm it and write a short
235
+ `EURON.md`: commands, layout, conventions and a compact repo map. It also offers to create
236
+ `.euron/rules/` and `.euron/settings.json` skeletons.
237
+
238
+ ## Rules
239
+
240
+ Rules are short instructions for every session, kept in separate files:
241
+ `.euron/rules/*.md` (project, commit them) and `~/.euron/rules/*.md` (yours, all projects). They are
242
+ loaded after `EURON.md`. `/rules` lists them, `/rules new testing` creates
243
+ `.euron/rules/testing.md` (add `--user` for your own folder).
244
+
245
+ A rule can apply to some files only:
246
+
247
+ ```markdown
248
+ ---
249
+ paths: ["src/**/*.py", "tests/**"]
250
+ ---
251
+ - Use type hints on every function.
252
+ - Tests use pytest fixtures, never unittest.
253
+ ```
254
+
255
+ Such a rule is sent to the model the first time it reads or edits a matching file in the session,
256
+ not before. `**` matches any folders, `*` anything within a name; a pattern without `/` (like `*.py`)
257
+ matches the file name anywhere. HTML comments (`<!-- -->`) in rule files are never sent.
258
+
259
+ ## Skills
260
+
261
+ A skill is a saved set of instructions for a job, in `.euron/skills/<name>/SKILL.md` (project) or
262
+ `~/.euron/skills/<name>/SKILL.md` (yours):
263
+
264
+ ```markdown
265
+ ---
266
+ name: deploy-check
267
+ description: Check the app is ready to deploy (tests, lint, migrations). Use before a release.
268
+ ---
269
+ 1. Run the tests and the linter...
270
+ ```
271
+
272
+ Only the names and descriptions are in the model's context; it loads the full instructions with its
273
+ `skill` tool when a request matches. You can run one yourself: `/deploy-check staging`. `$ARGUMENTS`
274
+ in the body is replaced by what you type after the name. `/skills` lists them, `/skills new <name>`
275
+ creates one.
276
+
277
+ Built in: `/review` (reviews your uncommitted git changes), `/test-writer <target>` (writes and runs
278
+ tests with your project's framework) and `/explain-codebase [topic]`. A project skill with the same
279
+ name replaces a built-in one.
280
+
281
+ ## Custom commands
282
+
283
+ A Markdown file in `.euron/commands/<name>.md` (or `~/.euron/commands/`) becomes `/<name>`. Its text is
284
+ sent as your message, with `$ARGUMENTS` replaced:
285
+
286
+ ```markdown
287
+ ---
288
+ description: Fix a GitHub issue
289
+ ---
290
+ Read issue $ARGUMENTS with `gh issue view`, find the cause, fix it and add a test.
291
+ ```
292
+
293
+ `/fix-issue 42` then does exactly that. Commands show up in `/help` and Tab completion.
294
+
295
+ ## Hooks
296
+
297
+ Hooks are your own shell commands that run at fixed points. Put them in `settings.json`
298
+ (`~/.euron/settings.json` or `.euron/settings.json`):
299
+
300
+ ```json
301
+ {
302
+ "hooks": {
303
+ "PostToolUse": [{"matcher": "Edit|Write", "command": "npx prettier --write .", "timeout": 30}],
304
+ "PreToolUse": [{"matcher": "Bash", "command": "python scripts/check_command.py"}],
305
+ "UserPromptSubmit": [{"command": "git status --short"}],
306
+ "SessionStart": [{"command": "git log --oneline -5"}],
307
+ "Stop": [{"command": "python -m pytest -q || (echo tests fail 1>&2 && exit 2)"}]
308
+ }
309
+ }
310
+ ```
311
+
312
+ | Event | When | Exit code 2 |
313
+ |---|---|---|
314
+ | `SessionStart` | once, at the start | (stdout is added as context) |
315
+ | `UserPromptSubmit` | before your message is sent | drops the message; stderr is shown. stdout is added as context |
316
+ | `PreToolUse` | before a tool runs | blocks the tool; stderr goes to the model |
317
+ | `PostToolUse` | after a tool ran | stderr goes to the model as feedback |
318
+ | `Stop` | when the model finishes its answer | stderr goes to the model and it continues (at most twice) |
319
+
320
+ Any other non-zero exit is shown as a warning and blocks nothing. `matcher` is a regular expression
321
+ over the tool name; Claude Code names (`Edit`, `Write`, `MultiEdit`, `Read`, `Bash`, `Grep`, `Glob`,
322
+ `WebFetch`) and Euron Code names (`edit_file`, `bash`, ...) both work. The command runs in the project
323
+ folder with `cmd.exe` on Windows and `sh` elsewhere, and gets one JSON object on stdin: `event`,
324
+ `session_id`, `cwd`, `tool_name`, `tool_input`, `tool_output` (PostToolUse) or `prompt`. Environment:
325
+ `EURON_PROJECT_DIR`, `EURON_SESSION_ID`, `EURON_HOOK_EVENT`, `EURON_TOOL_NAME`, `EURON_FILE`.
326
+ `/hooks` lists them, `/hooks new` adds an example (format Python files with ruff after each edit).
327
+
328
+ **Project hooks need your OK.** A cloned repository could ship a harmful hook, so hooks from
329
+ `.euron/settings*.json` are shown to you once and only run after you trust them. The answer is
330
+ remembered in `~/.euron/trusted-hooks.json`; if the project's hooks change you are asked again. In
331
+ `-p` mode untrusted project hooks are skipped with a warning. Your own `~/.euron/settings.json` hooks
332
+ always run.
333
+
334
+ ## Saving tokens (automatic)
335
+
336
+ The servers keep a cache of the start of each conversation, so a request that begins exactly like
337
+ the last one is cheaper and faster. Euron Code is built around that, with nothing to set up:
338
+
339
+ - The system prompt and tool list never change during a session. Changing data (date, git branch,
340
+ plan mode, hook output, `!` command output) goes at the end of your message instead.
341
+ - Reading a file again that has not changed since the last read returns a one-line note
342
+ ("unchanged since your last read at turn 4") instead of the whole file.
343
+ - Huge tool outputs are cut to their head and tail with a note (`toolOutputMaxChars`, default 12000).
344
+ - When the context is 60% full, old tool outputs (older than the last 3 steps) become one-line stubs.
345
+ Only at 75% is the conversation summarised.
346
+ - Path-scoped rules and skills are only loaded when needed.
347
+
348
+ `/cost` and `/context` show what was sent, how much the server served from its cache, and how many
349
+ tokens these measures kept out of the context.
188
350
 
189
351
  ## Non-interactive use (scripts, CI)
190
352
 
@@ -199,8 +361,10 @@ In `-p` mode nothing can ask you, so anything that needs permission is refused u
199
361
  covers it (`--allowed-tools`, or settings). `--yolo` skips all prompts: only use it in a throwaway
200
362
  folder or container.
201
363
 
364
+ `--permission-mode plan` gives a read-only run that ends with a plan.
365
+
202
366
  Exit codes: `0` ok, `1` error, `2` bad usage, `3` no Euron Plus / Super 30 access, `4` not logged in or
203
- key rejected, `5` daily token allowance used, `6` `--max-turns` reached, `130` interrupted.
367
+ key rejected, `5` daily or weekly token allowance used, `6` `--max-turns` reached, `130` interrupted.
204
368
 
205
369
  ## Database explorer
206
370
 
@@ -226,10 +390,15 @@ the connection itself is opened read-only. To let it write (local dev databases
226
390
  | `model` | your account default | model id |
227
391
  | `reasoning` | `collapse` | `show`, `collapse` or `hide` the model's thinking |
228
392
  | `permissions.allow` / `permissions.deny` | `[]` | rules like `Edit`, `Bash(npm test:*)`, `WebFetch(domain:docs.python.org)`, `Read(~/notes/**)` |
229
- | `permissions.defaultMode` | `default` | `default`, `acceptEdits` (edits inside the project need no prompt) or `yolo` |
393
+ | `permissions.defaultMode` | `default` | `default`, `acceptEdits` (edits inside the project need no prompt), `plan` (read-only) or `yolo` |
230
394
  | `bashTimeout` | `120` | seconds before a command is stopped |
231
395
  | `shell` | auto | PowerShell on Windows, bash/zsh elsewhere; or `cmd`, `bash`, a path |
232
- | `autoCompact` | `true` | summarise old turns when the context is 75% full |
396
+ | `autoCompact` | `true` | clear old tool outputs at 60%, summarise at 75% |
397
+ | `compactThreshold` | `0.75` | when to summarise the conversation |
398
+ | `microCompactThreshold` | `0.6` | when to replace old tool outputs with stubs |
399
+ | `microCompactKeepSteps` | `3` | tool outputs of the last N steps are always kept |
400
+ | `toolOutputMaxChars` | `12000` | longer tool output is cut to head + tail |
401
+ | `hooks` | `{}` | see [Hooks](#hooks) |
233
402
  | `webFetch` | `true` | allow the web page tool (it still asks per site) |
234
403
  | `db.connections.<name>` | | database DSNs |
235
404
 
@@ -258,6 +427,8 @@ in the editor straight away. Tips:
258
427
  | `servers are busy, retrying` | normal at peak times; it retries for you. If it gives up, try again in a few minutes |
259
428
  | `Rate limit reached` | too many requests in one minute; it waits and retries |
260
429
  | `today's token allowance` | you used today's limit; it resets at the time shown (midnight IST) |
430
+ | `this week's token allowance` | you used this week's limit; it resets at the time shown (Monday, midnight IST) |
431
+ | `untrusted project hook(s)` | the folder has hooks you have not approved; run `euron` there interactively once to review them |
261
432
  | `The response stopped part-way` | the connection dropped mid-answer; nothing more was applied, send your message again |
262
433
  | `euron: command not found` | see the VS Code tips above, or run `python -m euron_code` |
263
434
  | garbled colours on old Windows consoles | use Windows Terminal or VS Code's terminal |
@@ -271,6 +442,9 @@ and the keychain.
271
442
  reads. Nothing is uploaded anywhere else. There is no telemetry.
272
443
  - Your key is never printed in full and never logged.
273
444
  - Edits and commands ask first. Files outside the project folder always ask, even to read.
445
+ - Each request carries a random session id and task id so your usage page can count sessions and
446
+ tasks. Nothing else about the conversation is stored by the gateway.
447
+ - Hooks are commands you configure; project hooks only run after you trust them.
274
448
  - Text inside your files, web pages and command output is treated as data, not instructions.
275
449
 
276
450
  ## Licence
@@ -0,0 +1,391 @@
1
+ # Euron Code
2
+
3
+ An AI coding agent for your terminal, made for Euron students. Ask it to explain a codebase, fix a
4
+ bug, write tests or build a feature: it reads your files, proposes edits, runs commands and checks
5
+ its own work, asking you before it changes anything.
6
+
7
+ Euron Code runs on your computer. Only the conversation goes to Euron's model servers.
8
+
9
+ > **Requires Euron Plus or Super 30.** Euron Code is included with both. Get Plus at
10
+ > https://euron.one/plus
11
+
12
+ ## Install
13
+
14
+ Python 3.9 or newer, on Windows, macOS or Linux.
15
+
16
+ ```bash
17
+ pip install euron-code
18
+ # or, to keep it isolated from your projects:
19
+ pipx install euron-code
20
+ ```
21
+
22
+ Optional database drivers for the database explorer:
23
+
24
+ ```bash
25
+ pip install "euron-code[postgres]" # Postgres
26
+ pip install "euron-code[mysql]" # MySQL / MariaDB
27
+ ```
28
+
29
+ Check the install with `euron --version` and `euron doctor`.
30
+
31
+ ## Log in
32
+
33
+ ```bash
34
+ euron login
35
+ ```
36
+
37
+ Your browser opens a Euron page that shows a code (for example `WXYZ-1234`). Check that it matches
38
+ the code in your terminal and click **Approve**. The terminal finishes by itself. If no browser opens
39
+ (SSH, WSL), copy the link it prints into any browser where you are logged in to euron.one.
40
+
41
+ Your key is saved in the system keychain (Windows Credential Manager, macOS Keychain, Linux Secret
42
+ Service). If there is no keychain it goes in `~/.euron/credentials.json`, readable only by you.
43
+
44
+ ```bash
45
+ euron whoami # who you are logged in as, and your plan
46
+ euron logout # remove the key from this computer
47
+ ```
48
+
49
+ ## Use it
50
+
51
+ Open a terminal **in your project folder** and run:
52
+
53
+ ```bash
54
+ euron
55
+ ```
56
+
57
+ Then type what you want, for example:
58
+
59
+ - `explain how authentication works in this project`
60
+ - `the tests in tests/test_api.py fail, find out why and fix it`
61
+ - `add input validation to the signup form and a test for it`
62
+
63
+ Euron Code works step by step: it looks around, reads files, shows you a diff before each edit, and
64
+ asks before running commands. Answer:
65
+
66
+ | Key | Meaning |
67
+ |---|---|
68
+ | `y` | yes, once |
69
+ | `n` | no (you can then tell it what to do instead) |
70
+ | `a` | always allow this for the rest of the session |
71
+ | `p` | always allow commands starting the same way (e.g. every `npm test ...`) this session |
72
+ | `s` | always, and save the rule to `.euron/settings.local.json` |
73
+
74
+ Press **Esc** or **Ctrl-C** to stop a reply; the session stays open. **Ctrl-D** or `/exit` quits.
75
+ **Esc then Enter** inserts a newline.
76
+
77
+ ### Commands inside a session
78
+
79
+ | Command | What it does |
80
+ |---|---|
81
+ | `/help` | list commands, your own commands and skills, and the shortcuts |
82
+ | `/usage` | today / this week / this month with limits, reset times, sessions, tasks, cache share, last 30 days |
83
+ | `/cost` | tokens this session: sent, served from the server's cache, and saved automatically |
84
+ | `/context` | what fills the context window (system, memory, rules, skills, tools, messages, tool results) |
85
+ | `/model [id]` | show or switch the model |
86
+ | `/compact [focus]` | summarise the conversation to free context |
87
+ | `/clear` | start a fresh conversation |
88
+ | `/resume [id]` | switch to a saved session |
89
+ | `/rewind` | undo the last turn's file edits and drop it from the conversation (also **Esc Esc**) |
90
+ | `/export [file]` | save the conversation as Markdown |
91
+ | `/memory`, `/memory edit` | show or edit `EURON.md` memory |
92
+ | `/init` | map the repo and write `EURON.md`; offers `.euron/` skeletons |
93
+ | `/rules`, `/rules new <name>` | list rules, create a rule file |
94
+ | `/skills`, `/skills new <name>` | list skills and commands, create a skill |
95
+ | `/hooks`, `/hooks new` | list hooks, add an example hook |
96
+ | `/review [focus]` | review your uncommitted changes (built-in skill) |
97
+ | `/plan` | toggle plan mode |
98
+ | `/permissions` | show rules; `/permissions mode acceptEdits`, `/permissions allow "Bash(pytest:*)"` |
99
+ | `/thinking show\|collapse\|hide` | how the model's reasoning is displayed |
100
+ | `/todos` | the current task list |
101
+ | `/doctor` | check your setup |
102
+ | `/login`, `/logout`, `/exit` | |
103
+ | `/<skill or command> [args]` | run one of your skills or custom commands |
104
+
105
+ The bar at the bottom shows the model, tokens used this session, how full the context is, how many
106
+ tokens you have left (today or this week, whichever is tighter) and the permission mode.
107
+
108
+ ### Shortcuts
109
+
110
+ | Type | What it does |
111
+ |---|---|
112
+ | `!npm test` | run a command yourself; the output goes into your next message |
113
+ | `@src/app.py` | attach a file (or a folder listing) to your message; **Tab** completes paths |
114
+ | `# note` | save a note to memory (asks: project or user) |
115
+ | **Shift+Tab** | cycle the mode: default -> acceptEdits -> plan |
116
+ | **Esc Esc** | on an empty prompt: rewind the last turn; otherwise clear the line |
117
+ | **Esc** / **Ctrl-C** | interrupt a reply |
118
+ | **Esc Enter** | new line |
119
+ | **Ctrl-L** | clear the screen |
120
+ | **Tab** | complete `/commands` and `@paths` |
121
+
122
+ ### Plan mode
123
+
124
+ In plan mode (Shift+Tab twice, `/plan`, or `euron --permission-mode plan`) Euron Code can only read
125
+ and search: edits, shell commands and database writes are refused. It explores and answers with a
126
+ numbered plan. You then choose: `a` accept edits and go, `y` go but ask before each change, or Enter to
127
+ keep planning. The model cannot leave plan mode by itself.
128
+
129
+ ### Rewind
130
+
131
+ Before Euron Code's file tools change a file, the original is kept in memory for that turn.
132
+ `/rewind` (or Esc Esc) puts the files back, removes the turn from the conversation and puts your
133
+ prompt back in the input line. Files you changed again after that turn are skipped (use
134
+ `/rewind --force`). Changes made by shell commands (`npm install`, a code generator) are not undone.
135
+
136
+ ### Continue later
137
+
138
+ Every session is saved under `~/.euron/sessions/`.
139
+
140
+ ```bash
141
+ euron --continue # pick up the latest session in this folder
142
+ euron --resume # choose from a list
143
+ ```
144
+
145
+ ### Usage and limits
146
+
147
+ ```bash
148
+ euron usage
149
+ ```
150
+
151
+ (or `/usage` inside a session) shows, like Claude's usage page:
152
+
153
+ - **Today**: a bar of tokens used against your daily limit, what is left, and when it resets.
154
+ - **This week**: the same against your weekly limit, if your plan has one.
155
+ - **This month**: tokens used since the 1st (no monthly cap).
156
+ - For each period: requests, sessions, tasks (one task = one message you sent, with all the model
157
+ calls it took) and how much of your prompt was served from the server's cache.
158
+ - A day-by-day table for the last 30 days.
159
+
160
+ Reset times are shown in your local time. The day resets at midnight IST, the week on Monday at
161
+ midnight IST. When the daily or weekly allowance is used up, Euron Code says so and when it resets.
162
+
163
+ Euron Code sends one request at a time per student. When the servers are busy it waits and retries
164
+ by itself, and tells you.
165
+
166
+ ## Memory: EURON.md
167
+
168
+ Put project instructions in `EURON.md` at the project root (commands to build and test, conventions,
169
+ things to avoid). Euron Code reads it at the start of every session, together with `EURON.md` files in
170
+ parent folders up to the git root and your personal `~/.euron/EURON.md`.
171
+
172
+ `/init` builds a map of the repository on your computer (detected stack, commands from the
173
+ manifests, top-level layout, entry points), then has the model confirm it and write a short
174
+ `EURON.md`: commands, layout, conventions and a compact repo map. It also offers to create
175
+ `.euron/rules/` and `.euron/settings.json` skeletons.
176
+
177
+ ## Rules
178
+
179
+ Rules are short instructions for every session, kept in separate files:
180
+ `.euron/rules/*.md` (project, commit them) and `~/.euron/rules/*.md` (yours, all projects). They are
181
+ loaded after `EURON.md`. `/rules` lists them, `/rules new testing` creates
182
+ `.euron/rules/testing.md` (add `--user` for your own folder).
183
+
184
+ A rule can apply to some files only:
185
+
186
+ ```markdown
187
+ ---
188
+ paths: ["src/**/*.py", "tests/**"]
189
+ ---
190
+ - Use type hints on every function.
191
+ - Tests use pytest fixtures, never unittest.
192
+ ```
193
+
194
+ Such a rule is sent to the model the first time it reads or edits a matching file in the session,
195
+ not before. `**` matches any folders, `*` anything within a name; a pattern without `/` (like `*.py`)
196
+ matches the file name anywhere. HTML comments (`<!-- -->`) in rule files are never sent.
197
+
198
+ ## Skills
199
+
200
+ A skill is a saved set of instructions for a job, in `.euron/skills/<name>/SKILL.md` (project) or
201
+ `~/.euron/skills/<name>/SKILL.md` (yours):
202
+
203
+ ```markdown
204
+ ---
205
+ name: deploy-check
206
+ description: Check the app is ready to deploy (tests, lint, migrations). Use before a release.
207
+ ---
208
+ 1. Run the tests and the linter...
209
+ ```
210
+
211
+ Only the names and descriptions are in the model's context; it loads the full instructions with its
212
+ `skill` tool when a request matches. You can run one yourself: `/deploy-check staging`. `$ARGUMENTS`
213
+ in the body is replaced by what you type after the name. `/skills` lists them, `/skills new <name>`
214
+ creates one.
215
+
216
+ Built in: `/review` (reviews your uncommitted git changes), `/test-writer <target>` (writes and runs
217
+ tests with your project's framework) and `/explain-codebase [topic]`. A project skill with the same
218
+ name replaces a built-in one.
219
+
220
+ ## Custom commands
221
+
222
+ A Markdown file in `.euron/commands/<name>.md` (or `~/.euron/commands/`) becomes `/<name>`. Its text is
223
+ sent as your message, with `$ARGUMENTS` replaced:
224
+
225
+ ```markdown
226
+ ---
227
+ description: Fix a GitHub issue
228
+ ---
229
+ Read issue $ARGUMENTS with `gh issue view`, find the cause, fix it and add a test.
230
+ ```
231
+
232
+ `/fix-issue 42` then does exactly that. Commands show up in `/help` and Tab completion.
233
+
234
+ ## Hooks
235
+
236
+ Hooks are your own shell commands that run at fixed points. Put them in `settings.json`
237
+ (`~/.euron/settings.json` or `.euron/settings.json`):
238
+
239
+ ```json
240
+ {
241
+ "hooks": {
242
+ "PostToolUse": [{"matcher": "Edit|Write", "command": "npx prettier --write .", "timeout": 30}],
243
+ "PreToolUse": [{"matcher": "Bash", "command": "python scripts/check_command.py"}],
244
+ "UserPromptSubmit": [{"command": "git status --short"}],
245
+ "SessionStart": [{"command": "git log --oneline -5"}],
246
+ "Stop": [{"command": "python -m pytest -q || (echo tests fail 1>&2 && exit 2)"}]
247
+ }
248
+ }
249
+ ```
250
+
251
+ | Event | When | Exit code 2 |
252
+ |---|---|---|
253
+ | `SessionStart` | once, at the start | (stdout is added as context) |
254
+ | `UserPromptSubmit` | before your message is sent | drops the message; stderr is shown. stdout is added as context |
255
+ | `PreToolUse` | before a tool runs | blocks the tool; stderr goes to the model |
256
+ | `PostToolUse` | after a tool ran | stderr goes to the model as feedback |
257
+ | `Stop` | when the model finishes its answer | stderr goes to the model and it continues (at most twice) |
258
+
259
+ Any other non-zero exit is shown as a warning and blocks nothing. `matcher` is a regular expression
260
+ over the tool name; Claude Code names (`Edit`, `Write`, `MultiEdit`, `Read`, `Bash`, `Grep`, `Glob`,
261
+ `WebFetch`) and Euron Code names (`edit_file`, `bash`, ...) both work. The command runs in the project
262
+ folder with `cmd.exe` on Windows and `sh` elsewhere, and gets one JSON object on stdin: `event`,
263
+ `session_id`, `cwd`, `tool_name`, `tool_input`, `tool_output` (PostToolUse) or `prompt`. Environment:
264
+ `EURON_PROJECT_DIR`, `EURON_SESSION_ID`, `EURON_HOOK_EVENT`, `EURON_TOOL_NAME`, `EURON_FILE`.
265
+ `/hooks` lists them, `/hooks new` adds an example (format Python files with ruff after each edit).
266
+
267
+ **Project hooks need your OK.** A cloned repository could ship a harmful hook, so hooks from
268
+ `.euron/settings*.json` are shown to you once and only run after you trust them. The answer is
269
+ remembered in `~/.euron/trusted-hooks.json`; if the project's hooks change you are asked again. In
270
+ `-p` mode untrusted project hooks are skipped with a warning. Your own `~/.euron/settings.json` hooks
271
+ always run.
272
+
273
+ ## Saving tokens (automatic)
274
+
275
+ The servers keep a cache of the start of each conversation, so a request that begins exactly like
276
+ the last one is cheaper and faster. Euron Code is built around that, with nothing to set up:
277
+
278
+ - The system prompt and tool list never change during a session. Changing data (date, git branch,
279
+ plan mode, hook output, `!` command output) goes at the end of your message instead.
280
+ - Reading a file again that has not changed since the last read returns a one-line note
281
+ ("unchanged since your last read at turn 4") instead of the whole file.
282
+ - Huge tool outputs are cut to their head and tail with a note (`toolOutputMaxChars`, default 12000).
283
+ - When the context is 60% full, old tool outputs (older than the last 3 steps) become one-line stubs.
284
+ Only at 75% is the conversation summarised.
285
+ - Path-scoped rules and skills are only loaded when needed.
286
+
287
+ `/cost` and `/context` show what was sent, how much the server served from its cache, and how many
288
+ tokens these measures kept out of the context.
289
+
290
+ ## Non-interactive use (scripts, CI)
291
+
292
+ ```bash
293
+ euron -p "summarise what this repo does"
294
+ git diff | euron -p "review this diff"
295
+ euron -p "run the tests and fix failures" --allowed-tools "Edit,Bash(pytest:*)" --max-turns 20
296
+ euron -p "list the API routes" --output-format json
297
+ ```
298
+
299
+ In `-p` mode nothing can ask you, so anything that needs permission is refused unless an allow rule
300
+ covers it (`--allowed-tools`, or settings). `--yolo` skips all prompts: only use it in a throwaway
301
+ folder or container.
302
+
303
+ `--permission-mode plan` gives a read-only run that ends with a plan.
304
+
305
+ Exit codes: `0` ok, `1` error, `2` bad usage, `3` no Euron Plus / Super 30 access, `4` not logged in or
306
+ key rejected, `5` daily or weekly token allowance used, `6` `--max-turns` reached, `130` interrupted.
307
+
308
+ ## Database explorer
309
+
310
+ Euron Code can look at your app's database while it works. SQLite files inside the project work
311
+ directly (`look at app.db and tell me which tables have no index`). For Postgres or MySQL, name a
312
+ connection in your settings; `${VAR}` reads from the environment so passwords stay out of the file:
313
+
314
+ ```bash
315
+ euron config set --project db.connections.app "postgresql://dev:${PGPASSWORD}@localhost:5432/app"
316
+ ```
317
+
318
+ It is **read-only**: only `SELECT`, `WITH`, `EXPLAIN`, `SHOW`, `PRAGMA` and similar are allowed, and
319
+ the connection itself is opened read-only. To let it write (local dev databases only), run
320
+ `euron config set db.allowWrites true`; every write statement still asks you first.
321
+
322
+ ## Settings
323
+
324
+ `euron config set <key> <value>` writes `~/.euron/settings.json` (add `--project` for
325
+ `.euron/settings.json` in the current folder). `euron config list` shows the merged result.
326
+
327
+ | Key | Default | |
328
+ |---|---|---|
329
+ | `model` | your account default | model id |
330
+ | `reasoning` | `collapse` | `show`, `collapse` or `hide` the model's thinking |
331
+ | `permissions.allow` / `permissions.deny` | `[]` | rules like `Edit`, `Bash(npm test:*)`, `WebFetch(domain:docs.python.org)`, `Read(~/notes/**)` |
332
+ | `permissions.defaultMode` | `default` | `default`, `acceptEdits` (edits inside the project need no prompt), `plan` (read-only) or `yolo` |
333
+ | `bashTimeout` | `120` | seconds before a command is stopped |
334
+ | `shell` | auto | PowerShell on Windows, bash/zsh elsewhere; or `cmd`, `bash`, a path |
335
+ | `autoCompact` | `true` | clear old tool outputs at 60%, summarise at 75% |
336
+ | `compactThreshold` | `0.75` | when to summarise the conversation |
337
+ | `microCompactThreshold` | `0.6` | when to replace old tool outputs with stubs |
338
+ | `microCompactKeepSteps` | `3` | tool outputs of the last N steps are always kept |
339
+ | `toolOutputMaxChars` | `12000` | longer tool output is cut to head + tail |
340
+ | `hooks` | `{}` | see [Hooks](#hooks) |
341
+ | `webFetch` | `true` | allow the web page tool (it still asks per site) |
342
+ | `db.connections.<name>` | | database DSNs |
343
+
344
+ Environment variables: `EURON_CODE_API` (gateway URL, default
345
+ `https://api.euron.one/api/v1/code-agent`), `EURON_API_KEY` (use a key without logging in, for CI),
346
+ `EURON_HOME` (instead of `~/.euron`), `EURON_NO_BROWSER=1`.
347
+
348
+ ## In VS Code
349
+
350
+ Open your project folder in VS Code, then open the integrated terminal (**Ctrl+`**, or
351
+ **Terminal > New Terminal**) and run `euron`. It works in the folder VS Code opened, and edits show up
352
+ in the editor straight away. Tips:
353
+
354
+ - On Windows the integrated terminal is PowerShell by default; Euron Code runs commands with
355
+ PowerShell too. To use Git Bash instead: `euron config set shell bash`.
356
+ - If `euron` is not found after `pip install`, the Python `Scripts` folder is not on your PATH.
357
+ Use `python -m euron_code`, or install with `pipx` (`pipx ensurepath`), then restart VS Code.
358
+ - Keep your edits saved before asking Euron Code to change the same file.
359
+
360
+ ## Troubleshooting
361
+
362
+ | You see | What to do |
363
+ |---|---|
364
+ | `You don't have Euron Plus access...` | Euron Code needs Euron Plus or an active Super 30 enrolment: https://euron.one/plus |
365
+ | `not logged in` / `key was rejected` | run `euron login` again (keys can be revoked at euron.one/code-agent) |
366
+ | `servers are busy, retrying` | normal at peak times; it retries for you. If it gives up, try again in a few minutes |
367
+ | `Rate limit reached` | too many requests in one minute; it waits and retries |
368
+ | `today's token allowance` | you used today's limit; it resets at the time shown (midnight IST) |
369
+ | `this week's token allowance` | you used this week's limit; it resets at the time shown (Monday, midnight IST) |
370
+ | `untrusted project hook(s)` | the folder has hooks you have not approved; run `euron` there interactively once to review them |
371
+ | `The response stopped part-way` | the connection dropped mid-answer; nothing more was applied, send your message again |
372
+ | `euron: command not found` | see the VS Code tips above, or run `python -m euron_code` |
373
+ | garbled colours on old Windows consoles | use Windows Terminal or VS Code's terminal |
374
+
375
+ `euron doctor` checks Python, the connection, your login and plan, ripgrep (faster search; optional)
376
+ and the keychain.
377
+
378
+ ## Privacy and safety
379
+
380
+ - Your files are only sent as part of the conversation with Euron's model, and only what the agent
381
+ reads. Nothing is uploaded anywhere else. There is no telemetry.
382
+ - Your key is never printed in full and never logged.
383
+ - Edits and commands ask first. Files outside the project folder always ask, even to read.
384
+ - Each request carries a random session id and task id so your usage page can count sessions and
385
+ tasks. Nothing else about the conversation is stored by the gateway.
386
+ - Hooks are commands you configure; project hooks only run after you trust them.
387
+ - Text inside your files, web pages and command output is treated as data, not instructions.
388
+
389
+ ## Licence
390
+
391
+ Copyright (c) 2026 Euron. All rights reserved. See `LICENSE`.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "euron-code"
7
- version = "0.1.0"
7
+ version = "0.2.0"
8
8
  description = "Euron Code: an agentic coding assistant in your terminal for Euron Plus and Super 30 students."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"