agentmap 0.7.1 → 0.9.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 (96) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +24 -0
  3. package/dist/cli.js +44 -12
  4. package/dist/cli.js.map +1 -1
  5. package/dist/extract/definitions.js +12 -12
  6. package/dist/extract/definitions.js.map +1 -1
  7. package/dist/extract/definitions.test.js +30 -259
  8. package/dist/extract/definitions.test.js.map +1 -1
  9. package/dist/extract/git-status.d.ts +11 -4
  10. package/dist/extract/git-status.d.ts.map +1 -1
  11. package/dist/extract/git-status.js +21 -16
  12. package/dist/extract/git-status.js.map +1 -1
  13. package/dist/extract/markdown.js +1 -1
  14. package/dist/extract/markdown.test.js +3 -3
  15. package/dist/extract/markdown.test.js.map +1 -1
  16. package/dist/extract/marker.js +1 -1
  17. package/dist/extract/marker.test.js +4 -4
  18. package/dist/extract/marker.test.js.map +1 -1
  19. package/dist/extract/submodules.d.ts +12 -0
  20. package/dist/extract/submodules.d.ts.map +1 -0
  21. package/dist/extract/submodules.js +234 -0
  22. package/dist/extract/submodules.js.map +1 -0
  23. package/dist/extract/submodules.test.d.ts +2 -0
  24. package/dist/extract/submodules.test.d.ts.map +1 -0
  25. package/dist/extract/submodules.test.js +84 -0
  26. package/dist/extract/submodules.test.js.map +1 -0
  27. package/dist/index.d.ts +4 -1
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +10 -9
  30. package/dist/index.js.map +1 -1
  31. package/dist/logger.d.ts +10 -0
  32. package/dist/logger.d.ts.map +1 -0
  33. package/dist/logger.js +41 -0
  34. package/dist/logger.js.map +1 -0
  35. package/dist/map/builder.d.ts +3 -3
  36. package/dist/map/builder.d.ts.map +1 -1
  37. package/dist/map/builder.js +59 -9
  38. package/dist/map/builder.js.map +1 -1
  39. package/dist/map/builder.test.d.ts +2 -0
  40. package/dist/map/builder.test.d.ts.map +1 -0
  41. package/dist/map/builder.test.js +66 -0
  42. package/dist/map/builder.test.js.map +1 -0
  43. package/dist/map/truncate.d.ts +7 -3
  44. package/dist/map/truncate.d.ts.map +1 -1
  45. package/dist/map/truncate.js +90 -9
  46. package/dist/map/truncate.js.map +1 -1
  47. package/dist/map/yaml.d.ts.map +1 -1
  48. package/dist/map/yaml.js +13 -3
  49. package/dist/map/yaml.js.map +1 -1
  50. package/dist/scanner.d.ts +9 -2
  51. package/dist/scanner.d.ts.map +1 -1
  52. package/dist/scanner.js +172 -49
  53. package/dist/scanner.js.map +1 -1
  54. package/dist/scanner.test.d.ts +2 -0
  55. package/dist/scanner.test.d.ts.map +1 -0
  56. package/dist/scanner.test.js +84 -0
  57. package/dist/scanner.test.js.map +1 -0
  58. package/dist/test-helpers/git-test-helpers.d.ts +13 -0
  59. package/dist/test-helpers/git-test-helpers.d.ts.map +1 -0
  60. package/dist/test-helpers/git-test-helpers.js +48 -0
  61. package/dist/test-helpers/git-test-helpers.js.map +1 -0
  62. package/dist/types.d.ts +42 -2
  63. package/dist/types.d.ts.map +1 -1
  64. package/package.json +15 -3
  65. package/src/cli.ts +164 -0
  66. package/src/extract/definitions.test.ts +2040 -0
  67. package/src/extract/definitions.ts +379 -0
  68. package/src/extract/git-status.test.ts +507 -0
  69. package/src/extract/git-status.ts +359 -0
  70. package/src/extract/markdown.test.ts +159 -0
  71. package/src/extract/markdown.ts +202 -0
  72. package/src/extract/marker.test.ts +566 -0
  73. package/src/extract/marker.ts +398 -0
  74. package/src/extract/submodules.test.ts +95 -0
  75. package/src/extract/submodules.ts +269 -0
  76. package/src/extract/utils.ts +27 -0
  77. package/src/index.ts +106 -0
  78. package/src/languages/cpp.ts +129 -0
  79. package/src/languages/go.ts +72 -0
  80. package/src/languages/index.ts +231 -0
  81. package/src/languages/javascript.ts +33 -0
  82. package/src/languages/python.ts +41 -0
  83. package/src/languages/rust.ts +72 -0
  84. package/src/languages/typescript.ts +74 -0
  85. package/src/languages/zig.ts +106 -0
  86. package/src/logger.ts +55 -0
  87. package/src/map/builder.test.ts +72 -0
  88. package/src/map/builder.ts +175 -0
  89. package/src/map/truncate.ts +188 -0
  90. package/src/map/yaml.ts +66 -0
  91. package/src/parser/index.ts +53 -0
  92. package/src/parser/languages.ts +64 -0
  93. package/src/scanner.test.ts +95 -0
  94. package/src/scanner.ts +364 -0
  95. package/src/test-helpers/git-test-helpers.ts +62 -0
  96. package/src/types.ts +191 -0
package/src/cli.ts ADDED
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env node
2
+ // CLI entrypoint for generating codebase maps.
3
+
4
+ import { writeFile } from 'fs/promises'
5
+ import { resolve } from 'path'
6
+ import { goke } from 'goke'
7
+ import { generateMap, toYaml } from './index.js'
8
+ import { createConsoleLogger } from './logger.js'
9
+
10
+ const cli = goke('agentmap')
11
+ const logger = createConsoleLogger()
12
+
13
+ function normalizePatterns(value: unknown): string[] | undefined {
14
+ if (typeof value === 'string') {
15
+ const normalized = value.trim()
16
+ return normalized ? [normalized] : undefined
17
+ }
18
+
19
+ if (!Array.isArray(value)) {
20
+ return undefined
21
+ }
22
+
23
+ const normalized = value
24
+ .filter((entry): entry is string => typeof entry === 'string')
25
+ .map(entry => entry.trim())
26
+ .filter(Boolean)
27
+
28
+ return normalized.length > 0 ? normalized : undefined
29
+ }
30
+
31
+ const NO_FILES_MESSAGE = `No files found with header comments.
32
+
33
+ To include a file in the map, add a comment at the top:
34
+
35
+ // Description of this file.
36
+ // What it does and why.
37
+
38
+ export function main() { ... }
39
+
40
+ The description will appear in the 'desc' field of the output.
41
+ `
42
+
43
+ cli
44
+ .command('[dir]', 'Generate a YAML map of the codebase')
45
+ .option('-o, --output <file>', 'Write output to file (default: stdout)')
46
+ .option('-i, --ignore <pattern>', 'Ignore pattern (can be repeated)')
47
+ .option('-f, --filter <pattern>', 'Filter pattern - only include matching files (can be repeated)')
48
+ .option('--no-submodules', 'Exclude submodule info from the map')
49
+ .option('--max-desc-chars <chars>', 'Max characters for descriptions (default: 300, rounds up to full line)')
50
+ .action(async (dir, options) => {
51
+ const targetDir = resolve(dir ?? '.')
52
+
53
+ try {
54
+ const map = await generateMap({
55
+ dir: targetDir,
56
+ ignore: normalizePatterns(options.ignore),
57
+ filter: normalizePatterns(options.filter),
58
+ diff: true,
59
+ submodules: options.noSubmodules ? false : undefined,
60
+ maxDescChars: options.maxDescChars != null && Number.isFinite(Number(options.maxDescChars)) && Number(options.maxDescChars) > 0
61
+ ? Number(options.maxDescChars)
62
+ : undefined,
63
+ logger,
64
+ })
65
+
66
+ // Check if map is empty (only has root key with empty object)
67
+ const rootKey = Object.keys(map)[0]
68
+ const rootValue = map[rootKey]
69
+ if (!rootValue || Object.keys(rootValue).length === 0) {
70
+ logger.warn(NO_FILES_MESSAGE.trimEnd())
71
+ process.exit(0)
72
+ }
73
+
74
+ const yaml = toYaml(map)
75
+
76
+ if (options.output) {
77
+ await writeFile(options.output, yaml, 'utf8')
78
+ logger.info(`Wrote map to ${options.output}`)
79
+ } else {
80
+ process.stdout.write(yaml.endsWith('\n') ? yaml : `${yaml}\n`)
81
+ }
82
+ } catch (err) {
83
+ logger.error('Error:', err instanceof Error ? err.message : err)
84
+ process.exit(1)
85
+ }
86
+ })
87
+
88
+ const PROMPT_TEXT = `Analyze the repository structure first. Look for clear separation of concerns:
89
+ - Monorepo workspaces (package.json workspaces, pnpm-workspace.yaml, etc.)
90
+ - Separate packages or modules
91
+ - Different languages or technology stacks
92
+ - Independent services or apps
93
+
94
+ If you find well-separated packages, use the Task tool to process them concurrently - assign each package/workspace to a separate task agent for speed.
95
+
96
+ For each package/area, identify the most important files - entry points, core modules, main utilities, and key abstractions.
97
+
98
+ For each important file, add a descriptive comment at the top (before any imports or code). The comment should:
99
+ - Be 2-4 lines describing what the file does and why it exists
100
+ - Use the appropriate comment style for the language (// for JS/TS, # for Python, //! for Rust modules, etc.)
101
+ - If the file is an entry point (CLI, main, server start, etc.), mark it as such in the description
102
+ - If the file already has a top comment, review and update it to be accurate and descriptive - don't skip it
103
+ - If the file has a shebang (#!/...), keep it as the first line and add the description comment immediately after
104
+ - Ensure the description comment appears above any import statements in the file
105
+
106
+ Examples:
107
+
108
+ TypeScript/JavaScript:
109
+ // CLI entrypoint for the application.
110
+ // Parses command-line arguments and orchestrates the main workflow.
111
+ import { run } from "./runner"
112
+
113
+ Python:
114
+ # Database connection manager.
115
+ # Handles connection pooling and provides transaction helpers.
116
+ import asyncio
117
+
118
+ Rust:
119
+ //! HTTP server module.
120
+ //! Entry point for the web API, configures routes and middleware.
121
+ use crate::server::start
122
+
123
+ With shebang (shell scripts, node CLI, etc.):
124
+ #!/usr/bin/env node
125
+ // CLI entrypoint for the build tool.
126
+ // Handles argument parsing and runs the build pipeline.
127
+ import { build } from "./build"
128
+
129
+ After adding comments to all important files, run \`npx -y agentmap\` to verify the files appear in the generated map.
130
+
131
+ You can run this prompt again anytime to keep file descriptions up to date as the codebase evolves.
132
+
133
+ Finally, add these instructions to the project's AGENTS.md or CLAUDE.md file (create it if it doesn't exist):
134
+
135
+ \`\`\`markdown
136
+ ## Codebase Map
137
+
138
+ Run \`npx -y agentmap\` to see the repo structure with file descriptions, definitions, and git diff status.
139
+
140
+ When editing files with top-level description comments, keep them accurate and up-to-date with your changes.
141
+ \`\`\`
142
+
143
+ For OpenCode users, also set up the agentmap plugin so future sessions automatically get the codebase map:
144
+ 1. Add "@agentmap/opencode" to the plugin array in ~/.config/opencode/config.json
145
+ - Create the file if it doesn't exist
146
+ - If a plugin array already exists, append to it
147
+ - Example: { "plugin": ["@agentmap/opencode"] }
148
+ 2. Tell the user to restart OpenCode to activate the plugin.`
149
+
150
+ cli
151
+ .command('prompt', 'Generate a prompt to help AI agents add file descriptions')
152
+ .action(() => {
153
+ process.stdout.write(`${PROMPT_TEXT}\n`)
154
+ })
155
+
156
+ cli.help()
157
+ cli.version('0.8.0')
158
+
159
+ if (process.argv.slice(2).some(arg => arg === '-v' || arg === '--version')) {
160
+ cli.outputVersion()
161
+ process.exit(0)
162
+ }
163
+
164
+ cli.parse()