Skip to content

feat(adapters): name SDK-embedded hosts instead of mislabeling as Claude Code - #39

Merged
DevVig merged 1 commit into
mainfrom
feat/detect-sdk-host
Jul 18, 2026
Merged

feat(adapters): name SDK-embedded hosts instead of mislabeling as Claude Code#39
DevVig merged 1 commit into
mainfrom
feat/detect-sdk-host

Conversation

@DevVig

@DevVig DevVig commented Jul 18, 2026

Copy link
Copy Markdown
Owner

The bug

Every session in the menu bar app showed as "Claude Code" — even when it was actually driven by Synara or T3 Code.

Root cause: the Claude adapter (crates/mb-adapters/src/claude.rs) watches ~/.claude/projects and hardcoded app: "Claude Code". But Synara, T3 Code, and other Claude Agent SDK hosts write their session journals into that same store — indistinguishable by location — so they all got labeled "Claude Code".

The fix (file-watch only, zero host cooperation)

Attribute the host truthfully from two fields already present in the journal the daemon already reads in full — so there are no new watchers, no polling, no process inspection, and no host/IDE files touched (just two extra Value::gets per line):

Signal Label
entrypoint: cli Claude Code
entrypoint: claude-desktop Claude Desktop
entrypoint: sdk-* + cwd under ~/.synara Synara
entrypoint: sdk-* + cwd under ~/.t3 T3 Code
entrypoint: sdk-* + cwd under ~/.cursor Cursor
entrypoint: sdk-* (no host cwd) Claude Agent SDK
missing / unknown Claude Code (back-compat)

The host registry is a small static table, trivial to extend as more SDK hosts appear.

Known limit (by design)

For an in-place SDK session (cwd is the plain repo, not a host worktree) there is genuinely no on-disk signal that names Synara vs T3 Code — lsof shows no open handle to correlate a PID, the host homes don't cross-map the Claude session id, and reading another process's env is out of scope. Those sessions show the honest generic "Claude Agent SDK". Full host-naming everywhere would require a host-run adapter, which the "don't touch host files / minimal footprint" constraint rules out.

Footprint

No added syscalls in steady state — the parse already happens on every journal change; this only reads two more fields from lines already being parsed.

Verification

  • New unit test covers the full label matrix (cli / desktop / sdk+cwd / sdk-generic / missing).
  • Workspace: cargo fmt --check, clippy --workspace --all-targets -D warnings, and all 31 tests pass.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Session records now show a more accurate app label based on how and where they were started.
    • Added support for identifying interactive, desktop, and SDK-embedded session hosts.
  • Bug Fixes

    • Session updates are now detected when the associated app label changes.

…ude Code

The Claude adapter watches ~/.claude/projects and hardcoded every session as
"Claude Code". But Synara, T3 Code, and other Claude Agent SDK hosts write
their journals into that same store, so their sessions showed up as
"Claude Code" in the app.

Attribute the host truthfully using two fields already present in the journal
the daemon reads — no new watchers, no polling, no process inspection, and no
host/IDE files touched:

- entrypoint: cli -> "Claude Code", claude-desktop -> "Claude Desktop",
  sdk-* -> an embedded host.
- For SDK hosts, name from cwd when it runs under a known host home
  (~/.synara -> "Synara", ~/.t3 -> "T3 Code", ~/.cursor -> "Cursor"); else
  fall back to the honest generic "Claude Agent SDK".

In-place SDK sessions (cwd is the plain repo) have no on-disk host marker and
show "Claude Agent SDK" — truthful, just not host-named. Missing/unknown
entrypoint keeps the historical "Claude Code" default.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 18, 2026 14:21
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The Claude adapter derives per-session application labels from entrypoint and cwd journal fields, includes those labels in session fingerprints, and adds coverage for CLI, desktop, SDK-hosted, fallback, and missing-entrypoint cases.

Changes

Claude app labeling

Layer / File(s) Summary
Derive app labels
crates/mb-adapters/src/claude.rs
Session parsing captures entrypoint and cwd, then maps them to CLI, desktop, SDK-host, or fallback application labels.
Fingerprint and validate labels
crates/mb-adapters/src/claude.rs
Session fingerprints include session.app, and tests verify derived labels and backward-compatible defaults.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: copilot

Poem

I’m a rabbit with labels to spare,
Finding hosts in the journal air.
CLI, desktop, SDK in a row,
Fingerprints now know where sessions go.
Hop, hop—tests confirm the show!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: deriving better labels for SDK-embedded Claude sessions instead of defaulting to Claude Code.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/mb-adapters/src/claude.rs`:
- Line 178: Update the entrypoint match arm in the Claude label logic to
recognize only documented “sdk-*” values, not arbitrary strings beginning with
“sdk”; preserve the “Claude Code” fallback for unknown entrypoints such as
“sdkfoo”. Add a regression case to the existing label matrix covering this
unknown value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c7591d07-e037-4633-9da6-d43031875d39

📥 Commits

Reviewing files that changed from the base of the PR and between b66df92 and f113e1a.

📒 Files selected for processing (1)
  • crates/mb-adapters/src/claude.rs

match entrypoint {
Some("cli") => "Claude Code".into(),
Some("claude-desktop") => "Claude Desktop".into(),
Some(ep) if ep.starts_with("sdk") => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Match only the documented sdk-* entrypoints.

starts_with("sdk") incorrectly labels unknown values such as sdkfoo as “Claude Agent SDK”; unknown entrypoints should retain the “Claude Code” fallback. Add a regression case alongside the label matrix.

Proposed fix
-        Some(ep) if ep.starts_with("sdk") => {
+        Some(ep) if ep.starts_with("sdk-") => {
             host_from_cwd(cwd).unwrap_or("Claude Agent SDK").into()
         }
+        assert_eq!(claude_app_label(Some("sdkfoo"), None), "Claude Code");

Also applies to: 286-318

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/mb-adapters/src/claude.rs` at line 178, Update the entrypoint match
arm in the Claude label logic to recognize only documented “sdk-*” values, not
arbitrary strings beginning with “sdk”; preserve the “Claude Code” fallback for
unknown entrypoints such as “sdkfoo”. Add a regression case to the existing
label matrix covering this unknown value.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes incorrect session app labeling in the Claude adapter by deriving the displayed host name from fields already present in the Claude journal (entrypoint and cwd), instead of hardcoding "Claude Code" for all sessions. This improves correctness for Claude Agent SDK–embedded hosts that share the same ~/.claude/projects store.

Changes:

  • Track app in the adapter’s Fingerprint so label changes trigger updates.
  • Parse entrypoint and cwd from journal lines and derive SessionStatus.app via claude_app_label(...).
  • Add unit tests covering label selection across CLI, desktop, SDK-embedded, and missing-entrypoint cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +303 to +316
// SDK-embedded host running under a known host home → named host.
let home = std::env::var("HOME").unwrap();
assert_eq!(
claude_app_label(
Some("sdk-ts"),
Some(&format!("{home}/.synara/worktrees/Foo"))
),
"Synara"
);
assert_eq!(
claude_app_label(Some("sdk-cli"), Some(&format!("{home}/.t3/worktrees/Bar"))),
"T3 Code"
);

Comment on lines +190 to +200
let cwd = cwd?;
let home = std::env::var("HOME").ok()?;
// (home-relative dir, display name) — extend as more SDK hosts appear.
const HOSTS: &[(&str, &str)] = &[
(".synara", "Synara"),
(".t3", "T3 Code"),
(".cursor", "Cursor"),
];
for (dir, name) in HOSTS {
let prefix = format!("{home}/{dir}/");
if cwd.starts_with(&prefix) {
@DevVig
DevVig merged commit 4959494 into main Jul 18, 2026
8 checks passed
@DevVig
DevVig deleted the feat/detect-sdk-host branch July 18, 2026 14:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants