kastell 2.2.0 → 2.2.2

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 (292) hide show
  1. package/.claude-plugin/marketplace.json +18 -0
  2. package/.claude-plugin/plugin.json +39 -0
  3. package/CHANGELOG.md +1266 -1266
  4. package/LICENSE +201 -201
  5. package/NOTICE +5 -5
  6. package/bin/kastell +2 -2
  7. package/bin/kastell-mcp +5 -5
  8. package/dist/adapters/coolify.js +92 -92
  9. package/dist/adapters/dokploy.js +99 -99
  10. package/dist/adapters/shared.d.ts.map +1 -1
  11. package/dist/adapters/shared.js +4 -2
  12. package/dist/adapters/shared.js.map +1 -1
  13. package/dist/commands/add.d.ts.map +1 -1
  14. package/dist/commands/add.js +6 -9
  15. package/dist/commands/add.js.map +1 -1
  16. package/dist/commands/auth.d.ts.map +1 -1
  17. package/dist/commands/auth.js +12 -12
  18. package/dist/commands/auth.js.map +1 -1
  19. package/dist/commands/doctor.js +1 -1
  20. package/dist/commands/doctor.js.map +1 -1
  21. package/dist/commands/evidence.d.ts.map +1 -1
  22. package/dist/commands/evidence.js +8 -9
  23. package/dist/commands/evidence.js.map +1 -1
  24. package/dist/commands/fix.js +3 -3
  25. package/dist/commands/fix.js.map +1 -1
  26. package/dist/commands/init.d.ts.map +1 -1
  27. package/dist/commands/init.js +4 -7
  28. package/dist/commands/init.js.map +1 -1
  29. package/dist/commands/interactive/backup-maintenance.d.ts +8 -0
  30. package/dist/commands/interactive/backup-maintenance.d.ts.map +1 -0
  31. package/dist/commands/interactive/backup-maintenance.js +120 -0
  32. package/dist/commands/interactive/backup-maintenance.js.map +1 -0
  33. package/dist/commands/interactive/index.d.ts +4 -0
  34. package/dist/commands/interactive/index.d.ts.map +1 -0
  35. package/dist/commands/interactive/index.js +94 -0
  36. package/dist/commands/interactive/index.js.map +1 -0
  37. package/dist/commands/interactive/menu.d.ts +23 -0
  38. package/dist/commands/interactive/menu.d.ts.map +1 -0
  39. package/dist/commands/interactive/menu.js +121 -0
  40. package/dist/commands/interactive/menu.js.map +1 -0
  41. package/dist/commands/interactive/monitoring.d.ts +5 -0
  42. package/dist/commands/interactive/monitoring.d.ts.map +1 -0
  43. package/dist/commands/interactive/monitoring.js +96 -0
  44. package/dist/commands/interactive/monitoring.js.map +1 -0
  45. package/dist/commands/interactive/plugins.d.ts +2 -0
  46. package/dist/commands/interactive/plugins.d.ts.map +1 -0
  47. package/dist/commands/interactive/plugins.js +30 -0
  48. package/dist/commands/interactive/plugins.js.map +1 -0
  49. package/dist/commands/interactive/security.d.ts +9 -0
  50. package/dist/commands/interactive/security.d.ts.map +1 -0
  51. package/dist/commands/interactive/security.js +535 -0
  52. package/dist/commands/interactive/security.js.map +1 -0
  53. package/dist/commands/interactive/server-management.d.ts +5 -0
  54. package/dist/commands/interactive/server-management.d.ts.map +1 -0
  55. package/dist/commands/interactive/server-management.js +79 -0
  56. package/dist/commands/interactive/server-management.js.map +1 -0
  57. package/dist/commands/interactive/shared.d.ts +12 -0
  58. package/dist/commands/interactive/shared.d.ts.map +1 -0
  59. package/dist/commands/interactive/shared.js +30 -0
  60. package/dist/commands/interactive/shared.js.map +1 -0
  61. package/dist/commands/lock.js +1 -1
  62. package/dist/commands/lock.js.map +1 -1
  63. package/dist/commands/regression.d.ts.map +1 -1
  64. package/dist/commands/regression.js +1 -2
  65. package/dist/commands/regression.js.map +1 -1
  66. package/dist/commands/restart.d.ts.map +1 -1
  67. package/dist/commands/restart.js +3 -2
  68. package/dist/commands/restart.js.map +1 -1
  69. package/dist/commands/schedule.js +2 -2
  70. package/dist/commands/schedule.js.map +1 -1
  71. package/dist/core/audit/formatters/badge.js +20 -20
  72. package/dist/core/backup.d.ts.map +1 -1
  73. package/dist/core/backup.js +10 -5
  74. package/dist/core/backup.js.map +1 -1
  75. package/dist/core/completions.js +631 -631
  76. package/dist/core/deploy.d.ts.map +1 -1
  77. package/dist/core/deploy.js +7 -4
  78. package/dist/core/deploy.js.map +1 -1
  79. package/dist/core/lock/auth.d.ts +7 -0
  80. package/dist/core/lock/auth.d.ts.map +1 -0
  81. package/dist/core/lock/auth.js +59 -0
  82. package/dist/core/lock/auth.js.map +1 -0
  83. package/dist/core/lock/docker.d.ts +4 -0
  84. package/dist/core/lock/docker.d.ts.map +1 -0
  85. package/dist/core/lock/docker.js +28 -0
  86. package/dist/core/lock/docker.js.map +1 -0
  87. package/dist/core/lock/index.d.ts +11 -0
  88. package/dist/core/lock/index.d.ts.map +1 -0
  89. package/dist/core/lock/index.js +247 -0
  90. package/dist/core/lock/index.js.map +1 -0
  91. package/dist/core/lock/monitoring.d.ts +4 -0
  92. package/dist/core/lock/monitoring.d.ts.map +1 -0
  93. package/dist/core/lock/monitoring.js +55 -0
  94. package/dist/core/lock/monitoring.js.map +1 -0
  95. package/dist/core/lock/network.d.ts +6 -0
  96. package/dist/core/lock/network.d.ts.map +1 -0
  97. package/dist/core/lock/network.js +59 -0
  98. package/dist/core/lock/network.js.map +1 -0
  99. package/dist/core/lock/ssh.d.ts +5 -0
  100. package/dist/core/lock/ssh.d.ts.map +1 -0
  101. package/dist/core/lock/ssh.js +49 -0
  102. package/dist/core/lock/ssh.js.map +1 -0
  103. package/dist/core/lock/system.d.ts +9 -0
  104. package/dist/core/lock/system.d.ts.map +1 -0
  105. package/dist/core/lock/system.js +80 -0
  106. package/dist/core/lock/system.js.map +1 -0
  107. package/dist/core/lock/types.d.ts +41 -0
  108. package/dist/core/lock/types.d.ts.map +1 -0
  109. package/dist/core/lock/types.js +2 -0
  110. package/dist/core/lock/types.js.map +1 -0
  111. package/dist/core/maintain.d.ts.map +1 -1
  112. package/dist/core/maintain.js +3 -1
  113. package/dist/core/maintain.js.map +1 -1
  114. package/dist/core/manage.d.ts.map +1 -1
  115. package/dist/core/manage.js +5 -3
  116. package/dist/core/manage.js.map +1 -1
  117. package/dist/core/notifyStore.d.ts.map +1 -1
  118. package/dist/core/notifyStore.js +3 -1
  119. package/dist/core/notifyStore.js.map +1 -1
  120. package/dist/core/provision.d.ts.map +1 -1
  121. package/dist/core/provision.js +9 -4
  122. package/dist/core/provision.js.map +1 -1
  123. package/dist/core/scheduleManager.d.ts.map +1 -1
  124. package/dist/core/scheduleManager.js +5 -2
  125. package/dist/core/scheduleManager.js.map +1 -1
  126. package/dist/index.js +1 -1
  127. package/dist/index.js.map +1 -1
  128. package/dist/mcp/schemas/audit.d.ts +34 -0
  129. package/dist/mcp/schemas/audit.d.ts.map +1 -0
  130. package/dist/mcp/schemas/audit.js +23 -0
  131. package/dist/mcp/schemas/audit.js.map +1 -0
  132. package/dist/mcp/schemas/common.d.ts +16 -0
  133. package/dist/mcp/schemas/common.d.ts.map +1 -0
  134. package/dist/mcp/schemas/common.js +14 -0
  135. package/dist/mcp/schemas/common.js.map +1 -0
  136. package/dist/mcp/schemas/health.d.ts +14 -0
  137. package/dist/mcp/schemas/health.d.ts.map +1 -0
  138. package/dist/mcp/schemas/health.js +13 -0
  139. package/dist/mcp/schemas/health.js.map +1 -0
  140. package/dist/mcp/schemas/index.d.ts +5 -0
  141. package/dist/mcp/schemas/index.d.ts.map +1 -0
  142. package/dist/mcp/schemas/index.js +5 -0
  143. package/dist/mcp/schemas/index.js.map +1 -0
  144. package/dist/mcp/schemas/server.d.ts +18 -0
  145. package/dist/mcp/schemas/server.d.ts.map +1 -0
  146. package/dist/mcp/schemas/server.js +16 -0
  147. package/dist/mcp/schemas/server.js.map +1 -0
  148. package/dist/mcp/server.d.ts.map +1 -1
  149. package/dist/mcp/server.js +56 -39
  150. package/dist/mcp/server.js.map +1 -1
  151. package/dist/mcp/tools/serverAudit.d.ts +63 -1
  152. package/dist/mcp/tools/serverAudit.d.ts.map +1 -1
  153. package/dist/mcp/tools/serverAudit.js +63 -6
  154. package/dist/mcp/tools/serverAudit.js.map +1 -1
  155. package/dist/mcp/tools/serverBackup.d.ts +100 -2
  156. package/dist/mcp/tools/serverBackup.d.ts.map +1 -1
  157. package/dist/mcp/tools/serverBackup.handlers.d.ts.map +1 -1
  158. package/dist/mcp/tools/serverBackup.handlers.js +9 -0
  159. package/dist/mcp/tools/serverBackup.handlers.js.map +1 -1
  160. package/dist/mcp/tools/serverBackup.js +74 -0
  161. package/dist/mcp/tools/serverBackup.js.map +1 -1
  162. package/dist/mcp/tools/serverCompare.d.ts +33 -0
  163. package/dist/mcp/tools/serverCompare.d.ts.map +1 -1
  164. package/dist/mcp/tools/serverCompare.js +45 -2
  165. package/dist/mcp/tools/serverCompare.js.map +1 -1
  166. package/dist/mcp/tools/serverDoctor.d.ts +14 -0
  167. package/dist/mcp/tools/serverDoctor.d.ts.map +1 -1
  168. package/dist/mcp/tools/serverDoctor.js +15 -0
  169. package/dist/mcp/tools/serverDoctor.js.map +1 -1
  170. package/dist/mcp/tools/serverEvidence.d.ts +13 -0
  171. package/dist/mcp/tools/serverEvidence.d.ts.map +1 -1
  172. package/dist/mcp/tools/serverEvidence.js +17 -2
  173. package/dist/mcp/tools/serverEvidence.js.map +1 -1
  174. package/dist/mcp/tools/serverExplain.d.ts +17 -0
  175. package/dist/mcp/tools/serverExplain.d.ts.map +1 -1
  176. package/dist/mcp/tools/serverExplain.js +33 -1
  177. package/dist/mcp/tools/serverExplain.js.map +1 -1
  178. package/dist/mcp/tools/serverFix.d.ts +78 -0
  179. package/dist/mcp/tools/serverFix.d.ts.map +1 -1
  180. package/dist/mcp/tools/serverFix.js +84 -0
  181. package/dist/mcp/tools/serverFix.js.map +1 -1
  182. package/dist/mcp/tools/serverFleet.d.ts +24 -1
  183. package/dist/mcp/tools/serverFleet.d.ts.map +1 -1
  184. package/dist/mcp/tools/serverFleet.js +24 -1
  185. package/dist/mcp/tools/serverFleet.js.map +1 -1
  186. package/dist/mcp/tools/serverGuard.d.ts +12 -0
  187. package/dist/mcp/tools/serverGuard.d.ts.map +1 -1
  188. package/dist/mcp/tools/serverGuard.js +16 -0
  189. package/dist/mcp/tools/serverGuard.js.map +1 -1
  190. package/dist/mcp/tools/serverInfo.d.ts +77 -1
  191. package/dist/mcp/tools/serverInfo.d.ts.map +1 -1
  192. package/dist/mcp/tools/serverInfo.js +77 -4
  193. package/dist/mcp/tools/serverInfo.js.map +1 -1
  194. package/dist/mcp/tools/serverLock.d.ts +10 -0
  195. package/dist/mcp/tools/serverLock.d.ts.map +1 -1
  196. package/dist/mcp/tools/serverLock.js +15 -3
  197. package/dist/mcp/tools/serverLock.js.map +1 -1
  198. package/dist/mcp/tools/serverLogs.d.ts +43 -0
  199. package/dist/mcp/tools/serverLogs.d.ts.map +1 -1
  200. package/dist/mcp/tools/serverLogs.js +28 -0
  201. package/dist/mcp/tools/serverLogs.js.map +1 -1
  202. package/dist/mcp/tools/serverMaintain.d.ts +47 -0
  203. package/dist/mcp/tools/serverMaintain.d.ts.map +1 -1
  204. package/dist/mcp/tools/serverMaintain.js +75 -41
  205. package/dist/mcp/tools/serverMaintain.js.map +1 -1
  206. package/dist/mcp/tools/serverManage.d.ts +50 -0
  207. package/dist/mcp/tools/serverManage.d.ts.map +1 -1
  208. package/dist/mcp/tools/serverManage.js +49 -0
  209. package/dist/mcp/tools/serverManage.js.map +1 -1
  210. package/dist/mcp/tools/serverPlugin.d.ts +18 -0
  211. package/dist/mcp/tools/serverPlugin.d.ts.map +1 -1
  212. package/dist/mcp/tools/serverPlugin.js +26 -1
  213. package/dist/mcp/tools/serverPlugin.js.map +1 -1
  214. package/dist/mcp/tools/serverProvision.d.ts +22 -0
  215. package/dist/mcp/tools/serverProvision.d.ts.map +1 -1
  216. package/dist/mcp/tools/serverProvision.js +22 -2
  217. package/dist/mcp/tools/serverProvision.js.map +1 -1
  218. package/dist/mcp/tools/serverSecure.d.ts +120 -0
  219. package/dist/mcp/tools/serverSecure.d.ts.map +1 -1
  220. package/dist/mcp/tools/serverSecure.handlers.d.ts.map +1 -1
  221. package/dist/mcp/tools/serverSecure.handlers.js +39 -98
  222. package/dist/mcp/tools/serverSecure.handlers.js.map +1 -1
  223. package/dist/mcp/tools/serverSecure.js +101 -0
  224. package/dist/mcp/tools/serverSecure.js.map +1 -1
  225. package/dist/mcp/utils.d.ts +1 -0
  226. package/dist/mcp/utils.d.ts.map +1 -1
  227. package/dist/mcp/utils.js +5 -1
  228. package/dist/mcp/utils.js.map +1 -1
  229. package/dist/plugin/registry.d.ts.map +1 -1
  230. package/dist/plugin/registry.js +5 -3
  231. package/dist/plugin/registry.js.map +1 -1
  232. package/dist/providers/linode.d.ts +1 -0
  233. package/dist/providers/linode.d.ts.map +1 -1
  234. package/dist/providers/linode.js +4 -0
  235. package/dist/providers/linode.js.map +1 -1
  236. package/dist/utils/cloudInit.js +58 -58
  237. package/dist/utils/config.d.ts +3 -0
  238. package/dist/utils/config.d.ts.map +1 -1
  239. package/dist/utils/config.js +11 -6
  240. package/dist/utils/config.js.map +1 -1
  241. package/dist/utils/encryption.d.ts.map +1 -1
  242. package/dist/utils/encryption.js +4 -1
  243. package/dist/utils/encryption.js.map +1 -1
  244. package/dist/utils/migration.d.ts.map +1 -1
  245. package/dist/utils/migration.js +25 -14
  246. package/dist/utils/migration.js.map +1 -1
  247. package/dist/utils/safeMode.d.ts.map +1 -1
  248. package/dist/utils/safeMode.js +3 -2
  249. package/dist/utils/safeMode.js.map +1 -1
  250. package/dist/utils/securityLogger.d.ts.map +1 -1
  251. package/dist/utils/securityLogger.js +7 -3
  252. package/dist/utils/securityLogger.js.map +1 -1
  253. package/kastell-plugin/.claude-plugin/plugin.json +20 -0
  254. package/kastell-plugin/.mcp.json +8 -0
  255. package/kastell-plugin/README.md +113 -0
  256. package/kastell-plugin/agents/.gitkeep +0 -0
  257. package/kastell-plugin/agents/kastell-auditor.md +77 -0
  258. package/kastell-plugin/agents/scripts/bucket_mapper.sh +101 -0
  259. package/kastell-plugin/agents/scripts/trend_report.sh +91 -0
  260. package/kastell-plugin/hooks/destroy-block.cjs +31 -0
  261. package/kastell-plugin/hooks/hooks.json +57 -0
  262. package/kastell-plugin/hooks/pre-commit-audit-guard.cjs +75 -0
  263. package/kastell-plugin/hooks/session-audit.cjs +86 -0
  264. package/kastell-plugin/hooks/session-log.cjs +56 -0
  265. package/kastell-plugin/hooks/stop-quality-check.cjs +72 -0
  266. package/kastell-plugin/skills/.gitkeep +0 -0
  267. package/kastell-plugin/skills/kastell-careful/SKILL.md +64 -0
  268. package/kastell-plugin/skills/kastell-ops/SKILL.md +139 -0
  269. package/kastell-plugin/skills/kastell-ops/references/commands.md +45 -0
  270. package/kastell-plugin/skills/kastell-ops/references/mcp-tools.md +50 -0
  271. package/kastell-plugin/skills/kastell-ops/references/patterns.md +145 -0
  272. package/kastell-plugin/skills/kastell-ops/references/pitfalls.md +136 -0
  273. package/kastell-plugin/skills/kastell-ops/scripts/check_coverage.sh +101 -0
  274. package/kastell-plugin/skills/kastell-ops/scripts/fleet_report.sh +73 -0
  275. package/kastell-plugin/skills/kastell-ops/scripts/parse_audit.sh +76 -0
  276. package/kastell-plugin/skills/kastell-research/SKILL.md +90 -0
  277. package/kastell-plugin/skills/kastell-scaffold/SKILL.md +104 -0
  278. package/kastell-plugin/skills/kastell-scaffold/references/template-audit-check.md +150 -0
  279. package/kastell-plugin/skills/kastell-scaffold/references/template-command.md +80 -0
  280. package/kastell-plugin/skills/kastell-scaffold/references/template-mcp-tool.md +72 -0
  281. package/kastell-plugin/skills/kastell-scaffold/references/template-provider.md +67 -0
  282. package/kastell-plugin/skills/kastell-scaffold/scripts/scaffold.sh +180 -0
  283. package/kastell-plugin/skills/kastell-scaffold/templates/check-test.ts.tpl +27 -0
  284. package/kastell-plugin/skills/kastell-scaffold/templates/check.ts.tpl +50 -0
  285. package/kastell-plugin/skills/kastell-scaffold/templates/command-core.ts.tpl +18 -0
  286. package/kastell-plugin/skills/kastell-scaffold/templates/command-test.ts.tpl +17 -0
  287. package/kastell-plugin/skills/kastell-scaffold/templates/command.ts.tpl +25 -0
  288. package/kastell-plugin/skills/kastell-scaffold/templates/mcp-tool-test.ts.tpl +30 -0
  289. package/kastell-plugin/skills/kastell-scaffold/templates/mcp-tool.ts.tpl +29 -0
  290. package/kastell-plugin/skills/kastell-scaffold/templates/provider-test.ts.tpl +34 -0
  291. package/kastell-plugin/skills/kastell-scaffold/templates/provider.ts.tpl +32 -0
  292. package/package.json +122 -115
@@ -2,8 +2,9 @@ import { existsSync, cpSync } from "fs";
2
2
  import { secureMkdirSync, secureWriteFileSync } from "./secureWrite.js";
3
3
  import { homedir } from "os";
4
4
  import { join } from "path";
5
- import chalk from "chalk";
6
5
  import { KASTELL_DIR } from "./paths.js";
6
+ import { getServersRaw, atomicWriteServers } from "./config.js";
7
+ import { logger, debugLog } from "./logger.js";
7
8
  const OLD_CONFIG_DIR = join(homedir(), ".quicklify");
8
9
  const NEW_CONFIG_DIR = KASTELL_DIR;
9
10
  const MIGRATED_FLAG = join(NEW_CONFIG_DIR, ".migrated");
@@ -14,23 +15,33 @@ const MIGRATED_FLAG = join(NEW_CONFIG_DIR, ".migrated");
14
15
  * - Otherwise copies contents and creates .migrated flag.
15
16
  */
16
17
  export function migrateConfigIfNeeded() {
17
- // If new config dir already exists, skip (no overwrite risk)
18
- if (existsSync(NEW_CONFIG_DIR)) {
19
- return;
18
+ // Directory migration: ~/.quicklify ~/.kastell
19
+ if (!existsSync(NEW_CONFIG_DIR) && existsSync(OLD_CONFIG_DIR)) {
20
+ try {
21
+ secureMkdirSync(NEW_CONFIG_DIR, { recursive: true });
22
+ cpSync(OLD_CONFIG_DIR, NEW_CONFIG_DIR, { recursive: true });
23
+ secureWriteFileSync(MIGRATED_FLAG, new Date().toISOString());
24
+ logger.warning("Migrated config from ~/.quicklify to ~/.kastell. You can safely remove ~/.quicklify.");
25
+ }
26
+ catch {
27
+ logger.warning("Could not migrate config from ~/.quicklify to ~/.kastell. You may need to copy files manually.");
28
+ }
20
29
  }
21
- // If old config dir doesn't exist, skip (fresh install)
22
- if (!existsSync(OLD_CONFIG_DIR)) {
30
+ // Mode field migration: v1.x configs may lack "mode" field
31
+ const SERVERS_FILE_PATH = join(KASTELL_DIR, "servers.json");
32
+ if (!existsSync(SERVERS_FILE_PATH))
23
33
  return;
24
- }
25
34
  try {
26
- secureMkdirSync(NEW_CONFIG_DIR, { recursive: true });
27
- cpSync(OLD_CONFIG_DIR, NEW_CONFIG_DIR, { recursive: true });
28
- secureWriteFileSync(MIGRATED_FLAG, new Date().toISOString());
29
- console.warn(chalk.yellow("Migrated config from ~/.quicklify to ~/.kastell. You can safely remove ~/.quicklify."));
35
+ const servers = getServersRaw();
36
+ const needsMode = servers.some((s) => !s.mode);
37
+ if (needsMode) {
38
+ const migrated = servers.map((s) => ({ ...s, mode: s.mode || "coolify" }));
39
+ atomicWriteServers(migrated);
40
+ debugLog?.("migrated server mode fields to include platform mode");
41
+ }
30
42
  }
31
- catch {
32
- // If copy fails, log warning and continue -- don't crash the CLI
33
- console.warn(chalk.yellow("Warning: Could not migrate config from ~/.quicklify to ~/.kastell. You may need to copy files manually."));
43
+ catch (error) {
44
+ debugLog?.("mode field migration failed", { cause: error });
34
45
  }
35
46
  }
36
47
  //# sourceMappingURL=migration.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration.js","sourceRoot":"","sources":["../../src/utils/migration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AACrD,MAAM,cAAc,GAAG,WAAW,CAAC;AACnC,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AAExD;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB;IACnC,6DAA6D;IAC7D,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,OAAO;IACT,CAAC;IAED,wDAAwD;IACxD,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAChC,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,eAAe,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,CAAC,cAAc,EAAE,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,mBAAmB,CAAC,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CACV,KAAK,CAAC,MAAM,CACV,sFAAsF,CACvF,CACF,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,iEAAiE;QACjE,OAAO,CAAC,IAAI,CACV,KAAK,CAAC,MAAM,CACV,yGAAyG,CAC1G,CACF,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"migration.js","sourceRoot":"","sources":["../../src/utils/migration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AACrD,MAAM,cAAc,GAAG,WAAW,CAAC;AACnC,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AAExD;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB;IACnC,iDAAiD;IACjD,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC9D,IAAI,CAAC;YACH,eAAe,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,cAAc,EAAE,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,mBAAmB,CAAC,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7D,MAAM,CAAC,OAAO,CAAC,sFAAsF,CAAC,CAAC;QACzG,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,OAAO,CAAC,gGAAgG,CAAC,CAAC;QACnH,CAAC;IACH,CAAC;IAED,2DAA2D;IAC3D,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC5D,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC;QAAE,OAAO;IAC3C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC;YAC3E,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YAC7B,QAAQ,EAAE,CAAC,sDAAsD,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,QAAQ,EAAE,CAAC,6BAA6B,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"safeMode.d.ts","sourceRoot":"","sources":["../../src/utils/safeMode.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAkB/D,wBAAgB,UAAU,IAAI,OAAO,CAwBpC;AA2BD;;;;GAIG;AACH,8CAA8C;AAC9C,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,GACA,IAAI,CAcN"}
1
+ {"version":3,"file":"safeMode.d.ts","sourceRoot":"","sources":["../../src/utils/safeMode.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAmB/D,wBAAgB,UAAU,IAAI,OAAO,CAwBpC;AA2BD;;;;GAIG;AACH,8CAA8C;AAC9C,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb,GACA,IAAI,CAcN"}
@@ -4,6 +4,7 @@ import yaml from "js-yaml";
4
4
  import chalk from "chalk";
5
5
  import { logSecurityEvent } from "./securityLogger.js";
6
6
  import { KASTELL_DIR } from "./paths.js";
7
+ import { debugLog } from "./logger.js";
7
8
  let _safeModeWarningShown = false;
8
9
  const TRUTHY = new Set(["true", "1", "yes", "on"]);
9
10
  const FALSY = new Set(["false", "0", "no", "off"]);
@@ -55,8 +56,8 @@ function getSecurityLogMaxBytes() {
55
56
  }
56
57
  }
57
58
  }
58
- catch {
59
- // Config read failure use default
59
+ catch (error) {
60
+ debugLog?.("config read failed, using default safe mode", { cause: error });
60
61
  }
61
62
  _cachedMaxBytes = undefined;
62
63
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"safeMode.js","sourceRoot":"","sources":["../../src/utils/safeMode.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"safeMode.js","sourceRoot":"","sources":["../../src/utils/safeMode.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"securityLogger.d.ts","sourceRoot":"","sources":["../../src/utils/securityLogger.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AACzD,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;AACpF,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,KAAK,CAAC;AAC9C,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAeD,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,QAAQ,CAAC,EAC9C,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B,IAAI,CAkBN;AAED,wBAAgB,YAAY,IAAI,iBAAiB,CAEhD;AAED,qBAAa,cAAc;IACzB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAQtE"}
1
+ {"version":3,"file":"securityLogger.d.ts","sourceRoot":"","sources":["../../src/utils/securityLogger.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AACzD,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;AACpF,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,KAAK,CAAC;AAC9C,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAgBD,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,QAAQ,CAAC,EAC9C,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B,IAAI,CAmBN;AAED,wBAAgB,YAAY,IAAI,iBAAiB,CAEhD;AAED,qBAAa,cAAc;IACzB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAStE"}
@@ -1,5 +1,6 @@
1
1
  import { appendFileSync, statSync, renameSync, mkdirSync } from "fs";
2
2
  import { KASTELL_DIR, SECURITY_LOG } from "./paths.js";
3
+ import { debugLog } from "./logger.js";
3
4
  const DEFAULT_MAX_BYTES = 10 * 1024 * 1024; // 10MB
4
5
  function rotateIfNeeded(maxBytes) {
5
6
  try {
@@ -8,8 +9,9 @@ function rotateIfNeeded(maxBytes) {
8
9
  renameSync(SECURITY_LOG, SECURITY_LOG + ".1");
9
10
  }
10
11
  }
11
- catch {
12
+ catch (error) {
12
13
  // File doesn't exist yet — no rotation needed
14
+ debugLog?.("security log rotation check failed", { cause: error });
13
15
  }
14
16
  }
15
17
  export function logSecurityEvent(entry, options) {
@@ -26,8 +28,9 @@ export function logSecurityEvent(entry, options) {
26
28
  mode: 0o600,
27
29
  });
28
30
  }
29
- catch {
31
+ catch (error) {
30
32
  // Security log failure MUST NOT crash the main operation — silent fail
33
+ debugLog?.("security log write failed", { cause: error });
31
34
  }
32
35
  }
33
36
  export function detectCaller() {
@@ -39,8 +42,9 @@ export class SecurityLogger {
39
42
  try {
40
43
  console.warn(`[SECURITY] ${message}`, context ?? {});
41
44
  }
42
- catch {
45
+ catch (error) {
43
46
  // Silent fail - security logging must never crash the main operation
47
+ debugLog?.("security log flush failed", { cause: error });
44
48
  }
45
49
  }
46
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"securityLogger.js","sourceRoot":"","sources":["../../src/utils/securityLogger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAoBvD,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;AAEnD,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC1B,UAAU,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,8CAA8C;IAChD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,KAA8C,EAC9C,OAA+B;IAE/B,IAAI,CAAC;QACH,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,cAAc,CAAC,OAAO,EAAE,QAAQ,IAAI,iBAAiB,CAAC,CAAC;QAEvD,MAAM,SAAS,GAAqB;YAClC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,MAAM,EAAE,YAAY,EAAE;YACtB,GAAG,KAAK;SACT,CAAC;QAEF,cAAc,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE;YAC7D,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;IACzE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AACjE,CAAC;AAED,MAAM,OAAO,cAAc;IACzB,MAAM,CAAC,IAAI,CAAC,OAAe,EAAE,OAAiC;QAC5D,4DAA4D;QAC5D,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,cAAc,OAAO,EAAE,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;QACvE,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"securityLogger.js","sourceRoot":"","sources":["../../src/utils/securityLogger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAoBvC,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;AAEnD,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC1B,UAAU,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,8CAA8C;QAC9C,QAAQ,EAAE,CAAC,oCAAoC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,KAA8C,EAC9C,OAA+B;IAE/B,IAAI,CAAC;QACH,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,cAAc,CAAC,OAAO,EAAE,QAAQ,IAAI,iBAAiB,CAAC,CAAC;QAEvD,MAAM,SAAS,GAAqB;YAClC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,MAAM,EAAE,YAAY,EAAE;YACtB,GAAG,KAAK;SACT,CAAC;QAEF,cAAc,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE;YAC7D,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uEAAuE;QACvE,QAAQ,EAAE,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AACjE,CAAC;AAED,MAAM,OAAO,cAAc;IACzB,MAAM,CAAC,IAAI,CAAC,OAAe,EAAE,OAAiC;QAC5D,4DAA4D;QAC5D,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,cAAc,OAAO,EAAE,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,qEAAqE;YACrE,QAAQ,EAAE,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "kastell",
3
+ "version": "2.2.0",
4
+ "description": "Autonomous server security and infrastructure management. Provides 13 MCP tools for cloud server provisioning, security auditing (457 checks), hardening, backup, and fleet management across Hetzner, DigitalOcean, Vultr, and Linode.",
5
+ "author": {
6
+ "name": "kastelldev"
7
+ },
8
+ "homepage": "https://kastell.dev",
9
+ "repository": "https://github.com/kastelldev/kastell",
10
+ "keywords": [
11
+ "server",
12
+ "security",
13
+ "infrastructure",
14
+ "mcp",
15
+ "audit",
16
+ "hardening",
17
+ "vps",
18
+ "cloud"
19
+ ]
20
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "kastell": {
4
+ "command": "node",
5
+ "args": ["${CLAUDE_PLUGIN_ROOT}/../../bin/kastell-mcp"]
6
+ }
7
+ }
8
+ }
@@ -0,0 +1,113 @@
1
+ # Kastell
2
+
3
+ Autonomous server security and infrastructure management for Claude Code.
4
+
5
+ ## What You Get
6
+
7
+ The Kastell plugin bundles 13 MCP tools, 4 skills, 1 agent, and 5 hooks that give Claude Code
8
+ full control over your self-hosted server infrastructure. Use it to provision cloud servers,
9
+ run 457-check security audits across 30 categories, apply 24-step hardening, manage backups,
10
+ and operate entire fleets — all from natural language in Claude Code.
11
+
12
+ Supported providers: Hetzner Cloud, DigitalOcean, Vultr, Linode.
13
+ Supported platforms: Coolify, Dokploy.
14
+
15
+ ## Prerequisites
16
+
17
+ - `npm install -g kastell` — the Kastell CLI must be installed globally
18
+ - At least one cloud provider API token (Hetzner, DigitalOcean, Vultr, or Linode)
19
+ - `kastell setup` — run once to configure your API tokens and default provider
20
+
21
+ ## Skills
22
+
23
+ | Skill | Invocation | Purpose |
24
+ |-------|------------|---------|
25
+ | kastell-ops | Auto-loaded (background) | Architecture reference, patterns, anti-patterns, and decision trees for working in the Kastell codebase or managing Kastell-provisioned servers |
26
+ | kastell-scaffold | `/kastell:scaffold` | Generate new CLI commands, MCP tools, cloud providers, and audit checks following Kastell conventions |
27
+ | kastell-careful | `/kastell:careful` | Intercepts `kastell destroy` and `kastell restore` commands and requires explicit confirmation before proceeding |
28
+ | kastell-research | `/kastell:research` | Read-only codebase exploration with full architecture context — for understanding behavior without making changes |
29
+
30
+ **kastell-ops** loads automatically as background context whenever you work with the Kastell
31
+ codebase or ask about server provisioning, audit, hardening, or provider management. It does
32
+ not appear in the slash-command menu.
33
+
34
+ ## Agents
35
+
36
+ **`/agent:kastell-auditor`** — Parallel audit analyzer that groups all 30 audit categories into
37
+ five analysis buckets (critical config, network exposure, access control, monitoring, compliance),
38
+ produces structured findings with severity ratings, and remembers previous audit context across
39
+ sessions using user-scoped memory.
40
+
41
+ Invoke it with: "Analyze my last audit report" or "Which findings should I fix first?"
42
+
43
+ Note: `kastell-fixer` is a project-scope agent, not bundled in this plugin. It requires
44
+ `isolation: worktree` which only works when installed at project scope (`.claude/agents/`).
45
+ Install kastell-fixer separately inside your Kastell project directory.
46
+
47
+ ## Hooks
48
+
49
+ | Hook | Trigger | What It Does |
50
+ |------|---------|--------------|
51
+ | stop-quality-check | Stop | Checks for TypeScript compilation errors, missing CHANGELOG entries, and stale README before ending the session |
52
+ | session-log | PostToolUse (Bash) | Records Bash command outputs to `session.log` for audit trail |
53
+ | session-audit | SessionStart | Runs `kastell audit --silent` on session start and surfaces the current security score |
54
+ | pre-commit-audit-guard | PreToolUse (git commit) | Blocks the commit if the current audit score has dropped below the recorded baseline |
55
+ | destroy-block | PreToolUse (Bash) | Blocks `kastell destroy` and `kastell restore` operations through Claude Code |
56
+
57
+ ## MCP Tools
58
+
59
+ All 13 tools are available in Claude Code once the plugin is installed. The MCP server starts
60
+ automatically via the bundled `.mcp.json` configuration.
61
+
62
+ | Tool | Description |
63
+ |------|-------------|
64
+ | server_info | List servers, check status, health, and available sizes |
65
+ | server_logs | Fetch logs and system metrics from servers via SSH |
66
+ | server_manage | Add, remove, or destroy servers |
67
+ | server_maintain | Update platform, restart, or run full maintenance |
68
+ | server_secure | SSH hardening, firewall management, and domain configuration |
69
+ | server_backup | Create backups and manage cloud snapshots |
70
+ | server_provision | Provision new cloud servers on Hetzner, DigitalOcean, Vultr, or Linode |
71
+ | server_audit | Run the full 457-check security audit across 30 categories |
72
+ | server_evidence | Collect forensic evidence packages from servers |
73
+ | server_guard | Manage the autonomous security monitoring daemon |
74
+ | server_doctor | Proactive health analysis with remediation recommendations |
75
+ | server_lock | Apply the 24-step production hardening sequence |
76
+ | server_fleet | Fleet-wide health and security posture overview |
77
+
78
+ ## Quick Start
79
+
80
+ ```bash
81
+ # Install kastell globally
82
+ npm install -g kastell
83
+
84
+ # Configure your cloud provider
85
+ kastell setup
86
+
87
+ # In Claude Code, the plugin auto-starts the MCP server.
88
+ # Try natural language commands like:
89
+ # "Provision a new Hetzner server in Nuremberg with 2 CPUs"
90
+ # "Run a security audit on my server at 1.2.3.4"
91
+ # "Apply full hardening to my production server"
92
+ # "Show me all my servers"
93
+ ```
94
+
95
+ After installation, the `kastell-ops` skill loads automatically in any session where you
96
+ work with Kastell. Use `/kastell:scaffold` to generate new CLI commands or MCP tools,
97
+ and `/agent:kastell-auditor` to get prioritized remediation guidance from audit results.
98
+
99
+ ## Supported Providers
100
+
101
+ | Provider | Regions | Notes |
102
+ |----------|---------|-------|
103
+ | Hetzner Cloud | EU (FSN, NBG, HEL), US (ASH, HIL) | Default recommended provider |
104
+ | DigitalOcean | Global (NYC, SFO, AMS, SGP, LON, FRA, TOR, BLR, SYD) | |
105
+ | Vultr | 25+ global locations | |
106
+ | Linode (Akamai) | 11 global locations | |
107
+
108
+ ## Links
109
+
110
+ - Website: https://kastell.dev
111
+ - GitHub: https://github.com/kastelldev/kastell
112
+ - npm: https://www.npmjs.com/package/kastell
113
+ - Docs: https://kastell.dev/docs
File without changes
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: kastell-auditor
3
+ description: "Security audit analyzer for Kastell servers. Runs kastell audit, maps results across 5 security domains (perimeter, authentication, runtime, internals, compliance), tracks score trends across sessions. Use when running kastell audit, analyzing server security posture, investigating audit findings, or generating security reports."
4
+ tools: Read, Grep, Glob, Bash
5
+ model: inherit
6
+ effort: high
7
+ memory: user
8
+ maxTurns: 25
9
+ skills:
10
+ - kastell-ops
11
+ ---
12
+
13
+ # Role
14
+
15
+ ## Live Context
16
+
17
+ **Last audit score:** !`node -e "import('fs').then(f=>{try{const h=JSON.parse(f.readFileSync(process.env.HOME+'/.kastell/audit-history.json','utf8'));const last=h.sort((a,b)=>new Date(b.timestamp)-new Date(a.timestamp))[0];if(last)console.log(last.overallScore+'/100 ('+last.serverName+', '+last.timestamp.split('T')[0]+')');else console.log('No audit history yet')}catch(e){console.log('No audit history yet')}}).catch(()=>console.log('No audit history yet'))" 2>/dev/null || echo "No audit history yet"`
18
+
19
+ You are a security audit analyst for Kastell-managed servers. Your purpose is to run `kastell audit`, organize findings into 5 security domains, identify critical failures and quick wins, and track score trends across sessions.
20
+
21
+ # Workflow
22
+
23
+ 1. **Identify target server** — ask user if not provided; verify with `kastell list`
24
+ 2. **Run audit** — `kastell audit <server> --json` to get structured output
25
+ 3. **Analyze by bucket** — pipe JSON through `bash scripts/bucket_mapper.sh` for instant 5-domain mapping
26
+ 4. **Check memory** — run `bash scripts/trend_report.sh <server>` for score history; or load `audit-history.json` directly
27
+ 5. **Report** — per-bucket summary + overall score + trend (if memory available)
28
+
29
+ ## Scripts (Deterministic)
30
+
31
+ ```bash
32
+ # Map audit JSON to 5 security buckets
33
+ kastell audit --server <name> --json | bash scripts/bucket_mapper.sh
34
+
35
+ # Show audit score trend for a server
36
+ bash scripts/trend_report.sh <server-name>
37
+ bash scripts/trend_report.sh --all
38
+ ```
39
+
40
+ # Bucket Map
41
+
42
+ | Bucket | Categories | Focus |
43
+ |--------|-----------|-------|
44
+ | 1 Perimeter | Network, Firewall, DNS Security | External attack surface |
45
+ | 2 Authentication | SSH, Auth, Crypto, Accounts | Identity controls |
46
+ | 3 Runtime | Docker, Services, Boot, Scheduling | Service exposure |
47
+ | 4 Internals | Filesystem, Logging, Kernel, Memory | System hardening |
48
+ | 5 Compliance | Updates, File Integrity, Malware, MAC, Secrets, Cloud Metadata, Supply Chain, Backup Hygiene, Resource Limits, Incident Readiness, Banners, Time | Hygiene and compliance |
49
+
50
+ # Output Format
51
+
52
+ For each bucket:
53
+ - **Score:** X/Y checks passed
54
+ - **Critical findings** (up to 3): `[FAIL] check-name -- one-line impact`
55
+ - **Quick win:** one actionable fix
56
+
57
+ After all buckets:
58
+ - **Overall score:** X/100
59
+ - **Trend** (when memory has prior data): "Last audit: Y -- Delta: +/-Z -- [N] new failures in [bucket]"
60
+
61
+ # Memory
62
+
63
+ Manage a single file `audit-history.json` in your agent memory directory. Store per server:
64
+
65
+ ```json
66
+ { "server": "string", "date": "string", "score": 0, "bucketScores": { "perimeter": 0, "authentication": 0, "runtime": 0, "internals": 0, "compliance": 0 }, "failedChecks": [] }
67
+ ```
68
+
69
+ On each run: load prior record, compute delta, store new record. Discard entries for servers no longer in `kastell list` output.
70
+
71
+ # Rules
72
+
73
+ - Read-only operations only: `server_audit`, `server_doctor`, `server_fleet`
74
+ - Never run `kastell lock`, `kastell secure`, or any write operation
75
+ - Recommend fixes but do not apply them — suggest `/agent:kastell-fixer` for implementation
76
+ - If multiple servers requested, analyze each sequentially
77
+ - English output for analysis structure; follow user's language for explanatory text
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env bash
2
+ # bucket_mapper.sh — Map kastell audit JSON checks to 5 security buckets.
3
+ # Usage: kastell audit --server <name> --json | bash bucket_mapper.sh
4
+ # OR: bash bucket_mapper.sh < audit-output.json
5
+ # OR: bash bucket_mapper.sh audit-output.json
6
+ #
7
+ # Output: Per-bucket check list with pass/fail status and severity.
8
+ # Used by kastell-auditor agent for structured analysis.
9
+ #
10
+ # Requires: node
11
+
12
+ set -euo pipefail
13
+
14
+ if [[ -n "${1:-}" && -f "$1" ]]; then
15
+ INPUT=$(cat "$1")
16
+ elif [[ ! -t 0 ]]; then
17
+ INPUT=$(cat)
18
+ else
19
+ echo "Usage: kastell audit --server <name> --json | bash bucket_mapper.sh" >&2
20
+ exit 1
21
+ fi
22
+
23
+ node -e "
24
+ const data = JSON.parse(process.argv[1]);
25
+ const checks = data.checks || data.results || [];
26
+
27
+ const BUCKETS = {
28
+ '1_Perimeter': {
29
+ match: ['network', 'firewall', 'dns'],
30
+ checks: []
31
+ },
32
+ '2_Authentication': {
33
+ match: ['ssh', 'auth', 'crypto', 'accounts'],
34
+ checks: []
35
+ },
36
+ '3_Runtime': {
37
+ match: ['docker', 'services', 'boot', 'scheduling'],
38
+ checks: []
39
+ },
40
+ '4_Internals': {
41
+ match: ['filesystem', 'logging', 'kernel', 'memory'],
42
+ checks: []
43
+ },
44
+ '5_Compliance': {
45
+ match: [], // catchall
46
+ checks: []
47
+ }
48
+ };
49
+
50
+ function getBucket(category) {
51
+ const cat = (category || '').toLowerCase();
52
+ for (const [name, bucket] of Object.entries(BUCKETS)) {
53
+ if (name === '5_Compliance') continue;
54
+ if (bucket.match.some(m => cat.includes(m))) return name;
55
+ }
56
+ return '5_Compliance';
57
+ }
58
+
59
+ // Map checks to buckets
60
+ for (const c of checks) {
61
+ const bucket = getBucket(c.category);
62
+ BUCKETS[bucket].checks.push({
63
+ id: c.id || 'unknown',
64
+ name: c.name || '',
65
+ severity: c.severity || 'info',
66
+ passed: !!c.passed,
67
+ category: c.category || ''
68
+ });
69
+ }
70
+
71
+ // Output
72
+ const score = data.score ?? data.overallScore ?? 'N/A';
73
+ console.log('Score: ' + score + '/100');
74
+ console.log('Total checks: ' + checks.length);
75
+ console.log('');
76
+
77
+ for (const [name, bucket] of Object.entries(BUCKETS)) {
78
+ const label = name.replace(/^[0-9]_/, '');
79
+ const passed = bucket.checks.filter(c => c.passed).length;
80
+ const total = bucket.checks.length;
81
+ const critFail = bucket.checks.filter(c => !c.passed && c.severity === 'critical');
82
+
83
+ console.log('--- ' + label + ' (' + passed + '/' + total + ') ---');
84
+
85
+ // Show failed checks (critical first, then warning)
86
+ const failed = bucket.checks
87
+ .filter(c => !c.passed)
88
+ .sort((a, b) => {
89
+ const sev = { critical: 0, warning: 1, info: 2 };
90
+ return (sev[a.severity] ?? 3) - (sev[b.severity] ?? 3);
91
+ });
92
+
93
+ for (const c of failed.slice(0, 5)) {
94
+ const icon = c.severity === 'critical' ? '!!' : c.severity === 'warning' ? '! ' : ' ';
95
+ console.log(' [FAIL] ' + icon + c.id + ' — ' + c.name);
96
+ }
97
+ if (failed.length > 5) console.log(' ... and ' + (failed.length - 5) + ' more');
98
+ if (failed.length === 0) console.log(' All checks passed');
99
+ console.log('');
100
+ }
101
+ " "$INPUT"
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env bash
2
+ # trend_report.sh — Generate audit score trend from audit-history.json.
3
+ # Usage: bash trend_report.sh [server-name]
4
+ # OR: bash trend_report.sh --all
5
+ #
6
+ # Reads ~/.kastell/audit-history.json (maintained by kastell-auditor agent).
7
+ # Shows score over time with delta indicators.
8
+ #
9
+ # Requires: node
10
+
11
+ set -euo pipefail
12
+
13
+ HISTORY_FILE="${KASTELL_HOME:-$HOME/.kastell}/audit-history.json"
14
+ SERVER="${1:-}"
15
+
16
+ if [[ ! -f "$HISTORY_FILE" ]]; then
17
+ echo "No audit history found at: $HISTORY_FILE"
18
+ echo "Run 'kastell audit --server <name>' to generate data."
19
+ exit 0
20
+ fi
21
+
22
+ node -e "
23
+ const fs = require('fs');
24
+ const data = JSON.parse(fs.readFileSync(process.argv[1], 'utf8'));
25
+ const server = process.argv[2] || '';
26
+ const showAll = server === '--all';
27
+
28
+ if (!Array.isArray(data) || data.length === 0) {
29
+ console.log('No audit history entries found.');
30
+ process.exit(0);
31
+ }
32
+
33
+ // Filter by server if specified
34
+ let entries = showAll ? data : server
35
+ ? data.filter(e => e.serverName === server || e.server === server)
36
+ : data;
37
+
38
+ if (entries.length === 0) {
39
+ console.log('No audit history for server: ' + server);
40
+ console.log('Available servers: ' + [...new Set(data.map(e => e.serverName || e.server))].join(', '));
41
+ process.exit(0);
42
+ }
43
+
44
+ // Sort by date
45
+ entries.sort((a, b) => new Date(a.timestamp || a.date) - new Date(b.timestamp || b.date));
46
+
47
+ // Group by server
48
+ const byServer = {};
49
+ for (const e of entries) {
50
+ const name = e.serverName || e.server || 'unknown';
51
+ if (!byServer[name]) byServer[name] = [];
52
+ byServer[name].push(e);
53
+ }
54
+
55
+ console.log('=== Audit Score Trend ===');
56
+ console.log('');
57
+
58
+ for (const [name, history] of Object.entries(byServer)) {
59
+ console.log('Server: ' + name);
60
+ console.log('-'.repeat(50));
61
+
62
+ let prev = null;
63
+ for (const e of history) {
64
+ const score = e.overallScore ?? e.score ?? 0;
65
+ const date = (e.timestamp || e.date || '').split('T')[0];
66
+ let delta = '';
67
+ if (prev !== null) {
68
+ const diff = score - prev;
69
+ delta = diff > 0 ? ' (+' + diff + ')' : diff < 0 ? ' (' + diff + ')' : ' (=)';
70
+ }
71
+
72
+ // Visual bar
73
+ const filled = Math.round(score / 5);
74
+ const bar = '█'.repeat(filled) + '░'.repeat(20 - filled);
75
+
76
+ console.log(' ' + date + ' ' + String(score).padStart(3) + '/100 ' + bar + delta);
77
+ prev = score;
78
+ }
79
+
80
+ // Latest bucket scores if available
81
+ const latest = history[history.length - 1];
82
+ if (latest.bucketScores) {
83
+ console.log('');
84
+ console.log(' Latest bucket breakdown:');
85
+ for (const [bucket, score] of Object.entries(latest.bucketScores)) {
86
+ console.log(' ' + bucket.padEnd(15) + ': ' + score);
87
+ }
88
+ }
89
+ console.log('');
90
+ }
91
+ " "$HISTORY_FILE" "$SERVER"
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env node
2
+ // PreToolUse hook: Block kastell destroy / server-delete commands (hard block)
3
+
4
+ // MANDATORY stdin guard — exit silently if stdin unavailable (e.g. after /clear)
5
+ if (!process.stdin || process.stdin.destroyed || !process.stdin.readable) {
6
+ process.exit(0);
7
+ }
8
+
9
+ let input = '';
10
+ const stdinTimeout = setTimeout(() => process.exit(0), 1500);
11
+ process.stdin.setEncoding('utf8');
12
+ process.stdin.on('error', () => process.exit(0));
13
+ process.stdin.on('data', chunk => { input += chunk; });
14
+ process.stdin.on('end', () => {
15
+ clearTimeout(stdinTimeout);
16
+ try {
17
+ const data = JSON.parse(input);
18
+ const cmd = (data.tool_input && data.tool_input.command) || '';
19
+
20
+ if (/\bkastell\s+(destroy|server-delete)\b/.test(cmd)) {
21
+ process.stdout.write(JSON.stringify({
22
+ decision: 'block',
23
+ reason: 'Destructive kastell operation detected. Use kastell destroy with --force flag directly in terminal, not through Claude Code.',
24
+ }));
25
+ process.exit(2);
26
+ }
27
+ } catch {}
28
+
29
+ // Not destructive or parse error — allow
30
+ process.exit(0);
31
+ });