Skip to content

Commit 42e8de9

Browse files
committed
feat: add support for cursor cli
1 parent 1b6c85b commit 42e8de9

File tree

19 files changed

+245
-5
lines changed

19 files changed

+245
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# AgentAPI
22

3-
Control [Claude Code](https://github.com/anthropics/claude-code), [Goose](https://github.com/block/goose), [Aider](https://github.com/Aider-AI/aider), [Gemini](https://github.com/google-gemini/gemini-cli), [Sourcegraph Amp](https://github.com/sourcegraph/amp-cli) and [Codex](https://github.com/openai/codex) with an HTTP API.
3+
Control [Claude Code](https://github.com/anthropics/claude-code), [Goose](https://github.com/block/goose), [Aider](https://github.com/Aider-AI/aider), [Gemini](https://github.com/google-gemini/gemini-cli), [Sourcegraph Amp](https://github.com/sourcegraph/amp-cli), [Codex](https://github.com/openai/codex) and [Cursor CLI](https://cursor.com/en/cli) with an HTTP API.
44

55
![agentapi-chat](https://github.com/user-attachments/assets/57032c9f-4146-4b66-b219-09e38ab7690d)
66

cmd/server/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const (
2929
AgentTypeCodex AgentType = msgfmt.AgentTypeCodex
3030
AgentTypeGemini AgentType = msgfmt.AgentTypeGemini
3131
AgentTypeAmp AgentType = msgfmt.AgentTypeAmp
32+
AgentTypeCursor AgentType = msgfmt.AgentTypeCursor
3233
AgentTypeCustom AgentType = msgfmt.AgentTypeCustom
3334
)
3435

@@ -40,6 +41,7 @@ var agentTypeMap = map[AgentType]bool{
4041
AgentTypeCodex: true,
4142
AgentTypeGemini: true,
4243
AgentTypeAmp: true,
44+
AgentTypeCursor: true,
4345
AgentTypeCustom: true,
4446
}
4547

cmd/server/server_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ func TestParseAgentType(t *testing.T) {
4747
agentTypeVar: "",
4848
want: AgentTypeGemini,
4949
},
50+
{
51+
firstArg: "cursor",
52+
agentTypeVar: "",
53+
want: AgentTypeCursor,
54+
},
5055
{
5156
firstArg: "amp",
5257
agentTypeVar: "",
@@ -82,6 +87,11 @@ func TestParseAgentType(t *testing.T) {
8287
agentTypeVar: "gemini",
8388
want: AgentTypeGemini,
8489
},
90+
{
91+
firstArg: "claude",
92+
agentTypeVar: "cursor",
93+
want: AgentTypeCursor,
94+
},
8595
{
8696
firstArg: "aider",
8797
agentTypeVar: "claude",

lib/msgfmt/msgfmt.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,22 @@ func findUserInputEndIdx(userInputStartIdx int, msg []rune, userInput []rune) in
140140
return msgIdx
141141
}
142142

143+
// skipTrailingInputBoxLine skips the next line if it contains any of the markers.
144+
// In case of Gemini and Cursor, the user input is echoed back in a box
145+
// This function searches for the markers passed by the caller and skips the next line if it contains all of them.
146+
func skipTrailingInputBoxLine(lines []string, lastUserInputLineIdx *int, markers ...string) {
147+
if *lastUserInputLineIdx+1 >= len(lines) {
148+
return
149+
}
150+
line := lines[*lastUserInputLineIdx+1]
151+
for _, m := range markers {
152+
if !strings.Contains(line, m) {
153+
return
154+
}
155+
}
156+
*lastUserInputLineIdx++
157+
}
158+
143159
// RemoveUserInput removes the user input from the message.
144160
// Goose, Aider, and Claude Code echo back the user's input to
145161
// make it visible in the terminal. This function makes a best effort
@@ -169,10 +185,8 @@ func RemoveUserInput(msgRaw string, userInputRaw string) string {
169185
// that doesn't contain the echoed user input.
170186
lastUserInputLineIdx := msgRuneLineLocations[userInputEndIdx]
171187

172-
// In case of Gemini, the user input echoed back is wrapped in a rounded box, so we remove it.
173-
if lastUserInputLineIdx+1 < len(msgLines) && strings.Contains(msgLines[lastUserInputLineIdx+1], "╯") && strings.Contains(msgLines[lastUserInputLineIdx+1], "╰") {
174-
lastUserInputLineIdx += 1
175-
}
188+
skipTrailingInputBoxLine(msgLines, &lastUserInputLineIdx, "╯", "╰") // Gemini
189+
skipTrailingInputBoxLine(msgLines, &lastUserInputLineIdx, "┘", "└") // Cursor
176190

177191
return strings.Join(msgLines[lastUserInputLineIdx+1:], "\n")
178192
}
@@ -207,6 +221,7 @@ const (
207221
AgentTypeCodex AgentType = "codex"
208222
AgentTypeGemini AgentType = "gemini"
209223
AgentTypeAmp AgentType = "amp"
224+
AgentTypeCursor AgentType = "cursor"
210225
AgentTypeCustom AgentType = "custom"
211226
)
212227

@@ -238,6 +253,8 @@ func FormatAgentMessage(agentType AgentType, message string, userInput string) s
238253
return formatGenericMessage(message, userInput)
239254
case AgentTypeAmp:
240255
return formatGenericMessage(message, userInput)
256+
case AgentTypeCursor:
257+
return formatGenericMessage(message, userInput)
241258
case AgentTypeCustom:
242259
return formatGenericMessage(message, userInput)
243260
default:
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
I'll check the repository's root, name, remotes, and current branch.
2+
3+
4+
5+
6+
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
7+
│ $ git rev-parse --show-toplevel in . │
8+
│ $ basename "$(git rev-parse --show-toplevel)" in . │
9+
│ $ git remote -v in . │
10+
│ $ git rev-parse --abbrev-ref HEAD in . │
11+
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
12+
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
13+
│ Run this command? │
14+
│ Not in allowlist: git │
15+
│ → Run (y) (enter) │
16+
│ Reject (esc or p) │
17+
│ Add Shell(git) to allowlist? (tab) │
18+
│ Auto-run all commands (shift+tab) │
19+
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Cursor Agent
2+
~/Documents/work/agentapi · feat-cursor-cli
3+
4+
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
5+
│ Which repo is this ? │
6+
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
7+
8+
I'll check the repository's root, name, remotes, and current branch.
9+
10+
11+
12+
13+
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
14+
│ $ git rev-parse --show-toplevel in . │
15+
│ $ basename "$(git rev-parse --show-toplevel)" in . │
16+
│ $ git remote -v in . │
17+
│ $ git rev-parse --abbrev-ref HEAD in . │
18+
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
19+
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
20+
│ Run this command? │
21+
│ Not in allowlist: git │
22+
│ → Run (y) (enter) │
23+
│ Reject (esc or p) │
24+
│ Add Shell(git) to allowlist? (tab) │
25+
│ Auto-run all commands (shift+tab) │
26+
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Which repo is this ?
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
2+
│ ⬢ Welcome to Cursor Agent Beta │
3+
│ │
4+
│ Cursor Agent CLI is in beta. Security safeguards are still evolving. It can read, modify, and delete files, and execute shell commands you approve. Use at your own risk and only in trusted environments. │
5+
│ │
6+
│ Please read about our security at https://cursor.com/security. │
7+
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
8+
9+
10+
Cursor Agent
11+
~/Documents/work/agentapi · feat-cursor-cli

0 commit comments

Comments
 (0)