kon-coding-agent 0.3.1__tar.gz → 0.3.3__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 (139) hide show
  1. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/AGENTS.md +2 -2
  2. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/CHANGELOG.md +16 -1
  3. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/PKG-INFO +11 -68
  4. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/README.md +10 -67
  5. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/docs/local-models.md +16 -2
  6. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/pyproject.toml +2 -1
  7. kon_coding_agent-0.3.3/scripts/show_themes.py +216 -0
  8. kon_coding_agent-0.3.3/src/kon/async_utils.py +40 -0
  9. kon_coding_agent-0.3.3/src/kon/builtin_skills/init/SKILL.md +73 -0
  10. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/config.py +38 -5
  11. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/context/skills.py +68 -2
  12. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/core/types.py +1 -0
  13. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/defaults/config.toml +12 -1
  14. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/events.py +0 -1
  15. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/base.py +53 -0
  16. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/models.py +3 -3
  17. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/oauth/openai.py +7 -2
  18. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/anthropic.py +9 -3
  19. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/openai_completions.py +8 -5
  20. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/loop.py +10 -1
  21. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/_tool_utils.py +25 -36
  22. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/bash.py +30 -25
  23. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/edit.py +2 -10
  24. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/find.py +10 -3
  25. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/grep.py +11 -4
  26. kon_coding_agent-0.3.3/src/kon/tools/read.py +237 -0
  27. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/web_fetch.py +3 -4
  28. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/web_search.py +1 -1
  29. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools_manager.py +6 -14
  30. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/turn.py +31 -20
  31. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/app.py +87 -59
  32. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/blocks.py +6 -3
  33. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/chat.py +2 -0
  34. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/commands.py +17 -11
  35. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/input.py +19 -3
  36. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/session_ui.py +4 -1
  37. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/styles.py +2 -2
  38. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/widgets.py +18 -14
  39. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/conftest.py +0 -9
  40. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/context/test_skills.py +78 -0
  41. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/llm/test_anthropic_provider.py +28 -0
  42. kon_coding_agent-0.3.3/tests/llm/test_openai_oauth.py +14 -0
  43. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_agentic_loop.py +52 -4
  44. kon_coding_agent-0.3.3/tests/test_cli_auth_flags.py +26 -0
  45. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_config_binaries.py +1 -3
  46. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_config_migration.py +2 -0
  47. kon_coding_agent-0.3.3/tests/test_handoff_link_interrupt.py +74 -0
  48. kon_coding_agent-0.3.3/tests/test_local_auth_config.py +67 -0
  49. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_openai_compat.py +48 -1
  50. kon_coding_agent-0.3.3/tests/test_tools_manager.py +18 -0
  51. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/tools/test_edit_display.py +7 -12
  52. kon_coding_agent-0.3.3/tests/tools/test_read.py +180 -0
  53. kon_coding_agent-0.3.3/tests/tools/test_subprocess_cancellation.py +87 -0
  54. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/ui/test_input_paste.py +21 -0
  55. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/ui/test_status_line.py +0 -12
  56. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/uv.lock +28 -1
  57. kon_coding_agent-0.3.1/src/kon/metrics.py +0 -37
  58. kon_coding_agent-0.3.1/src/kon/tools/read.py +0 -136
  59. kon_coding_agent-0.3.1/tests/test_metrics.py +0 -50
  60. kon_coding_agent-0.3.1/tests/tools/test_read.py +0 -80
  61. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/.gitignore +0 -0
  62. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/.kon/skills/kon-release-publish/SKILL.md +0 -0
  63. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/.kon/skills/kon-tmux-test/SKILL.md +0 -0
  64. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/.kon/skills/kon-tmux-test/run-e2e-tests.sh +0 -0
  65. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/.kon/skills/kon-tmux-test/setup-test-project.sh +0 -0
  66. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/.python-version +0 -0
  67. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/LICENSE +0 -0
  68. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/docs/architecture-review.md +0 -0
  69. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/docs/images/kon-screenshot.png +0 -0
  70. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/__init__.py +0 -0
  71. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/context/__init__.py +0 -0
  72. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/context/_xml.py +0 -0
  73. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/context/agent_mds.py +0 -0
  74. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/context/git.py +0 -0
  75. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/context/loader.py +0 -0
  76. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/core/__init__.py +0 -0
  77. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/core/compaction.py +0 -0
  78. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/core/handoff.py +0 -0
  79. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/defaults/__init__.py +0 -0
  80. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/__init__.py +0 -0
  81. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/oauth/__init__.py +0 -0
  82. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/oauth/copilot.py +0 -0
  83. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/__init__.py +0 -0
  84. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/azure_ai_foundry.py +0 -0
  85. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/copilot.py +0 -0
  86. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/copilot_anthropic.py +0 -0
  87. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/github_copilot_headers.py +0 -0
  88. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/mock.py +0 -0
  89. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/openai_codex_responses.py +0 -0
  90. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/openai_compat.py +0 -0
  91. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/openai_responses.py +0 -0
  92. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/llm/providers/sanitize.py +0 -0
  93. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/permissions.py +0 -0
  94. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/py.typed +0 -0
  95. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/session.py +0 -0
  96. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/themes.py +0 -0
  97. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/__init__.py +0 -0
  98. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/_read_image.py +0 -0
  99. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/base.py +0 -0
  100. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/tools/write.py +0 -0
  101. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/__init__.py +0 -0
  102. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/app_protocol.py +0 -0
  103. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/autocomplete.py +0 -0
  104. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/clipboard.py +0 -0
  105. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/export.py +0 -0
  106. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/floating_list.py +0 -0
  107. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/formatting.py +0 -0
  108. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/path_complete.py +0 -0
  109. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/prompt_history.py +0 -0
  110. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/ui/selection_mode.py +0 -0
  111. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/src/kon/update_check.py +0 -0
  112. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/context/test_agents.py +0 -0
  113. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/llm/__init__.py +0 -0
  114. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/llm/test_azure_ai_foundry_provider.py +0 -0
  115. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/llm/test_mock_provider.py +0 -0
  116. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/llm/test_openai_codex_provider_errors.py +0 -0
  117. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_cli_provider_resolution.py +0 -0
  118. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_compaction.py +0 -0
  119. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_config_error_fallback.py +0 -0
  120. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_config_injection.py +0 -0
  121. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_handoff.py +0 -0
  122. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_launch_warnings.py +0 -0
  123. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_model_provider_resolution.py +0 -0
  124. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_permissions.py +0 -0
  125. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_session_persistence.py +0 -0
  126. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_session_resume.py +0 -0
  127. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_system_prompt.py +0 -0
  128. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_system_prompt_git_context.py +0 -0
  129. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_update_check.py +0 -0
  130. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/test_update_notice_behavior.py +0 -0
  131. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/tools/test_diff.py +0 -0
  132. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/tools/test_edit.py +0 -0
  133. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/tools/test_read_image.py +0 -0
  134. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/tools/test_read_image_integration.py +0 -0
  135. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/tools/test_write.py +0 -0
  136. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/ui/test_autocomplete.py +0 -0
  137. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/ui/test_floating_list.py +0 -0
  138. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/ui/test_input_handoff.py +0 -0
  139. {kon_coding_agent-0.3.1 → kon_coding_agent-0.3.3}/tests/ui/test_prompt_history.py +0 -0
@@ -7,7 +7,7 @@
7
7
 
8
8
  ## Testing
9
9
 
10
- - Use `uv run pytest` for testing in general; after edits/writes
10
+ - Use `uv run python -m pytest` for testing in general; after edits/writes
11
11
  - If the user asks for e2e tests then run the kon-tmux e2e test if available
12
12
 
13
13
  ## Committing code
@@ -17,5 +17,5 @@
17
17
 
18
18
  ## Pushing
19
19
 
20
- - If the user asks you to push code, run these first before doing so: `uv run ruff format .`, `uv run ruff check .`, `uv run pyright .` and `uv run pytest` in parallel (same tool call)
20
+ - If the user asks you to push code, run these first before doing so: `uv run ruff format .`, `uv run ruff check .`, `uv run python -m pyright .` and `uv run python -m pytest` in parallel (same tool call)
21
21
  - Only if these all pass without issues should you push otherwise report the warnings/errors back to user and ask for next steps
@@ -6,6 +6,22 @@ All notable changes to this project will be documented in this file.
6
6
 
7
7
  - No changes yet.
8
8
 
9
+ ## 0.3.2 - 2026-03-22
10
+
11
+ ### Added
12
+
13
+ - Added a `collapse_thinking` config flag to control thinking block display.
14
+ - Added a Ghostty theme preview script.
15
+
16
+ ### Changed
17
+
18
+ - Improved theme and model picker indicators.
19
+ - Refactored tool display helpers into shared `truncate_text` and `shorten_path` utilities.
20
+
21
+ ### Fixed
22
+
23
+ - Fixed duplicate skill warnings coming from the home directory.
24
+
9
25
  ## 0.3.1 - 2026-03-21
10
26
 
11
27
  ### Added
@@ -14,7 +30,6 @@ All notable changes to this project will be documented in this file.
14
30
  - Added tool permission controls with bash safety analysis - @Meltedd.
15
31
  - Added popular built-in themes.
16
32
  - Added tool previews in approval prompts.
17
- - Added run token throughput metrics.
18
33
 
19
34
  ### Changed
20
35
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kon-coding-agent
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: Minimal coding agent
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -167,7 +167,7 @@ Here is the full config shape:
167
167
 
168
168
  ```toml
169
169
  [meta]
170
- config_version = 3
170
+ config_version = 4
171
171
 
172
172
  [llm]
173
173
  default_provider = "openai-codex"
@@ -176,6 +176,10 @@ default_base_url = ""
176
176
  default_thinking_level = "high"
177
177
  tool_call_idle_timeout_seconds = 180
178
178
 
179
+ [llm.auth]
180
+ openai_compat = "auto"
181
+ anthropic_compat = "auto"
182
+
179
183
  [llm.system_prompt]
180
184
  git_context = true
181
185
  content = """You are an expert coding assistant called Kon.
@@ -248,8 +252,9 @@ Kon is built around a terminal UI that stays simple but practical.
248
252
  | --- | --- |
249
253
  | File reference | Type `@` to fuzzy-search files and folders in the current project |
250
254
  | Path completion | Press **Tab** to complete paths like `./`, `../`, `~`, quoted paths, and absolute paths |
251
- | Queued prompts | You can submit follow-up prompts while the agent is still running |
252
- | Queue limit | Up to **5** queued prompts |
255
+ | Queued prompts | Press **Enter** while the agent is running to queue a follow-up prompt |
256
+ | Steer queue | Press **Alt+Enter** to queue a steer message that is processed before normal queued prompts |
257
+ | Queue limit | Up to **5** normal queued prompts and **5** steer messages |
253
258
  | Model switching | Use `/model` to switch interactively |
254
259
  | Session browsing | Use `/resume` to browse prior sessions |
255
260
 
@@ -437,73 +442,12 @@ kon --provider openai --model some-model --api-key "$OPENAI_API_KEY"
437
442
 
438
443
  ### Local models
439
444
 
440
- Kon works well with local models served through an OpenAI-compatible endpoint.
441
-
442
- Example with `llama-server`:
443
-
444
- ```bash
445
- ./llama-server -m <models-dir>/GLM-4.7-Flash-GGUF/GLM-4.7-Flash-Q4_K_M.gguf \
446
- -n 8192 \
447
- -c 64000
448
-
449
- kon --model zai-org/glm-4.7-flash \
450
- --provider openai \
451
- --base-url http://localhost:8080/v1 \
452
- --api-key ""
453
- ```
445
+ Kon works well with local models served through an OpenAI-compatible endpoint. For one-off launches, you can force unauthenticated local behavior with `--openai-compat-auth none` or `--anthropic-compat-auth none`. To make that persistent across sessions, set `[llm.auth] openai_compat = "auto"|"none"` and/or `anthropic_compat = "auto"|"none"` in `~/.kon/config.toml`.
454
446
 
455
447
  More notes, tested models, and examples live in [docs/local-models.md](docs/local-models.md).
456
448
 
457
449
  ---
458
450
 
459
- ### Configuration
460
-
461
- Kon stores config at:
462
-
463
- ```text
464
- ~/.kon/config.toml
465
- ```
466
-
467
- It is created automatically on first run, and old schemas are migrated forward automatically when needed.
468
-
469
- Users are recommended to customize this config based on their model, workflow, safety preferences, and UI taste.
470
-
471
- Here is the full config shape:
472
-
473
- ```toml
474
- [meta]
475
- config_version = 3
476
-
477
- [llm]
478
- default_provider = "openai-codex"
479
- default_model = "gpt-5.4"
480
- default_base_url = ""
481
- default_thinking_level = "high"
482
- tool_call_idle_timeout_seconds = 180
483
-
484
- [llm.system_prompt]
485
- git_context = true
486
- content = """You are an expert coding assistant called Kon.
487
- ..."""
488
-
489
- [compaction]
490
- on_overflow = "continue"
491
- buffer_tokens = 20000
492
-
493
- [agent]
494
- max_turns = 500
495
- default_context_window = 200000
496
-
497
- [tools]
498
- extra = ["web_search", "web_fetch"]
499
-
500
- [ui]
501
- theme = "gruvbox-dark"
502
-
503
- [permissions]
504
- mode = "prompt"
505
- ```
506
-
507
451
  ### Permissions
508
452
 
509
453
  Kon supports two permission modes:
@@ -526,9 +470,8 @@ Kon depends on a few fast CLI tools for file discovery and search:
526
470
 
527
471
  - **[`fd`](https://github.com/sharkdp/fd)** - required for fast file discovery
528
472
  - **[`ripgrep`](https://github.com/BurntSushi/ripgrep)** - required for fast content search
529
- - **[`eza`](https://github.com/eza-community/eza)** - optional
530
473
 
531
- If `fd` or `rg` are missing, Kon can download them automatically. `eza` is optional and mainly useful for cleaner, `.gitignore`-aware directory listings.
474
+ If `fd` or `rg` are missing, Kon can download them automatically.
532
475
 
533
476
  ---
534
477
 
@@ -149,7 +149,7 @@ Here is the full config shape:
149
149
 
150
150
  ```toml
151
151
  [meta]
152
- config_version = 3
152
+ config_version = 4
153
153
 
154
154
  [llm]
155
155
  default_provider = "openai-codex"
@@ -158,6 +158,10 @@ default_base_url = ""
158
158
  default_thinking_level = "high"
159
159
  tool_call_idle_timeout_seconds = 180
160
160
 
161
+ [llm.auth]
162
+ openai_compat = "auto"
163
+ anthropic_compat = "auto"
164
+
161
165
  [llm.system_prompt]
162
166
  git_context = true
163
167
  content = """You are an expert coding assistant called Kon.
@@ -230,8 +234,9 @@ Kon is built around a terminal UI that stays simple but practical.
230
234
  | --- | --- |
231
235
  | File reference | Type `@` to fuzzy-search files and folders in the current project |
232
236
  | Path completion | Press **Tab** to complete paths like `./`, `../`, `~`, quoted paths, and absolute paths |
233
- | Queued prompts | You can submit follow-up prompts while the agent is still running |
234
- | Queue limit | Up to **5** queued prompts |
237
+ | Queued prompts | Press **Enter** while the agent is running to queue a follow-up prompt |
238
+ | Steer queue | Press **Alt+Enter** to queue a steer message that is processed before normal queued prompts |
239
+ | Queue limit | Up to **5** normal queued prompts and **5** steer messages |
235
240
  | Model switching | Use `/model` to switch interactively |
236
241
  | Session browsing | Use `/resume` to browse prior sessions |
237
242
 
@@ -419,73 +424,12 @@ kon --provider openai --model some-model --api-key "$OPENAI_API_KEY"
419
424
 
420
425
  ### Local models
421
426
 
422
- Kon works well with local models served through an OpenAI-compatible endpoint.
423
-
424
- Example with `llama-server`:
425
-
426
- ```bash
427
- ./llama-server -m <models-dir>/GLM-4.7-Flash-GGUF/GLM-4.7-Flash-Q4_K_M.gguf \
428
- -n 8192 \
429
- -c 64000
430
-
431
- kon --model zai-org/glm-4.7-flash \
432
- --provider openai \
433
- --base-url http://localhost:8080/v1 \
434
- --api-key ""
435
- ```
427
+ Kon works well with local models served through an OpenAI-compatible endpoint. For one-off launches, you can force unauthenticated local behavior with `--openai-compat-auth none` or `--anthropic-compat-auth none`. To make that persistent across sessions, set `[llm.auth] openai_compat = "auto"|"none"` and/or `anthropic_compat = "auto"|"none"` in `~/.kon/config.toml`.
436
428
 
437
429
  More notes, tested models, and examples live in [docs/local-models.md](docs/local-models.md).
438
430
 
439
431
  ---
440
432
 
441
- ### Configuration
442
-
443
- Kon stores config at:
444
-
445
- ```text
446
- ~/.kon/config.toml
447
- ```
448
-
449
- It is created automatically on first run, and old schemas are migrated forward automatically when needed.
450
-
451
- Users are recommended to customize this config based on their model, workflow, safety preferences, and UI taste.
452
-
453
- Here is the full config shape:
454
-
455
- ```toml
456
- [meta]
457
- config_version = 3
458
-
459
- [llm]
460
- default_provider = "openai-codex"
461
- default_model = "gpt-5.4"
462
- default_base_url = ""
463
- default_thinking_level = "high"
464
- tool_call_idle_timeout_seconds = 180
465
-
466
- [llm.system_prompt]
467
- git_context = true
468
- content = """You are an expert coding assistant called Kon.
469
- ..."""
470
-
471
- [compaction]
472
- on_overflow = "continue"
473
- buffer_tokens = 20000
474
-
475
- [agent]
476
- max_turns = 500
477
- default_context_window = 200000
478
-
479
- [tools]
480
- extra = ["web_search", "web_fetch"]
481
-
482
- [ui]
483
- theme = "gruvbox-dark"
484
-
485
- [permissions]
486
- mode = "prompt"
487
- ```
488
-
489
433
  ### Permissions
490
434
 
491
435
  Kon supports two permission modes:
@@ -508,9 +452,8 @@ Kon depends on a few fast CLI tools for file discovery and search:
508
452
 
509
453
  - **[`fd`](https://github.com/sharkdp/fd)** - required for fast file discovery
510
454
  - **[`ripgrep`](https://github.com/BurntSushi/ripgrep)** - required for fast content search
511
- - **[`eza`](https://github.com/eza-community/eza)** - optional
512
455
 
513
- If `fd` or `rg` are missing, Kon can download them automatically. `eza` is optional and mainly useful for cleaner, `.gitignore`-aware directory listings.
456
+ If `fd` or `rg` are missing, Kon can download them automatically.
514
457
 
515
458
  ---
516
459
 
@@ -20,9 +20,23 @@ Run a local model using llama-server with the following command:
20
20
  -c 65536
21
21
  ```
22
22
 
23
- Then start kon:
23
+ Then start Kon for a one-off local session:
24
24
 
25
25
  ```bash
26
- kon --model unsloth/Qwen3.5-9B-GGUF --provider openai --base-url http://localhost:5000/v1 --api-key ""
26
+ kon --model unsloth/Qwen3.5-9B-GGUF --provider openai \
27
+ --base-url http://localhost:5000/v1 \
28
+ --openai-compat-auth none
29
+ ```
30
+
31
+ If this is your default setup, put it in `~/.kon/config.toml` instead:
32
+
33
+ ```toml
34
+ [llm]
35
+ default_provider = "openai"
36
+ default_model = "unsloth/Qwen3.5-9B-GGUF"
37
+ default_base_url = "http://localhost:5000/v1"
38
+
39
+ [llm.auth]
40
+ openai_compat = "auto" # or "none" to always inject a placeholder key
27
41
  ```
28
42
 
@@ -14,7 +14,7 @@ default = true
14
14
 
15
15
  [project]
16
16
  name = "kon-coding-agent"
17
- version = "0.3.1"
17
+ version = "0.3.3"
18
18
  description = "Minimal coding agent"
19
19
  readme = "README.md"
20
20
  requires-python = ">=3.12"
@@ -36,6 +36,7 @@ dev = [
36
36
  "pyright>=1.1.408",
37
37
  "pytest>=9.0.2",
38
38
  "pytest-asyncio>=1.3.0",
39
+ "ruff>=0.15.8",
39
40
  "twine>=5.1.1",
40
41
  ]
41
42
 
@@ -0,0 +1,216 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import subprocess
5
+ import sys
6
+ import time
7
+ from pathlib import Path
8
+
9
+ KON_THEME_TO_GHOSTTY_THEME = {
10
+ "catppuccin-latte": "Catppuccin Latte",
11
+ "catppuccin-mocha": "Catppuccin Mocha",
12
+ "dracula": "Dracula",
13
+ "github-dark": "GitHub Dark",
14
+ "github-light": "GitHub Light Default",
15
+ "gruvbox-dark": "Gruvbox Dark",
16
+ "gruvbox-light": "Gruvbox Light",
17
+ "nord": "Nord",
18
+ "one-dark": "Atom One Dark",
19
+ "one-light": "Atom One Light",
20
+ "solarized-dark": "Builtin Solarized Dark",
21
+ "solarized-light": "Builtin Solarized Light",
22
+ "tokyo-day": "TokyoNight Day",
23
+ "tokyo-night": "TokyoNight Night",
24
+ }
25
+
26
+
27
+ def parse_args() -> argparse.Namespace:
28
+ parser = argparse.ArgumentParser()
29
+ parser.add_argument(
30
+ "--project-dir",
31
+ type=Path,
32
+ default=Path.cwd(),
33
+ help="Directory to open before running `uv run kon -c`.",
34
+ )
35
+ parser.add_argument(
36
+ "--ghostty-config",
37
+ type=Path,
38
+ default=Path.home() / ".config/ghostty/config",
39
+ help="Ghostty config file to rewrite during previews.",
40
+ )
41
+ parser.add_argument(
42
+ "--kon-config",
43
+ type=Path,
44
+ default=Path.home() / ".kon/config.toml",
45
+ help="Kon config file to rewrite during previews.",
46
+ )
47
+ parser.add_argument(
48
+ "--duration", type=float, default=10.0, help="How long each preview stays open in seconds."
49
+ )
50
+ parser.add_argument(
51
+ "--pause", type=float, default=1.5, help="Pause between previews in seconds."
52
+ )
53
+ parser.add_argument(
54
+ "--ghostty-app",
55
+ type=Path,
56
+ default=Path("/Applications/Ghostty.app"),
57
+ help="Path to Ghostty.app for launching new macOS instances.",
58
+ )
59
+ return parser.parse_args()
60
+
61
+
62
+ def list_ghostty_themes() -> set[str]:
63
+ result = subprocess.run(
64
+ ["ghostty", "+list-themes"], check=True, capture_output=True, text=True
65
+ )
66
+ themes = set()
67
+ for line in result.stdout.splitlines():
68
+ theme = line.strip()
69
+ if not theme:
70
+ continue
71
+ if theme.endswith("(resources)"):
72
+ theme = theme[: -len("(resources)")].rstrip()
73
+ themes.add(theme)
74
+ return themes
75
+
76
+
77
+ def ensure_theme_mapping_is_valid(available_themes: set[str]) -> None:
78
+ missing = {
79
+ kon_theme: ghostty_theme
80
+ for kon_theme, ghostty_theme in KON_THEME_TO_GHOSTTY_THEME.items()
81
+ if ghostty_theme not in available_themes
82
+ }
83
+ if missing:
84
+ lines = ["Missing Ghostty theme mappings:"]
85
+ for kon_theme, ghostty_theme in missing.items():
86
+ lines.append(f" {kon_theme} -> {ghostty_theme}")
87
+ raise RuntimeError("\n".join(lines))
88
+
89
+
90
+ def replace_or_append_theme_line(config_text: str, theme_name: str) -> str:
91
+ lines = config_text.splitlines()
92
+ in_ui_section = False
93
+ ui_section_found = False
94
+
95
+ for index, line in enumerate(lines):
96
+ stripped = line.strip()
97
+ if stripped.startswith("[") and stripped.endswith("]"):
98
+ if stripped == "[ui]":
99
+ in_ui_section = True
100
+ ui_section_found = True
101
+ continue
102
+ if in_ui_section:
103
+ lines.insert(index, f'theme = "{theme_name}"')
104
+ return "\n".join(lines) + "\n"
105
+ in_ui_section = False
106
+ continue
107
+
108
+ if in_ui_section and stripped.startswith("theme") and "=" in stripped:
109
+ lines[index] = f'theme = "{theme_name}"'
110
+ return "\n".join(lines) + "\n"
111
+
112
+ if ui_section_found:
113
+ lines.append(f'theme = "{theme_name}"')
114
+ return "\n".join(lines) + "\n"
115
+
116
+ suffix = "\n" if config_text.endswith("\n") or not config_text else "\n\n"
117
+ return f'{config_text}{suffix}[ui]\ntheme = "{theme_name}"\n'
118
+
119
+
120
+ def write_ghostty_config(config_path: Path, theme_name: str) -> None:
121
+ config_path.parent.mkdir(parents=True, exist_ok=True)
122
+ config_path.write_text(f"theme = {theme_name}\n", encoding="utf-8")
123
+
124
+
125
+ def write_kon_theme(config_path: Path, theme_name: str) -> None:
126
+ config_path.parent.mkdir(parents=True, exist_ok=True)
127
+ original = config_path.read_text(encoding="utf-8") if config_path.exists() else ""
128
+ updated = replace_or_append_theme_line(original, theme_name)
129
+ config_path.write_text(updated, encoding="utf-8")
130
+
131
+
132
+ def sh_quote(value: str) -> str:
133
+ return "'" + value.replace("'", "'\"'\"'") + "'"
134
+
135
+
136
+ def launch_preview(ghostty_app: Path, project_dir: Path, duration: float) -> None:
137
+ trap_cmd = (
138
+ 'trap \'test -n "$kon_pid" && kill -TERM "$kon_pid" 2>/dev/null || true\' EXIT INT TERM'
139
+ )
140
+ shell_script = (
141
+ f"cd {sh_quote(str(project_dir))} && "
142
+ "kon_pid='' && "
143
+ f"{trap_cmd} && "
144
+ "uv run kon -c & kon_pid=$! && "
145
+ f"sleep {duration} && "
146
+ 'kill -TERM "$kon_pid" 2>/dev/null || true && '
147
+ 'wait "$kon_pid" 2>/dev/null || true'
148
+ )
149
+ subprocess.run(
150
+ [
151
+ "open",
152
+ "-na",
153
+ str(ghostty_app),
154
+ "--args",
155
+ f"--working-directory={project_dir}",
156
+ "-e",
157
+ "sh",
158
+ "-lc",
159
+ shell_script,
160
+ ],
161
+ check=True,
162
+ )
163
+
164
+
165
+ def main() -> int:
166
+ args = parse_args()
167
+ project_dir = args.project_dir.expanduser().resolve()
168
+ ghostty_config_path = args.ghostty_config.expanduser()
169
+ kon_config_path = args.kon_config.expanduser()
170
+ ghostty_app = args.ghostty_app.expanduser()
171
+
172
+ if not project_dir.exists():
173
+ raise FileNotFoundError(f"Project directory does not exist: {project_dir}")
174
+ if not ghostty_app.exists():
175
+ raise FileNotFoundError(f"Ghostty app not found: {ghostty_app}")
176
+
177
+ available_themes = list_ghostty_themes()
178
+ ensure_theme_mapping_is_valid(available_themes)
179
+
180
+ original_ghostty_config = (
181
+ ghostty_config_path.read_text(encoding="utf-8") if ghostty_config_path.exists() else None
182
+ )
183
+ original_kon_config = (
184
+ kon_config_path.read_text(encoding="utf-8") if kon_config_path.exists() else None
185
+ )
186
+
187
+ try:
188
+ for kon_theme, ghostty_theme in KON_THEME_TO_GHOSTTY_THEME.items():
189
+ print(f"Previewing kon={kon_theme} ghostty={ghostty_theme}")
190
+ write_kon_theme(kon_config_path, kon_theme)
191
+ write_ghostty_config(ghostty_config_path, ghostty_theme)
192
+ launch_preview(ghostty_app, project_dir, args.duration)
193
+ time.sleep(args.duration + args.pause + 2)
194
+ finally:
195
+ if original_kon_config is None:
196
+ if kon_config_path.exists():
197
+ kon_config_path.unlink()
198
+ else:
199
+ kon_config_path.write_text(original_kon_config, encoding="utf-8")
200
+
201
+ if original_ghostty_config is None:
202
+ if ghostty_config_path.exists():
203
+ ghostty_config_path.unlink()
204
+ else:
205
+ ghostty_config_path.write_text(original_ghostty_config, encoding="utf-8")
206
+
207
+ print("Done. Restored Ghostty and kon config files.")
208
+ return 0
209
+
210
+
211
+ if __name__ == "__main__":
212
+ try:
213
+ raise SystemExit(main())
214
+ except KeyboardInterrupt as exc:
215
+ print("Interrupted.", file=sys.stderr)
216
+ raise SystemExit(130) from exc
@@ -0,0 +1,40 @@
1
+ import asyncio
2
+ from contextlib import suppress
3
+ from typing import Any
4
+
5
+
6
+ class OperationCancelledError(Exception):
7
+ pass
8
+
9
+
10
+ async def cancel_and_await(task: asyncio.Future[Any]) -> None:
11
+ if task.done():
12
+ return
13
+ task.cancel()
14
+ with suppress(asyncio.CancelledError):
15
+ await task
16
+
17
+
18
+ async def await_or_cancel[T](work: asyncio.Future[T], cancel_event: asyncio.Event | None) -> T:
19
+ if not cancel_event:
20
+ return await work
21
+
22
+ if cancel_event.is_set():
23
+ await cancel_and_await(work)
24
+ raise OperationCancelledError
25
+
26
+ cancel = asyncio.create_task(cancel_event.wait())
27
+ try:
28
+ done, pending = await asyncio.wait({work, cancel}, return_when=asyncio.FIRST_COMPLETED)
29
+
30
+ for task in pending:
31
+ await cancel_and_await(task)
32
+
33
+ if cancel in done and cancel_event.is_set():
34
+ if not work.done():
35
+ await cancel_and_await(work)
36
+ raise OperationCancelledError
37
+
38
+ return work.result()
39
+ finally:
40
+ await cancel_and_await(cancel)
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: init
3
+ description: Create or update AGENTS.md for this repository
4
+ register_cmd: true
5
+ cmd_info: Guided AGENTS.md setup
6
+ ---
7
+
8
+ Create or update `AGENTS.md` for this repository.
9
+
10
+ The goal is a compact instruction file that helps future Kon sessions avoid mistakes and ramp up quickly. Every line should answer: "Would an agent likely miss this without help?" If not, leave it out.
11
+
12
+ User-provided focus or constraints (honor these):
13
+ $ARGUMENTS
14
+
15
+ ## How to investigate
16
+
17
+ Read the highest-value sources first:
18
+ - `README*`, root manifests, workspace config, lockfiles
19
+ - build, test, lint, formatter, typecheck, and codegen config
20
+ - CI workflows and pre-commit / task runner config
21
+ - existing instruction files (`AGENTS.md`, `CLAUDE.md`, `.cursor/rules/`, `.cursorrules`, `.github/copilot-instructions.md`)
22
+ - repo-local Kon config and conventions
23
+
24
+ If architecture is still unclear after reading config and docs, inspect a small number of representative code files to find the real entrypoints, package boundaries, and execution flow. Prefer reading the files that explain how the system is wired together over random leaf files.
25
+
26
+ Prefer executable sources of truth over prose. If docs conflict with config or scripts, trust the executable source and only keep what you can verify.
27
+
28
+ ## What to extract
29
+
30
+ Look for the highest-signal facts for an agent working in this repo:
31
+ - exact developer commands, especially non-obvious ones
32
+ - how to run a single test, a single package, or a focused verification step
33
+ - required command order when it matters, such as `lint -> typecheck -> test`
34
+ - monorepo or multi-package boundaries, ownership of major directories, and the real app/library entrypoints
35
+ - framework or toolchain quirks: generated code, migrations, codegen, build artifacts, special env loading, dev servers, infra deploy flow
36
+ - repo-specific style or workflow conventions that differ from defaults
37
+ - testing quirks: fixtures, integration test prerequisites, snapshot workflows, required services, flaky or expensive suites
38
+ - important constraints from existing instruction files worth preserving
39
+
40
+ Good `AGENTS.md` content is usually hard-earned context that took reading multiple files to infer.
41
+
42
+ ## Questions
43
+
44
+ Only ask the user questions if the repo cannot answer something important. Use the question tool for one short batch at most.
45
+
46
+ Good questions:
47
+ - undocumented team conventions
48
+ - branch / PR / release expectations
49
+ - missing setup or test prerequisites that are known but not written down
50
+
51
+ Do not ask about anything the repo already makes clear.
52
+
53
+ ## Writing rules
54
+
55
+ Include only high-signal, repo-specific guidance such as:
56
+ - exact commands and shortcuts the agent would otherwise guess wrong
57
+ - architecture notes that are not obvious from filenames
58
+ - conventions that differ from language or framework defaults
59
+ - setup requirements, environment quirks, and operational gotchas
60
+ - references to existing instruction sources that matter
61
+
62
+ Exclude:
63
+ - generic software advice
64
+ - long tutorials or exhaustive file trees
65
+ - obvious language conventions
66
+ - speculative claims or anything you could not verify
67
+ - content better stored in another file referenced via Kon config or another instruction file
68
+
69
+ When in doubt, omit.
70
+
71
+ Prefer short sections and bullets. If the repo is simple, keep the file simple. If the repo is large, summarize the few structural facts that actually change how an agent should work.
72
+
73
+ If `AGENTS.md` already exists, improve it in place rather than rewriting blindly. Preserve verified useful guidance, delete fluff or stale claims, and reconcile it with the current codebase.