kastell 2.2.3 → 2.2.5

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 (75) hide show
  1. package/.claude-plugin/marketplace.json +18 -18
  2. package/.claude-plugin/plugin.json +45 -39
  3. package/CHANGELOG.md +1294 -1266
  4. package/LICENSE +201 -201
  5. package/NOTICE +5 -5
  6. package/README.md +1 -1
  7. package/README.tr.md +1 -1
  8. package/bin/kastell +2 -2
  9. package/bin/kastell-mcp +5 -5
  10. package/dist/adapters/coolify.js +92 -92
  11. package/dist/adapters/dokploy.js +99 -99
  12. package/dist/core/audit/formatters/badge.js +20 -20
  13. package/dist/core/completions.js +631 -631
  14. package/dist/mcp/server.d.ts.map +1 -1
  15. package/dist/mcp/server.js +25 -31
  16. package/dist/mcp/server.js.map +1 -1
  17. package/dist/mcp/tools/serverExplain.d.ts.map +1 -1
  18. package/dist/mcp/tools/serverExplain.js.map +1 -1
  19. package/dist/mcp/tools/serverFleet.d.ts.map +1 -1
  20. package/dist/mcp/tools/serverFleet.js.map +1 -1
  21. package/dist/mcp/tools/serverInfo.d.ts +1 -1
  22. package/dist/mcp/tools/serverInfo.js +1 -1
  23. package/dist/mcp/tools/serverPlugin.d.ts.map +1 -1
  24. package/dist/mcp/tools/serverPlugin.js.map +1 -1
  25. package/dist/mcp-bundle.mjs +101015 -0
  26. package/dist/utils/cloudInit.js +58 -58
  27. package/dist/utils/version.d.ts.map +1 -1
  28. package/dist/utils/version.js +19 -4
  29. package/dist/utils/version.js.map +1 -1
  30. package/kastell-plugin/.claude-plugin/plugin.json +20 -20
  31. package/kastell-plugin/.mcp.json +15 -8
  32. package/kastell-plugin/README.md +113 -113
  33. package/kastell-plugin/agents/kastell-auditor.md +77 -77
  34. package/kastell-plugin/agents/scripts/bucket_mapper.sh +101 -101
  35. package/kastell-plugin/agents/scripts/trend_report.sh +91 -91
  36. package/kastell-plugin/hooks/destroy-block.cjs +31 -31
  37. package/kastell-plugin/hooks/hooks.json +57 -57
  38. package/kastell-plugin/hooks/pre-commit-audit-guard.cjs +75 -75
  39. package/kastell-plugin/hooks/session-audit.cjs +86 -86
  40. package/kastell-plugin/hooks/session-log.cjs +56 -56
  41. package/kastell-plugin/hooks/stop-quality-check.cjs +72 -72
  42. package/kastell-plugin/skills/kastell-careful/SKILL.md +64 -64
  43. package/kastell-plugin/skills/kastell-ops/SKILL.md +139 -139
  44. package/kastell-plugin/skills/kastell-ops/references/commands.md +45 -45
  45. package/kastell-plugin/skills/kastell-ops/references/mcp-tools.md +50 -50
  46. package/kastell-plugin/skills/kastell-ops/references/patterns.md +145 -145
  47. package/kastell-plugin/skills/kastell-ops/references/pitfalls.md +136 -136
  48. package/kastell-plugin/skills/kastell-ops/scripts/check_coverage.sh +101 -101
  49. package/kastell-plugin/skills/kastell-ops/scripts/fleet_report.sh +73 -73
  50. package/kastell-plugin/skills/kastell-ops/scripts/parse_audit.sh +76 -76
  51. package/kastell-plugin/skills/kastell-research/SKILL.md +90 -90
  52. package/kastell-plugin/skills/kastell-scaffold/SKILL.md +104 -104
  53. package/kastell-plugin/skills/kastell-scaffold/references/template-audit-check.md +150 -150
  54. package/kastell-plugin/skills/kastell-scaffold/references/template-command.md +80 -80
  55. package/kastell-plugin/skills/kastell-scaffold/references/template-mcp-tool.md +72 -72
  56. package/kastell-plugin/skills/kastell-scaffold/references/template-provider.md +67 -67
  57. package/kastell-plugin/skills/kastell-scaffold/scripts/scaffold.sh +180 -180
  58. package/kastell-plugin/skills/kastell-scaffold/templates/check-test.ts.tpl +27 -27
  59. package/kastell-plugin/skills/kastell-scaffold/templates/check.ts.tpl +50 -50
  60. package/kastell-plugin/skills/kastell-scaffold/templates/command-core.ts.tpl +18 -18
  61. package/kastell-plugin/skills/kastell-scaffold/templates/command-test.ts.tpl +17 -17
  62. package/kastell-plugin/skills/kastell-scaffold/templates/command.ts.tpl +25 -25
  63. package/kastell-plugin/skills/kastell-scaffold/templates/mcp-tool-test.ts.tpl +30 -30
  64. package/kastell-plugin/skills/kastell-scaffold/templates/mcp-tool.ts.tpl +29 -29
  65. package/kastell-plugin/skills/kastell-scaffold/templates/provider-test.ts.tpl +34 -34
  66. package/kastell-plugin/skills/kastell-scaffold/templates/provider.ts.tpl +32 -32
  67. package/package.json +125 -122
  68. package/dist/commands/interactive.d.ts +0 -11
  69. package/dist/commands/interactive.d.ts.map +0 -1
  70. package/dist/commands/interactive.js +0 -1079
  71. package/dist/commands/interactive.js.map +0 -1
  72. package/dist/core/lock.d.ts +0 -66
  73. package/dist/core/lock.d.ts.map +0 -1
  74. package/dist/core/lock.js +0 -556
  75. package/dist/core/lock.js.map +0 -1
@@ -1,18 +1,18 @@
1
- export interface __NAME_PASCAL__Options {
2
- server?: string;
3
- json?: boolean;
4
- }
5
-
6
- export interface __NAME_PASCAL__Result {
7
- success: boolean;
8
- message: string;
9
- }
10
-
11
- export async function __NAME_CAMEL__Core(
12
- options: __NAME_PASCAL__Options,
13
- ): Promise<__NAME_PASCAL__Result> {
14
- // ALL business logic here. NO chalk/ora/UI imports.
15
- // assertValidIp() before SSH. getAdapter(platform) for platform ops.
16
- // withProviderErrorHandling() for provider calls.
17
- throw new Error("Not implemented");
18
- }
1
+ export interface __NAME_PASCAL__Options {
2
+ server?: string;
3
+ json?: boolean;
4
+ }
5
+
6
+ export interface __NAME_PASCAL__Result {
7
+ success: boolean;
8
+ message: string;
9
+ }
10
+
11
+ export async function __NAME_CAMEL__Core(
12
+ options: __NAME_PASCAL__Options,
13
+ ): Promise<__NAME_PASCAL__Result> {
14
+ // ALL business logic here. NO chalk/ora/UI imports.
15
+ // assertValidIp() before SSH. getAdapter(platform) for platform ops.
16
+ // withProviderErrorHandling() for provider calls.
17
+ throw new Error("Not implemented");
18
+ }
@@ -1,17 +1,17 @@
1
- import { __NAME_CAMEL__Core } from "../../core/__NAME__.js";
2
-
3
- jest.mock("../../utils/ssh.js");
4
-
5
- describe("__NAME_CAMEL__Core", () => {
6
- beforeEach(() => jest.resetAllMocks());
7
-
8
- it("should TODO: describe expected behavior", async () => {
9
- const result = await __NAME_CAMEL__Core({ server: "test-server" });
10
- expect(result.success).toBe(true);
11
- });
12
-
13
- it("should handle missing server gracefully", async () => {
14
- const result = await __NAME_CAMEL__Core({});
15
- expect(result.success).toBe(false);
16
- });
17
- });
1
+ import { __NAME_CAMEL__Core } from "../../core/__NAME__.js";
2
+
3
+ jest.mock("../../utils/ssh.js");
4
+
5
+ describe("__NAME_CAMEL__Core", () => {
6
+ beforeEach(() => jest.resetAllMocks());
7
+
8
+ it("should TODO: describe expected behavior", async () => {
9
+ const result = await __NAME_CAMEL__Core({ server: "test-server" });
10
+ expect(result.success).toBe(true);
11
+ });
12
+
13
+ it("should handle missing server gracefully", async () => {
14
+ const result = await __NAME_CAMEL__Core({});
15
+ expect(result.success).toBe(false);
16
+ });
17
+ });
@@ -1,25 +1,25 @@
1
- import { program } from "commander";
2
- import chalk from "chalk";
3
- import ora from "ora";
4
- import { __NAME_CAMEL__Core } from "../core/__NAME__.js";
5
-
6
- program
7
- .command("__NAME__")
8
- .description("TODO: describe what this command does")
9
- .option("--server <name>", "Target server name or IP")
10
- .option("--json", "Output as JSON")
11
- .action(async (options) => {
12
- const spinner = ora("Running __NAME__...").start();
13
- try {
14
- const result = await __NAME_CAMEL__Core(options);
15
- spinner.succeed("Done");
16
- if (options.json) {
17
- console.log(JSON.stringify(result, null, 2));
18
- } else {
19
- console.log(chalk.green(result.message));
20
- }
21
- } catch (error) {
22
- spinner.fail(error instanceof Error ? error.message : "Unknown error");
23
- process.exitCode = 1;
24
- }
25
- });
1
+ import { program } from "commander";
2
+ import chalk from "chalk";
3
+ import ora from "ora";
4
+ import { __NAME_CAMEL__Core } from "../core/__NAME__.js";
5
+
6
+ program
7
+ .command("__NAME__")
8
+ .description("TODO: describe what this command does")
9
+ .option("--server <name>", "Target server name or IP")
10
+ .option("--json", "Output as JSON")
11
+ .action(async (options) => {
12
+ const spinner = ora("Running __NAME__...").start();
13
+ try {
14
+ const result = await __NAME_CAMEL__Core(options);
15
+ spinner.succeed("Done");
16
+ if (options.json) {
17
+ console.log(JSON.stringify(result, null, 2));
18
+ } else {
19
+ console.log(chalk.green(result.message));
20
+ }
21
+ } catch (error) {
22
+ spinner.fail(error instanceof Error ? error.message : "Unknown error");
23
+ process.exitCode = 1;
24
+ }
25
+ });
@@ -1,30 +1,30 @@
1
- import { handle__NAME_PASCAL__ } from "../../mcp/tools/__NAME__.js";
2
-
3
- // Mock the core dependency
4
- // jest.mock("../../core/__NAME__.js");
5
-
6
- describe("handle__NAME_PASCAL__", () => {
7
- beforeEach(() => jest.resetAllMocks());
8
-
9
- it("returns success response", async () => {
10
- const result = await handle__NAME_PASCAL__({
11
- server: "test-server",
12
- action: "TODO",
13
- });
14
-
15
- expect(result.isError).toBeUndefined();
16
- expect(result.content[0].text).toContain("success");
17
- });
18
-
19
- it("handles missing server gracefully", async () => {
20
- const result = await handle__NAME_PASCAL__({
21
- action: "TODO",
22
- });
23
-
24
- expect(result.content).toBeDefined();
25
- });
26
-
27
- it("returns error on failure", async () => {
28
- // TODO: mock core to reject, verify isError
29
- });
30
- });
1
+ import { handle__NAME_PASCAL__ } from "../../mcp/tools/__NAME__.js";
2
+
3
+ // Mock the core dependency
4
+ // jest.mock("../../core/__NAME__.js");
5
+
6
+ describe("handle__NAME_PASCAL__", () => {
7
+ beforeEach(() => jest.resetAllMocks());
8
+
9
+ it("returns success response", async () => {
10
+ const result = await handle__NAME_PASCAL__({
11
+ server: "test-server",
12
+ action: "TODO",
13
+ });
14
+
15
+ expect(result.isError).toBeUndefined();
16
+ expect(result.content[0].text).toContain("success");
17
+ });
18
+
19
+ it("handles missing server gracefully", async () => {
20
+ const result = await handle__NAME_PASCAL__({
21
+ action: "TODO",
22
+ });
23
+
24
+ expect(result.content).toBeDefined();
25
+ });
26
+
27
+ it("returns error on failure", async () => {
28
+ // TODO: mock core to reject, verify isError
29
+ });
30
+ });
@@ -1,29 +1,29 @@
1
- import { z } from "zod";
2
- import type { McpResponse } from "../types.js";
3
-
4
- // IMPORTANT: Schema is a flat object, NOT wrapped in z.object()
5
- // The SDK wraps it automatically
6
- export const __NAME_CAMEL__Schema = {
7
- server: z
8
- .string()
9
- .optional()
10
- .describe("Server name or IP. Auto-selected if only one server exists."),
11
- action: z.enum(["TODO"]).describe("TODO: describe actions"),
12
- };
13
-
14
- export async function handle__NAME_PASCAL__(params: {
15
- server?: string;
16
- action: string;
17
- }): Promise<McpResponse> {
18
- // Delegate to core function (NOT direct SSH/provider calls)
19
- // Example: const result = await someCoreFunction(params);
20
-
21
- return {
22
- content: [
23
- {
24
- type: "text" as const,
25
- text: JSON.stringify({ success: true }, null, 2),
26
- },
27
- ],
28
- };
29
- }
1
+ import { z } from "zod";
2
+ import type { McpResponse } from "../types.js";
3
+
4
+ // IMPORTANT: Schema is a flat object, NOT wrapped in z.object()
5
+ // The SDK wraps it automatically
6
+ export const __NAME_CAMEL__Schema = {
7
+ server: z
8
+ .string()
9
+ .optional()
10
+ .describe("Server name or IP. Auto-selected if only one server exists."),
11
+ action: z.enum(["TODO"]).describe("TODO: describe actions"),
12
+ };
13
+
14
+ export async function handle__NAME_PASCAL__(params: {
15
+ server?: string;
16
+ action: string;
17
+ }): Promise<McpResponse> {
18
+ // Delegate to core function (NOT direct SSH/provider calls)
19
+ // Example: const result = await someCoreFunction(params);
20
+
21
+ return {
22
+ content: [
23
+ {
24
+ type: "text" as const,
25
+ text: JSON.stringify({ success: true }, null, 2),
26
+ },
27
+ ],
28
+ };
29
+ }
@@ -1,34 +1,34 @@
1
- import { __NAME_PASCAL__Provider } from "../../providers/__NAME__.js";
2
-
3
- // Mock axios at module level
4
- jest.mock("axios", () => ({
5
- create: jest.fn(() => ({
6
- get: jest.fn(),
7
- post: jest.fn(),
8
- delete: jest.fn(),
9
- })),
10
- }));
11
-
12
- describe("__NAME_PASCAL__Provider", () => {
13
- let provider: __NAME_PASCAL__Provider;
14
-
15
- beforeEach(() => {
16
- jest.resetAllMocks();
17
- provider = new __NAME_PASCAL__Provider("test-token");
18
- });
19
-
20
- it("should create instance with correct base URL", () => {
21
- expect(provider).toBeDefined();
22
- });
23
-
24
- it("should list servers", async () => {
25
- // TODO: mock API response and verify
26
- await expect(provider.listServers()).resolves.toBeDefined();
27
- });
28
-
29
- it("should create server", async () => {
30
- // TODO: mock API response and verify
31
- const params = { name: "test", region: "us-east", size: "small" };
32
- await expect(provider.createServer(params)).resolves.toBeDefined();
33
- });
34
- });
1
+ import { __NAME_PASCAL__Provider } from "../../providers/__NAME__.js";
2
+
3
+ // Mock axios at module level
4
+ jest.mock("axios", () => ({
5
+ create: jest.fn(() => ({
6
+ get: jest.fn(),
7
+ post: jest.fn(),
8
+ delete: jest.fn(),
9
+ })),
10
+ }));
11
+
12
+ describe("__NAME_PASCAL__Provider", () => {
13
+ let provider: __NAME_PASCAL__Provider;
14
+
15
+ beforeEach(() => {
16
+ jest.resetAllMocks();
17
+ provider = new __NAME_PASCAL__Provider("test-token");
18
+ });
19
+
20
+ it("should create instance with correct base URL", () => {
21
+ expect(provider).toBeDefined();
22
+ });
23
+
24
+ it("should list servers", async () => {
25
+ // TODO: mock API response and verify
26
+ await expect(provider.listServers()).resolves.toBeDefined();
27
+ });
28
+
29
+ it("should create server", async () => {
30
+ // TODO: mock API response and verify
31
+ const params = { name: "test", region: "us-east", size: "small" };
32
+ await expect(provider.createServer(params)).resolves.toBeDefined();
33
+ });
34
+ });
@@ -1,32 +1,32 @@
1
- import {
2
- BaseProvider,
3
- type ProviderServer,
4
- type CreateServerParams,
5
- type ProviderResponse,
6
- } from "./base.js";
7
-
8
- export class __NAME_PASCAL__Provider extends BaseProvider {
9
- constructor(token: string) {
10
- super(token, "https://api.__NAME__.com/v1"); // TODO: adjust API base URL
11
- }
12
-
13
- async listServers(): Promise<ProviderResponse<ProviderServer[]>> {
14
- return this.request<ProviderServer[]>("GET", "/servers");
15
- }
16
-
17
- async createServer(
18
- params: CreateServerParams,
19
- ): Promise<ProviderResponse<ProviderServer>> {
20
- return this.request<ProviderServer>("POST", "/servers", { body: params });
21
- }
22
-
23
- async deleteServer(serverId: string): Promise<ProviderResponse<void>> {
24
- return this.request<void>("DELETE", `/servers/${serverId}`);
25
- }
26
-
27
- async getServer(
28
- serverId: string,
29
- ): Promise<ProviderResponse<ProviderServer>> {
30
- return this.request<ProviderServer>("GET", `/servers/${serverId}`);
31
- }
32
- }
1
+ import {
2
+ BaseProvider,
3
+ type ProviderServer,
4
+ type CreateServerParams,
5
+ type ProviderResponse,
6
+ } from "./base.js";
7
+
8
+ export class __NAME_PASCAL__Provider extends BaseProvider {
9
+ constructor(token: string) {
10
+ super(token, "https://api.__NAME__.com/v1"); // TODO: adjust API base URL
11
+ }
12
+
13
+ async listServers(): Promise<ProviderResponse<ProviderServer[]>> {
14
+ return this.request<ProviderServer[]>("GET", "/servers");
15
+ }
16
+
17
+ async createServer(
18
+ params: CreateServerParams,
19
+ ): Promise<ProviderResponse<ProviderServer>> {
20
+ return this.request<ProviderServer>("POST", "/servers", { body: params });
21
+ }
22
+
23
+ async deleteServer(serverId: string): Promise<ProviderResponse<void>> {
24
+ return this.request<void>("DELETE", `/servers/${serverId}`);
25
+ }
26
+
27
+ async getServer(
28
+ serverId: string,
29
+ ): Promise<ProviderResponse<ProviderServer>> {
30
+ return this.request<ProviderServer>("GET", `/servers/${serverId}`);
31
+ }
32
+ }
package/package.json CHANGED
@@ -1,122 +1,125 @@
1
- {
2
- "name": "kastell",
3
- "version": "2.2.3",
4
- "description": "CLI toolkit for provisioning, securing, and managing self-hosted servers",
5
- "type": "module",
6
- "main": "dist/index.js",
7
- "bin": {
8
- "kastell": "bin/kastell",
9
- "kastell-mcp": "bin/kastell-mcp"
10
- },
11
- "files": [
12
- "bin/",
13
- "dist/",
14
- ".claude-plugin/",
15
- "kastell-plugin/skills/",
16
- "kastell-plugin/agents/",
17
- "kastell-plugin/hooks/",
18
- "kastell-plugin/.claude-plugin/",
19
- "kastell-plugin/.mcp.json",
20
- "kastell-plugin/README.md",
21
- "README.md",
22
- "LICENSE",
23
- "NOTICE",
24
- "SECURITY.md",
25
- "CHANGELOG.md"
26
- ],
27
- "scripts": {
28
- "dev": "tsx src/index.ts",
29
- "build": "tsc",
30
- "start": "node dist/index.js",
31
- "test": "jest --config jest.config.cjs",
32
- "test:watch": "jest --config jest.config.cjs --watch",
33
- "test:coverage": "jest --config jest.config.cjs --coverage",
34
- "test:mutate": "cp .stryker-tmp/incremental.json .stryker-tmp/incremental.backup.json 2>/dev/null; stryker run",
35
- "lint": "eslint src/",
36
- "lint:fix": "eslint src/ --fix",
37
- "format": "prettier --write \"src/**/*.ts\"",
38
- "format:check": "prettier --check \"src/**/*.ts\""
39
- },
40
- "mcpName": "io.github.kastelldev/kastell",
41
- "keywords": [
42
- "kastell",
43
- "mcp-server",
44
- "coolify",
45
- "deployment",
46
- "hetzner",
47
- "digitalocean",
48
- "vultr",
49
- "linode",
50
- "cli",
51
- "vps",
52
- "cloud",
53
- "automation",
54
- "self-hosted",
55
- "server-security",
56
- "server-maintenance",
57
- "infrastructure",
58
- "devops",
59
- "server"
60
- ],
61
- "engines": {
62
- "node": ">=20.0.0"
63
- },
64
- "license": "Apache-2.0",
65
- "repository": {
66
- "type": "git",
67
- "url": "https://github.com/kastelldev/kastell.git"
68
- },
69
- "bugs": {
70
- "url": "https://github.com/kastelldev/kastell/issues"
71
- },
72
- "homepage": "https://kastell.dev",
73
- "author": {
74
- "name": "Ömer",
75
- "email": "hello@omrfc.dev",
76
- "url": "https://omrfc.dev"
77
- },
78
- "funding": {
79
- "type": "github",
80
- "url": "https://github.com/sponsors/omrfc"
81
- },
82
- "dependencies": {
83
- "@modelcontextprotocol/sdk": "1.27.1",
84
- "@napi-rs/keyring": "1.2.0",
85
- "axios": "1.15.0",
86
- "chalk": "5.6.2",
87
- "commander": "14.0.3",
88
- "grammy": "1.41.1",
89
- "inquirer": "12.11.1",
90
- "js-yaml": "4.1.1",
91
- "ora": "9.3.0",
92
- "p-limit": "7.3.0",
93
- "semver": "7.7.2",
94
- "zod": "4.3.6"
95
- },
96
- "overrides": {
97
- "minimatch": "^10.2.4"
98
- },
99
- "devDependencies": {
100
- "@eslint/js": "^10.0.1",
101
- "@stryker-mutator/core": "^9.6.0",
102
- "@stryker-mutator/jest-runner": "^9.6.0",
103
- "@stryker-mutator/typescript-checker": "^9.6.0",
104
- "@types/inquirer": "^9.0.7",
105
- "@types/jest": "^30.0.0",
106
- "@types/js-yaml": "^4.0.9",
107
- "@types/node": "^22.12.0",
108
- "@types/semver": "7.7.0",
109
- "eslint": "^10.0.2",
110
- "eslint-config-prettier": "^10.1.8",
111
- "eslint-plugin-no-secrets": "^2.3.3",
112
- "eslint-plugin-security": "^4.0.0",
113
- "fast-check": "^4.7.0",
114
- "ignore": "^7.0.5",
115
- "jest": "^30.2.0",
116
- "prettier": "^3.8.1",
117
- "ts-jest": "^29.4.6",
118
- "tsx": "^4.21.0",
119
- "typescript": "^5.9.3",
120
- "typescript-eslint": "^8.56.1"
121
- }
122
- }
1
+ {
2
+ "name": "kastell",
3
+ "version": "2.2.5",
4
+ "description": "CLI toolkit for provisioning, securing, and managing self-hosted servers",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "kastell": "bin/kastell",
9
+ "kastell-mcp": "bin/kastell-mcp"
10
+ },
11
+ "files": [
12
+ "bin/",
13
+ "dist/",
14
+ ".claude-plugin/",
15
+ "kastell-plugin/skills/",
16
+ "kastell-plugin/agents/",
17
+ "kastell-plugin/hooks/",
18
+ "kastell-plugin/.claude-plugin/",
19
+ "kastell-plugin/.mcp.json",
20
+ "kastell-plugin/README.md",
21
+ "README.md",
22
+ "LICENSE",
23
+ "NOTICE",
24
+ "SECURITY.md",
25
+ "CHANGELOG.md"
26
+ ],
27
+ "scripts": {
28
+ "dev": "tsx src/index.ts",
29
+ "build": "tsc && node scripts/bundle-mcp.mjs",
30
+ "bundle:mcp": "node scripts/bundle-mcp.mjs",
31
+ "start": "node dist/index.js",
32
+ "test": "jest --config jest.config.cjs",
33
+ "test:watch": "jest --config jest.config.cjs --watch",
34
+ "test:coverage": "jest --config jest.config.cjs --coverage",
35
+ "test:mutate": "cp .stryker-tmp/incremental.json .stryker-tmp/incremental.backup.json 2>/dev/null; stryker run",
36
+ "lint": "eslint src/",
37
+ "lint:fix": "eslint src/ --fix",
38
+ "format": "prettier --write \"src/**/*.ts\"",
39
+ "format:check": "prettier --check \"src/**/*.ts\""
40
+ },
41
+ "mcpName": "io.github.kastelldev/kastell",
42
+ "keywords": [
43
+ "kastell",
44
+ "mcp-server",
45
+ "coolify",
46
+ "deployment",
47
+ "hetzner",
48
+ "digitalocean",
49
+ "vultr",
50
+ "linode",
51
+ "cli",
52
+ "vps",
53
+ "cloud",
54
+ "automation",
55
+ "self-hosted",
56
+ "server-security",
57
+ "server-maintenance",
58
+ "infrastructure",
59
+ "devops",
60
+ "server"
61
+ ],
62
+ "engines": {
63
+ "node": ">=20.0.0"
64
+ },
65
+ "license": "Apache-2.0",
66
+ "repository": {
67
+ "type": "git",
68
+ "url": "https://github.com/kastelldev/kastell.git"
69
+ },
70
+ "bugs": {
71
+ "url": "https://github.com/kastelldev/kastell/issues"
72
+ },
73
+ "homepage": "https://kastell.dev",
74
+ "author": {
75
+ "name": "Ömer",
76
+ "email": "hello@omrfc.dev",
77
+ "url": "https://omrfc.dev"
78
+ },
79
+ "funding": {
80
+ "type": "github",
81
+ "url": "https://github.com/sponsors/omrfc"
82
+ },
83
+ "dependencies": {
84
+ "@modelcontextprotocol/sdk": "1.27.1",
85
+ "@napi-rs/keyring": "1.2.0",
86
+ "axios": "1.15.2",
87
+ "chalk": "5.6.2",
88
+ "commander": "14.0.3",
89
+ "grammy": "1.41.1",
90
+ "inquirer": "12.11.1",
91
+ "js-yaml": "4.1.1",
92
+ "ora": "9.3.0",
93
+ "p-limit": "7.3.0",
94
+ "semver": "7.7.2",
95
+ "zod": "4.3.6"
96
+ },
97
+ "overrides": {
98
+ "minimatch": "^10.2.4",
99
+ "ip-address": "^10.1.1"
100
+ },
101
+ "devDependencies": {
102
+ "@eslint/js": "^10.0.1",
103
+ "@stryker-mutator/core": "^9.6.0",
104
+ "@stryker-mutator/jest-runner": "^9.6.0",
105
+ "@stryker-mutator/typescript-checker": "^9.6.0",
106
+ "@types/inquirer": "^9.0.7",
107
+ "@types/jest": "^30.0.0",
108
+ "@types/js-yaml": "^4.0.9",
109
+ "@types/node": "^22.12.0",
110
+ "@types/semver": "7.7.0",
111
+ "esbuild": "^0.28.0",
112
+ "eslint": "^10.0.2",
113
+ "eslint-config-prettier": "^10.1.8",
114
+ "eslint-plugin-no-secrets": "^2.3.3",
115
+ "eslint-plugin-security": "^4.0.0",
116
+ "fast-check": "^4.7.0",
117
+ "ignore": "^7.0.5",
118
+ "jest": "^30.2.0",
119
+ "prettier": "^3.8.1",
120
+ "ts-jest": "^29.4.6",
121
+ "tsx": "^4.21.0",
122
+ "typescript": "^5.9.3",
123
+ "typescript-eslint": "^8.56.1"
124
+ }
125
+ }
@@ -1,11 +0,0 @@
1
- import inquirer from "inquirer";
2
- type SeparatorInstance = InstanceType<typeof inquirer.Separator>;
3
- type Choice = {
4
- name: string;
5
- value: string;
6
- description?: string;
7
- } | SeparatorInstance;
8
- export declare function buildSearchSource(term: string | undefined): Choice[];
9
- export declare function interactiveMenu(): Promise<string[] | null>;
10
- export {};
11
- //# sourceMappingURL=interactive.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/commands/interactive.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAyIhC,KAAK,iBAAiB,GAAG,YAAY,CAAC,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC;AACjE,KAAK,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,iBAAiB,CAAC;AAkBxF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAsBpE;AAu3BD,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAqChE"}