Repository navigation
Releases: syahrul84/codemap
Release list
codemap v0.1.4
Rust support, for crates and Cargo workspaces:
- Structs, enums, traits, functions, methods from
implblocks (named after the type even when theimplis in another file, through itsuseimports), fields, enum variants, consts, statics, type aliases andmacro_rules!are symbols named by their Rust path (my_crate::store::Store::open), forsearch_symbol,get_symbolandverify(Type::method). Module paths follow Cargo's layout:lib.rs/main.rs,mod.rs,src/bin/,tests/, and a binary-only crate under its binary's name. find_usageslists where a type, function, constant or method is used, including names inside macro calls (println!("{}", MAX)); uses in#[cfg(test)]modules and#[test]functions are listed as tests. Methods are matched by name as for Swift and Kotlin.list_pageslists the binaries and their command-line subcommands (enums deriving clap'sSubcommand, with#[command(name = …)]and doc comments).project_overviewgives a Rust section: crates with their folder, library and binaries, file counts and which other crates of the workspace each uses; symbol counts and commands. PHP files without acomposer.json(test fixtures) no longer make a repository look like a PHP app.get_symbolprefers the name spelled exactly as asked (Storeoverstore()), and a method over a field of the same name.- In a Cargo project every top-level folder is read and
target/is skipped. codemap's own 135 Rust files in 10 crates index in 0.4 s.
Android support, for Kotlin and Java apps with Jetpack Compose:
- Classes, interfaces, objects, enums and their members (functions, properties including
class X(val a: Int), enum entries, typealiases; companion members as static) are symbols, named by package (com.example.ui.Root), forsearch_symbol,get_symbolandverify(Class::methodorClass.method). get_componenttakes a@Composablefunction: its parameters (callbacks marked), the state it keeps (remember,rememberSaveable,collectAsState,viewModel, … with starting values), the composables it shows, where it is shown and how it is opened.list_pageslists the app's screens: activities, services, receivers and providers fromAndroidManifest.xml(with the launcher activity and what itssetContentshows), Navigation Compose destinations (composable("route"),composable<Route>,dialog), dialogs and bottom sheets that show the project's composables, Fragments, and app-made navigation: awhenwhose branches show different composables (is Route.Detail -> DetailScreen(),0 -> TimesScreen()).find_usageslists where a class or composable is used, and members by name as for Swift. String keys (app_name) are found in code (R.string.x,stringResource) and XML (@string/x).- Translations from
res/values*/strings.xml(<string>,<plurals>,<string-array>;values-pt-rBR→pt-BR,values-b+sr+Latn→sr-Latn), withres/values/as the base andtranslatable="false"strings expected in no other language. project_overviewgives an Android section: modules, packages, counts, composables, screens and the manifest's components.- In a Gradle project (at the root, or one folder down beside an iOS app) every top-level folder is read;
build/,.gradle/,.idea/are skipped. The countSolat Android app (36 Kotlin files) indexes in about 0.1 s. - Two Kotlin forms the grammar cannot read are rewritten before parsing, keeping lines and columns:
var x by …; private set, and a modifier word used as a name (var open by remember { … }).
Swift support, for Swift packages and Xcode apps (iOS, macOS) with SwiftUI:
- Classes, structs, enums, actors, protocols and their members (methods,
init, properties with their wrappers, enum cases, typealiases) are symbols forsearch_symbol,get_symbolandverify(Type::methodorType.method). Members added in an extension belong to the type. get_componenttakes a SwiftUI view: what callers pass in (let,@Binding,@ObservedObject), its own state (@State,@StateObject,@AppStorage, …) with starting values, what it reads from the environment, the views it shows, where it is shown, and how it is opened.list_pageslists the app's screens: windows (WindowGroup,Window,Settings,MenuBarExtra,DocumentGroup), tabs,NavigationLinkand.navigationDestinationpushes, sheets, full-screen covers, popovers and inspectors, each with the view it shows and where it is opened.find_usageslists where a type is used; for a member it lists the uses in its own file and, since there is no type checker, other uses of the same name as possible.- Translations: keys from
xx.lproj/*.strings(UTF-8 or UTF-16) and.xcstringscatalogs; texts used throughText("…"),Label,Button,.navigationTitleand other SwiftUI calls (shown as written when not translated),NSLocalizedStringandString(localized:).InfoPlisttables are left out. project_overviewgives a Swift section: package or Xcode project, app entry points, counts of types, views and screens, imported frameworks and folders.- In a Swift project every top-level folder is read (not only the usual Laravel / JS folders);
.build,DerivedData,Pods,Carthageand asset catalogs are skipped. Five apps with 9–38 files each index in about 0.1 s.
Faster, measured on a Laravel API with 6,105 files and 6,126 routes and its two Vue frontends (10,305 files):
-
First index of the API 9.4 s → about 4.5 s: translations are scanned in parallel, inserts reuse prepared statements, and a first index builds the reference indexes once at the end. A workspace's apps are indexed side by side.
-
find_usageson a controller behind 1,024 routes: 31 s → 0.2 s, and its brief answer lists 50 routes with the total (126 KB → 8 KB). -
api_usageon a frontend with 5,300 calls: 5.6–6 s → about 1 s: routes are looked up by length and first and last word, the controllers are parsed on all cores once, and "closest route" suggestions compare each distinct word once. -
get_schemawithbackground: 2.9 s → 0.2–0.7 s. Several reference lookups (Xor its members, imports, tables) ran as a scan of every reference; they now use indexes, with a newrefs(kind, target)index. -
The release check searches for leftover names on all cores while its other checks run.
-
codemap usageshows how codemap is used in a project: AI app sessions; tool calls per tool with time taken, answer size, answers that found nothing, refused arguments, errors and calls the AI had to repeat; wrong answers reported by the AI or caught by codemap, and names the AI asked for that do not exist; index runs with why they ran, files read and time taken (also for a linked project read by its frontend).--jsongives every number, per tool and per day. Each app keepsusage.jsonlnext to its index for 90 days, with code cut out of the arguments;CODEMAP_NO_USAGE_LOG=1turns it off.
codemap v0.1.3
Fixes for the issues reported through report_wrong_answer (#3–#9):
api_usage: a variable URL prefix with known values (kind === 'x' ? 'area/x' : 'area', also through a small helper function or a local constant) is expanded and each full URL matched; on irems-sg this resolved 45 of 64 unresolved calls. Suggestions for calls that stay unresolved are ranked by how many words of the URL tail match (#8).api_usage: method spoofing is read from a request body in a variable, a helper's returned object,payload._method = 'PUT'andform.append('_method', 'PUT')(#3).api_usage: a call no longer matches a route by crossing wildcards (/widgets/{}/archiveagainstwidgets/history/{widgetId}): it is reported as having no route (#5).- Routes registered by Laravel Passport (
oauth/token,oauth/authorize, …) and Sanctum (sanctum/csrf-cookie) are known without artisan mode (#4). composer.lockand other JSON files without a.jsonname are no longer read as JavaScript (#6).- Every tool refuses unknown arguments and names the accepted ones (
uri→uri_contains); so doesverify'sclaims(#7). - Wrong-answer report examples may use Laravel's standard app names (
AuthServiceProvider,App\Providers, …) and any class name declared by an installed package (#9).
New, from the feature requests (#10–#15):
- Routes registered by packages are known without artisan mode: Sanctum, Broadcasting (
broadcasting/auth), Fortify (following the features enabled inconfig/fortify.php), Horizon, Telescope, Pulse, Cashier (stripe/webhook) and Livewire (v2 and v3), with prefixes from their config files; Passport follows its version (automatic from v11 unlessignoreRoutes()) (#10). get_schemacan read tables and columns from a live database ([[databases]] schema = "live": information_schema for MySQL / MariaDB and PostgreSQL, pragma for SQLite, read-only, re-read at most every 10 minutes) or from a structure dump (dump = "file.sql"). Each column says where it comes from (source), and differences from the migrations are kept asdrift(#11).api_usagechecks what a call sends against what the action accepts: the Form Request'srules(), an inlinevalidate(), or the fields it reads (also in the controller's helper methods). New findingsmissing_requiredandunknown_field(status: payload), with the evidence; payloads built through spreads or helpers arepayload_unchecked, not guessed (#12).api_usagetakesgit_changes/changed_files(only the calls the change touches, including calls to backend routes whose route file or controller changed) andnew_only(hide findings saved by the newcodemap baseline).codemap check api [--changed]prints new findings and exits 1 on a new missing or wrong-method call, for CI and pre-commit hooks (#13).- Fields findings carry
evidence: where the response shape came from (Resource and itstoArrayfile:line, or the action'sreturn), every key it returns with conditional ones marked, and the paths the frontend read; brief answers name the shape too (#14). - A generated stress project (4,000 routes, 300 modules) is part of the tests; when a prefix is not expanded, the reason says whether a limit was hit or the value comes from code codemap does not follow (#15).
Fixes from the dev-build retest (17 Oct):
_methodspoofing follows conditions and scope:if (editing) payload._method = 'PATCH'makes the call "POST or PATCH" (either method fits), a helper that sets it under a parameter is decided by the argument at each call (widgetForm(record, false)stays POST), and a same-named variable in another function no longer inherits it. This was a regression in the #3 fix.- A payload copied into
FormDatawithObject.entries(…).forEach(…)orfor … of Object.entries(…), also through a localappendhelper, carries the object's keys. A body handed to other code, or one whose keys can't be read, is unchecked instead of "sends nothing". accepts_atfor rules in a controller helper names thevalidate()line and the call:NoteController.php:28 (in project(), called at line 14); it never says:0.- Less noise from the payload check: unread query parameters of a GET (or of a call with an unknown method) are a note (
unknown_query_note, listed withstatus: "payload_all"); nounknown_fieldwhen the payload was not fully followed; a missing required field and an unknown sent field on one call are reported aspossible_rename(unit_id → tenant_id);pageandcursorare accepted only when the action or a helper paginates. The evidence sayssends_completeandaccepts_completeseparately.
Fixes for two more reports (17 Oct):
- A URL value with a small known choice anywhere in the template is expanded and each full URL matched, including a parameter typed as a string union or an alias of one (
`/${kind}-permit/${id}`withkind: PermitKind,type PermitKind = 'loading' | 'unloading'). When none of the full URLs has a route, the call is reported as missing rather than matched loosely. - A variable inside a URL segment stands for one word:
{}-permitno longer fitsspfm-work-permit. _methodspoofing across files: a function that posts a body parameter takes the method its callers pass in that argument (invitationAction(id, 'void', { …, _method: 'PUT' })in another file makes it "POST or PUT"), and a body built by an imported helper (also copied intoFormData) takes the method that helper sets.
Fixes from the accuracy check on 9d73973 (17 Oct):
- More
_methodspoofing is followed: a caller that builds the body with a helper (inline or through a variable), a function that spreads its body parameter into a new body ({ ...record, reason }) or converts it (toFormData(payload)), Vue 2 component state (this.record._method = 'PATCH'then postingthis.recordorjsonFormData(this.record)), and?_method=PUTin the URL. On the test apps, wrong-method findings went from 6 to 3 and from 25 to 20, the ones checked by hand as real. - Calls to imported functions from packages (
reactive,ref) no longer count as body helpers; facts from both script blocks of a.vuefile are kept. - URLs naming a scaffold placeholder (
/_api_url_/{},/unitURL) get their ownplaceholderstatus instead ofmissing, and do not failcodemap check api. - A call whose URL has several known values says which ones have no route (
variants_without_route), also when another one matched; values from a component's computed property (this.reportSegment) are expanded. - A broken call inside an object's method that nothing calls (
billingDraftApi.post) is marked as dead code. - URL variants are built per value of the variables the URL depends on, so one variable that decides two parts (
${kind}${kind === 'rates' ? '/bulk' : ''}) only gives the URLs it can make. When a part cannot be tied to a known value, its URLs are tried but never reported as missing.
Also:
- Two folders of one repository (a monorepo's
frontend/andbackend/linked with[[links]]) get their own index; they shared one and re-indexed each other on every call. Such folders are indexed once more after updating. - Parsing threads get a larger stack, so very deeply nested files cannot crash a scan.
codemap v0.1.2
- Fixes from the 17 Oct retest (round 8):
find_usagescounts functions called by bare name in Vue templates ({{ formatMyr(x) }}), which in Nuxt are auto-imported helpers; such a helper is no longer reported unused.- A JS constant or function used only inside its own file counts those uses (
same file) and is no longer reported unused. - The send result names the AI app (recorded when it connects), and an added comment on an existing issue says so: a short "seen again" note with this build's answer, not the whole issue again.
- Fixes from the 17 Oct retest (round 6):
codemap reports --sendrefuses a closed report, and checks the report on the current build first: if its check passes or its example no longer reproduces, the report is closed as fixed and nothing is sent.- The issue names the build the example was checked on just now, with that build's answer, plus "first seen on" the build it was reported on.
- A report closed because its example no longer reproduces records that ("does not reproduce (reproduced on …)") with the new answer; the list shows a closed report's example as "reproduced on …".
- Fixes from the 17 Oct retest (round 4):
- Test commands never include a base test class (abstract, or without test methods), which made PHPUnit run nothing; the tests that extend it are run instead.
- A brief change summary that leaves out a long test list says so (
tests_note).
- Fixes from the 17 Oct retest (round 3):
- Change impact links tests that call a route with
$this->call('POST', '/uri', …)or$this->json('PATCH', '/uri'), and requests after set-up calls ($this->actingAs($u)->postJson(…),withHeaders(…)->post(…)). - Change impact links tests that run a console command (
$this->artisan('name'),Artisan::call('name')) to the command's class, so a change to anything the command uses lists them. - The development version stamp follows every commit (it watched only
HEAD).
- Change impact links tests that call a route with
- Fixes from the 17 Oct retest (round 2):
find_usagesfollows services resolved from the container:app(X::class),resolve(X::class),App::make(X::class),app()->make(…),$this->app->make(…), chained or assigned to a variable first.- Live-data tests: browser tests of a page opened from a file (
file://) or written withsetContentare skipped.
- Fixes from the 17 Oct retest:
- Release steps: static Nuxt apps (
nuxt generate,ssr: false, a static preset) getgenerateand "deploy .output/public" instead of a Node server restart; Next.jsoutput: 'export'too. Laravel + Vite cites only files the bundler reads. - Live-data tests: text the test typed or sent itself, negated checks, sentences, text patterns and text from the app's own code or translations no longer count.
- Made-up examples: everyday words (
save,phone,error) pass; only the project's compound names and its own name are blocked. - Resending a report for the same answer updates it instead of counting a repeat, and replaces the evidence.
- The send result names the AI app when it does not offer question forms, with the terminal command first.
- Development builds report
<version>-dev+<commit>; release builds (and a checkout of the release tag) report the plain version.
- Release steps: static Nuxt apps (
- Wrong-answer reports: an 11th tool,
report_wrong_answer, records an answer codemap got wrong (every answer now hasmeta.call_id). codemap also records contradictions, tool failures and slow answers on its own.codemap reportslists, re-checks, exports, closes and clears them. A report with a made-up example that reproduces (checked to hold nothing from the real project) can be sent as a GitHub issue after the person agrees. - Release check:
release_steps, the server steps a release needs (installs, migrations, caches, queue and server restarts, rebuilds, new environment variables), worked out from what changed. - Project rules tied to files (
[[rules]]in.codemap.toml), returned by the release check and by change impact when a matching file changes. - Leftover mentions: names deleted or renamed on the branch that code, tests, comments or docs still use.
- Tests that depend on live data: browser and PHP tests that check data they never create.
- New type errors only:
verifywithtype_errors(the type check's output) reports only errors not in the saved starting point.
codemap v0.1.1
codemap updateinstalls the latest release, checked against its SHA256SUMS (--checkonly reports,--forcereinstalls).- A once-a-day check for new releases;
codemap doctorandproject_overviewmention a newer version. Turn it off withCODEMAP_NO_UPDATE_CHECK=1.
codemap v0.1.0
First release. codemap reads a Laravel, Vue 2, Vue 3, Nuxt (2/3/4) or Next.js project and serves facts about it to Claude over MCP, so Claude checks what exists instead of guessing.
- Ten MCP tools: project overview, symbol search and details, Vue / React components, pages, routes, the frontend ↔ backend API link, usages and change impact (with the tests to run), database schema (plus settings, migrations not yet applied, cache keys, background work) and
verify. - Release check (
verifywithrelease_check: true): missing endpoints, fields not returned, translation gaps in every shipped language, validation messages that would show raw field keys, unused code on the branch, migrations not applied to configured databases, config and env keys, settings without defaults and house copy rules. Lines can be marked as intended withcodemap-ignore. - Code map (
codemap map): one self-contained web page from screens to API calls, endpoints, controllers, models and tables, with the release check's problems. - AI mistakes log (
codemap misses): names Claude asked for that do not exist, ranked, with the real name and what to do about it. - Workspaces: several apps in one folder, each with its own index, linked frontend to backend.
- Ready-made programs for macOS (Apple Silicon, Intel) and Linux (x86-64, ARM64), or build with Cargo or Docker.