Repository navigation
feat(agent-lab): open Claude Code tasks via official Android handoff - #396
Conversation
🐤 Kanarek · 🟣 merged
Documentation, App · 7 files |
Reviewer's GuideThis PR adds an opt-in Studio Tools → Agents → Claude Code flow that validates and confirms a user-authored task, then launches an official Claude app/web universal link with optional GitHub context. It preserves Aistee’s existing tools and authentication boundaries, and adds JVM coverage plus documentation clarifying that Claude owns login, usage, entitlement, and billing. Sequence diagram for the Claude Code external handoffsequenceDiagram
actor User
participant Aistee as Aistee Studio Tools
participant Claude as Official Claude app or website
User->>Aistee: Enter task, optional repository/branch, and mode
Aistee->>Aistee: canOpen(task, repository, branch)
User->>Aistee: Tap Open in Claude Code
Aistee->>User: Show confirmation dialog
User->>Aistee: Confirm Open Claude
Aistee->>Aistee: newSessionUrl(task, repository, branch, mode)
Aistee->>Claude: openExternalUri(newSessionUrl)
Claude->>User: Handle login, entitlement, usage, and billing
Flow diagram for Claude Code task validation and launchflowchart TD
Tools[Studio Tools] --> Agents[Agents]
Agents --> Panel[Claude Code handoff panel]
Panel --> Fields[Task plus optional GitHub repository and branch]
Fields --> Mode[Plan or Code mode]
Mode --> Valid{canOpen valid?}
Valid -- No --> Fields
Valid -- Yes --> Confirm[Explicit confirmation]
Confirm -- Cancel --> Panel
Confirm -- Open Claude --> URL[newSessionUrl]
URL --> External[Official Claude app or website]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
This pull request does not currently match the merge queue conditions, so it cannot be queued from here. The box comes back if it matches again. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 865f164e8b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Hey - I've found 5 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt" line_range="151" />
<code_context>
+ TextButton(onClick = {
+ confirmation = false
+ val url = ClaudeCodeHandoff.newSessionUrl(task, repository, branch, mode)
+ notice = if (openExternalUri(context, Uri.parse(url))) null
+ else "No app or browser could open Claude Code."
+ }) { Text("Open Claude") }
</code_context>
<issue_to_address>
**Task text leaks to logs**
When opening the handoff fails because Android has no URL handler or rejects the launch, `openExternalUri` logs the caught launch exception, whose message includes the intent URI and its task text. The composed task is exposed in logcat without the user being told.
Avoid logging the exception or intent URI, or redact the task text before logging.
</issue_to_address>
### Comment 2
<location path="app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt" line_range="68" />
<code_context>
+@Composable
+internal fun ClaudeCodeHandoffPanel(modifier: Modifier = Modifier) {
+ val context = LocalContext.current
+ var task by remember { mutableStateOf("") }
+ var repository by remember { mutableStateOf("") }
+ var branch by remember { mutableStateOf("") }
</code_context>
<issue_to_address>
**Handoff drafts disappear**
When the user switches away from Agents or Android recreates the activity while composing a handoff, `ClaudeCodeHandoffPanel` stores the draft in `remember` state, which is discarded when the panel leaves composition and is not restored after activity recreation. Returning to Agents shows an empty form and loses the task and its options.
Store the draft in state that survives both panel disposal and activity recreation, such as state hoisted to a saveable owner.
Also at `app/src/main/java/ais/tee/ui/screens/StudioToolsHubScreen.kt:65-67`.
</issue_to_address>
### Comment 3
<location path="app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt" line_range="105" />
<code_context>
+ value = branch,
+ onValueChange = { branch = it },
+ label = { Text("Branch (optional)") },
+ enabled = repository.isNotBlank(),
+ singleLine = true,
+ modifier = Modifier.fillMaxWidth().testTag("claude_code_branch"),
</code_context>
<issue_to_address>
**Branch cannot be cleared**
When the user enters a branch and then clears the repository, `branch` remains populated while the field is disabled, and `canOpen` rejects a branch without a repository. The user cannot clear the stale branch, so the Open button stays disabled.
Keep the branch field editable or clear the branch when the repository is emptied.
Also at `app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt:47`.
</issue_to_address>
### Comment 4
<location path="app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt" line_range="36-37" />
<code_context>
+ const val SESSIONS_URL = "https://claude.ai/code"
+ private const val NEW_SESSION_URL = "https://claude.ai/code/new"
+ const val MAX_TASK_CHARS = 2_000
+ private val repoPattern = Regex("^[A-Za-z0-9][A-Za-z0-9-]{0,38}/[A-Za-z0-9._-]{1,100}$")
+ private val branchPattern = Regex("^[A-Za-z0-9._/-]{1,150}$")
+
+ enum class Mode(val value: String) { PLAN("plan"), CODE("code") }
</code_context>
<issue_to_address>
**Invalid GitHub references pass**
When the user enters a repository or branch that the regex accepts but GitHub or Git rejects, or a valid branch containing `+`, `repoPattern` and `branchPattern` accept invalid names and reject some valid branch names, so `canOpen` enables unusable references or blocks valid ones; `newSessionUrl` then sends the accepted reference to Claude Code. The requested repository or branch cannot be used.
Validate repository names against GitHub naming rules and branches against Git ref rules.
</issue_to_address>
### Comment 5
<location path="app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt" line_range="144" />
<code_context>
+ Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
+ Text("Only this task, mode and optional GitHub reference will be passed to " +
+ "the official Claude Code composer. Aistee does not authenticate to Claude.")
+ Text(task, maxLines = 5, style = MaterialTheme.typography.bodySmall)
+ }
+ },
</code_context>
<issue_to_address>
**Handoff payload cannot be verified**
When the task exceeds five rendered lines or the user has entered GitHub context or selected Code mode, the confirmation dialog limits the displayed task to five lines and omits the selected mode and repository and branch values, while `newSessionUrl` submits the full payload. The user cannot review what will be sent to Claude.
Show the complete task and all selected handoff options in the confirmation dialog.
</issue_to_address>Sourcery assessment
Needs a human reviewer. 5 findings to address first, and opening the handoff URL sends the task text and optional repository details to Claude in the URL; once transmitted, reverting the feature cannot retract that disclosure. The confirmation gate limits this to an explicit user action, but a mistaken or unintended handoff could still expose information externally.
Blocking findings: app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt:151, app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt:68, app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt:105, app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt:37, app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt:144
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 Walkthrough
Priority: ⬇️ Low Merge Risk: 🟡 Moderate · up to
|
There was a problem hiding this comment.
Note
Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.
🟡 Other comments: 2
app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.kt: 2
130-132: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win让“打开会话”入口与实际目标一致。
官方文档将
https://claude.ai/code标为新会话编辑器,不是会话列表。用户点击“Open Claude Code sessions”时,当前代码仍打开该地址。若要打开已安装应用的会话列表,请使用文档中的claude://code,并为浏览器回退提供准确的按钮文案;同时更新文档中的入口说明。(support.claude.com)
37-37: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win修正 Git 分支名校验。
石头人看:
branchPattern接受main/、foo//bar和topic..next,但 Git 不允许这些分支名。用户可以确认交接,却无法让 Claude 预选所填分支。请按 Git refname 规则校验各个路径段,并补上这些输入的测试。(git-scm.com)
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: QUIET
- Plan: Advanced
- Run ID:
880ee0d0-4f65-4db6-8908-7fb3acd7d6a2
📒 Files selected for processing: 6
README.mdapp/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.ktapp/src/main/java/ais/tee/ui/screens/StudioToolsHubScreen.ktapp/src/test/java/ais/tee/ui/screens/ClaudeCodeHandoffTest.ktapp/src/test/java/ais/tee/ui/screens/StudioToolsHubScreenTest.ktdocs/provider-runtime.md
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
2fb31ff to
c9bf5a1
Compare
9558c7e to
5a4386e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 824da195c0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 3
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: QUIET
- Plan: Advanced
- Run ID:
af251d36-8b9a-4624-9e99-8c7592455535
📒 Files selected for processing: 5
app/src/main/java/ais/tee/ui/screens/ClaudeCodeHandoffPanel.ktapp/src/main/java/ais/tee/ui/screens/StudioToolsHubScreen.ktapp/src/main/java/ais/tee/ui/screens/WebNavigationSafety.ktapp/src/test/java/ais/tee/ui/screens/ClaudeCodeHandoffTest.ktdocs/provider-runtime.md
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
Changes
Validation
This is an opt-in convenience, not a prerequisite for Aistee. Actual Claude Code entitlement and usage/extra credits remain controlled by Claude.