devctl 1.2.3__tar.gz → 1.2.4__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 (151) hide show
  1. {devctl-1.2.3 → devctl-1.2.4}/PKG-INFO +9 -4
  2. {devctl-1.2.3 → devctl-1.2.4}/README.md +7 -2
  3. {devctl-1.2.3 → devctl-1.2.4}/devctl/commands/init.py +25 -0
  4. devctl-1.2.4/devctl/generators/agent/__init__.py +7 -0
  5. devctl-1.2.4/devctl/generators/agent/generator.py +269 -0
  6. devctl-1.2.4/devctl/generators/agent/templates/AGENTS.md.j2 +87 -0
  7. devctl-1.2.4/devctl/generators/agent/templates/CLAUDE.md.j2 +8 -0
  8. {devctl-1.2.3 → devctl-1.2.4}/devctl/tui/app.py +2 -0
  9. devctl-1.2.4/devctl/tui/app.tcss +353 -0
  10. {devctl-1.2.3 → devctl-1.2.4}/devctl.egg-info/PKG-INFO +9 -4
  11. {devctl-1.2.3 → devctl-1.2.4}/devctl.egg-info/SOURCES.txt +6 -0
  12. {devctl-1.2.3 → devctl-1.2.4}/pyproject.toml +3 -3
  13. devctl-1.2.4/test/test_agent_context.py +80 -0
  14. devctl-1.2.4/test/test_init.py +46 -0
  15. devctl-1.2.3/test/test_init.py +0 -33
  16. {devctl-1.2.3 → devctl-1.2.4}/LICENSE +0 -0
  17. {devctl-1.2.3 → devctl-1.2.4}/devctl/__init__.py +0 -0
  18. {devctl-1.2.3 → devctl-1.2.4}/devctl/commands/__init__.py +0 -0
  19. {devctl-1.2.3 → devctl-1.2.4}/devctl/commands/add.py +0 -0
  20. {devctl-1.2.3 → devctl-1.2.4}/devctl/commands/deploy.py +0 -0
  21. {devctl-1.2.3 → devctl-1.2.4}/devctl/commands/docker.py +0 -0
  22. {devctl-1.2.3 → devctl-1.2.4}/devctl/commands/run.py +0 -0
  23. {devctl-1.2.3 → devctl-1.2.4}/devctl/commands/tui.py +0 -0
  24. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/__init__.py +0 -0
  25. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/__init__.py +0 -0
  26. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/generator.py +0 -0
  27. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/scaffolder.py +0 -0
  28. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/config/environment.development.ts.j2 +0 -0
  29. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/config/environment.ts.j2 +0 -0
  30. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/config/proxy.conf.json.j2 +0 -0
  31. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/feature/models/request.model.ts.j2 +0 -0
  32. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/feature/models/response.model.ts.j2 +0 -0
  33. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/feature/pages/form/form.component.html.j2 +0 -0
  34. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/feature/pages/form/form.component.scss.j2 +0 -0
  35. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/feature/pages/form/form.component.ts.j2 +0 -0
  36. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/feature/pages/list/list.component.html.j2 +0 -0
  37. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/feature/pages/list/list.component.scss.j2 +0 -0
  38. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/feature/pages/list/list.component.ts.j2 +0 -0
  39. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/feature/routes.ts.j2 +0 -0
  40. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/angular/templates/feature/services/service.ts.j2 +0 -0
  41. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/django/__init__.py +0 -0
  42. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/django/generator.py +0 -0
  43. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/django/scaffolder.py +0 -0
  44. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/django/templates/config/requirements.txt.j2 +0 -0
  45. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/django/templates/resource/model.py.j2 +0 -0
  46. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/django/templates/resource/serializer.py.j2 +0 -0
  47. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/django/templates/resource/view.py.j2 +0 -0
  48. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/__init__.py +0 -0
  49. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/scaffolder.py +0 -0
  50. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/templates/deploy.yml.j2 +0 -0
  51. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/templates/django/Dockerfile.j2 +0 -0
  52. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/templates/fastapi/Dockerfile.j2 +0 -0
  53. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/templates/frontend/Dockerfile.j2 +0 -0
  54. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/templates/go/Dockerfile.j2 +0 -0
  55. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/templates/nestjs/Dockerfile.j2 +0 -0
  56. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/templates/nextjs/Dockerfile.j2 +0 -0
  57. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/templates/nodejs/Dockerfile.j2 +0 -0
  58. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/templates/spring/Dockerfile.j2 +0 -0
  59. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/docker/templates/svelte/Dockerfile.j2 +0 -0
  60. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/fastapi/__init__.py +0 -0
  61. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/fastapi/generator.py +0 -0
  62. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/fastapi/scaffolder.py +0 -0
  63. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/fastapi/templates/config/main.py.j2 +0 -0
  64. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/fastapi/templates/config/requirements.txt.j2 +0 -0
  65. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/fastapi/templates/resource/router.py.j2 +0 -0
  66. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/fastapi/templates/resource/schema.py.j2 +0 -0
  67. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/go_fiber/__init__.py +0 -0
  68. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/go_fiber/generator.py +0 -0
  69. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/go_fiber/scaffolder.py +0 -0
  70. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/go_fiber/templates/config/main.go.j2 +0 -0
  71. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/go_fiber/templates/resource/handler.go.j2 +0 -0
  72. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/go_fiber/templates/resource/model.go.j2 +0 -0
  73. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nestjs/__init__.py +0 -0
  74. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nestjs/generator.py +0 -0
  75. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nestjs/scaffolder.py +0 -0
  76. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nextjs/__init__.py +0 -0
  77. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nextjs/generator.py +0 -0
  78. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nextjs/scaffolder.py +0 -0
  79. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nextjs/templates/resource/component.tsx.j2 +0 -0
  80. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nextjs/templates/resource/page.tsx.j2 +0 -0
  81. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nodejs/__init__.py +0 -0
  82. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nodejs/generator.py +0 -0
  83. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nodejs/scaffolder.py +0 -0
  84. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nodejs/templates/config/index.ts.j2 +0 -0
  85. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nodejs/templates/resource/controller.ts.j2 +0 -0
  86. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/nodejs/templates/resource/routes.ts.j2 +0 -0
  87. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/react/__init__.py +0 -0
  88. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/react/generator.py +0 -0
  89. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/react/scaffolder.py +0 -0
  90. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/react/templates/resource/component.tsx.j2 +0 -0
  91. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/react/templates/resource/service.ts.j2 +0 -0
  92. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/__init__.py +0 -0
  93. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/generator.py +0 -0
  94. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/scaffolder.py +0 -0
  95. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/Controller.java.j2 +0 -0
  96. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/Entity.java.j2 +0 -0
  97. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/Repository.java.j2 +0 -0
  98. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/Service.java.j2 +0 -0
  99. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/ServiceImpl.java.j2 +0 -0
  100. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/application.properties.j2 +0 -0
  101. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/config/ApplicationConfig.java.j2 +0 -0
  102. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/config/JwtAuthenticationFilter.java.j2 +0 -0
  103. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/config/JwtService.java.j2 +0 -0
  104. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/config/SecurityConfig.java.j2 +0 -0
  105. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/docker-compose.yml.j2 +0 -0
  106. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/dto/Request.java.j2 +0 -0
  107. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/dto/Response.java.j2 +0 -0
  108. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/spring/templates/mapper/Mapper.java.j2 +0 -0
  109. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/svelte/__init__.py +0 -0
  110. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/svelte/generator.py +0 -0
  111. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/svelte/scaffolder.py +0 -0
  112. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/svelte/templates/resource/component.svelte.j2 +0 -0
  113. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/svelte/templates/resource/page.svelte.j2 +0 -0
  114. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/__init__.py +0 -0
  115. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/generator.py +0 -0
  116. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/scaffolder.py +0 -0
  117. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/templates/config/App.vue.j2 +0 -0
  118. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/templates/config/main.ts.j2 +0 -0
  119. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/templates/config/router.ts.j2 +0 -0
  120. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/templates/config/vite.config.ts.j2 +0 -0
  121. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/templates/feature/Form.vue.j2 +0 -0
  122. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/templates/feature/List.vue.j2 +0 -0
  123. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/templates/feature/models.ts.j2 +0 -0
  124. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/templates/feature/routes.ts.j2 +0 -0
  125. {devctl-1.2.3 → devctl-1.2.4}/devctl/generators/vue/templates/feature/service.ts.j2 +0 -0
  126. {devctl-1.2.3 → devctl-1.2.4}/devctl/main.py +0 -0
  127. {devctl-1.2.3 → devctl-1.2.4}/devctl/orchestrator/__init__.py +0 -0
  128. {devctl-1.2.3 → devctl-1.2.4}/devctl/orchestrator/config_builder.py +0 -0
  129. {devctl-1.2.3 → devctl-1.2.4}/devctl/orchestrator/process_manager.py +0 -0
  130. {devctl-1.2.3 → devctl-1.2.4}/devctl/orchestrator/runner.py +0 -0
  131. {devctl-1.2.3 → devctl-1.2.4}/devctl/orchestrator/scanner.py +0 -0
  132. {devctl-1.2.3 → devctl-1.2.4}/devctl/utils/__init__.py +0 -0
  133. {devctl-1.2.3 → devctl-1.2.4}/devctl/utils/dependencies.py +0 -0
  134. {devctl-1.2.3 → devctl-1.2.4}/devctl/utils/env_loader.py +0 -0
  135. {devctl-1.2.3 → devctl-1.2.4}/devctl/utils/platform.py +0 -0
  136. {devctl-1.2.3 → devctl-1.2.4}/devctl.egg-info/dependency_links.txt +0 -0
  137. {devctl-1.2.3 → devctl-1.2.4}/devctl.egg-info/entry_points.txt +0 -0
  138. {devctl-1.2.3 → devctl-1.2.4}/devctl.egg-info/requires.txt +0 -0
  139. {devctl-1.2.3 → devctl-1.2.4}/devctl.egg-info/top_level.txt +0 -0
  140. {devctl-1.2.3 → devctl-1.2.4}/setup.cfg +0 -0
  141. {devctl-1.2.3 → devctl-1.2.4}/test/test_add.py +0 -0
  142. {devctl-1.2.3 → devctl-1.2.4}/test/test_commands.py +0 -0
  143. {devctl-1.2.3 → devctl-1.2.4}/test/test_deploy.py +0 -0
  144. {devctl-1.2.3 → devctl-1.2.4}/test/test_env_loader.py +0 -0
  145. {devctl-1.2.3 → devctl-1.2.4}/test/test_main.py +0 -0
  146. {devctl-1.2.3 → devctl-1.2.4}/test/test_mongodb.py +0 -0
  147. {devctl-1.2.3 → devctl-1.2.4}/test/test_platform.py +0 -0
  148. {devctl-1.2.3 → devctl-1.2.4}/test/test_runner.py +0 -0
  149. {devctl-1.2.3 → devctl-1.2.4}/test/test_scanner.py +0 -0
  150. {devctl-1.2.3 → devctl-1.2.4}/test/test_tui.py +0 -0
  151. {devctl-1.2.3 → devctl-1.2.4}/test/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devctl
3
- Version: 1.2.3
3
+ Version: 1.2.4
4
4
  Summary: Local development orchestrator for Spring Boot, Angular, and Vue.js
5
5
  Author: Youssef Fellah
6
6
  License: MIT License
@@ -29,7 +29,7 @@ Classifier: Programming Language :: Python :: 3
29
29
  Classifier: License :: OSI Approved :: MIT License
30
30
  Classifier: Operating System :: OS Independent
31
31
  Classifier: Topic :: Software Development :: Build Tools
32
- Requires-Python: >=3.9
32
+ Requires-Python: >=3.10
33
33
  Description-Content-Type: text/markdown
34
34
  License-File: LICENSE
35
35
  Requires-Dist: typer>=0.12.3
@@ -64,6 +64,9 @@ containerization across Linux, macOS, and Windows.
64
64
  - **Interactive Dashboard**: Real-time system monitoring (CPU/RAM/Disk) and service orchestration with side-by-side log streaming (`devctl tui`).
65
65
  - **Security by Default**: Inject standardized JWT authentication and security
66
66
  configurations into new projects.
67
+ - **AI Agent Context Generation**: Automatically creates and updates `AGENTS.md`,
68
+ `CLAUDE.md`, and `.cursorrules` on project initialization, aligning coding agents
69
+ (Claude Code, Cursor, Copilot) with active ports, commands, and contract conventions.
67
70
 
68
71
  ## Interactive Dashboard (TUI)
69
72
 
@@ -153,5 +156,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
153
156
  for details.
154
157
 
155
158
  ---
156
- Authored by Youssef Fellah.
157
- Professional Development Orchestrator.
159
+
160
+ ## Author
161
+
162
+ - **Author:** Youssef Fellah ([ind4x_](https://github.com/ind4x))
@@ -21,6 +21,9 @@ containerization across Linux, macOS, and Windows.
21
21
  - **Interactive Dashboard**: Real-time system monitoring (CPU/RAM/Disk) and service orchestration with side-by-side log streaming (`devctl tui`).
22
22
  - **Security by Default**: Inject standardized JWT authentication and security
23
23
  configurations into new projects.
24
+ - **AI Agent Context Generation**: Automatically creates and updates `AGENTS.md`,
25
+ `CLAUDE.md`, and `.cursorrules` on project initialization, aligning coding agents
26
+ (Claude Code, Cursor, Copilot) with active ports, commands, and contract conventions.
24
27
 
25
28
  ## Interactive Dashboard (TUI)
26
29
 
@@ -110,5 +113,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
110
113
  for details.
111
114
 
112
115
  ---
113
- Authored by Youssef Fellah.
114
- Professional Development Orchestrator.
116
+
117
+ ## Author
118
+
119
+ - **Author:** Youssef Fellah ([ind4x_](https://github.com/ind4x))
@@ -6,6 +6,7 @@ Django, Svelte, and Go.
6
6
 
7
7
  import typer
8
8
 
9
+ from devctl.generators.agent import generate_agent_context
9
10
  from devctl.generators.angular import generate_angular_boilerplate
10
11
  from devctl.generators.django import generate_django_boilerplate
11
12
  from devctl.generators.fastapi import generate_fastapi_boilerplate
@@ -46,6 +47,7 @@ def init_spring(
46
47
 
47
48
  if success_download:
48
49
  generate_config(name, db_type=db, custom_port=port)
50
+ generate_agent_context()
49
51
  typer.secho("\nSpring project ready!", fg=typer.colors.GREEN)
50
52
 
51
53
 
@@ -61,6 +63,7 @@ def init_angular(name: str):
61
63
  success = generate_angular_boilerplate(name)
62
64
 
63
65
  if success:
66
+ generate_agent_context()
64
67
  typer.secho("\nAngular project ready!", fg=typer.colors.GREEN)
65
68
 
66
69
 
@@ -75,6 +78,7 @@ def init_vue(name: str):
75
78
  success = generate_vue_boilerplate(name)
76
79
 
77
80
  if success:
81
+ generate_agent_context()
78
82
  typer.secho("\nVue.js project ready!", fg=typer.colors.GREEN)
79
83
 
80
84
 
@@ -89,6 +93,7 @@ def init_nest(name: str):
89
93
  success = generate_nest_boilerplate(name)
90
94
 
91
95
  if success:
96
+ generate_agent_context()
92
97
  typer.secho("\nNestJS project ready!", fg=typer.colors.GREEN)
93
98
 
94
99
 
@@ -103,6 +108,7 @@ def init_nodejs(name: str):
103
108
  success = generate_nodejs_boilerplate(name)
104
109
 
105
110
  if success:
111
+ generate_agent_context()
106
112
  typer.secho("\nNodeJS project ready!", fg=typer.colors.GREEN)
107
113
 
108
114
 
@@ -117,6 +123,7 @@ def init_react(name: str):
117
123
  success = generate_react_boilerplate(name)
118
124
 
119
125
  if success:
126
+ generate_agent_context()
120
127
  typer.secho("\nReactJS project ready!", fg=typer.colors.GREEN)
121
128
 
122
129
 
@@ -131,6 +138,7 @@ def init_nextjs(name: str):
131
138
  success = generate_nextjs_boilerplate(name)
132
139
 
133
140
  if success:
141
+ generate_agent_context()
134
142
  typer.secho("\nNextJS project ready!", fg=typer.colors.GREEN)
135
143
 
136
144
 
@@ -145,6 +153,7 @@ def init_fastapi(name: str):
145
153
  success = generate_fastapi_boilerplate(name)
146
154
 
147
155
  if success:
156
+ generate_agent_context()
148
157
  typer.secho("\nFastAPI project ready!", fg=typer.colors.GREEN)
149
158
 
150
159
 
@@ -159,6 +168,7 @@ def init_django(name: str):
159
168
  success = generate_django_boilerplate(name)
160
169
 
161
170
  if success:
171
+ generate_agent_context()
162
172
  typer.secho("\nDjango project ready!", fg=typer.colors.GREEN)
163
173
 
164
174
 
@@ -173,6 +183,7 @@ def init_svelte(name: str):
173
183
  success = generate_svelte_boilerplate(name)
174
184
 
175
185
  if success:
186
+ generate_agent_context()
176
187
  typer.secho("\nSvelte project ready!", fg=typer.colors.GREEN)
177
188
 
178
189
 
@@ -187,4 +198,18 @@ def init_go(name: str):
187
198
  success = generate_go_boilerplate(name)
188
199
 
189
200
  if success:
201
+ generate_agent_context()
190
202
  typer.secho("\nGo project ready!", fg=typer.colors.GREEN)
203
+
204
+
205
+ @app.command("agent")
206
+ def init_agent():
207
+ """
208
+ Generates or refreshes AGENTS.md, CLAUDE.md, and .cursorrules for the current project.
209
+ """
210
+ success = generate_agent_context()
211
+ if success:
212
+ typer.secho("\nAgent context ready!", fg=typer.colors.GREEN)
213
+ else:
214
+ typer.secho("\nFailed to generate agent context.", fg=typer.colors.RED)
215
+ raise typer.Exit(code=1)
@@ -0,0 +1,7 @@
1
+ """
2
+ Agent context generator package.
3
+ """
4
+
5
+ from devctl.generators.agent.generator import generate_agent_context
6
+
7
+ __all__ = ["generate_agent_context"]
@@ -0,0 +1,269 @@
1
+ """
2
+ Agent context generator.
3
+ Produces AGENTS.md, CLAUDE.md, and .cursorrules for AI coding assistants.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import os
9
+ import re
10
+ from pathlib import Path
11
+ from typing import Any, Dict, List, Union
12
+
13
+ import typer
14
+ import yaml
15
+ from jinja2 import Environment, FileSystemLoader
16
+
17
+ from devctl.generators.docker.scaffolder import IGNORED_DIRECTORIES, discover_docker_projects
18
+
19
+ FRAMEWORK_METADATA: Dict[str, Dict[str, Any]] = {
20
+ "spring": {
21
+ "framework": "Spring Boot",
22
+ "category": "backend",
23
+ "default_port": 8080,
24
+ "run_cmd": "./mvnw spring-boot:run",
25
+ "test_cmd": "./mvnw test",
26
+ },
27
+ "fastapi": {
28
+ "framework": "FastAPI",
29
+ "category": "backend",
30
+ "default_port": 8000,
31
+ "run_cmd": "uvicorn main:app --reload",
32
+ "test_cmd": "pytest",
33
+ },
34
+ "django": {
35
+ "framework": "Django",
36
+ "category": "backend",
37
+ "default_port": 8000,
38
+ "run_cmd": "python manage.py runserver",
39
+ "test_cmd": "python manage.py test",
40
+ },
41
+ "nest": {
42
+ "framework": "NestJS",
43
+ "category": "backend",
44
+ "default_port": 3000,
45
+ "run_cmd": "npm run start:dev",
46
+ "test_cmd": "npm test",
47
+ },
48
+ "nodejs": {
49
+ "framework": "NodeJS / Express",
50
+ "category": "backend",
51
+ "default_port": 3000,
52
+ "run_cmd": "npm run dev",
53
+ "test_cmd": "npm test",
54
+ },
55
+ "go": {
56
+ "framework": "Go (Fiber)",
57
+ "category": "backend",
58
+ "default_port": 3000,
59
+ "run_cmd": "go run .",
60
+ "test_cmd": "go test ./...",
61
+ },
62
+ "angular": {
63
+ "framework": "Angular",
64
+ "category": "frontend",
65
+ "default_port": 4200,
66
+ "run_cmd": "npx ng serve",
67
+ "test_cmd": "npm test",
68
+ },
69
+ "vue": {
70
+ "framework": "Vue 3",
71
+ "category": "frontend",
72
+ "default_port": 5173,
73
+ "run_cmd": "npm run dev",
74
+ "test_cmd": "npm test",
75
+ },
76
+ "react": {
77
+ "framework": "React",
78
+ "category": "frontend",
79
+ "default_port": 5173,
80
+ "run_cmd": "npm run dev",
81
+ "test_cmd": "npm test",
82
+ },
83
+ "nextjs": {
84
+ "framework": "Next.js",
85
+ "category": "frontend",
86
+ "default_port": 3000,
87
+ "run_cmd": "npm run dev",
88
+ "test_cmd": "npm test",
89
+ },
90
+ "svelte": {
91
+ "framework": "Svelte",
92
+ "category": "frontend",
93
+ "default_port": 5173,
94
+ "run_cmd": "npm run dev",
95
+ "test_cmd": "npm test",
96
+ },
97
+ }
98
+
99
+
100
+ def _detect_service_port(project_path: Path, kind: str, default_port: int) -> int:
101
+ """Extract configured service port or fallback to default."""
102
+ if kind == "spring":
103
+ props_path = project_path / "src" / "main" / "resources" / "application.properties"
104
+ if props_path.exists():
105
+ try:
106
+ content = props_path.read_text(encoding="utf-8")
107
+ match = re.search(r"^server\.port\s*=\s*(\d+)", content, re.MULTILINE)
108
+ if match:
109
+ return int(match.group(1))
110
+ except Exception:
111
+ pass
112
+ return default_port
113
+
114
+
115
+ def _discover_databases(root: Path) -> List[Dict[str, Any]]:
116
+ """Scan for docker-compose-db.yml files and extract service configuration."""
117
+ databases: List[Dict[str, Any]] = []
118
+
119
+ for dirpath, dirnames, filenames in os.walk(root):
120
+ dirnames[:] = [d for d in dirnames if d not in IGNORED_DIRECTORIES]
121
+ if "docker-compose-db.yml" in filenames:
122
+ compose_path = Path(dirpath) / "docker-compose-db.yml"
123
+ try:
124
+ content = yaml.safe_load(compose_path.read_text(encoding="utf-8")) or {}
125
+ services = content.get("services", {})
126
+ for s_name, s_conf in services.items():
127
+ image = str(s_conf.get("image", "unknown"))
128
+ ports = s_conf.get("ports", [])
129
+ host_port = "unknown"
130
+ if ports:
131
+ raw_port = str(ports[0])
132
+ host_port = raw_port.split(":")[0] if ":" in raw_port else raw_port
133
+
134
+ env_vars = s_conf.get("environment", {})
135
+ if isinstance(env_vars, list):
136
+ parsed_env = {}
137
+ for item in env_vars:
138
+ if isinstance(item, str) and "=" in item:
139
+ k, v = item.split("=", 1)
140
+ parsed_env[k.strip()] = v.strip()
141
+ env_vars = parsed_env
142
+
143
+ db_user = (
144
+ env_vars.get("POSTGRES_USER")
145
+ or env_vars.get("MYSQL_USER")
146
+ or env_vars.get("MONGO_INITDB_ROOT_USERNAME")
147
+ or "admin"
148
+ )
149
+ db_password = (
150
+ env_vars.get("POSTGRES_PASSWORD")
151
+ or env_vars.get("MYSQL_PASSWORD")
152
+ or env_vars.get("MONGO_INITDB_ROOT_PASSWORD")
153
+ or "password"
154
+ )
155
+ db_name = (
156
+ env_vars.get("POSTGRES_DB")
157
+ or env_vars.get("MYSQL_DATABASE")
158
+ or env_vars.get("MONGO_INITDB_DATABASE")
159
+ or "default_db"
160
+ )
161
+
162
+ image_lower = image.lower()
163
+ if "postgres" in image_lower:
164
+ db_type = "PostgreSQL"
165
+ elif "mysql" in image_lower:
166
+ db_type = "MySQL"
167
+ elif "mongo" in image_lower:
168
+ db_type = "MongoDB"
169
+ else:
170
+ db_type = "Database"
171
+
172
+ rel_compose = compose_path.relative_to(root).as_posix()
173
+ databases.append(
174
+ {
175
+ "service_name": s_name,
176
+ "db_type": db_type,
177
+ "image": image,
178
+ "port": host_port,
179
+ "db_name": db_name,
180
+ "db_user": db_user,
181
+ "db_password": db_password,
182
+ "compose_file": f"./{rel_compose}",
183
+ }
184
+ )
185
+ except Exception:
186
+ pass
187
+
188
+ return databases
189
+
190
+
191
+ def generate_agent_context(root_path: Union[str, Path] = ".") -> bool:
192
+ """
193
+ Scans the repository and generates AGENTS.md, CLAUDE.md, and .cursorrules.
194
+ """
195
+ root = Path(root_path).resolve()
196
+ if not root.exists() or not root.is_dir():
197
+ return False
198
+
199
+ try:
200
+ discovered = discover_docker_projects(root)
201
+ except Exception:
202
+ discovered = []
203
+
204
+ services: List[Dict[str, Any]] = []
205
+ backends: List[Dict[str, Any]] = []
206
+ frontends: List[Dict[str, Any]] = []
207
+
208
+ for p in discovered:
209
+ meta = FRAMEWORK_METADATA.get(
210
+ p.kind,
211
+ {
212
+ "framework": p.kind.capitalize(),
213
+ "category": "backend",
214
+ "default_port": 8080,
215
+ "run_cmd": "devctl run",
216
+ "test_cmd": "npm test",
217
+ },
218
+ )
219
+ port = _detect_service_port(p.path, p.kind, meta["default_port"])
220
+ try:
221
+ rel_path = f"./{p.path.relative_to(root).as_posix()}"
222
+ except ValueError:
223
+ rel_path = f"./{p.name}"
224
+
225
+ service_data = {
226
+ "name": p.name,
227
+ "kind": p.kind,
228
+ "framework": meta["framework"],
229
+ "category": meta["category"],
230
+ "relative_path": rel_path,
231
+ "port": port,
232
+ "run_cmd": meta["run_cmd"],
233
+ "test_cmd": meta["test_cmd"],
234
+ }
235
+ services.append(service_data)
236
+ if meta["category"] == "backend":
237
+ backends.append(service_data)
238
+ else:
239
+ frontends.append(service_data)
240
+
241
+ databases = _discover_databases(root)
242
+
243
+ template_dir = Path(__file__).parent / "templates"
244
+ env = Environment(loader=FileSystemLoader(str(template_dir)), autoescape=False)
245
+
246
+ context = {
247
+ "services": services,
248
+ "backends": backends,
249
+ "frontends": frontends,
250
+ "databases": databases,
251
+ }
252
+
253
+ try:
254
+ agents_tpl = env.get_template("AGENTS.md.j2")
255
+ claude_tpl = env.get_template("CLAUDE.md.j2")
256
+ cursor_tpl = env.get_template(".cursorrules.j2")
257
+
258
+ (root / "AGENTS.md").write_text(agents_tpl.render(context), encoding="utf-8")
259
+ (root / "CLAUDE.md").write_text(claude_tpl.render(context), encoding="utf-8")
260
+ (root / ".cursorrules").write_text(cursor_tpl.render(context), encoding="utf-8")
261
+
262
+ typer.secho(
263
+ "Agent context generated (AGENTS.md, CLAUDE.md, .cursorrules).",
264
+ fg=typer.colors.CYAN,
265
+ )
266
+ return True
267
+ except Exception as e:
268
+ typer.secho(f"Warning: Failed to generate agent context: {e}", fg=typer.colors.YELLOW)
269
+ return False
@@ -0,0 +1,87 @@
1
+ # Project Development Guide for AI Agents
2
+
3
+ > This project is orchestrated using `devctl`. All commands, multi-tier processes,
4
+ > and scaffolding workflows must adhere to the boundaries documented below.
5
+
6
+ ## 1. Project Architecture & Active Topology
7
+ {% if backends %}
8
+ ### Backend Services
9
+ {% for b in backends %}
10
+ - **{{ b.name }}** ({{ b.framework }})
11
+ - Path: `{{ b.relative_path }}`
12
+ - Local Port: `{{ b.port }}`
13
+ - Run Command: `{{ b.run_cmd }}`
14
+ - Test Suite: `{{ b.test_cmd }}`
15
+ {% endfor %}
16
+ {% endif %}
17
+ {% if frontends %}
18
+ ### Frontend Services
19
+ {% for f in frontends %}
20
+ - **{{ f.name }}** ({{ f.framework }})
21
+ - Path: `{{ f.relative_path }}`
22
+ - Local Dev Port: `{{ f.port }}`
23
+ - Run Command: `{{ f.run_cmd }}`
24
+ - Test Suite: `{{ f.test_cmd }}`
25
+ {% endfor %}
26
+ {% endif %}
27
+ {% if databases %}
28
+ ### Databases & Infrastructure
29
+ {% for db in databases %}
30
+ - **Service**: `{{ db.service_name }}`
31
+ - Type: `{{ db.db_type }}`
32
+ - Image: `{{ db.image }}`
33
+ - Host Port: `{{ db.port }}`
34
+ - Database Name: `{{ db.db_name }}`
35
+ - Credentials: User=`{{ db.db_user }}`, Password=`{{ db.db_password }}`
36
+ - Compose File: `{{ db.compose_file }}`
37
+ {% endfor %}
38
+ {% endif %}
39
+ {% if not backends and not frontends and not databases %}
40
+ - Topology: No active microservices detected yet. Run `devctl init <framework> <name>` to add services.
41
+ {% endif %}
42
+
43
+ ## 2. Devctl Orchestration & Lifecycle Commands
44
+
45
+ Always use `devctl` to orchestrate services. Do NOT start background daemons, manually detached docker processes, or raw ad-hoc runners unless debugging an isolated failure.
46
+
47
+ - **Start entire stack** (Databases + Backends + Frontends in parallel with unified log streaming):
48
+ ```bash
49
+ devctl run
50
+ ```
51
+ - **Interactive TUI Dashboard** (System metrics, real-time log inspection, process management):
52
+ ```bash
53
+ devctl tui
54
+ ```
55
+ - **Vertical Full-Stack Scaffolding** (Generates Entity, DTOs, Repository, Service, Controller, and Frontend client):
56
+ ```bash
57
+ devctl add resource <ResourceName> -f "<field1>:<type>,<field2>:<type>"
58
+ ```
59
+ - **Containerization & Deployment Scaffolding**:
60
+ ```bash
61
+ devctl docker scaffold
62
+ devctl docker generate
63
+ ```
64
+
65
+ ## 3. Full-Stack Contract & Coding Conventions
66
+
67
+ When adding or modifying API endpoints or data models:
68
+ - **API Endpoints**: Use standard RESTful patterns with `/api/v1` prefixes.
69
+ - **DTOs / Contracts**:
70
+ - Request payloads must be modeled with `<Entity>Request` DTOs.
71
+ - Response payloads must be modeled with `<Entity>Response` DTOs.
72
+ - **Type Compatibility**:
73
+ - Backend numeric IDs / Long / Integer -> Frontend TypeScript `number`
74
+ - Backend UUID / String -> Frontend TypeScript `string`
75
+ - Backend Instant / LocalDateTime / DateTime -> Frontend TypeScript `string` (ISO 8601 formatted)
76
+ - Backend Boolean -> Frontend TypeScript `boolean`
77
+ - **Synchronization**: Any change to backend DTO fields or endpoints MUST be immediately reflected in the corresponding frontend API client, models, and interfaces.
78
+
79
+ ## 4. Agent Operational Guardrails
80
+
81
+ - **Process Management**: Do NOT run detached background processes (`nohup`, `&`, `screen`, `tmux`) that outlive the session. Use `devctl run` for execution.
82
+ - **Testing Before Completion**: Always run the respective test suite for modified services before concluding any task:
83
+ {% for s in services %}
84
+ - `{{ s.name }}`: `{{ s.test_cmd }}`
85
+ {% endfor %}
86
+ - **Docker Compose Boundaries**: Do NOT alter database port mappings in `docker-compose-db.yml` without updating application configuration files in lockstep.
87
+ - **Dependency Checks**: Ensure required tools are available using `devctl` verification conventions before executing framework-specific build scripts.
@@ -0,0 +1,8 @@
1
+ # Claude Code Guidelines
2
+
3
+ This project is managed and orchestrated by `devctl`.
4
+
5
+ - Review [AGENTS.md](AGENTS.md) for complete architecture topology, active services, port allocations, and devctl lifecycle commands.
6
+ - Use `devctl run` to boot services and `devctl add resource` for full-stack CRUD scaffolding.
7
+ - Ensure backend DTOs and frontend TypeScript interfaces remain strictly synchronized.
8
+ - Execute unit and integration tests before finishing tasks.
@@ -55,6 +55,7 @@ from devctl.commands.init import (
55
55
  generate_svelte_boilerplate,
56
56
  generate_vue_boilerplate,
57
57
  )
58
+ from devctl.generators.agent import generate_agent_context
58
59
  from devctl.generators.docker import discover_docker_projects, scaffold_docker_assets
59
60
  from devctl.orchestrator.config_builder import generate_config
60
61
  from devctl.orchestrator.process_manager import ProcessManager
@@ -789,6 +790,7 @@ class DevctlTUI(App):
789
790
  generate_go_boilerplate(name)
790
791
  else:
791
792
  print(f"Error: Unknown framework boilerplate '{framework}'")
793
+ generate_agent_context(".")
792
794
  print("\nProject initialized successfully!")
793
795
  except Exception as e:
794
796
  print(f"Error during initialization: {e}", file=f)