From 47e9001634394caa6f2d00f7983973f9f5410de1 Mon Sep 17 00:00:00 2001 From: Evan Alferez Date: Mon, 25 May 2026 09:20:33 +0900 Subject: [PATCH 1/4] docs(readme): add Cursor manual install fallback to 7 translated READMEs (#172) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #199 documented the community-reported Cursor Settings → Plugins workaround in README.md only; the seven READMEs/* locale files still said auto-discovery always works. Mirror that fallback here so non-English readers hit the same fix without hunting issue #172. --- READMEs/README.es-ES.md | 2 ++ READMEs/README.ja-JP.md | 2 ++ READMEs/README.ko-KR.md | 2 ++ READMEs/README.ru-RU.md | 2 ++ READMEs/README.tr-TR.md | 2 ++ READMEs/README.zh-CN.md | 2 ++ READMEs/README.zh-TW.md | 2 ++ 7 files changed, 14 insertions(+) diff --git a/READMEs/README.es-ES.md b/READMEs/README.es-ES.md index 27884f9..542d83b 100644 --- a/READMEs/README.es-ES.md +++ b/READMEs/README.es-ES.md @@ -205,6 +205,8 @@ El instalador clona el repositorio en `~/.understand-anything/repo` y crea los e Cursor detecta automáticamente el plugin a través de `.cursor-plugin/plugin.json` cuando se clona este repositorio. No requiere instalación manual: simplemente clona y abre en Cursor. +Si la detección automática no lo reconoce, instálalo manualmente: abre **Cursor Settings → Plugins**, pega `https://github.com/Lum1104/Understand-Anything` en el campo de búsqueda y añádelo desde allí. + ### VS Code + GitHub Copilot VS Code con GitHub Copilot (v1.108+) detecta automáticamente el plugin a través de `.copilot-plugin/plugin.json` cuando se clona este repositorio. No requiere instalación manual: simplemente clona y abre en VS Code. diff --git a/READMEs/README.ja-JP.md b/READMEs/README.ja-JP.md index 78fe62c..cbe8a43 100644 --- a/READMEs/README.ja-JP.md +++ b/READMEs/README.ja-JP.md @@ -206,6 +206,8 @@ iwr -useb https://raw.githubusercontent.com/Lum1104/Understand-Anything/main/ins Cursorはこのリポジトリをクローンすると `.cursor-plugin/plugin.json` 経由でプラグインを自動検出します。手動インストールは不要です — クローンしてCursorで開くだけです。 +自動検出されない場合は、手動でインストールしてください:**Cursor Settings → Plugins** を開き、検索欄に `https://github.com/Lum1104/Understand-Anything` を貼り付けて追加します。 + ### VS Code + GitHub Copilot GitHub Copilot拡張機能(v1.108+)をインストールしたVS Codeは、`.copilot-plugin/plugin.json` 経由でプラグインを自動検出します。クローンしてVS Codeで開くだけで、手動インストールは不要です。 diff --git a/READMEs/README.ko-KR.md b/READMEs/README.ko-KR.md index 13c4aef..2e51742 100644 --- a/READMEs/README.ko-KR.md +++ b/READMEs/README.ko-KR.md @@ -205,6 +205,8 @@ iwr -useb https://raw.githubusercontent.com/Lum1104/Understand-Anything/main/ins 이 저장소를 클론하면 Cursor가 `.cursor-plugin/plugin.json`을 통해 플러그인을 자동으로 인식합니다. 수동 설치가 필요 없습니다. 클론 후 Cursor에서 열기만 하면 됩니다. +자동 인식이 되지 않으면 수동으로 설치하세요: **Cursor Settings → Plugins**를 열고 검색란에 `https://github.com/Lum1104/Understand-Anything`를 붙여넣은 뒤 추가하세요. + ### VS Code + GitHub Copilot GitHub Copilot(v1.108+)이 설치된 VS Code는 `.copilot-plugin/plugin.json`을 통해 플러그인을 자동으로 인식합니다. 수동 설치가 필요 없습니다. 클론 후 VS Code에서 열기만 하면 됩니다. diff --git a/READMEs/README.ru-RU.md b/READMEs/README.ru-RU.md index 67182fb..3b11cb3 100644 --- a/READMEs/README.ru-RU.md +++ b/READMEs/README.ru-RU.md @@ -206,6 +206,8 @@ iwr -useb https://raw.githubusercontent.com/Lum1104/Understand-Anything/main/ins Cursor автоматически обнаруживает плагин через `.cursor-plugin/plugin.json` при клонировании этого репозитория. Ручная установка не требуется — просто склонируйте и откройте в Cursor. +Если автообнаружение не сработало, установите вручную: откройте **Cursor Settings → Plugins**, вставьте `https://github.com/Lum1104/Understand-Anything` в поле поиска и добавьте оттуда. + ### VS Code + GitHub Copilot VS Code с GitHub Copilot (v1.108+) автоматически обнаруживает плагин через `.copilot-plugin/plugin.json` при клонировании этого репозитория. Ручная установка не требуется — просто склонируйте и откройте в VS Code. diff --git a/READMEs/README.tr-TR.md b/READMEs/README.tr-TR.md index e03b993..7f3168d 100644 --- a/READMEs/README.tr-TR.md +++ b/READMEs/README.tr-TR.md @@ -206,6 +206,8 @@ Kurulum betiği depoyu `~/.understand-anything/repo` dizinine klonlar ve seçile Bu depo klonlandığında Cursor, eklentiyi `.cursor-plugin/plugin.json` aracılığıyla otomatik olarak keşfeder. Manuel kurulum gerekmez — sadece klonla ve Cursor'da aç. +Otomatik keşif çalışmazsa manuel kur: **Cursor Settings → Plugins**'i aç, arama alanına `https://github.com/Lum1104/Understand-Anything` yapıştır ve oradan ekle. + ### VS Code + GitHub Copilot GitHub Copilot uzantısı (v1.108+) yüklü VS Code, `.copilot-plugin/plugin.json` aracılığıyla eklentiyi otomatik keşfeder. Manuel kurulum gerekmez — sadece klonla ve VS Code'da aç. diff --git a/READMEs/README.zh-CN.md b/READMEs/README.zh-CN.md index 17b6e91..87fedc6 100644 --- a/READMEs/README.zh-CN.md +++ b/READMEs/README.zh-CN.md @@ -205,6 +205,8 @@ iwr -useb https://raw.githubusercontent.com/Lum1104/Understand-Anything/main/ins 克隆此仓库后,Cursor 会自动通过 `.cursor-plugin/plugin.json`文件发现插件。无需手动安装 — 只需克隆并在 Cursor 中打开即可。 +若自动发现未生效,可手动安装:打开 **Cursor Settings → Plugins**,在搜索框中粘贴 `https://github.com/Lum1104/Understand-Anything` 并添加。 + ### VS Code + GitHub Copilot 安装 GitHub Copilot 扩展(v1.108+)后,VS Code 会通过 `.copilot-plugin/plugin.json` 自动发现插件,克隆后直接在 VS Code 中打开即可,无需手动安装。 diff --git a/READMEs/README.zh-TW.md b/READMEs/README.zh-TW.md index 1d8c297..0b4ef96 100644 --- a/READMEs/README.zh-TW.md +++ b/READMEs/README.zh-TW.md @@ -205,6 +205,8 @@ iwr -useb https://raw.githubusercontent.com/Lum1104/Understand-Anything/main/ins 複製此儲存庫後,Cursor 會自動透過 `.cursor-plugin/plugin.json` 檔案發現外掛程式。無需手動安裝 — 只需複製並在 Cursor 中開啟即可。 +若自動發現未生效,可手動安裝:開啟 **Cursor Settings → Plugins**,在搜尋框中貼上 `https://github.com/Lum1104/Understand-Anything` 並新增。 + ### VS Code + GitHub Copilot 安裝 GitHub Copilot 擴充功能(v1.108+)後,VS Code 會透過 `.copilot-plugin/plugin.json` 自動發現外掛程式,複製後直接在 VS Code 中開啟即可,無需手動安裝。 From d9ae3c290c73b6494dae0a8317581d45124c2dd7 Mon Sep 17 00:00:00 2001 From: Zebang Cheng Date: Mon, 25 May 2026 14:02:01 +0000 Subject: [PATCH 2/4] fix(extract-import-map): normalize tsconfig path-alias candidates with leading "./" (#214) --- .../test_extract_import_map.test.mjs | 105 ++++++++++++++++++ .../skills/understand/extract-import-map.mjs | 15 ++- 2 files changed, 117 insertions(+), 3 deletions(-) diff --git a/tests/skill/understand/test_extract_import_map.test.mjs b/tests/skill/understand/test_extract_import_map.test.mjs index ee64136..0f17277 100644 --- a/tests/skill/understand/test_extract_import_map.test.mjs +++ b/tests/skill/understand/test_extract_import_map.test.mjs @@ -237,6 +237,111 @@ describe('extract-import-map.mjs — TypeScript / JavaScript resolver', () => { 'packages/foo/src/y.ts', ); }); + + // ── Issue #214: tsconfig path-alias targets with leading "./" ─────────── + // create-next-app ships `"@/*": ["./*"]` as the default. With a root + // tsconfig the candidate would stay as "./lib/thing" while ctx.fileSet + // stores normalized "lib/thing", silently dropping every cross-module + // import edge. Three originally broken cases plus one regression guard + // for the already working `["*"]` form. + + it('resolves tsconfig paths with leading "./" target and no baseUrl (#214)', () => { + projectRoot = setupTree({ + 'tsconfig.json': JSON.stringify({ + compilerOptions: { + paths: { '@/*': ['./*'] }, + }, + }), + 'src/app.ts': `import { x } from '@/lib/thing';\nconst _ = x;\n`, + 'lib/thing.ts': `export const x = 1;\n`, + }); + + const result = runScript(projectRoot, { + projectRoot, + files: [ + { path: 'tsconfig.json', language: 'json', fileCategory: 'config' }, + { path: 'src/app.ts', language: 'typescript', fileCategory: 'code' }, + { path: 'lib/thing.ts', language: 'typescript', fileCategory: 'code' }, + ], + }); + + expect(result.status).toBe(0); + expect(result.output.importMap['src/app.ts']).toContain('lib/thing.ts'); + }); + + it('resolves tsconfig paths with leading "./" target and baseUrl "." (#214)', () => { + projectRoot = setupTree({ + 'tsconfig.json': JSON.stringify({ + compilerOptions: { + baseUrl: '.', + paths: { '@/*': ['./*'] }, + }, + }), + 'src/app.ts': `import { x } from '@/lib/thing';\nconst _ = x;\n`, + 'lib/thing.ts': `export const x = 1;\n`, + }); + + const result = runScript(projectRoot, { + projectRoot, + files: [ + { path: 'tsconfig.json', language: 'json', fileCategory: 'config' }, + { path: 'src/app.ts', language: 'typescript', fileCategory: 'code' }, + { path: 'lib/thing.ts', language: 'typescript', fileCategory: 'code' }, + ], + }); + + expect(result.status).toBe(0); + expect(result.output.importMap['src/app.ts']).toContain('lib/thing.ts'); + }); + + it('resolves tsconfig paths with leading "./" target and baseUrl "src" (#214)', () => { + projectRoot = setupTree({ + 'tsconfig.json': JSON.stringify({ + compilerOptions: { + baseUrl: 'src', + paths: { '@/*': ['./*'] }, + }, + }), + 'src/app.ts': `import { x } from '@/thing';\nconst _ = x;\n`, + 'src/thing.ts': `export const x = 1;\n`, + }); + + const result = runScript(projectRoot, { + projectRoot, + files: [ + { path: 'tsconfig.json', language: 'json', fileCategory: 'config' }, + { path: 'src/app.ts', language: 'typescript', fileCategory: 'code' }, + { path: 'src/thing.ts', language: 'typescript', fileCategory: 'code' }, + ], + }); + + expect(result.status).toBe(0); + expect(result.output.importMap['src/app.ts']).toContain('src/thing.ts'); + }); + + it('keeps resolving tsconfig paths with bare "*" target (#214 regression guard)', () => { + projectRoot = setupTree({ + 'tsconfig.json': JSON.stringify({ + compilerOptions: { + paths: { '@/*': ['*'] }, + }, + }), + 'src/app.ts': `import { x } from '@/lib/thing';\nconst _ = x;\n`, + 'lib/thing.ts': `export const x = 1;\n`, + }); + + const result = runScript(projectRoot, { + projectRoot, + files: [ + { path: 'tsconfig.json', language: 'json', fileCategory: 'config' }, + { path: 'src/app.ts', language: 'typescript', fileCategory: 'code' }, + { path: 'lib/thing.ts', language: 'typescript', fileCategory: 'code' }, + ], + }); + + expect(result.status).toBe(0); + expect(result.output.importMap['src/app.ts']).toContain('lib/thing.ts'); + }); }); describe('extract-import-map.mjs — Python resolver', () => { diff --git a/understand-anything-plugin/skills/understand/extract-import-map.mjs b/understand-anything-plugin/skills/understand/extract-import-map.mjs index 6c547d3..00f9181 100644 --- a/understand-anything-plugin/skills/understand/extract-import-map.mjs +++ b/understand-anything-plugin/skills/understand/extract-import-map.mjs @@ -430,9 +430,18 @@ export function resolveTsJsImport(rawImport, file, ctx) { const relativeToConfig = normalizedBase ? posix.join(normalizedBase, mapped) : mapped; - const candidate = tsConfigDir - ? posix.join(tsConfigDir, relativeToConfig) - : relativeToConfig; + // posix.normalize strips a leading "./" left over when both + // tsConfigDir and normalizedBase are empty (root tsconfig with + // `"@/*": ["./*"]`, the create-next-app default). Without this the + // candidate stays as "./foo" while ctx.fileSet stores "foo", and + // probeWithExtensions silently drops every cross-module edge. + const candidate = posix.normalize( + tsConfigDir + ? posix.join(tsConfigDir, relativeToConfig) + : relativeToConfig, + ); + // Defensive: tsconfig targets shouldn't escape the project root. + if (candidate.startsWith('..')) continue; const probed = probeWithExtensions(candidate, ctx.fileSet); if (probed) return probed; } From b4b599e21486411bd32a57bf6db61e20847aa133 Mon Sep 17 00:00:00 2001 From: Zebang Cheng Date: Mon, 25 May 2026 15:45:48 +0000 Subject: [PATCH 3/4] feat(install): add Trae (ByteDance AI IDE) platform support (#229) --- README.md | 6 ++++-- install.ps1 | 1 + install.sh | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d68f341..3bdb4db 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Gemini CLI OpenCode Vibe CLI + Trae Homepage Live Demo

@@ -183,7 +184,7 @@ Understand-Anything works across multiple AI coding platforms. /plugin install understand-anything ``` -### One-line install (Codex / OpenCode / OpenClaw / Antigravity / Gemini CLI / Pi Agent / Vibe CLI / VS Code Copilot / Hermes / Cline / KIMI CLI) +### One-line install (Codex / OpenCode / OpenClaw / Antigravity / Gemini CLI / Pi Agent / Vibe CLI / VS Code Copilot / Hermes / Cline / KIMI CLI / Trae) **macOS / Linux:** ```bash @@ -199,7 +200,7 @@ iwr -useb https://raw.githubusercontent.com/Lum1104/Understand-Anything/main/ins The installer clones the repo to `~/.understand-anything/repo` and creates the right symlinks for the chosen platform. Restart your CLI/IDE afterwards. -- Supported `` values: `gemini`, `codex`, `opencode`, `pi`, `openclaw`, `antigravity`, `vibe`, `vscode`, `hermes`, `cline`, `kimi` +- Supported `` values: `gemini`, `codex`, `opencode`, `pi`, `openclaw`, `antigravity`, `vibe`, `vscode`, `hermes`, `cline`, `kimi`, `trae` - Update later: `./install.sh --update` - Uninstall: `./install.sh --uninstall ` @@ -239,6 +240,7 @@ copilot plugin install Lum1104/Understand-Anything:understand-anything-plugin | Hermes | ✅ Supported | `install.sh hermes` | | Cline | ✅ Supported | `install.sh cline` | | KIMI CLI | ✅ Supported | `install.sh kimi` | +| Trae | ✅ Supported | `install.sh trae` | --- diff --git a/install.ps1 b/install.ps1 index 4eb6ece..1a4b4df 100644 --- a/install.ps1 +++ b/install.ps1 @@ -38,6 +38,7 @@ $Platforms = [ordered]@{ hermes = @{ Target = (Join-Path $HOME '.hermes\skills'); Style = 'folder' } cline = @{ Target = (Join-Path $HOME '.cline\skills'); Style = 'folder' } kimi = @{ Target = (Join-Path $HOME '.kimi\skills'); Style = 'folder' } + trae = @{ Target = (Join-Path $HOME '.trae\skills'); Style = 'per-skill' } } function Show-Usage { diff --git a/install.sh b/install.sh index b23f8ae..8ff4293 100755 --- a/install.sh +++ b/install.sh @@ -39,6 +39,7 @@ vscode|$HOME/.copilot/skills|per-skill hermes|$HOME/.hermes/skills|folder cline|$HOME/.cline/skills|folder kimi|$HOME/.kimi/skills|folder +trae|$HOME/.trae/skills|per-skill EOF } From b4d856d3b895974b072bc236c451fa0848e7c312 Mon Sep 17 00:00:00 2001 From: Adam Herring Date: Mon, 25 May 2026 11:09:20 -0700 Subject: [PATCH 4/4] fix(scan-project): preserve non-ASCII path bytes via `git ls-files -z` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `enumerateViaGit` ran `git ls-files -co --exclude-standard` (newline-separated output) and then `split('\n').map(trim)` on the result. Without `-z`, `git ls-files` C-escapes any byte outside the locale's "safe" set and wraps the path in double quotes — for example, a directory named `30. 🏗️ docs/` comes back as `"30. \360\237\217\227\357\270\217 docs/"`. Downstream consumers then can't round-trip those octal-quoted strings to real disk paths, so every file under such directories is silently dropped from the scan. This is particularly biting on Windows (where the issue surfaces even with UTF-8 locale settings) and for any project that uses emoji, accented characters, or CJK codepoints in directory names — which is increasingly common in design/spec/journal trees. The fix is to use `-z` (NUL-terminated output), the same approach git itself documents for downstream consumers (e.g. `xargs -0`). NUL-separated chunks are raw bytes, so every codepoint round-trips back to its real disk path on every platform. Split on `\0` instead of `\n`; drop the now- unnecessary `.trim()`. Verified on a real project with emoji-prefixed directory names: bare `git ls-files`: "30. \360\237\217\227\357\270\217\360\237\247\231\342\200\215..." `git ls-files -z`: 30. 🏗️🧙‍♂️🔮 BD-CCSP/01. Demo's/DEMO--... Discovered during a multi-agent scan of an Atlas Intelligence spoke repo; ~33 design-intent files in `30. 🏗️ BD-{app}/` directories were silently dropped per scan. Full report: atlas-intelligence-io/fleet-feedback#491. Co-Authored-By: Claude Opus 4.7 --- .../skills/understand/scan-project.mjs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/understand-anything-plugin/skills/understand/scan-project.mjs b/understand-anything-plugin/skills/understand/scan-project.mjs index 553a82e..83ccc7d 100644 --- a/understand-anything-plugin/skills/understand/scan-project.mjs +++ b/understand-anything-plugin/skills/understand/scan-project.mjs @@ -464,17 +464,25 @@ function toPosix(p) { * so the ignore filter has to do more work in the fallback path. */ function enumerateViaGit(projectRoot) { - const result = spawnSync('git', ['ls-files', '-co', '--exclude-standard'], { + // -z = NUL-terminated output. Without it, `git ls-files` C-escapes non-ASCII + // bytes in path names — paths containing emoji, accented characters, CJK + // codepoints, etc. come back quoted with octal escapes (e.g. + // `"30. \360\237\217\227 BD-CCER/file.md"` for a path containing 🏗️). + // Those quoted-escaped strings then fail to round-trip back to real disk + // paths in downstream consumers, so files in such directories are silently + // dropped from the scan. The -z form emits raw bytes between NUL separators, + // preserving every codepoint as-is. This is the same approach git itself + // uses for `--null` everywhere downstream (xargs -0, etc.). + const result = spawnSync('git', ['ls-files', '-z', '-co', '--exclude-standard'], { cwd: projectRoot, encoding: 'utf-8', maxBuffer: 256 * 1024 * 1024, // 256MB — huge monorepos can produce >10MB of paths }); if (result.status !== 0 || !result.stdout) return null; - // Each line is one path, project-relative, already POSIX on all platforms - // because git emits forward slashes regardless of OS. + // Each NUL-separated chunk is one path, project-relative, already POSIX on + // all platforms because git emits forward slashes regardless of OS. return result.stdout - .split('\n') - .map(s => s.trim()) + .split('\0') .filter(Boolean) .map(toPosix); }