An Obsidian plugin that embeds Claude Code, Codex and other agents as an AI collaborator in your vault.
This report summarizes scanner evidence for YishenTu/claudian, a TypeScript project with 15,869 GitHub stars. SynthScan examined 358,427 lines of code across 1661 source files, recording 791 pattern matches distributed across 5 syntactic categories. The legacy adjusted pattern signal is 3.0 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 716 finding(s).
Are imports declared and package/API names verified? 75 finding(s).
Are wrappers, guards, and repeated structures necessary? 712 finding(s).
Which changes need focused human review? 791 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 791 distinct pattern matches across 5 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/setupWindow.ts | 14 | function reportProcessEnvReplacement(): void { | CODE |
| LOW | tests/__mocks__/obsidian.ts | 741 | export function setObsidianActiveDocument(document?: Document): void { | CODE |
| LOW | tests/__mocks__/claude-agent-sdk.ts | 162 | export function setMockSupportedCommandsImplementation( | CODE |
| LOW | tests/__mocks__/claude-agent-sdk.ts | 201 | export function setMockInitializationResult(implementation: () => Promise<SDKControlInitializeResponse>): void { | CODE |
| LOW | tests/__mocks__/claude-agent-sdk.ts | 337 | export function createScriptedPersistentQuery( | CODE |
| LOW | tests/__mocks__/claude-agent-sdk.ts | 361 | export function createFailingPersistentQuery( | CODE |
| LOW | tests/__mocks__/claude-agent-sdk.ts | 385 | export function createPromptDrivenPersistentQuery( | CODE |
| LOW | tests/__mocks__/claude-agent-sdk.ts | 450 | export function createThrowingPersistentQuery(error: Error): ReturnType< | CODE |
| LOW | tests/__mocks__/claude-agent-sdk.ts | 460 | export function createIdlePersistentQuery(): ReturnType< | CODE |
| LOW | …p/conversations/ConversationRepository.history.test.ts | 66 | function createOpencodeHistoryService(readMessages: (route: string) => Promise<unknown[]>): OpencodeConversationHistoryS | CODE |
| LOW | …laude/execution/ClaudeExecutionEventNormalizer.test.ts | 189 | function expectAuthenticationOverrideGuidance(message: string): void { | CODE |
| LOW | …nit/providers/codex/runtime/CodexBinaryLocator.test.ts | 27 | function restoreEnvironmentVariable( | CODE |
| LOW | …nit/providers/codex/runtime/CodexBinaryLocator.test.ts | 38 | function createCompleteWindowsCodexRuntime(dir: string): string { | CODE |
| LOW | tests/integration/main.test.ts | 179 | function getConversationPersistence( | CODE |
| LOW | tests/integration/main.test.ts | 1309 | async function prepareHeldHistoryRelease() { | CODE |
| LOW | tests/integration/main.test.ts | 3723 | async function detachedLinkedContentSession() { | CODE |
| LOW | …sts/integration/app/startup/ApplicationStartup.test.ts | 81 | async function loadApplicationWithMetadata(): Promise<ApplicationDomains> { | CODE |
| LOW | …viders/claude/execution/ClaudeExecutionBackend.test.ts | 3677 | function applyProviderStateProjection( | CODE |
| LOW | …codex/execution/CodexExecutionBackend.protocol.test.ts | 255 | function expectPendingForkOwnership( | CODE |
| LOW | …codex/execution/CodexExecutionBackend.protocol.test.ts | 275 | function expectPendingForkOwnershipEvent( | CODE |
| LOW | …codex/execution/CodexExecutionBackend.protocol.test.ts | 2244 | function countTranscriptRootProbes(): number { | CODE |
| LOW | …rs/deepseek/execution/DeepSeekExecutionBackend.test.ts | 633 | async function queueBehindFailedAutomaticTurn(): Promise<{ run: ReturnType<ProviderExecutionSession['execute']>; events: | CODE |
| LOW | …runtime/GrokModelCatalogCoordinator.concurrent.test.ts | 87 | function deferNextConditionalMutation(host: ProviderHost): { | CODE |
| LOW | …runtime/GrokModelCatalogCoordinator.concurrent.test.ts | 119 | function deferConditionalMutations(host: ProviderHost, count: number): { | CODE |
| LOW | …/integration/providers/pi/runtime/PiSubprocess.test.ts | 526 | function createWindowsCommandTarget(commandPath: string, targetPath: string): string { | CODE |
| LOW | …oviders/pi/execution/PiExecutionBackend.kernel.test.ts | 220 | function createConversationHistory(prefix: string) { | CODE |
| LOW | …n/providers/pi/history/PiRetiredBindingRestore.test.ts | 79 | async function treeBranchesOfEditedPrompt(repository: ConversationRepository, id: string) { | CODE |
| LOW | …iders/opencode/metadata/OpencodeHTTPMetadataFixture.ts | 43 | export function createOpencodeHTTPMetadataFixture(): OpencodeHTTPMetadataFixture { | CODE |
| LOW | …tegration/features/chat/tabs/TabRuntimeFactory.test.ts | 150 | function expectTabManagerMetadataReleased(manager: TabManager, tabId: string): void { | CODE |
| LOW | …tegration/features/chat/tabs/TabRuntimeFactory.test.ts | 156 | function createTrackedTabContainer(): { | CODE |
| LOW | …tegration/features/chat/tabs/TabRuntimeFactory.test.ts | 679 | async function startLaterTurnUnderQuestion() { | CODE |
| LOW | …atures/chat/side-chat/SideChatInteractions.dom.test.ts | 200 | async function startLaterTurnUnderQuestion() { | CODE |
| LOW | …ures/chat/composer/PromptHistoryNavigation.dom.test.ts | 137 | function accessibilityFingerprints(result: Awaited<ReturnType<typeof axe>>): string[] { | CODE |
| LOW | …/conversation/ConversationController.branching.test.ts | 12 | async function createConversationControllerDeps(...args: Parameters<typeof createBaseDeps>) { | CODE |
| LOW | tests/helpers/ChatInputHarness.ts | 54 | export function requestedUserMessageStarted( | CODE |
| LOW | tests/helpers/providerRuntimeHost.ts | 25 | export async function createProviderHostFixture(options: ProviderHostFixtureOptions = {}) { | CODE |
| LOW | tests/helpers/providerModelCatalogs.ts | 28 | export function assertCatalogModelAvailable( | CODE |
| LOW | tests/helpers/sdkMessages.ts | 140 | export function buildCompactBoundaryMessage( | CODE |
| LOW | tests/helpers/sdkMessages.ts | 193 | export function buildResultSuccessMessage( | CODE |
| LOW | tests/helpers/ChatExecutionHarness.ts | 272 | export function createExecutionPersistence(): Mocked<ChatExecutionPersistence> { | CODE |
| LOW | tests/helpers/core/fsWriteFaults.ts | 27 | export function createFsPromisesWithWriteFaults(): typeof FsPromises { | CODE |
| LOW | tests/helpers/providers/grokHistory.ts | 24 | export function resolveGrokPromptIndexAfterAssistant( | CODE |
| LOW | tests/helpers/providers/codex/CodexWorkspaceHarness.ts | 9 | export async function createCodexWorkspaceHarness(config: Record<string, unknown> = {}, options: Pick<ProviderHostFixtur | CODE |
| LOW | …ts/helpers/providers/opencode/OpencodeKernelFixture.ts | 6 | export function createOpencodeKernelLease(databasePath: string | null = null) { | CODE |
| LOW | …elpers/providers/opencode/FakeOpencodeHistoryServer.ts | 18 | export function writeFakeOpencodeHistoryCLI(directory: string): string { | CODE |
| LOW | …ers/providers/opencode/OpencodeHTTPExecutionFixture.ts | 33 | function releaseSteeringEventsOnAdmission(): void { | CODE |
| LOW | …s/helpers/features/chat/ProviderRecoveryTestHarness.ts | 39 | export function createProviderRecoveryTestHarness( | CODE |
| LOW | tests/helpers/features/chat/SessionEventsHarness.ts | 42 | function canAcceptTabBackgroundWork(tab: AssembledTabRuntime): boolean { | CODE |
| LOW | tests/helpers/features/chat/ProviderForkTestHarness.ts | 21 | export async function createForkTestEnvironment() { | CODE |
| LOW | …helpers/features/chat/ConversationControllerFixture.ts | 19 | export async function createConversationControllerDeps( | CODE |
| LOW | …s/helpers/features/inline-edit/InlineEditDOMHarness.ts | 21 | export async function disposeInlineEditHarnesses(): Promise<void> { | CODE |
| LOW | …s/helpers/features/inline-edit/InlineEditDOMHarness.ts | 54 | export function registerFakeInlineEditProvider( | CODE |
| LOW | tests/helpers/dom/animationFrames.ts | 8 | export function useNextTaskAnimationFrames(target: Window = window): () => void { | CODE |
| LOW | scripts/desktopRuntimeAliases.js | 4 | function createDesktopRuntimeAliases() { | CODE |
| LOW | scripts/rendererSafeUnref.js | 89 | function patchRendererUnsafeUnrefSites(contents) { | CODE |
| LOW | scripts/rendererSafeUnref.js | 116 | function findUnsafeTimerUnrefSites(contents) { | CODE |
| LOW | scripts/rendererSafeUnref.js | 120 | function findUnsafeTimerUnrefRanges(contents) { | CODE |
| LOW | scripts/compressedStaticAssets.js | 21 | function createCompressedStaticAssetsPlugin({ root = process.cwd() } = {}) { | CODE |
| LOW | src/core/tools/toolProviderPayload.ts | 3 | export function normalizeToolProviderPayload(value: unknown): ToolProviderPayload | null { | CODE |
| LOW | src/core/tools/toolInput.ts | 50 | function parseAnswersFromJSONObject(resultText: string): AskUserAnswers | undefined { | CODE |
| 652 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | …/unit/app/conversations/ConversationRepository.test.ts | 279 | const persisted = firstRun.persistence.saveMetadata.mock.calls.at(-1)?.[0]; | CODE |
| CRITICAL | …/unit/app/conversations/ConversationRepository.test.ts | 352 | const persisted = firstRun.persistence.saveMetadata.mock.calls.at(-1)?.[0]; | CODE |
| CRITICAL | …atures/chat/execution/ChatExecutionCoordinator.test.ts | 1726 | .toBeLessThan(harness.repository.releaseExecutionBinding.mock.invocationCallOrder.at(-1)!); | CODE |
| CRITICAL | tests/integration/main.test.ts | 1811 | const writeCall = mockApp.vault.adapter.write.mock.calls.find( | CODE |
| CRITICAL | tests/integration/main.test.ts | 2430 | expect(mockApp.vault.adapter.write.mock.calls.filter( | CODE |
| CRITICAL | tests/integration/main.test.ts | 3745 | const listener = mockApp.vault.on.mock.calls.find((call: unknown[]) => call[0] === 'create')![1]; | CODE |
| CRITICAL | tests/integration/main.test.ts | 3878 | const createListener = mockApp.vault.on.mock.calls.find( | CODE |
| CRITICAL | …sts/integration/app/startup/ApplicationStartup.test.ts | 369 | const sessionWrite = mockApp.vault.adapter.write.mock.calls.find( | CODE |
| CRITICAL | …/integration/features/chat/tabs/TabManager.dom.test.ts | 247 | expect([preview.controllers.drafts.capture('main').content, preview.session.runtime.model.linkedContentController.ge | CODE |
| CRITICAL | …/integration/features/chat/tabs/TabManager.dom.test.ts | 254 | expect([restored.controllers.drafts.capture('main').content, restored.session.runtime.model.linkedContentController. | CODE |
| CRITICAL | tests/integration/features/chat/tabs/ViewerSlot.test.ts | 352 | expect(draft.session.runtime.model.linkedContentController.getSnapshot()).toEqual({ mode: 'explicit-draft', path: | CODE |
| CRITICAL | tests/integration/features/chat/tabs/ViewerSlot.test.ts | 629 | const pending = tab.session.runtime.model.inlinePrompts.requestApproval('waiting', 'Read', {}, 'Read note', undefine | CODE |
| CRITICAL | tests/integration/features/chat/tabs/TabManager.test.ts | 773 | tab.session.runtime.model.linkedContentController.beginSubmission(), { providerId: 'claude' }, | CODE |
| CRITICAL | …ures/chat/composer/PromptHistoryNavigation.dom.test.ts | 614 | expect(view.tab.dom.inputWrapper.classList.contains('claudian-input-side-chat-preview')).toBe(true); | CODE |
| CRITICAL | …ures/chat/composer/PromptHistoryNavigation.dom.test.ts | 619 | expect(view.tab.dom.inputWrapper.classList.contains('claudian-input-side-chat-preview')).toBe(false); | CODE |
| CRITICAL⚡ | tests/integration/features/chat/zen/ZenMode.dom.test.ts | 1734 | expect(fixture.workspace.revealLeaf.mock.calls.at(-1)?.[0] === second.leaf).toBe(true); | CODE |
| CRITICAL⚡ | tests/integration/features/chat/zen/ZenMode.dom.test.ts | 1742 | expect(fixture.workspace.revealLeaf.mock.calls.at(-1)?.[0] === fixture.leaf).toBe(true); | CODE |
| CRITICAL⚡ | tests/integration/features/chat/zen/ZenMode.dom.test.ts | 1746 | expect(fixture.workspace.revealLeaf.mock.calls.at(-1)?.[0] === fixture.leaf).toBe(true); | CODE |
| CRITICAL⚡ | tests/integration/features/chat/zen/ZenMode.dom.test.ts | 1750 | expect(fixture.workspace.revealLeaf.mock.calls.at(-1)?.[0] === fixture.leaf).toBe(true); | CODE |
| CRITICAL⚡ | tests/integration/features/chat/zen/ZenMode.dom.test.ts | 1760 | expect(fixture.workspace.revealLeaf.mock.calls.at(-1)?.[0] === deferredLeaf).toBe(true); | CODE |
| CRITICAL | …egration/features/chat/turns/MainTurnExecution.test.ts | 426 | expect(fixture.plugin.updateConversation.mock.calls.at(-1)?.[1].messages).toEqual(fixture.state.messages); | CODE |
| CRITICAL | …egration/features/chat/turns/MainTurnExecution.test.ts | 561 | expect(fixture.plugin.updateConversation.mock.calls.at(-1)?.[1].messages).toMatchObject([ | CODE |
| CRITICAL | src/features/chat/session-manager/SessionSidebar.ts | 80 | this.themeEvent = this.deps.plugin.app.workspace.on('css-change', () => this.syncThemeBackground()); | CODE |
| CRITICAL | src/features/chat/session-manager/SessionSidebar.ts | 154 | this.deps.plugin.app.workspace.offref(this.themeEvent); | CODE |
| CRITICAL | src/features/chat/session-manager/SessionSidebar.ts | 539 | const target = this.deps.plugin.app.vault.getAbstractFileByPath(contentPath); | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …viders/deepseek/ui/DeepSeekSettingsTab.wsl.dom.test.ts | 55 | expect(cli).toHaveProperty('placeholder', '%LOCALAPPDATA%\\Programs\\DeepSeek Harness'); | CODE |
| LOW | …viders/deepseek/ui/DeepSeekSettingsTab.wsl.dom.test.ts | 61 | expect(cli).toHaveProperty('placeholder', 'dsh'); | CODE |
| LOW | …res/chat/session-manager/SessionManagerSurface.test.ts | 237 | expect(input.getAttribute('placeholder')).toBe('Search sessions'); | CODE |
| LOW | …shared/settings/EnvironmentSettingsSection.dom.test.ts | 224 | error: new Error('post-commit apply rejected after persistence for TOKEN=fake-token-value at /fake/private/path'), | CODE |
| LOW | …shared/settings/EnvironmentSettingsSection.dom.test.ts | 262 | expect(renderedText).not.toContain('fake-token-value'); | CODE |
| LOW | src/features/chat/interactions/InlineAskUserQuestion.ts | 342 | inputEl.setAttribute('placeholder', q.isSecret ? t('chat.questions.secret') : t('chat.questions.customAnswer')); | CODE |
| LOW | src/i18n/locales/ja.json | 69 | "placeholder": "サイドチャットで続けて質問", | CODE |
| LOW | src/i18n/locales/ja.json | 100 | "placeholder": "変更を依頼、@でファイルを指定、/コマンドを実行", | CODE |
| LOW | src/i18n/locales/ja.json | 533 | "placeholder": "エイリアス", | CODE |
| LOW | src/i18n/locales/ja.json | 831 | "placeholder": "commit\ncompact\nskill:review" | CODE |
| LOW | src/i18n/locales/de.json | 69 | "placeholder": "Im Nebenchat nachfragen", | CODE |
| LOW | src/i18n/locales/de.json | 100 | "placeholder": "Änderungen anfragen, Dateien mit @ erwähnen, /Befehle ausführen", | CODE |
| LOW | src/i18n/locales/de.json | 533 | "placeholder": "Aliasname", | CODE |
| LOW | src/i18n/locales/de.json | 831 | "placeholder": "commit\ncompact\nskill:review" | CODE |
| LOW | src/i18n/locales/ru.json | 69 | "placeholder": "Задайте уточняющий вопрос в побочном чате", | CODE |
| LOW | src/i18n/locales/ru.json | 100 | "placeholder": "Запросите изменения, укажите файлы через @, выполните /команды", | CODE |
| LOW | src/i18n/locales/ru.json | 533 | "placeholder": "Псевдоним", | CODE |
| LOW | src/i18n/locales/ru.json | 831 | "placeholder": "commit\ncompact\nskill:review" | CODE |
| LOW | src/i18n/locales/zh-CN.json | 69 | "placeholder": "在侧边对话中继续提问", | CODE |
| LOW | src/i18n/locales/zh-CN.json | 100 | "placeholder": "请求修改、@提及文件、运行 /命令", | CODE |
| LOW | src/i18n/locales/zh-CN.json | 533 | "placeholder": "别名", | CODE |
| LOW | src/i18n/locales/zh-CN.json | 831 | "placeholder": "commit\ncompact\nskill:review" | CODE |
| LOW | src/i18n/locales/pt.json | 69 | "placeholder": "Faça uma pergunta na conversa lateral", | CODE |
| LOW | src/i18n/locales/pt.json | 100 | "placeholder": "Peça alterações, mencione arquivos com @, execute /comandos", | CODE |
| LOW | src/i18n/locales/pt.json | 533 | "placeholder": "Apelido", | CODE |
| LOW | src/i18n/locales/pt.json | 831 | "placeholder": "commit\ncompact\nskill:review" | CODE |
| LOW | src/i18n/locales/en.json | 69 | "placeholder": "Ask a follow-up in the side chat", | CODE |
| LOW | src/i18n/locales/en.json | 100 | "placeholder": "Ask to make changes, @mention files, run /commands", | CODE |
| LOW | src/i18n/locales/en.json | 533 | "placeholder": "Alias", | CODE |
| LOW | src/i18n/locales/en.json | 831 | "placeholder": "commit\ncompact\nskill:review" | CODE |
| LOW | src/i18n/locales/fr.json | 69 | "placeholder": "Poser une question dans la conversation annexe", | CODE |
| LOW | src/i18n/locales/fr.json | 100 | "placeholder": "Demandez des modifications, mentionnez des fichiers avec @, lancez des /commandes", | CODE |
| LOW | src/i18n/locales/fr.json | 533 | "placeholder": "Alias", | CODE |
| LOW | src/i18n/locales/fr.json | 831 | "placeholder": "commit\ncompact\nskill:review" | CODE |
| LOW | src/i18n/locales/ko.json | 69 | "placeholder": "사이드 채팅에서 이어서 질문하세요", | CODE |
| LOW | src/i18n/locales/ko.json | 100 | "placeholder": "변경 요청, @로 파일 언급, /명령 실행", | CODE |
| LOW | src/i18n/locales/ko.json | 533 | "placeholder": "별칭", | CODE |
| LOW | src/i18n/locales/ko.json | 831 | "placeholder": "commit\ncompact\nskill:review" | CODE |
| LOW | src/i18n/locales/zh-TW.json | 69 | "placeholder": "在側邊對話中繼續提問", | CODE |
| LOW | src/i18n/locales/zh-TW.json | 100 | "placeholder": "請求修改、@提及檔案、執行 /命令", | CODE |
| LOW | src/i18n/locales/zh-TW.json | 533 | "placeholder": "別名", | CODE |
| LOW | src/i18n/locales/zh-TW.json | 831 | "placeholder": "commit\ncompact\nskill:review" | CODE |
| LOW | src/i18n/locales/es.json | 69 | "placeholder": "Pregunta algo más en el chat lateral", | CODE |
| LOW | src/i18n/locales/es.json | 100 | "placeholder": "Pide cambios, menciona archivos con @, ejecuta /comandos", | CODE |
| LOW | src/i18n/locales/es.json | 533 | "placeholder": "Alias", | CODE |
| LOW | src/i18n/locales/es.json | 831 | "placeholder": "commit\ncompact\nskill:review" | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/helpers/WSLClaudeFixture.ts | 5 | print('2.1.99 (Claude Code)') | CODE |
| HIGH | tests/helpers/WSLClaudeFixture.ts | 9 | print(json.dumps(value), flush=True) | CODE |
| HIGH | tests/helpers/WSLClaudeFixture.ts | 33 | elif message.get('type') == 'user': | CODE |
| HIGH | tests/helpers/WSLClaudeFixture.ts | 40 | elif message.get('type') == 'control_response' and message['response'].get('request_id') == 'fixture-mcp': | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | …codex/runtime/notifications/CodexRawToolCallTracker.ts | 41 | #toolNamesByCallId = new Map<string, string>(); | COMMENT |
| LOW | src/features/chat/side-chat/SideChatController.ts | 41 | COMMENT | |
| LOW | src/features/chat/side-chat/SideChatRuntime.ts | 81 | readonly #prompts: SessionInteractions; | COMMENT |
| LOW | src/features/chat/execution/ChatExecutionCoordinator.ts | 221 | #conversation: ChatExecutionConversationBinding | null = null; | COMMENT |