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
2 changes: 2 additions & 0 deletions docs/usage-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -1873,6 +1873,8 @@ For canonical YAML agents, push compares each local file with the corresponding

### Cursor

Cursor subagents deploy to `.cursor/agents/*.md` with YAML frontmatter carrying `agent_id` (the team agent's name), `description`, `tools`, and the agent's `model` when it declares one, plus any `tool_extras.cursor` fields; `reverseFromCursor` reads the same fields back, so a `pull` → `push` round-trip keeps the model.

Cursor project rules must live in `.cursor/rules/` as **`.mdc`** files with YAML frontmatter — a plain `.md` file there is silently ignored by Cursor. teamai therefore writes rules to Cursor as `<name>.mdc` (every other tool still gets a plain `.md`), deriving the frontmatter from the team rule:

- A rule scoped with a `paths:` list becomes `globs: "<comma-joined>"` + `alwaysApply: false` (Cursor auto-attaches it when a matching file is in context). The value is quoted because a glob starting with `*` is not valid YAML unquoted.
Expand Down
2 changes: 2 additions & 0 deletions docs/usage-guide.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -1767,6 +1767,8 @@ JoyCode 规则清理采用保守策略:不在团队规则列表中的本地 `.

### Cursor

Cursor 的子代理部署到 `.cursor/agents/*.md`,YAML frontmatter 携带 `agent_id`(团队代理名)、`description`、`tools`,以及团队代理声明了的 `model`,外加所有 `tool_extras.cursor` 字段;`reverseFromCursor` 按同样字段读回,因此 `pull` → `push` 往返不会丢 model。

Cursor 的项目规则必须以 **`.mdc`** 文件形式放在 `.cursor/rules/` 下,且带 YAML frontmatter——放在那里的纯 `.md` 会被 Cursor 直接忽略。因此 teamai 向 Cursor 写规则时用 `<name>.mdc`(其他工具仍写纯 `.md`),并从团队规则派生 frontmatter:

- 带 `paths:` 列表的规则会转成 `globs: "<逗号拼接>"` + `alwaysApply: false`(上下文中有匹配文件时 Cursor 自动附加该规则)。值加引号是因为以 `*` 开头的 glob 不加引号时并非合法 YAML。
Expand Down
18 changes: 18 additions & 0 deletions src/__tests__/agent-format.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,24 @@ describe('renderForCursor', () => {
expect(content).toContain('You are a helpful assistant.');
});

it('carries the model into the frontmatter like every other renderer (#830)', () => {
const { content } = renderForCursor(makeSpec({ model: 'claude-opus-4' }));
expect(content).toContain('model: claude-opus-4');
});

it('omits model when the spec has none', () => {
const { content } = renderForCursor(makeSpec());
expect(content).not.toContain('model:');
});

it('round-trips the model through reverseFromCursor', () => {
const { content } = renderForCursor(makeSpec({ model: 'claude-opus-4' }));
const result = reverseFromCursor('/agents/test-agent.md', content);
expect(result.ok).toBe(true);
if (!result.ok) return;
expect(result.spec.model).toBe('claude-opus-4');
});

it('flattens tool_extras.cursor into frontmatter', () => {
const spec = makeSpec({ tool_extras: { cursor: { composer_mode: true } } });
const { content } = renderForCursor(spec);
Expand Down
3 changes: 3 additions & 0 deletions src/resources/agent-format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,9 @@ export function renderForCursor(spec: AgentSpec): RenderResult {
agent_id: spec.name,
description: spec.description,
};
if (spec.model !== undefined) {
frontmatterData['model'] = spec.model;
}
if (spec.tools !== undefined && spec.tools.length > 0) {
frontmatterData['tools'] = spec.tools;
}
Expand Down
Loading