codegate-ai 0.1.0

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 (147) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +390 -0
  3. package/dist/cli-prompts.d.ts +6 -0
  4. package/dist/cli-prompts.js +94 -0
  5. package/dist/cli.d.ts +64 -0
  6. package/dist/cli.js +443 -0
  7. package/dist/commands/run-policy.d.ts +27 -0
  8. package/dist/commands/run-policy.js +39 -0
  9. package/dist/commands/scan-command/helpers.d.ts +28 -0
  10. package/dist/commands/scan-command/helpers.js +233 -0
  11. package/dist/commands/scan-command.d.ts +90 -0
  12. package/dist/commands/scan-command.js +403 -0
  13. package/dist/commands/undo.d.ts +5 -0
  14. package/dist/commands/undo.js +14 -0
  15. package/dist/config.d.ts +50 -0
  16. package/dist/config.js +187 -0
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.js +1 -0
  19. package/dist/knowledge-base/claude-code.json +152 -0
  20. package/dist/knowledge-base/cline.json +224 -0
  21. package/dist/knowledge-base/codex.json +162 -0
  22. package/dist/knowledge-base/copilot.json +132 -0
  23. package/dist/knowledge-base/cursor.json +134 -0
  24. package/dist/knowledge-base/gemini-cli.json +112 -0
  25. package/dist/knowledge-base/jetbrains-junie.json +208 -0
  26. package/dist/knowledge-base/kiro.json +102 -0
  27. package/dist/knowledge-base/opencode.json +128 -0
  28. package/dist/knowledge-base/roo-code.json +116 -0
  29. package/dist/knowledge-base/schema.json +77 -0
  30. package/dist/knowledge-base/windsurf.json +80 -0
  31. package/dist/knowledge-base/zed.json +88 -0
  32. package/dist/layer1-discovery/config-parser.d.ts +12 -0
  33. package/dist/layer1-discovery/config-parser.js +52 -0
  34. package/dist/layer1-discovery/file-walker.d.ts +13 -0
  35. package/dist/layer1-discovery/file-walker.js +77 -0
  36. package/dist/layer1-discovery/knowledge-base.d.ts +36 -0
  37. package/dist/layer1-discovery/knowledge-base.js +58 -0
  38. package/dist/layer1-discovery/tool-detector.d.ts +20 -0
  39. package/dist/layer1-discovery/tool-detector.js +138 -0
  40. package/dist/layer2-static/detectors/command-exec.d.ts +11 -0
  41. package/dist/layer2-static/detectors/command-exec.js +343 -0
  42. package/dist/layer2-static/detectors/consent-bypass.d.ts +8 -0
  43. package/dist/layer2-static/detectors/consent-bypass.js +330 -0
  44. package/dist/layer2-static/detectors/env-override.d.ts +8 -0
  45. package/dist/layer2-static/detectors/env-override.js +132 -0
  46. package/dist/layer2-static/detectors/git-hooks.d.ts +11 -0
  47. package/dist/layer2-static/detectors/git-hooks.js +61 -0
  48. package/dist/layer2-static/detectors/ide-settings.d.ts +8 -0
  49. package/dist/layer2-static/detectors/ide-settings.js +66 -0
  50. package/dist/layer2-static/detectors/plugin-manifest.d.ts +9 -0
  51. package/dist/layer2-static/detectors/plugin-manifest.js +1943 -0
  52. package/dist/layer2-static/detectors/rule-file.d.ts +7 -0
  53. package/dist/layer2-static/detectors/rule-file.js +299 -0
  54. package/dist/layer2-static/detectors/symlink.d.ts +9 -0
  55. package/dist/layer2-static/detectors/symlink.js +45 -0
  56. package/dist/layer2-static/engine.d.ts +28 -0
  57. package/dist/layer2-static/engine.js +83 -0
  58. package/dist/layer2-static/evidence.d.ts +12 -0
  59. package/dist/layer2-static/evidence.js +128 -0
  60. package/dist/layer2-static/rule-engine.d.ts +24 -0
  61. package/dist/layer2-static/rule-engine.js +138 -0
  62. package/dist/layer2-static/state/scan-state.d.ts +32 -0
  63. package/dist/layer2-static/state/scan-state.js +296 -0
  64. package/dist/layer3-dynamic/command-builder.d.ts +15 -0
  65. package/dist/layer3-dynamic/command-builder.js +39 -0
  66. package/dist/layer3-dynamic/local-text-analysis.d.ts +19 -0
  67. package/dist/layer3-dynamic/local-text-analysis.js +73 -0
  68. package/dist/layer3-dynamic/meta-agent.d.ts +17 -0
  69. package/dist/layer3-dynamic/meta-agent.js +33 -0
  70. package/dist/layer3-dynamic/prompt-templates/local-text-analysis.md +32 -0
  71. package/dist/layer3-dynamic/prompt-templates/security-analysis.md +13 -0
  72. package/dist/layer3-dynamic/prompt-templates/tool-poisoning.md +15 -0
  73. package/dist/layer3-dynamic/resource-fetcher.d.ts +25 -0
  74. package/dist/layer3-dynamic/resource-fetcher.js +119 -0
  75. package/dist/layer3-dynamic/sandbox.d.ts +13 -0
  76. package/dist/layer3-dynamic/sandbox.js +40 -0
  77. package/dist/layer3-dynamic/tool-description-acquisition.d.ts +22 -0
  78. package/dist/layer3-dynamic/tool-description-acquisition.js +76 -0
  79. package/dist/layer3-dynamic/tool-description-scanner.d.ts +11 -0
  80. package/dist/layer3-dynamic/tool-description-scanner.js +53 -0
  81. package/dist/layer3-dynamic/toxic-flow.d.ts +12 -0
  82. package/dist/layer3-dynamic/toxic-flow.js +57 -0
  83. package/dist/layer4-remediation/actions/quarantine.d.ts +1 -0
  84. package/dist/layer4-remediation/actions/quarantine.js +8 -0
  85. package/dist/layer4-remediation/actions/remove-field.d.ts +5 -0
  86. package/dist/layer4-remediation/actions/remove-field.js +53 -0
  87. package/dist/layer4-remediation/actions/replace-value.d.ts +5 -0
  88. package/dist/layer4-remediation/actions/replace-value.js +26 -0
  89. package/dist/layer4-remediation/actions/strip-unicode.d.ts +5 -0
  90. package/dist/layer4-remediation/actions/strip-unicode.js +8 -0
  91. package/dist/layer4-remediation/backup-manager.d.ts +32 -0
  92. package/dist/layer4-remediation/backup-manager.js +138 -0
  93. package/dist/layer4-remediation/diff-generator.d.ts +6 -0
  94. package/dist/layer4-remediation/diff-generator.js +29 -0
  95. package/dist/layer4-remediation/remediation-runner.d.ts +36 -0
  96. package/dist/layer4-remediation/remediation-runner.js +230 -0
  97. package/dist/layer4-remediation/remediator.d.ts +36 -0
  98. package/dist/layer4-remediation/remediator.js +117 -0
  99. package/dist/path-display.d.ts +1 -0
  100. package/dist/path-display.js +20 -0
  101. package/dist/pipeline.d.ts +34 -0
  102. package/dist/pipeline.js +259 -0
  103. package/dist/report-summary.d.ts +6 -0
  104. package/dist/report-summary.js +48 -0
  105. package/dist/reporter/html.d.ts +2 -0
  106. package/dist/reporter/html.js +103 -0
  107. package/dist/reporter/json.d.ts +2 -0
  108. package/dist/reporter/json.js +3 -0
  109. package/dist/reporter/markdown.d.ts +2 -0
  110. package/dist/reporter/markdown.js +52 -0
  111. package/dist/reporter/sarif.d.ts +2 -0
  112. package/dist/reporter/sarif.js +84 -0
  113. package/dist/reporter/terminal.d.ts +5 -0
  114. package/dist/reporter/terminal.js +94 -0
  115. package/dist/runtime/signal-handlers.d.ts +10 -0
  116. package/dist/runtime/signal-handlers.js +17 -0
  117. package/dist/scan-target/helpers.d.ts +20 -0
  118. package/dist/scan-target/helpers.js +268 -0
  119. package/dist/scan-target/staging.d.ts +5 -0
  120. package/dist/scan-target/staging.js +114 -0
  121. package/dist/scan-target/types.d.ts +18 -0
  122. package/dist/scan-target/types.js +1 -0
  123. package/dist/scan-target.d.ts +3 -0
  124. package/dist/scan-target.js +31 -0
  125. package/dist/scan.d.ts +54 -0
  126. package/dist/scan.js +593 -0
  127. package/dist/tui/app.d.ts +10 -0
  128. package/dist/tui/app.js +21 -0
  129. package/dist/tui/theme.d.ts +8 -0
  130. package/dist/tui/theme.js +7 -0
  131. package/dist/tui/views/dashboard.d.ts +6 -0
  132. package/dist/tui/views/dashboard.js +8 -0
  133. package/dist/tui/views/deep-scan-consent.d.ts +5 -0
  134. package/dist/tui/views/deep-scan-consent.js +6 -0
  135. package/dist/tui/views/progress.d.ts +4 -0
  136. package/dist/tui/views/progress.js +6 -0
  137. package/dist/tui/views/summary.d.ts +5 -0
  138. package/dist/tui/views/summary.js +16 -0
  139. package/dist/types/discovery.d.ts +12 -0
  140. package/dist/types/discovery.js +1 -0
  141. package/dist/types/finding.d.ts +46 -0
  142. package/dist/types/finding.js +15 -0
  143. package/dist/types/report.d.ts +25 -0
  144. package/dist/types/report.js +23 -0
  145. package/dist/wrapper.d.ts +35 -0
  146. package/dist/wrapper.js +220 -0
  147. package/package.json +97 -0
@@ -0,0 +1,116 @@
1
+ {
2
+ "tool": "roo-code",
3
+ "version_range": ">=0.1.0",
4
+ "config_paths": [
5
+ {
6
+ "path": ".roo/settings.json",
7
+ "scope": "project",
8
+ "format": "jsonc",
9
+ "risk_surface": ["mcp_config", "consent_bypass", "command_exec"]
10
+ },
11
+ {
12
+ "path": ".roo/settings.json",
13
+ "scope": "user",
14
+ "format": "jsonc",
15
+ "risk_surface": ["mcp_config", "consent_bypass", "command_exec"]
16
+ },
17
+ {
18
+ "path": ".roo/mcp.json",
19
+ "scope": "project",
20
+ "format": "jsonc",
21
+ "risk_surface": ["mcp_config", "command_exec", "remote_resource", "consent_bypass"],
22
+ "fields_of_interest": {
23
+ "mcpServers.*.command": "stdio command",
24
+ "mcpServers.*.args": "stdio command arguments",
25
+ "mcpServers.*.url": "remote endpoint",
26
+ "mcpServers.*.env": "runtime environment variables",
27
+ "mcpServers.*.alwaysAllow": "per-server auto-approval",
28
+ "mcpServers.*.disabledTools": "restricted tool list"
29
+ }
30
+ },
31
+ {
32
+ "path": ".roo/mcp.json",
33
+ "scope": "user",
34
+ "format": "jsonc",
35
+ "risk_surface": ["mcp_config", "command_exec", "remote_resource", "consent_bypass"],
36
+ "fields_of_interest": {
37
+ "mcpServers.*.command": "stdio command",
38
+ "mcpServers.*.args": "stdio command arguments",
39
+ "mcpServers.*.url": "remote endpoint",
40
+ "mcpServers.*.env": "runtime environment variables",
41
+ "mcpServers.*.alwaysAllow": "per-server auto-approval",
42
+ "mcpServers.*.disabledTools": "restricted tool list"
43
+ }
44
+ },
45
+ {
46
+ "path": ".roorules",
47
+ "scope": "project",
48
+ "format": "markdown",
49
+ "risk_surface": ["prompt_injection", "unicode_backdoor"]
50
+ },
51
+ {
52
+ "path": "AGENTS.md",
53
+ "scope": "project",
54
+ "format": "markdown",
55
+ "risk_surface": ["prompt_injection", "unicode_backdoor"]
56
+ },
57
+ {
58
+ "path": ".roo/marketplace.json",
59
+ "scope": "project",
60
+ "format": "jsonc",
61
+ "risk_surface": ["plugin_config", "remote_resource", "command_exec"]
62
+ },
63
+ {
64
+ "path": ".roo/marketplace.json",
65
+ "scope": "user",
66
+ "format": "jsonc",
67
+ "risk_surface": ["plugin_config", "remote_resource", "command_exec"]
68
+ }
69
+ ],
70
+ "skill_paths": [
71
+ {
72
+ "path": ".roo/rules/**/*.md",
73
+ "scope": "project",
74
+ "type": "rule_file",
75
+ "risk_surface": ["prompt_injection", "unicode_backdoor"]
76
+ },
77
+ {
78
+ "path": ".roo/rules/**/*.md",
79
+ "scope": "user",
80
+ "type": "rule_file",
81
+ "risk_surface": ["prompt_injection", "unicode_backdoor"]
82
+ },
83
+ {
84
+ "path": ".roo/skills/**/*.md",
85
+ "scope": "project",
86
+ "type": "skill",
87
+ "risk_surface": ["prompt_injection"]
88
+ },
89
+ {
90
+ "path": ".roo/skills/**/*.md",
91
+ "scope": "user",
92
+ "type": "skill",
93
+ "risk_surface": ["prompt_injection"]
94
+ },
95
+ {
96
+ "path": ".roo/commands/**/*.md",
97
+ "scope": "project",
98
+ "type": "slash_command",
99
+ "risk_surface": ["prompt_injection", "command_exec"]
100
+ },
101
+ {
102
+ "path": ".roo/commands/**/*.md",
103
+ "scope": "user",
104
+ "type": "slash_command",
105
+ "risk_surface": ["prompt_injection", "command_exec"]
106
+ }
107
+ ],
108
+ "extension_mechanisms": [
109
+ {
110
+ "type": "roo_marketplace_package",
111
+ "install_pattern": "roo marketplace install <package>",
112
+ "risk": "marketplace packages can introduce arbitrary command execution surfaces",
113
+ "fetchable": true
114
+ }
115
+ ]
116
+ }
@@ -0,0 +1,77 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://codegate.dev/schemas/knowledge-base-entry.json",
4
+ "schema_version": "1.0.0",
5
+ "title": "CodeGate Knowledge Base Entry",
6
+ "type": "object",
7
+ "required": ["tool", "version_range", "config_paths"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "tool": {
11
+ "type": "string",
12
+ "minLength": 1
13
+ },
14
+ "version_range": {
15
+ "type": "string",
16
+ "minLength": 1
17
+ },
18
+ "config_paths": {
19
+ "type": "array",
20
+ "minItems": 1,
21
+ "items": {
22
+ "type": "object",
23
+ "required": ["path", "scope", "format", "risk_surface"],
24
+ "additionalProperties": false,
25
+ "properties": {
26
+ "path": { "type": "string", "minLength": 1 },
27
+ "scope": { "type": "string", "enum": ["project", "user"] },
28
+ "format": {
29
+ "type": "string",
30
+ "enum": ["jsonc", "json", "toml", "yaml", "dotenv", "text", "markdown"]
31
+ },
32
+ "risk_surface": {
33
+ "type": "array",
34
+ "minItems": 1,
35
+ "items": { "type": "string", "minLength": 1 }
36
+ },
37
+ "fields_of_interest": {
38
+ "type": "object",
39
+ "additionalProperties": { "type": "string" }
40
+ }
41
+ }
42
+ }
43
+ },
44
+ "skill_paths": {
45
+ "type": "array",
46
+ "items": {
47
+ "type": "object",
48
+ "required": ["path", "scope", "type", "risk_surface"],
49
+ "additionalProperties": false,
50
+ "properties": {
51
+ "path": { "type": "string", "minLength": 1 },
52
+ "scope": { "type": "string", "enum": ["project", "user"] },
53
+ "type": { "type": "string", "minLength": 1 },
54
+ "risk_surface": {
55
+ "type": "array",
56
+ "minItems": 1,
57
+ "items": { "type": "string", "minLength": 1 }
58
+ }
59
+ }
60
+ }
61
+ },
62
+ "extension_mechanisms": {
63
+ "type": "array",
64
+ "items": {
65
+ "type": "object",
66
+ "required": ["type", "install_pattern", "risk", "fetchable"],
67
+ "additionalProperties": false,
68
+ "properties": {
69
+ "type": { "type": "string", "minLength": 1 },
70
+ "install_pattern": { "type": "string", "minLength": 1 },
71
+ "risk": { "type": "string", "minLength": 1 },
72
+ "fetchable": { "type": "boolean" }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }
@@ -0,0 +1,80 @@
1
+ {
2
+ "tool": "windsurf",
3
+ "version_range": ">=0.1.0",
4
+ "config_paths": [
5
+ {
6
+ "path": ".windsurfrules",
7
+ "scope": "project",
8
+ "format": "markdown",
9
+ "risk_surface": ["prompt_injection", "unicode_backdoor"]
10
+ },
11
+ {
12
+ "path": ".windsurf/mcp.json",
13
+ "scope": "project",
14
+ "format": "jsonc",
15
+ "risk_surface": ["command_exec", "mcp_config", "remote_resource"]
16
+ },
17
+ {
18
+ "path": ".windsurf/mcp.json",
19
+ "scope": "user",
20
+ "format": "jsonc",
21
+ "risk_surface": ["command_exec", "mcp_config", "remote_resource"]
22
+ },
23
+ {
24
+ "path": ".windsurf/hooks.json",
25
+ "scope": "project",
26
+ "format": "jsonc",
27
+ "risk_surface": ["hooks", "command_exec"]
28
+ },
29
+ {
30
+ "path": ".windsurf/hooks.json",
31
+ "scope": "user",
32
+ "format": "jsonc",
33
+ "risk_surface": ["hooks", "command_exec"]
34
+ },
35
+ {
36
+ "path": ".windsurf/plugins.json",
37
+ "scope": "project",
38
+ "format": "jsonc",
39
+ "risk_surface": ["plugin_config", "command_exec", "remote_resource"]
40
+ },
41
+ {
42
+ "path": ".windsurf/plugins.json",
43
+ "scope": "user",
44
+ "format": "jsonc",
45
+ "risk_surface": ["plugin_config", "command_exec", "remote_resource"]
46
+ },
47
+ {
48
+ "path": ".vscode/settings.json",
49
+ "scope": "project",
50
+ "format": "json",
51
+ "risk_surface": ["ide_settings"]
52
+ }
53
+ ],
54
+ "skill_paths": [
55
+ {
56
+ "path": ".windsurf/workflows/*.md",
57
+ "scope": "project",
58
+ "type": "workflow",
59
+ "risk_surface": ["prompt_injection", "command_exec"]
60
+ },
61
+ {
62
+ "path": ".windsurf/workflows/*.md",
63
+ "scope": "user",
64
+ "type": "workflow",
65
+ "risk_surface": ["prompt_injection", "command_exec"]
66
+ },
67
+ {
68
+ "path": ".windsurf/memories/*.md",
69
+ "scope": "project",
70
+ "type": "memory",
71
+ "risk_surface": ["prompt_injection", "unicode_backdoor"]
72
+ },
73
+ {
74
+ "path": ".windsurf/memories/*.md",
75
+ "scope": "user",
76
+ "type": "memory",
77
+ "risk_surface": ["prompt_injection", "unicode_backdoor"]
78
+ }
79
+ ]
80
+ }
@@ -0,0 +1,88 @@
1
+ {
2
+ "tool": "zed",
3
+ "version_range": ">=0.1.0",
4
+ "config_paths": [
5
+ {
6
+ "path": ".zed/settings.json",
7
+ "scope": "project",
8
+ "format": "jsonc",
9
+ "risk_surface": ["mcp_config", "command_exec", "consent_bypass"],
10
+ "fields_of_interest": {
11
+ "context_servers.*.command": "stdio command",
12
+ "context_servers.*.args": "stdio command arguments",
13
+ "context_servers.*.url": "remote endpoint",
14
+ "context_servers.*.env": "runtime environment variables"
15
+ }
16
+ },
17
+ {
18
+ "path": ".zed/settings.json",
19
+ "scope": "user",
20
+ "format": "jsonc",
21
+ "risk_surface": ["mcp_config", "command_exec", "consent_bypass"],
22
+ "fields_of_interest": {
23
+ "context_servers.*.command": "stdio command",
24
+ "context_servers.*.args": "stdio command arguments",
25
+ "context_servers.*.url": "remote endpoint",
26
+ "context_servers.*.env": "runtime environment variables"
27
+ }
28
+ },
29
+ {
30
+ "path": ".zed/context-servers.json",
31
+ "scope": "project",
32
+ "format": "jsonc",
33
+ "risk_surface": ["mcp_config", "command_exec", "remote_resource"]
34
+ },
35
+ {
36
+ "path": ".zed/context-servers.json",
37
+ "scope": "user",
38
+ "format": "jsonc",
39
+ "risk_surface": ["mcp_config", "command_exec", "remote_resource"]
40
+ },
41
+ {
42
+ "path": ".zed/extensions.json",
43
+ "scope": "project",
44
+ "format": "jsonc",
45
+ "risk_surface": ["plugin_config", "remote_resource"]
46
+ },
47
+ {
48
+ "path": ".zed/extensions.json",
49
+ "scope": "user",
50
+ "format": "jsonc",
51
+ "risk_surface": ["plugin_config", "remote_resource"]
52
+ }
53
+ ],
54
+ "skill_paths": [
55
+ {
56
+ "path": ".zed/rules/**/*.md",
57
+ "scope": "project",
58
+ "type": "rule_file",
59
+ "risk_surface": ["prompt_injection", "unicode_backdoor"]
60
+ },
61
+ {
62
+ "path": ".zed/rules/**/*.md",
63
+ "scope": "user",
64
+ "type": "rule_file",
65
+ "risk_surface": ["prompt_injection", "unicode_backdoor"]
66
+ },
67
+ {
68
+ "path": ".zed/commands/**/*.md",
69
+ "scope": "project",
70
+ "type": "slash_command",
71
+ "risk_surface": ["prompt_injection", "command_exec"]
72
+ },
73
+ {
74
+ "path": ".zed/commands/**/*.md",
75
+ "scope": "user",
76
+ "type": "slash_command",
77
+ "risk_surface": ["prompt_injection", "command_exec"]
78
+ }
79
+ ],
80
+ "extension_mechanisms": [
81
+ {
82
+ "type": "zed_extension",
83
+ "install_pattern": "zed extension install <id>",
84
+ "risk": "extensions can register slash commands and MCP/context servers",
85
+ "fetchable": true
86
+ }
87
+ ]
88
+ }
@@ -0,0 +1,12 @@
1
+ import type { DiscoveryFormat } from "../types/discovery.js";
2
+ export interface ParseSuccess {
3
+ ok: true;
4
+ data: unknown;
5
+ }
6
+ export interface ParseFailure {
7
+ ok: false;
8
+ error: string;
9
+ }
10
+ export type ParseResult = ParseSuccess | ParseFailure;
11
+ export declare function parseConfigContent(content: string, format: DiscoveryFormat): ParseResult;
12
+ export declare function parseConfigFile(path: string, format: DiscoveryFormat): ParseResult;
@@ -0,0 +1,52 @@
1
+ import { readFileSync } from "node:fs";
2
+ import dotenv from "dotenv";
3
+ import yaml from "js-yaml";
4
+ import { parse as parseJsonc, printParseErrorCode } from "jsonc-parser";
5
+ import { parse as parseToml } from "smol-toml";
6
+ function fail(error) {
7
+ const message = error instanceof Error ? error.message : String(error);
8
+ return { ok: false, error: `parse error: ${message}` };
9
+ }
10
+ export function parseConfigContent(content, format) {
11
+ try {
12
+ if (content.includes("\u0000")) {
13
+ return fail(new Error("binary or corrupt file content"));
14
+ }
15
+ if (format === "json") {
16
+ return { ok: true, data: JSON.parse(content) };
17
+ }
18
+ if (format === "jsonc") {
19
+ const errors = [];
20
+ const data = parseJsonc(content, errors);
21
+ if (errors.length > 0) {
22
+ const firstError = errors[0];
23
+ return fail(new Error(`jsonc ${printParseErrorCode(firstError.error)} at offset ${firstError.offset}`));
24
+ }
25
+ return { ok: true, data: data };
26
+ }
27
+ if (format === "toml") {
28
+ return { ok: true, data: parseToml(content) };
29
+ }
30
+ if (format === "yaml") {
31
+ return { ok: true, data: yaml.load(content) };
32
+ }
33
+ if (format === "dotenv") {
34
+ return { ok: true, data: dotenv.parse(content) };
35
+ }
36
+ if (format === "text" || format === "markdown") {
37
+ return { ok: true, data: content };
38
+ }
39
+ return fail(new Error(`unsupported format: ${format}`));
40
+ }
41
+ catch (error) {
42
+ return fail(error);
43
+ }
44
+ }
45
+ export function parseConfigFile(path, format) {
46
+ try {
47
+ return parseConfigContent(readFileSync(path, "utf8"), format);
48
+ }
49
+ catch (error) {
50
+ return fail(error);
51
+ }
52
+ }
@@ -0,0 +1,13 @@
1
+ export interface WalkerOptions {
2
+ maxDepth?: number;
3
+ }
4
+ export interface SymlinkEscape {
5
+ path: string;
6
+ target: string;
7
+ }
8
+ export interface WalkResult {
9
+ files: string[];
10
+ symlinkEscapes: SymlinkEscape[];
11
+ circularSymlinks: string[];
12
+ }
13
+ export declare function walkProjectTree(root: string, options?: WalkerOptions): WalkResult;
@@ -0,0 +1,77 @@
1
+ import { existsSync, readdirSync, realpathSync } from "node:fs";
2
+ import { isAbsolute, join, relative, sep } from "node:path";
3
+ const SKIP_DIRS = new Set([
4
+ "node_modules",
5
+ "dist",
6
+ "build",
7
+ "__pycache__",
8
+ ".venv",
9
+ "vendor",
10
+ ".git/objects",
11
+ ".git/refs",
12
+ ]);
13
+ function isOutsideRoot(root, candidate) {
14
+ const rel = relative(root, candidate);
15
+ return rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute(rel);
16
+ }
17
+ function shouldSkipDirectory(relativePath) {
18
+ if (relativePath === ".git/hooks" || relativePath.startsWith(`.git/hooks${sep}`)) {
19
+ return false;
20
+ }
21
+ if (relativePath === ".git" || relativePath.startsWith(`.git${sep}`)) {
22
+ return true;
23
+ }
24
+ const normalized = relativePath.split(sep).join("/");
25
+ return SKIP_DIRS.has(normalized) || SKIP_DIRS.has(normalized.split("/").at(-1) ?? normalized);
26
+ }
27
+ export function walkProjectTree(root, options = {}) {
28
+ const maxDepth = options.maxDepth ?? 5;
29
+ const files = [];
30
+ const symlinkEscapes = [];
31
+ const circularSymlinks = [];
32
+ function walkDirectory(currentDir, depth) {
33
+ if (depth > maxDepth) {
34
+ return;
35
+ }
36
+ const entries = readdirSync(currentDir, { withFileTypes: true });
37
+ for (const entry of entries) {
38
+ const fullPath = join(currentDir, entry.name);
39
+ const relPath = relative(root, fullPath);
40
+ if (entry.isSymbolicLink()) {
41
+ try {
42
+ const target = realpathSync(fullPath);
43
+ if (isOutsideRoot(root, target)) {
44
+ symlinkEscapes.push({ path: fullPath, target });
45
+ }
46
+ }
47
+ catch (error) {
48
+ const err = error;
49
+ if (err.code === "ELOOP") {
50
+ circularSymlinks.push(fullPath);
51
+ }
52
+ }
53
+ files.push(fullPath);
54
+ continue;
55
+ }
56
+ if (entry.isDirectory()) {
57
+ if (relPath === ".git") {
58
+ const hooksDir = join(fullPath, "hooks");
59
+ if (existsSync(hooksDir)) {
60
+ walkDirectory(hooksDir, depth + 1);
61
+ }
62
+ continue;
63
+ }
64
+ if (shouldSkipDirectory(relPath)) {
65
+ continue;
66
+ }
67
+ walkDirectory(fullPath, depth + 1);
68
+ continue;
69
+ }
70
+ if (entry.isFile()) {
71
+ files.push(fullPath);
72
+ }
73
+ }
74
+ }
75
+ walkDirectory(root, 0);
76
+ return { files, symlinkEscapes, circularSymlinks };
77
+ }
@@ -0,0 +1,36 @@
1
+ export interface KnowledgeBasePathEntry {
2
+ path: string;
3
+ scope: "project" | "user";
4
+ format: "jsonc" | "json" | "toml" | "yaml" | "dotenv" | "text" | "markdown";
5
+ risk_surface: string[];
6
+ fields_of_interest?: Record<string, string>;
7
+ }
8
+ export interface KnowledgeBaseSkillEntry {
9
+ path: string;
10
+ scope: "project" | "user";
11
+ type: string;
12
+ risk_surface: string[];
13
+ }
14
+ export interface KnowledgeBaseExtensionMechanism {
15
+ type: string;
16
+ install_pattern: string;
17
+ risk: string;
18
+ fetchable: boolean;
19
+ }
20
+ export interface KnowledgeBaseEntry {
21
+ tool: string;
22
+ version_range: string;
23
+ config_paths: KnowledgeBasePathEntry[];
24
+ skill_paths?: KnowledgeBaseSkillEntry[];
25
+ extension_mechanisms?: KnowledgeBaseExtensionMechanism[];
26
+ }
27
+ export interface KnowledgeBaseLoadResult {
28
+ schemaVersion: string;
29
+ entries: KnowledgeBaseEntry[];
30
+ }
31
+ export interface ValidationResult {
32
+ valid: boolean;
33
+ errors: string[];
34
+ }
35
+ export declare function validateKnowledgeBaseEntry(candidate: unknown, path?: string): ValidationResult;
36
+ export declare function loadKnowledgeBase(baseDir?: string): KnowledgeBaseLoadResult;
@@ -0,0 +1,58 @@
1
+ import { readdirSync, readFileSync } from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { dirname, extname, join, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ const defaultKnowledgeBaseDir = resolve(dirname(fileURLToPath(import.meta.url)), "../knowledge-base");
6
+ const schemaPath = join(defaultKnowledgeBaseDir, "schema.json");
7
+ const require = createRequire(import.meta.url);
8
+ const Ajv = require("ajv");
9
+ function loadSchema(path = schemaPath) {
10
+ const raw = readFileSync(path, "utf8");
11
+ return JSON.parse(raw);
12
+ }
13
+ function createValidator(path = schemaPath) {
14
+ const ajv = new Ajv({ allErrors: true, strict: false });
15
+ const schema = JSON.parse(readFileSync(path, "utf8"));
16
+ return ajv.compile(schema);
17
+ }
18
+ function toErrors(errors) {
19
+ if (!errors) {
20
+ return [];
21
+ }
22
+ return errors.map((error) => {
23
+ const location = error.instancePath === "" ? "<root>" : error.instancePath;
24
+ return `${location}: ${error.message ?? "validation error"}`;
25
+ });
26
+ }
27
+ export function validateKnowledgeBaseEntry(candidate, path = schemaPath) {
28
+ const validator = createValidator(path);
29
+ const valid = validator(candidate);
30
+ return {
31
+ valid,
32
+ errors: toErrors(validator.errors),
33
+ };
34
+ }
35
+ export function loadKnowledgeBase(baseDir = defaultKnowledgeBaseDir) {
36
+ const schema = loadSchema(join(baseDir, "schema.json"));
37
+ const validator = createValidator(join(baseDir, "schema.json"));
38
+ const entryFiles = readdirSync(baseDir)
39
+ .filter((file) => extname(file) === ".json")
40
+ .filter((file) => file !== "schema.json")
41
+ .sort();
42
+ const entries = [];
43
+ for (const entryFile of entryFiles) {
44
+ const fullPath = join(baseDir, entryFile);
45
+ const raw = readFileSync(fullPath, "utf8");
46
+ const parsed = JSON.parse(raw);
47
+ const valid = validator(parsed);
48
+ if (!valid) {
49
+ const reasons = toErrors(validator.errors).join("; ");
50
+ throw new Error(`Invalid knowledge base entry: ${entryFile} (${reasons})`);
51
+ }
52
+ entries.push(parsed);
53
+ }
54
+ return {
55
+ schemaVersion: schema.schema_version ?? "unknown",
56
+ entries,
57
+ };
58
+ }
@@ -0,0 +1,20 @@
1
+ export type ToolName = "claude-code" | "codex-cli" | "opencode" | "cursor" | "windsurf" | "github-copilot" | "kiro" | "vscode" | "jetbrains";
2
+ export interface ToolDetection {
3
+ tool: ToolName;
4
+ installed: boolean;
5
+ version: string | null;
6
+ path: string | null;
7
+ source: "path" | "app-bundle" | "extension" | "none";
8
+ }
9
+ export interface ToolDetectorDeps {
10
+ platform: NodeJS.Platform;
11
+ homedir: string;
12
+ which: (binary: string) => string | undefined;
13
+ execVersion: (binary: string) => string | null;
14
+ pathExists: (path: string) => boolean;
15
+ listDirectory: (path: string) => string[];
16
+ }
17
+ export interface ToolDetectorOptions {
18
+ includeVersions?: boolean;
19
+ }
20
+ export declare function detectTools(customDeps?: ToolDetectorDeps, options?: ToolDetectorOptions): ToolDetection[];