krita-cli 1.0.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 (190) hide show
  1. krita_cli-1.0.0/.github/skills/krita-mcp.md +151 -0
  2. krita_cli-1.0.0/.github/workflows/ci.yml +113 -0
  3. krita_cli-1.0.0/.gitignore +40 -0
  4. krita_cli-1.0.0/.pre-commit-config.yaml +17 -0
  5. krita_cli-1.0.0/.python-version +1 -0
  6. krita_cli-1.0.0/LICENSE +21 -0
  7. krita_cli-1.0.0/PKG-INFO +103 -0
  8. krita_cli-1.0.0/README.md +70 -0
  9. krita_cli-1.0.0/SECRETS.md +28 -0
  10. krita_cli-1.0.0/benchmarks/test_rendering.py +67 -0
  11. krita_cli-1.0.0/conda-recipe/meta.yaml +48 -0
  12. krita_cli-1.0.0/conductor/archive/cli_command_grouping_20260406/index.md +5 -0
  13. krita_cli-1.0.0/conductor/archive/cli_command_grouping_20260406/metadata.json +7 -0
  14. krita_cli-1.0.0/conductor/archive/cli_command_grouping_20260406/plan.md +21 -0
  15. krita_cli-1.0.0/conductor/archive/cli_command_grouping_20260406/spec.md +22 -0
  16. krita_cli-1.0.0/conductor/archive/command_history_replay_20260405/index.md +5 -0
  17. krita_cli-1.0.0/conductor/archive/command_history_replay_20260405/metadata.json +8 -0
  18. krita_cli-1.0.0/conductor/archive/command_history_replay_20260405/plan.md +33 -0
  19. krita_cli-1.0.0/conductor/archive/command_history_replay_20260405/spec.md +34 -0
  20. krita_cli-1.0.0/conductor/archive/e2e_test_infrastructure_20260406/index.md +5 -0
  21. krita_cli-1.0.0/conductor/archive/e2e_test_infrastructure_20260406/metadata.json +7 -0
  22. krita_cli-1.0.0/conductor/archive/e2e_test_infrastructure_20260406/plan.md +14 -0
  23. krita_cli-1.0.0/conductor/archive/e2e_test_infrastructure_20260406/spec.md +24 -0
  24. krita_cli-1.0.0/conductor/archive/mcp_tool_discovery_20260406/index.md +5 -0
  25. krita_cli-1.0.0/conductor/archive/mcp_tool_discovery_20260406/metadata.json +7 -0
  26. krita_cli-1.0.0/conductor/archive/mcp_tool_discovery_20260406/plan.md +4 -0
  27. krita_cli-1.0.0/conductor/archive/mcp_tool_discovery_20260406/spec.md +22 -0
  28. krita_cli-1.0.0/conductor/archive/protocol_versioning_v2_20260406/index.md +5 -0
  29. krita_cli-1.0.0/conductor/archive/protocol_versioning_v2_20260406/metadata.json +7 -0
  30. krita_cli-1.0.0/conductor/archive/protocol_versioning_v2_20260406/plan.md +6 -0
  31. krita_cli-1.0.0/conductor/archive/protocol_versioning_v2_20260406/spec.md +24 -0
  32. krita_cli-1.0.0/conductor/archive/rollback_mechanisms_20260405/index.md +5 -0
  33. krita_cli-1.0.0/conductor/archive/rollback_mechanisms_20260405/metadata.json +8 -0
  34. krita_cli-1.0.0/conductor/archive/rollback_mechanisms_20260405/plan.md +23 -0
  35. krita_cli-1.0.0/conductor/archive/rollback_mechanisms_20260405/spec.md +33 -0
  36. krita_cli-1.0.0/conductor/archive/security_limits_validation_20260406/index.md +5 -0
  37. krita_cli-1.0.0/conductor/archive/security_limits_validation_20260406/metadata.json +7 -0
  38. krita_cli-1.0.0/conductor/archive/security_limits_validation_20260406/plan.md +16 -0
  39. krita_cli-1.0.0/conductor/archive/security_limits_validation_20260406/spec.md +31 -0
  40. krita_cli-1.0.0/conductor/archive/selection_advanced_features_20260406/index.md +5 -0
  41. krita_cli-1.0.0/conductor/archive/selection_advanced_features_20260406/metadata.json +7 -0
  42. krita_cli-1.0.0/conductor/archive/selection_advanced_features_20260406/plan.md +28 -0
  43. krita_cli-1.0.0/conductor/archive/selection_advanced_features_20260406/spec.md +27 -0
  44. krita_cli-1.0.0/conductor/archive/selection_clipping_integration_20260406/index.md +5 -0
  45. krita_cli-1.0.0/conductor/archive/selection_clipping_integration_20260406/metadata.json +7 -0
  46. krita_cli-1.0.0/conductor/archive/selection_clipping_integration_20260406/plan.md +19 -0
  47. krita_cli-1.0.0/conductor/archive/selection_clipping_integration_20260406/spec.md +31 -0
  48. krita_cli-1.0.0/conductor/archive/selection_persistence_20260406/index.md +5 -0
  49. krita_cli-1.0.0/conductor/archive/selection_persistence_20260406/metadata.json +7 -0
  50. krita_cli-1.0.0/conductor/archive/selection_persistence_20260406/plan.md +30 -0
  51. krita_cli-1.0.0/conductor/archive/selection_persistence_20260406/spec.md +27 -0
  52. krita_cli-1.0.0/conductor/archive/selection_quality_coverage_20260406/index.md +5 -0
  53. krita_cli-1.0.0/conductor/archive/selection_quality_coverage_20260406/metadata.json +7 -0
  54. krita_cli-1.0.0/conductor/archive/selection_quality_coverage_20260406/plan.md +14 -0
  55. krita_cli-1.0.0/conductor/archive/selection_quality_coverage_20260406/spec.md +35 -0
  56. krita_cli-1.0.0/conductor/archive/selection_transforms_modifiers_20260406/index.md +5 -0
  57. krita_cli-1.0.0/conductor/archive/selection_transforms_modifiers_20260406/metadata.json +7 -0
  58. krita_cli-1.0.0/conductor/archive/selection_transforms_modifiers_20260406/plan.md +14 -0
  59. krita_cli-1.0.0/conductor/archive/selection_transforms_modifiers_20260406/spec.md +25 -0
  60. krita_cli-1.0.0/conductor/code_styleguides/python.md +64 -0
  61. krita_cli-1.0.0/conductor/index.md +14 -0
  62. krita_cli-1.0.0/conductor/product-guidelines.md +54 -0
  63. krita_cli-1.0.0/conductor/product.md +62 -0
  64. krita_cli-1.0.0/conductor/tech-stack.md +119 -0
  65. krita_cli-1.0.0/conductor/tracks/implement_batch_operations_endpoint_20260405/index.md +5 -0
  66. krita_cli-1.0.0/conductor/tracks/implement_batch_operations_endpoint_20260405/metadata.json +8 -0
  67. krita_cli-1.0.0/conductor/tracks/implement_batch_operations_endpoint_20260405/plan.md +23 -0
  68. krita_cli-1.0.0/conductor/tracks/implement_batch_operations_endpoint_20260405/spec.md +16 -0
  69. krita_cli-1.0.0/conductor/tracks/performance_benchmarking_ci_20260406/index.md +5 -0
  70. krita_cli-1.0.0/conductor/tracks/performance_benchmarking_ci_20260406/metadata.json +7 -0
  71. krita_cli-1.0.0/conductor/tracks/performance_benchmarking_ci_20260406/plan.md +6 -0
  72. krita_cli-1.0.0/conductor/tracks/performance_benchmarking_ci_20260406/spec.md +24 -0
  73. krita_cli-1.0.0/conductor/tracks/selection_tools_20260406/index.md +5 -0
  74. krita_cli-1.0.0/conductor/tracks/selection_tools_20260406/metadata.json +7 -0
  75. krita_cli-1.0.0/conductor/tracks/selection_tools_20260406/plan.md +23 -0
  76. krita_cli-1.0.0/conductor/tracks/selection_tools_20260406/spec.md +31 -0
  77. krita_cli-1.0.0/conductor/tracks/windows_testing_20260406/index.md +5 -0
  78. krita_cli-1.0.0/conductor/tracks/windows_testing_20260406/metadata.json +7 -0
  79. krita_cli-1.0.0/conductor/tracks/windows_testing_20260406/plan.md +5 -0
  80. krita_cli-1.0.0/conductor/tracks/windows_testing_20260406/spec.md +24 -0
  81. krita_cli-1.0.0/conductor/tracks.md +14 -0
  82. krita_cli-1.0.0/conductor/workflow.md +110 -0
  83. krita_cli-1.0.0/fix_cli_tests.py +29 -0
  84. krita_cli-1.0.0/krita-plugin/kritamcp/__init__.py +2169 -0
  85. krita_cli-1.0.0/krita-plugin/kritamcp/history_store.py +68 -0
  86. krita_cli-1.0.0/krita-plugin/kritamcp/payload_validator.py +23 -0
  87. krita_cli-1.0.0/krita-plugin/kritamcp/rate_limiter.py +53 -0
  88. krita_cli-1.0.0/krita-plugin/kritamcp/snapshot_store.py +113 -0
  89. krita_cli-1.0.0/krita-plugin/kritamcp.desktop +8 -0
  90. krita_cli-1.0.0/pyproject.toml +284 -0
  91. krita_cli-1.0.0/renovate.json +56 -0
  92. krita_cli-1.0.0/requirements.txt +2 -0
  93. krita_cli-1.0.0/src/krita_cli/__init__.py +5 -0
  94. krita_cli-1.0.0/src/krita_cli/_shared.py +94 -0
  95. krita_cli-1.0.0/src/krita_cli/app.py +149 -0
  96. krita_cli-1.0.0/src/krita_cli/cli.py +59 -0
  97. krita_cli-1.0.0/src/krita_cli/commands/__init__.py +1 -0
  98. krita_cli-1.0.0/src/krita_cli/commands/batch.py +86 -0
  99. krita_cli-1.0.0/src/krita_cli/commands/brush.py +58 -0
  100. krita_cli-1.0.0/src/krita_cli/commands/call.py +49 -0
  101. krita_cli-1.0.0/src/krita_cli/commands/canvas.py +77 -0
  102. krita_cli-1.0.0/src/krita_cli/commands/color.py +42 -0
  103. krita_cli-1.0.0/src/krita_cli/commands/config.py +48 -0
  104. krita_cli-1.0.0/src/krita_cli/commands/file_ops.py +27 -0
  105. krita_cli-1.0.0/src/krita_cli/commands/health.py +32 -0
  106. krita_cli-1.0.0/src/krita_cli/commands/history_cmd.py +64 -0
  107. krita_cli-1.0.0/src/krita_cli/commands/introspect.py +46 -0
  108. krita_cli-1.0.0/src/krita_cli/commands/layers.py +112 -0
  109. krita_cli-1.0.0/src/krita_cli/commands/navigation.py +33 -0
  110. krita_cli-1.0.0/src/krita_cli/commands/replay.py +126 -0
  111. krita_cli-1.0.0/src/krita_cli/commands/rollback.py +39 -0
  112. krita_cli-1.0.0/src/krita_cli/commands/selection.py +364 -0
  113. krita_cli-1.0.0/src/krita_cli/commands/stroke.py +101 -0
  114. krita_cli-1.0.0/src/krita_cli/config_cmd.py +68 -0
  115. krita_cli-1.0.0/src/krita_cli/history.py +198 -0
  116. krita_cli-1.0.0/src/krita_client/__init__.py +68 -0
  117. krita_cli-1.0.0/src/krita_client/client.py +690 -0
  118. krita_cli-1.0.0/src/krita_client/config.py +53 -0
  119. krita_cli-1.0.0/src/krita_client/models.py +507 -0
  120. krita_cli-1.0.0/src/krita_client/schema.py +109 -0
  121. krita_cli-1.0.0/src/krita_mcp/__init__.py +1 -0
  122. krita_cli-1.0.0/src/krita_mcp/server.py +1022 -0
  123. krita_cli-1.0.0/tests/__init__.py +0 -0
  124. krita_cli-1.0.0/tests/conftest.py +9 -0
  125. krita_cli-1.0.0/tests/e2e/__init__.py +0 -0
  126. krita_cli-1.0.0/tests/e2e/conftest.py +328 -0
  127. krita_cli-1.0.0/tests/e2e/test_e2e.py +69 -0
  128. krita_cli-1.0.0/tests/e2e/test_e2e_mock.py +232 -0
  129. krita_cli-1.0.0/tests/integration/__init__.py +0 -0
  130. krita_cli-1.0.0/tests/integration/test_api_capabilities.py +127 -0
  131. krita_cli-1.0.0/tests/integration/test_batch_cli.py +120 -0
  132. krita_cli-1.0.0/tests/integration/test_batch_client.py +81 -0
  133. krita_cli-1.0.0/tests/integration/test_cli.py +51 -0
  134. krita_cli-1.0.0/tests/integration/test_cli_coverage.py +202 -0
  135. krita_cli-1.0.0/tests/integration/test_cli_error_paths.py +133 -0
  136. krita_cli-1.0.0/tests/integration/test_cli_full.py +272 -0
  137. krita_cli-1.0.0/tests/integration/test_cli_success.py +132 -0
  138. krita_cli-1.0.0/tests/integration/test_config_cli.py +54 -0
  139. krita_cli-1.0.0/tests/integration/test_config_cmd_cli.py +86 -0
  140. krita_cli-1.0.0/tests/integration/test_history_cli.py +54 -0
  141. krita_cli-1.0.0/tests/integration/test_history_endpoint.py +59 -0
  142. krita_cli-1.0.0/tests/integration/test_introspect_cli.py +60 -0
  143. krita_cli-1.0.0/tests/integration/test_layers_cli.py +142 -0
  144. krita_cli-1.0.0/tests/integration/test_mcp_coverage.py +117 -0
  145. krita_cli-1.0.0/tests/integration/test_mcp_error_coverage.py +276 -0
  146. krita_cli-1.0.0/tests/integration/test_mcp_error_result.py +205 -0
  147. krita_cli-1.0.0/tests/integration/test_mcp_full.py +156 -0
  148. krita_cli-1.0.0/tests/integration/test_mcp_remaining_tools.py +152 -0
  149. krita_cli-1.0.0/tests/integration/test_mcp_selection_tools.py +149 -0
  150. krita_cli-1.0.0/tests/integration/test_mcp_server.py +211 -0
  151. krita_cli-1.0.0/tests/integration/test_mcp_success.py +318 -0
  152. krita_cli-1.0.0/tests/integration/test_replay_cli.py +90 -0
  153. krita_cli-1.0.0/tests/integration/test_rollback.py +66 -0
  154. krita_cli-1.0.0/tests/integration/test_rollback_cli.py +35 -0
  155. krita_cli-1.0.0/tests/integration/test_security_limits.py +76 -0
  156. krita_cli-1.0.0/tests/integration/test_selection_advanced.py +54 -0
  157. krita_cli-1.0.0/tests/integration/test_selection_cli_coverage.py +230 -0
  158. krita_cli-1.0.0/tests/integration/test_selection_client.py +114 -0
  159. krita_cli-1.0.0/tests/integration/test_selection_persistence.py +78 -0
  160. krita_cli-1.0.0/tests/property/__init__.py +0 -0
  161. krita_cli-1.0.0/tests/property/test_input_sanitization.py +182 -0
  162. krita_cli-1.0.0/tests/property/test_models.py +190 -0
  163. krita_cli-1.0.0/tests/property/test_selection.py +110 -0
  164. krita_cli-1.0.0/tests/test_phase_11.py +41 -0
  165. krita_cli-1.0.0/tests/unit/__init__.py +0 -0
  166. krita_cli-1.0.0/tests/unit/test_batch_models.py +74 -0
  167. krita_cli-1.0.0/tests/unit/test_client.py +267 -0
  168. krita_cli-1.0.0/tests/unit/test_client_coverage.py +272 -0
  169. krita_cli-1.0.0/tests/unit/test_client_internal.py +21 -0
  170. krita_cli-1.0.0/tests/unit/test_config.py +34 -0
  171. krita_cli-1.0.0/tests/unit/test_config_cmd.py +100 -0
  172. krita_cli-1.0.0/tests/unit/test_error_codes.py +151 -0
  173. krita_cli-1.0.0/tests/unit/test_history_store.py +188 -0
  174. krita_cli-1.0.0/tests/unit/test_mcp_batch.py +57 -0
  175. krita_cli-1.0.0/tests/unit/test_mcp_history_tool.py +61 -0
  176. krita_cli-1.0.0/tests/unit/test_models.py +340 -0
  177. krita_cli-1.0.0/tests/unit/test_payload_validator.py +44 -0
  178. krita_cli-1.0.0/tests/unit/test_replay_cmd.py +77 -0
  179. krita_cli-1.0.0/tests/unit/test_rollback_client.py +63 -0
  180. krita_cli-1.0.0/tests/unit/test_rollback_models.py +44 -0
  181. krita_cli-1.0.0/tests/unit/test_schema.py +41 -0
  182. krita_cli-1.0.0/tests/unit/test_security_config.py +105 -0
  183. krita_cli-1.0.0/tests/unit/test_selection_advanced_models.py +73 -0
  184. krita_cli-1.0.0/tests/unit/test_selection_models.py +216 -0
  185. krita_cli-1.0.0/tests/unit/test_selection_persistence_models.py +65 -0
  186. krita_cli-1.0.0/tests/unit/test_shared_coverage.py +48 -0
  187. krita_cli-1.0.0/tests/unit/test_snapshot_store.py +90 -0
  188. krita_cli-1.0.0/tests/unit/test_type_safety_coverage.py +193 -0
  189. krita_cli-1.0.0/types/krita/__init__.pyi +191 -0
  190. krita_cli-1.0.0/uv.lock +2358 -0
@@ -0,0 +1,151 @@
1
+ # Krita MCP — Skill Reference
2
+
3
+ ## What is this?
4
+
5
+ A **SOTA CLI + MCP server** for programmatic painting in Krita. Two interfaces, one core:
6
+ - **CLI**: `krita stroke --points 100,100 200,200` — direct command-line control
7
+ - **MCP**: FastMCP server — for AI agents to paint programmatically
8
+
9
+ Both talk to a Krita plugin via HTTP on localhost:5678.
10
+
11
+ ## Quick Start
12
+
13
+ ### Prerequisites
14
+ - Python 3.12+
15
+ - Krita installed with MCP plugin enabled
16
+ - `uv` package manager
17
+
18
+ ### Setup
19
+ ```bash
20
+ uv sync
21
+ # Copy plugin to Krita's plugin directory
22
+ # Enable in Krita: Settings → Configure Krita → Python Plugin Manager
23
+ # Start Krita with plugin enabled
24
+ ```
25
+
26
+ ### CLI Usage
27
+ ```bash
28
+ # Check Krita is running
29
+ krita health
30
+
31
+ # Create a canvas
32
+ krita canvas new-canvas --width 1920 --height 1080
33
+
34
+ # Set color and draw
35
+ krita color set-color --color "#ff0000"
36
+ krita stroke stroke "0,0" "100,100" "200,50"
37
+
38
+ # Select and draw within bounds
39
+ krita selection select-rect --x 10 --y 10 --width 100 --height 100
40
+ krita stroke stroke "0,0" "200,200" # clipped to selection
41
+
42
+ # Export canvas
43
+ krita canvas get-canvas --filename output.png
44
+ ```
45
+
46
+ ### MCP Usage
47
+
48
+ Connect an MCP client (Claude, etc.) to `http://localhost:5678`. Available tools:
49
+
50
+ | Tool | Description |
51
+ |------|-------------|
52
+ | `krita_health` | Check Krita + plugin status |
53
+ | `krita_new_canvas` | Create canvas (width, height, bg color) |
54
+ | `krita_set_color` | Set foreground color (hex) |
55
+ | `krita_set_brush` | Set brush preset/size/opacity |
56
+ | `krita_stroke` | Paint stroke through [x, y] points |
57
+ | `krita_fill` | Fill circular area |
58
+ | `krita_draw_shape` | Draw rectangle/ellipse/line |
59
+ | `krita_get_canvas` | Export canvas to PNG |
60
+ | `krita_save` | Save canvas to file |
61
+ | `krita_undo` / `krita_redo` | Undo/redo |
62
+ | `krita_clear` | Clear canvas |
63
+ | `krita_get_color_at` | Eyedropper |
64
+ | `krita_list_brushes` | List brush presets |
65
+ | `krita_open_file` | Open existing file |
66
+ | `krita_batch` | Execute multiple commands sequentially |
67
+ | `krita_rollback` | Roll back a batch operation by batch ID |
68
+ | `krita_select_rect` | Select a rectangular area |
69
+ | `krita_select_ellipse` | Select an elliptical area |
70
+ | `krita_select_polygon` | Select a polygonal area |
71
+ | `krita_selection_info` | Get current selection bounds |
72
+ | `krita_invert_selection` | Invert the current selection |
73
+ | `krita_clear_selection` | Clear selection contents |
74
+ | `krita_fill_selection` | Fill selection with foreground color |
75
+ | `krita_deselect` | Remove current selection |
76
+ | `krita_transform_selection` | Move/rotate/scale selection |
77
+ | `krita_grow_selection` | Grow selection by N pixels |
78
+ | `krita_shrink_selection` | Shrink selection by N pixels |
79
+ | `krita_border_selection` | Create border around selection |
80
+ | `krita_get_capabilities` | Get detected API capabilities |
81
+ | `krita_security_status` | Get security limits and usage |
82
+ | `krita_list_tools` | List all available MCP tools |
83
+
84
+ ## Agent Workflow
85
+
86
+ ### Painting a simple shape
87
+ 1. `krita_new_canvas(width=800, height=600)` — create canvas
88
+ 2. `krita_set_color(color="#ff0000")` — set color
89
+ 3. `krita_stroke(points=[[100,100],[200,100],[150,200]])` — draw triangle
90
+ 4. `krita_get_canvas(filename="result.png")` — export result
91
+
92
+ ### Painting within a selection
93
+ 1. `krita_new_canvas(width=800, height=600)`
94
+ 2. `krita_select_rect(x=50, y=50, width=200, height=200)` — create selection
95
+ 3. `krita_set_color(color="#00ff00")`
96
+ 4. `krita_stroke(points=[[0,0],[400,400]])` — clipped to selection
97
+ 5. `krita_deselect()` — remove selection
98
+ 6. `krita_get_canvas(filename="clipped.png")`
99
+
100
+ ### Batch operations
101
+ 1. `krita_batch(commands=[{"action":"set_color","params":{"color":"#ff0000"}},{"action":"stroke","params":{"points":[[0,0],[100,100]]}}])`
102
+ 2. `krita_rollback(batch_id="...")` — if something went wrong
103
+
104
+ ### Iterative painting
105
+ 1. `krita_new_canvas()` → `krita_stroke()` → `krita_get_canvas()` — see result
106
+ 2. Analyze result, adjust parameters
107
+ 3. `krita_stroke()` with new points → `krita_get_canvas()` — iterate
108
+ 4. `krita_save(path="final.png")` when satisfied
109
+
110
+ ## Security Limits
111
+
112
+ | Limit | Default |
113
+ |-------|---------|
114
+ | Rate limit | 60 commands/minute |
115
+ | Max payload | 10 MB |
116
+ | Max batch size | 50 commands |
117
+ | Max canvas | 8192×8192 |
118
+ | Max layers | 100 |
119
+
120
+ Check current status: `krita selection security-status`
121
+
122
+ ## Command Groups
123
+
124
+ | Group | Commands |
125
+ |-------|----------|
126
+ | `krita canvas` | new-canvas, get-canvas, save, clear |
127
+ | `krita color` | set-color, get-color-at |
128
+ | `krita brush` | set-brush, list-brushes |
129
+ | `krita stroke` | stroke, fill, draw-shape |
130
+ | `krita navigation` | undo, redo |
131
+ | `krita file` | open-file |
132
+ | `krita selection` | select-rect, select-ellipse, select-polygon, selection-info, transform-selection, grow-selection, shrink-selection, border-selection, select-clear, select-invert, select-fill, deselect, security-status |
133
+ | `krita history` | history |
134
+ | `krita introspect` | canvas-info, current-color, current-brush |
135
+ | `krita replay` | replay |
136
+
137
+ ## Error Handling
138
+
139
+ All commands return structured errors:
140
+ ```json
141
+ {"code": "NO_ACTIVE_DOCUMENT", "message": "...", "recoverable": true}
142
+ ```
143
+
144
+ CLI shows: `[red]Error: ...[/red]` with hints for recovery.
145
+
146
+ ## Protocol
147
+
148
+ - HTTP POST to `localhost:5678` with `{"action": "...", "params": {...}}`
149
+ - Health check: GET `localhost:5678/health`
150
+ - Default timeout: 30s (120s for export/save)
151
+ - Protocol version included in health response
@@ -0,0 +1,113 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ tags: ["v*"]
7
+ pull_request:
8
+ branches: [main, master]
9
+ workflow_dispatch:
10
+
11
+ env:
12
+ UV_VERSION: "latest"
13
+ PYTHON_VERSION: "3.12"
14
+
15
+ jobs:
16
+ lint:
17
+ name: Lint (ruff)
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - uses: astral-sh/setup-uv@v5
22
+ with:
23
+ version: ${{ env.UV_VERSION }}
24
+ - uses: actions/setup-python@v5
25
+ with:
26
+ python-version: ${{ env.PYTHON_VERSION }}
27
+ - run: uv sync --frozen
28
+ - run: uv run ruff check src/ tests/
29
+ - run: uv run ruff format --check src/ tests/
30
+
31
+ typecheck:
32
+ name: Type Check (ty)
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ - uses: astral-sh/setup-uv@v5
37
+ with:
38
+ version: ${{ env.UV_VERSION }}
39
+ - uses: actions/setup-python@v5
40
+ with:
41
+ python-version: ${{ env.PYTHON_VERSION }}
42
+ - run: uv sync --frozen
43
+ - run: uv run ty check src/ types/
44
+
45
+ test:
46
+ name: All Tests
47
+ runs-on: ubuntu-latest
48
+ strategy:
49
+ matrix:
50
+ python-version: ["3.12", "3.13"]
51
+ steps:
52
+ - uses: actions/checkout@v4
53
+ - uses: astral-sh/setup-uv@v5
54
+ with:
55
+ version: ${{ env.UV_VERSION }}
56
+ - uses: actions/setup-python@v5
57
+ with:
58
+ python-version: ${{ matrix.python-version }}
59
+ - run: uv sync --frozen
60
+ - run: uv run pytest tests/ -v --cov=src --cov-fail-under=95
61
+
62
+ build:
63
+ name: Build Package
64
+ runs-on: ubuntu-latest
65
+ needs: [lint, typecheck, test]
66
+ steps:
67
+ - uses: actions/checkout@v4
68
+ - uses: astral-sh/setup-uv@v5
69
+ with:
70
+ version: ${{ env.UV_VERSION }}
71
+ - run: uv build
72
+ - uses: actions/upload-artifact@v4
73
+ with:
74
+ name: dist
75
+ path: dist/
76
+
77
+ publish-pypi:
78
+ name: Publish to PyPI
79
+ if: startsWith(github.ref, 'refs/tags/v')
80
+ needs: [build]
81
+ runs-on: ubuntu-latest
82
+ environment:
83
+ name: pypi
84
+ url: https://pypi.org/p/krita-cli
85
+ permissions:
86
+ id-token: write
87
+ steps:
88
+ - uses: actions/download-artifact@v4
89
+ with:
90
+ name: dist
91
+ path: dist/
92
+ - name: Publish to PyPI
93
+ uses: pypa/gh-action-pypi-publish@release/v1
94
+
95
+ publish-conda:
96
+ name: Publish to Conda
97
+ if: startsWith(github.ref, 'refs/tags/v')
98
+ needs: [build]
99
+ runs-on: ubuntu-latest
100
+ steps:
101
+ - uses: actions/checkout@v4
102
+ - name: Set up Conda
103
+ uses: conda-incubator/setup-miniconda@v3
104
+ with:
105
+ auto-update-conda: true
106
+ python-version: 3.12
107
+ channels: conda-forge,defaults
108
+ - name: Build and Upload to Anaconda
109
+ shell: bash -l {0}
110
+ run: |
111
+ conda install -y anaconda-client conda-build
112
+ conda build conda-recipe/ --output-folder dist/conda
113
+ anaconda -t ${{ secrets.ANACONDA_API_TOKEN }} upload dist/conda/noarch/krita-cli-*.tar.bz2 --force
@@ -0,0 +1,40 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ .env
5
+
6
+ # Build artifacts
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ *.egg
11
+
12
+ # Testing
13
+ .pytest_cache/
14
+ .coverage
15
+ htmlcov/
16
+ .mutmut-cache
17
+ .hypothesis/
18
+
19
+ # Tooling caches
20
+ .ruff_cache/
21
+ .ty_cache/
22
+
23
+ # IDE
24
+ .idea/
25
+ .vscode/
26
+ *.swp
27
+ *.swo
28
+
29
+ # OS
30
+ .DS_Store
31
+ Thumbs.db
32
+
33
+ # Project
34
+ logs/
35
+ pytest-of-*/
36
+ .swarm/
37
+ .gemini/
38
+ .geminiignore
39
+ history.log
40
+ refactor_plugin.py
@@ -0,0 +1,17 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.15.9
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix, --exit-non-zero-on-fix]
7
+ - id: ruff-format
8
+
9
+ - repo: local
10
+ hooks:
11
+ - id: ty
12
+ name: ty type check
13
+ entry: uv run ty check src/ types/
14
+ language: system
15
+ types: [python]
16
+ pass_filenames: false
17
+ require_serial: true
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025
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,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: krita-cli
3
+ Version: 1.0.0
4
+ Summary: SOTA CLI + MCP server for programmatic painting in Krita
5
+ Project-URL: Homepage, https://github.com/github/krita-cli
6
+ Project-URL: Repository, https://github.com/github/krita-cli
7
+ Project-URL: Issues, https://github.com/github/krita-cli/issues
8
+ Project-URL: Changelog, https://github.com/github/krita-cli/blob/master/CHANGELOG.md
9
+ Author: Krita MCP Contributors
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai,automation,claude,cli,fastmcp,krita,mcp,painting
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Multimedia :: Graphics :: Editors :: Raster-Based
20
+ Classifier: Typing :: Typed
21
+ Requires-Python: >=3.12
22
+ Requires-Dist: fastmcp>=3.1.0
23
+ Requires-Dist: httpx>=0.28.1
24
+ Requires-Dist: pydantic-settings>=2.0.0
25
+ Requires-Dist: pydantic>=2.12.5
26
+ Requires-Dist: rich>=13.0.0
27
+ Requires-Dist: typer>=0.9.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: beartype>=0.18.0; extra == 'dev'
30
+ Provides-Extra: numpy
31
+ Requires-Dist: numpy>=1.26.0; extra == 'numpy'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # Krita MCP Server & CLI
35
+
36
+ Let AI agents paint in [Krita](https://krita.org/) via the [Model Context Protocol](https://modelcontextprotocol.io/).
37
+
38
+ This subproject provides the core implementation of the Krita-MCP ecosystem, including the FastMCP server, the `krita` CLI, and the high-performance Python plugin.
39
+
40
+ ## 🛠️ Components
41
+
42
+ 1. **Krita Plugin** (`krita-plugin/`) — A Python plugin for Krita that exposes a thread-safe HTTP server on `localhost:5678`.
43
+ 2. **MCP Server** (`src/krita_mcp/`) — A FastMCP server exposing 40+ painting and manipulation tools.
44
+ 3. **Krita CLI** (`src/krita_cli/`) — A Typer-based command line interface for human operators.
45
+ 4. **Krita Client** (`src/krita_client/`) — A reusable, fully-typed Python library for Krita automation.
46
+
47
+ ## 🚀 Setup
48
+
49
+ ### 1. Krita Plugin Installation
50
+ Copy the contents of `krita-plugin/` to your Krita resources:
51
+ - **Windows**: `%APPDATA%\krita\pykrita\`
52
+ - **Linux**: `~/.local/share/krita/pykrita/`
53
+ - **macOS**: `~/Library/Application Support/krita/pykrita/`
54
+
55
+ Enable **"Krita MCP Bridge"** in Krita (Configure Krita → Python Plugin Manager) and restart.
56
+
57
+ ### 2. Environment Setup
58
+ ```bash
59
+ # Install dependencies with uv
60
+ uv sync
61
+ ```
62
+
63
+ ## 🔧 CLI Commands
64
+
65
+ The `krita` CLI is grouped into logical subcommands:
66
+
67
+ - **Painting**: `stroke`, `fill`, `clear`, `draw-shape`
68
+ - **Layers**: `layers list`, `layers create`, `layers select`, `layers delete`
69
+ - **Selection**: `selection select-rect`, `selection transform`, `selection save-channel`
70
+ - **Canvas**: `canvas-info`, `current-color`, `current-brush`
71
+ - **Session**: `history`, `replay`, `rollback`, `batch`
72
+ - **System**: `health`, `config`, `capabilities`, `security-status`
73
+
74
+ Run `uv run krita --help` for full details.
75
+
76
+ ## 🤖 MCP Server Tools (40 Total)
77
+
78
+ The MCP server exposes a vast range of capabilities to AI agents:
79
+
80
+ | Category | Key Tools |
81
+ |----------|-----------|
82
+ | **Core** | `krita_health`, `krita_new_canvas`, `krita_save`, `krita_open_file` |
83
+ | **Painting** | `krita_stroke`, `krita_fill`, `krita_draw_shape`, `krita_set_color`, `krita_set_brush` |
84
+ | **Selection** | `krita_select_rect`, `krita_select_ellipse`, `krita_select_polygon`, `krita_select_by_color`, `krita_select_by_alpha` |
85
+ | **Selection Ops** | `krita_transform_selection`, `krita_grow_selection`, `krita_combine_selections`, `krita_invert_selection` |
86
+ | **Persistence** | `krita_save_selection`, `krita_load_selection`, `krita_save_selection_channel`, `krita_list_selection_channels` |
87
+ | **Automation** | `krita_batch`, `krita_rollback`, `krita_get_command_history` |
88
+ | **Inspection** | `krita_get_canvas_info`, `krita_get_color_at`, `krita_selection_stats`, `krita_security_status` |
89
+
90
+ ## ⚡ Performance
91
+
92
+ The plugin uses **numpy-accelerated** direct pixel manipulation for rendering. This ensures that strokes and shapes are rendered significantly faster than standard Python loops, especially on high-resolution canvases.
93
+
94
+ ## 🔒 Security
95
+
96
+ Krita MCP includes a built-in security layer to protect your system:
97
+ - **Path Sanitization**: Restricts file operations to allowed directories.
98
+ - **Resource Limits**: Prevents OOM by limiting max canvas dimensions and layer counts.
99
+ - **Rate Limiting**: Throttles rapid command execution.
100
+ - **Security Tool**: `krita_security_status` allows agents to check active limits.
101
+
102
+ ## 📄 License
103
+ MIT
@@ -0,0 +1,70 @@
1
+ # Krita MCP Server & CLI
2
+
3
+ Let AI agents paint in [Krita](https://krita.org/) via the [Model Context Protocol](https://modelcontextprotocol.io/).
4
+
5
+ This subproject provides the core implementation of the Krita-MCP ecosystem, including the FastMCP server, the `krita` CLI, and the high-performance Python plugin.
6
+
7
+ ## 🛠️ Components
8
+
9
+ 1. **Krita Plugin** (`krita-plugin/`) — A Python plugin for Krita that exposes a thread-safe HTTP server on `localhost:5678`.
10
+ 2. **MCP Server** (`src/krita_mcp/`) — A FastMCP server exposing 40+ painting and manipulation tools.
11
+ 3. **Krita CLI** (`src/krita_cli/`) — A Typer-based command line interface for human operators.
12
+ 4. **Krita Client** (`src/krita_client/`) — A reusable, fully-typed Python library for Krita automation.
13
+
14
+ ## 🚀 Setup
15
+
16
+ ### 1. Krita Plugin Installation
17
+ Copy the contents of `krita-plugin/` to your Krita resources:
18
+ - **Windows**: `%APPDATA%\krita\pykrita\`
19
+ - **Linux**: `~/.local/share/krita/pykrita/`
20
+ - **macOS**: `~/Library/Application Support/krita/pykrita/`
21
+
22
+ Enable **"Krita MCP Bridge"** in Krita (Configure Krita → Python Plugin Manager) and restart.
23
+
24
+ ### 2. Environment Setup
25
+ ```bash
26
+ # Install dependencies with uv
27
+ uv sync
28
+ ```
29
+
30
+ ## 🔧 CLI Commands
31
+
32
+ The `krita` CLI is grouped into logical subcommands:
33
+
34
+ - **Painting**: `stroke`, `fill`, `clear`, `draw-shape`
35
+ - **Layers**: `layers list`, `layers create`, `layers select`, `layers delete`
36
+ - **Selection**: `selection select-rect`, `selection transform`, `selection save-channel`
37
+ - **Canvas**: `canvas-info`, `current-color`, `current-brush`
38
+ - **Session**: `history`, `replay`, `rollback`, `batch`
39
+ - **System**: `health`, `config`, `capabilities`, `security-status`
40
+
41
+ Run `uv run krita --help` for full details.
42
+
43
+ ## 🤖 MCP Server Tools (40 Total)
44
+
45
+ The MCP server exposes a vast range of capabilities to AI agents:
46
+
47
+ | Category | Key Tools |
48
+ |----------|-----------|
49
+ | **Core** | `krita_health`, `krita_new_canvas`, `krita_save`, `krita_open_file` |
50
+ | **Painting** | `krita_stroke`, `krita_fill`, `krita_draw_shape`, `krita_set_color`, `krita_set_brush` |
51
+ | **Selection** | `krita_select_rect`, `krita_select_ellipse`, `krita_select_polygon`, `krita_select_by_color`, `krita_select_by_alpha` |
52
+ | **Selection Ops** | `krita_transform_selection`, `krita_grow_selection`, `krita_combine_selections`, `krita_invert_selection` |
53
+ | **Persistence** | `krita_save_selection`, `krita_load_selection`, `krita_save_selection_channel`, `krita_list_selection_channels` |
54
+ | **Automation** | `krita_batch`, `krita_rollback`, `krita_get_command_history` |
55
+ | **Inspection** | `krita_get_canvas_info`, `krita_get_color_at`, `krita_selection_stats`, `krita_security_status` |
56
+
57
+ ## ⚡ Performance
58
+
59
+ The plugin uses **numpy-accelerated** direct pixel manipulation for rendering. This ensures that strokes and shapes are rendered significantly faster than standard Python loops, especially on high-resolution canvases.
60
+
61
+ ## 🔒 Security
62
+
63
+ Krita MCP includes a built-in security layer to protect your system:
64
+ - **Path Sanitization**: Restricts file operations to allowed directories.
65
+ - **Resource Limits**: Prevents OOM by limiting max canvas dimensions and layer counts.
66
+ - **Rate Limiting**: Throttles rapid command execution.
67
+ - **Security Tool**: `krita_security_status` allows agents to check active limits.
68
+
69
+ ## 📄 License
70
+ MIT
@@ -0,0 +1,28 @@
1
+ # Required Repository Secrets
2
+
3
+ The following secrets must be configured in GitHub → Settings → Secrets and variables → Actions:
4
+
5
+ | Secret | Description | How to Create |
6
+ |--------|-------------|---------------|
7
+ | `GH_TOKEN` | GitHub Personal Access Token with `repo` scope | GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens |
8
+ | `PYPI_TOKEN` | PyPI API token for publishing packages | https://pypi.org/manage/account/token/ → Create token |
9
+
10
+ ## Creating GH_TOKEN
11
+
12
+ 1. Go to https://github.com/settings/tokens
13
+ 2. Create a fine-grained token with:
14
+ - Repository access: This repository only
15
+ - Permissions: Contents (read/write), Pull requests (read/write), Workflows (read/write)
16
+ 3. Copy the token and add it as `GH_TOKEN` in repo secrets
17
+
18
+ ## Creating PYPI_TOKEN
19
+
20
+ 1. Go to https://pypi.org/manage/account/
21
+ 2. Scroll to "API tokens" section
22
+ 3. Click "Add API token"
23
+ 4. Set scope to "Entire account" or "Specific project" (if krita-cli exists)
24
+ 5. Copy the token and add it as `PYPI_TOKEN` in repo secrets
25
+
26
+ ## Verifying Secrets
27
+
28
+ After adding secrets, the CI release workflow will use them automatically when pushing to master with a conventional commit that triggers a release.
@@ -0,0 +1,67 @@
1
+ """Performance benchmarks for krita_client and plugin rendering."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import importlib.util
6
+ import time
7
+ from pathlib import Path
8
+
9
+
10
+ def _get_plugin_class() -> type:
11
+ """Import the plugin module via file path (not a pip-installable package)."""
12
+ plugin_path = Path(__file__).parent.parent / "krita-plugin" / "kritamcp" / "__init__.py"
13
+ spec = importlib.util.spec_from_file_location("kritamcp", plugin_path)
14
+ module = importlib.util.module_from_spec(spec)
15
+ spec.loader.exec_module(module) # type: ignore[union-attr]
16
+ return module.KritaMCPExtension # type: ignore[no-any-return]
17
+
18
+
19
+ def benchmark_stroke_rendering_python() -> float:
20
+ """Benchmark pure Python stroke rendering."""
21
+ plugin_cls = _get_plugin_class()
22
+
23
+ pixels = bytearray(255 * 255 * 4)
24
+ w, h = 255, 255
25
+ points = [[i * 10, i * 10] for i in range(25)]
26
+ radius = 20
27
+ hardness = 0.5
28
+ opacity = 1.0
29
+ r, g, b = 255, 0, 0
30
+
31
+ start = time.perf_counter()
32
+ plugin_cls._draw_stroke_python(pixels, w, h, points, radius, hardness, opacity, r, g, b)
33
+ return time.perf_counter() - start
34
+
35
+
36
+ def benchmark_stroke_rendering_numpy() -> float:
37
+ """Benchmark numpy-accelerated stroke rendering."""
38
+ try:
39
+ import numpy as np # noqa: F401, PLC0415
40
+ except ImportError:
41
+ return 0.0
42
+
43
+ plugin_cls = _get_plugin_class()
44
+
45
+ pixels = bytearray(255 * 255 * 4)
46
+ w, h = 255, 255
47
+ points = [[i * 10, i * 10] for i in range(25)]
48
+ radius = 20
49
+ hardness = 0.5
50
+ opacity = 1.0
51
+ r, g, b = 255, 0, 0
52
+
53
+ start = time.perf_counter()
54
+ plugin_cls._draw_stroke_numpy(pixels, w, h, points, radius, hardness, opacity, r, g, b)
55
+ return time.perf_counter() - start
56
+
57
+
58
+ if __name__ == "__main__":
59
+ python_time = benchmark_stroke_rendering_python()
60
+ numpy_time = benchmark_stroke_rendering_numpy()
61
+
62
+ print(f"Python stroke rendering: {python_time:.4f}s")
63
+ if numpy_time > 0:
64
+ print(f"Numpy stroke rendering: {numpy_time:.4f}s")
65
+ print(f"Speedup: {python_time / numpy_time:.1f}x")
66
+ else:
67
+ print("Numpy not available — skipping numpy benchmark")
@@ -0,0 +1,48 @@
1
+ {% set name = 'krita-cli' %}
2
+ {% set version = '1.0.0' %}
3
+
4
+ package:
5
+ name: {{ name|lower }}
6
+ version: {{ version }}
7
+
8
+ source:
9
+ path: ..
10
+
11
+ build:
12
+ number: 0
13
+ script: {{ PYTHON }} -m pip install . --no-deps -vv
14
+ entry_points:
15
+ - krita = krita_cli.cli:app
16
+
17
+ requirements:
18
+ host:
19
+ - python >=3.12
20
+ - pip
21
+ - hatchling
22
+ run:
23
+ - python >=3.12
24
+ - fastmcp >=3.1.0
25
+ - httpx >=0.28.1
26
+ - pydantic >=2.12.5
27
+ - pydantic-settings >=2.0.0
28
+ - rich >=13.0.0
29
+ - typer >=0.9.0
30
+
31
+ test:
32
+ commands:
33
+ - krita --help
34
+
35
+ about:
36
+ home: https://github.com/edithatogo/krita-cli
37
+ license: MIT
38
+ license_file: LICENSE
39
+ summary: SOTA CLI + MCP server for programmatic painting in Krita
40
+ description: |
41
+ Krita CLI provides a bridge between AI agents, developers, and the Krita desktop application.
42
+ It enables real-time painting, canvas manipulation, and workflow automation.
43
+ dev_url: https://github.com/edithatogo/krita-cli
44
+ doc_url: https://github.com/edithatogo/krita-cli
45
+
46
+ extra:
47
+ recipe-maintainers:
48
+ - edithatogo
@@ -0,0 +1,5 @@
1
+ # Track cli_command_grouping_20260406 Context
2
+
3
+ - [Specification](./spec.md)
4
+ - [Implementation Plan](./plan.md)
5
+ - [Metadata](./metadata.json)
@@ -0,0 +1,7 @@
1
+ {
2
+ "track_id": "cli_command_grouping_20260406",
3
+ "created_at": "2026-04-06",
4
+ "status": "pending",
5
+ "phase": "12",
6
+ "priority": "medium"
7
+ }