Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.3.2 — clearer "job not found" hint

### Fixed

- **`/cursor:status`, `/cursor:result`, `/cursor:cancel` now explain a missing job id** (#7). When `/cursor:delegate` runs as a Claude Code background command, Claude Code surfaces _its own_ wrapper id (`Command running in background with ID: …`), not the Cursor job id — so `/cursor:status <that-id>` always missed with a bare `No job … found`. The three commands now append a hint pointing out that a Claude Code background id is not the Cursor job id and that `/cursor:status` with no arguments lists the tracked jobs so the real id can be copied. New shared `lib/hints.mjs#jobNotFoundMessage`.

## 0.3.1 — model alias refresh (Composer 2.5 + Grok 4.3)

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion plugins/cursor/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cursor-plugin-cc",
"version": "0.3.1",
"version": "0.3.2",
"description": "Use Cursor CLI from Claude Code to delegate coding tasks to Composer and other Cursor models.",
"type": "module",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion plugins/cursor/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cursor",
"version": "0.3.1",
"version": "0.3.2",
"description": "Hand off tasks from Claude Code to cursor-agent. Composer-optimised.",
"author": {
"name": "Tomas Grasl",
Expand Down
3 changes: 2 additions & 1 deletion plugins/cursor/scripts/cancel.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env node
import { parseCommandArgv } from './lib/args.mjs';
import { repoRoot } from './lib/git.mjs';
import { jobNotFoundMessage } from './lib/hints.mjs';
import { cancelJob, findRunningJobs, readJob } from './lib/jobs.mjs';

/**
Expand Down Expand Up @@ -32,7 +33,7 @@ export async function main(rawArgv) {
const before = readJob(root, id);
const updated = await cancelJob(root, id);
if (!updated) {
process.stderr.write(`No job \`${id}\` found for this repository.\n`);
process.stderr.write(jobNotFoundMessage(id));
return 1;
}
if (before && before.status !== 'running') {
Expand Down
24 changes: 24 additions & 0 deletions plugins/cursor/scripts/lib/hints.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Shared user-facing hints for the job commands (status / result / cancel).

/**
* Message shown when a job id the user supplied does not resolve.
*
* The common cause is copying Claude Code's own background-command ID
* ("Command running in background with ID: …") instead of the Cursor job id —
* they are different values, and the real Cursor id is printed inside the job's
* own output, not in Claude Code's background notification. Rather than guess
* whether `id` is a Claude Code id (a fragile, coupling heuristic), we always
* append the recovery hint.
*
* @param {string} id
* @returns {string}
*/
export function jobNotFoundMessage(id) {
return (
`No job \`${id}\` found for this repository.\n` +
`Hint: if you copied this ID from a Claude Code background notification ` +
`("Command running in background with ID: …"), that is Claude Code's own ID, ` +
`not the Cursor job ID. Run \`/cursor:status\` with no arguments to list ` +
`tracked jobs and copy the real ID.\n`
);
}
5 changes: 2 additions & 3 deletions plugins/cursor/scripts/result.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env node
import { parseCommandArgv } from './lib/args.mjs';
import { repoRoot } from './lib/git.mjs';
import { jobNotFoundMessage } from './lib/hints.mjs';
import { mostRecentFinishedJob, readJob } from './lib/jobs.mjs';

function render(job) {
Expand Down Expand Up @@ -42,9 +43,7 @@ export async function main(rawArgv) {
const job = id ? readJob(root, id) : mostRecentFinishedJob(root);
if (!job) {
process.stderr.write(
id
? `No job \`${id}\` found for this repository.\n`
: 'No finished Cursor jobs tracked for this repository yet.\n',
id ? jobNotFoundMessage(id) : 'No finished Cursor jobs tracked for this repository yet.\n',
);
return 1;
}
Expand Down
3 changes: 2 additions & 1 deletion plugins/cursor/scripts/status.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env node
import { parseCommandArgv } from './lib/args.mjs';
import { repoRoot } from './lib/git.mjs';
import { jobNotFoundMessage } from './lib/hints.mjs';
import { listJobs, readJob } from './lib/jobs.mjs';
import { mdCell } from './lib/md.mjs';

Expand Down Expand Up @@ -82,7 +83,7 @@ export async function main(rawArgv) {
if (id) {
const job = readJob(root, id);
if (!job) {
process.stderr.write(`No job \`${id}\` found for this repository.\n`);
process.stderr.write(jobNotFoundMessage(id));
return 1;
}
process.stdout.write(renderDetail(job));
Expand Down
22 changes: 22 additions & 0 deletions plugins/cursor/tests/hints.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { describe, expect, it } from 'vitest';
import { jobNotFoundMessage } from '../scripts/lib/hints.mjs';

describe('jobNotFoundMessage', () => {
it('names the missing id and ends with a newline', () => {
const msg = jobNotFoundMessage('bo2565uts');
expect(msg).toContain('No job `bo2565uts` found for this repository.');
expect(msg.endsWith('\n')).toBe(true);
});

it('hints that a Claude Code background ID is not the Cursor job ID', () => {
const msg = jobNotFoundMessage('bo2565uts');
expect(msg).toContain('Claude Code background notification');
expect(msg).toContain("Claude Code's own ID");
// Points the user at the recovery path.
expect(msg).toContain('`/cursor:status` with no arguments');
});

it('escapes the id verbatim into a code span', () => {
expect(jobNotFoundMessage('7FfFUyUK5w')).toContain('`7FfFUyUK5w`');
});
});
Loading