Repository navigation
Description
What happened
Sending /goal <objective> to a Claude thread together with a skill invocation on a later line (for example /reverse-engineer-anything) does not set a goal. The goal banner never appears and the thread's goal stays null. The model reads the text as a normal prompt. A plain /goal <text> sent in the next turn worked.
Diagnosis
makeClaudeUserMessage in apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts (~line 2091) calls planClaudeSkillDispatch. When a skill is invoked it splits the message into two text blocks: everything before the skill, then the /skill command. The Claude CLI only treats /goal as a native command when it starts the prompt. After the split, the CLI sees a content-block array whose first block merely begins with the text /goal, so it never emits the Goal set: ... reply. nextClaudeGoal (~line 1791) only sets a goal from that reply, so none is recorded.
The server and the CLI also disagree. parseGoalCommand in packages/contracts/src/orchestrationV2.ts matches the whole multi-line message ([\s\S]*) and calls it a goal command, so the UI and queueing logic treat it as a goal set while the provider never receives a goal command.
Possible fix: skip skill dispatch when the message is a /goal command, or send /goal as its own message first.
Steps to reproduce
- Open a Claude thread on the desktop app.
- Send this as one message:
/goal fix all the gaps.
decompile target.ipa into ./target/
/reverse-engineer-anything
- No goal row appears and the thread's goal stays null.
- Send
/goal fix all the gapsalone in the next turn. The goal is set.
Version
0.1.7-nightly.20261102.4093 (desktop app, local server). The triage CLI is the same version.
Environment
macOS (Darwin 27.2.0, arm64), T3 Code Desktop with the local server, provider claudeAgent.
Evidence
- Three threads from 2026-11-03 show the same pattern. Each has a prompt.offer with two text blocks: the first starts `/goal fix all the gaps...`, the second is the skill expansion.
- `goal` is null on both the thread projection and the provider thread in all three.
- The provider event logs contain no `Goal set`, `Goal active` or `Stop hook feedback` message.
- In one thread the model's reasoning says "The user has added a new goal", so it treated the text as a plain prompt.Related issues
None match. #25954, #25951 and #23019 are goal bugs, but about UI placement, resuming and Codex limits.
Fix applied or workaround
Send /goal <objective> alone, then invoke the skill in a later turn.
Filed by
Claude Code (claude-sonnet-5-5), using the T3 Code triage playbook.
Activity
yspreen commentedon Nov 3, 2026
Side note on how this issue got its
via-triagelabel, since it looks like a gap in the triage flow and not part of the bug above.The triage playbook says to post with
gh issue create --repo pingdotgg/t3code --label via-triage, but only ifgh api repos/pingdotgg/t3code --jq .permissions.triageprintstrue. On this machine,ghwas logged in as a normal GitHub user with no write access to the repo, and that command printedfalse. Applying labels needs triage permission, so the directghroute was closed.The playbook's fallback is a prefilled
issues/new?template=via-triage.ymlURL. The form applies the label for whoever submits it, so that worked. The agent built the URL, opened it in Chrome, and the user clicked Create.Why this seems odd:
t3 triageis an outside contributor without triage permission, so the fallback is the common path and thegh issue createpath will rarely run.Suggestion: make the prefilled form URL the default and keep
gh issue createfor maintainers only.Posted by Claude Code (claude-sonnet-5-5) at the user's request.