feat(cursor): add sandbox option to disable restricted tool mode
Cursor Agent CLI defaults to sandbox mode in headless environments,
limiting available tools to read-only operations (ls, etc.). Add a
configurable `sandbox` option ("enabled"/"disabled"/"") that maps to
the `--sandbox` CLI flag, allowing users to unlock full tool access
(shell, edit, write) when running via cc-connect.
Config example:
[projects.agent.options]
sandbox = "disabled"
Made-with: Cursor
This commit is contained in:
1 parent
155b204b64
commit
6152854fa0
3 files changed
+31
-4
No files matched your search
+16
-1
@@ -34,6 +34,7 @@ type Agent struct {
|
||||
model string
|
||||
mode string
|
||||
cmd string // CLI binary name, default "agent"
|
||||
sandbox string // "enabled", "disabled", or "" (let CLI decide)
|
||||
providers []core.ProviderConfig
|
||||
activeIdx int
|
||||
sessionEnv []string
|
||||
@@ -52,6 +53,7 @@ func New(opts map[string]any) (core.Agent, error) {
|
||||
if cmd == "" {
|
||||
cmd = "agent"
|
||||
}
|
||||
sandbox := normalizeSandbox(opts["sandbox"])
|
||||
|
||||
if _, err := exec.LookPath(cmd); err != nil {
|
||||
return nil, fmt.Errorf("cursor: %q CLI not found in PATH, install with: npm i -g @anthropic-ai/cursor-agent (or from Cursor IDE settings)", cmd)
|
||||
@@ -62,6 +64,7 @@ func New(opts map[string]any) (core.Agent, error) {
|
||||
model: model,
|
||||
mode: mode,
|
||||
cmd: cmd,
|
||||
sandbox: sandbox,
|
||||
activeIdx: -1,
|
||||
}, nil
|
||||
}
|
||||
@@ -79,6 +82,18 @@ func normalizeMode(raw string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeSandbox(v any) string {
|
||||
s, _ := v.(string)
|
||||
switch strings.ToLower(strings.TrimSpace(s)) {
|
||||
case "enabled", "on", "true", "1":
|
||||
return "enabled"
|
||||
case "disabled", "off", "false", "0":
|
||||
return "disabled"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) Name() string { return "cursor" }
|
||||
func (a *Agent) CLIBinaryName() string { return "agent" }
|
||||
func (a *Agent) CLIDisplayName() string { return "Cursor Agent" }
|
||||
@@ -202,7 +217,7 @@ func (a *Agent) StartSession(ctx context.Context, sessionID string) (core.AgentS
|
||||
}
|
||||
a.mu.Unlock()
|
||||
|
||||
return newCursorSession(ctx, cmd, a.workDir, model, mode, sessionID, extraEnv)
|
||||
return newCursorSession(ctx, cmd, a.workDir, model, mode, a.sandbox, sessionID, extraEnv)
|
||||
}
|
||||
|
||||
// ListSessions reads sessions from ~/.cursor/chats/<workspace_hash>/.
|
||||
|
||||
@@ -26,6 +26,7 @@ type cursorSession struct {
|
||||
workDir string
|
||||
model string
|
||||
mode string
|
||||
sandbox string // "enabled", "disabled", or ""
|
||||
extraEnv []string
|
||||
events chan core.Event
|
||||
chatID atomic.Value // stores string — Cursor chat/session ID
|
||||
@@ -37,7 +38,7 @@ type cursorSession struct {
|
||||
thinkingBuf strings.Builder // accumulate thinking deltas
|
||||
}
|
||||
|
||||
func newCursorSession(ctx context.Context, cmd, workDir, model, mode, resumeID string, extraEnv []string) (*cursorSession, error) {
|
||||
func newCursorSession(ctx context.Context, cmd, workDir, model, mode, sandbox, resumeID string, extraEnv []string) (*cursorSession, error) {
|
||||
sessionCtx, cancel := context.WithCancel(ctx)
|
||||
|
||||
cs := &cursorSession{
|
||||
@@ -45,6 +46,7 @@ func newCursorSession(ctx context.Context, cmd, workDir, model, mode, resumeID s
|
||||
workDir: workDir,
|
||||
model: model,
|
||||
mode: mode,
|
||||
sandbox: sandbox,
|
||||
extraEnv: extraEnv,
|
||||
events: make(chan core.Event, 64),
|
||||
ctx: sessionCtx,
|
||||
@@ -89,6 +91,10 @@ func (cs *cursorSession) Send(prompt string, images []core.ImageAttachment, file
|
||||
args = append(args, "--mode", "ask")
|
||||
}
|
||||
|
||||
if cs.sandbox != "" {
|
||||
args = append(args, "--sandbox", cs.sandbox)
|
||||
}
|
||||
|
||||
if isResume {
|
||||
args = append(args, "--resume", chatID)
|
||||
}
|
||||
|
||||
+8
-2
@@ -911,8 +911,9 @@ app_secret = "your-feishu-app-secret"
|
||||
#
|
||||
# [projects.agent.options]
|
||||
# work_dir = "/path/to/project"
|
||||
# mode = "force" # "default" | "force" (yolo) | "plan" | "ask"
|
||||
# cmd = "agent" # CLI binary name (default: "agent") / CLI 二进制名称(默认 "agent")
|
||||
# mode = "force" # "default" | "force" (yolo) | "plan" | "ask"
|
||||
# cmd = "agent" # CLI binary name (default: "agent") / CLI 二进制名称(默认 "agent")
|
||||
# sandbox = "disabled" # "enabled" | "disabled" | "" (let CLI decide)
|
||||
#
|
||||
# Mode options / 模式说明:
|
||||
# - "default": Trust workspace, ask before tool use / 信任工作区,工具调用前询问
|
||||
@@ -920,6 +921,11 @@ app_secret = "your-feishu-app-secret"
|
||||
# - "plan": Read-only analysis, no edits / 只读分析,不做修改
|
||||
# - "ask": Q&A style, read-only / 问答风格,只读
|
||||
#
|
||||
# Sandbox options / 沙箱模式说明:
|
||||
# - "disabled": Full tool access (shell, edit, write, etc.) / 完整工具访问(shell、edit、write 等)
|
||||
# - "enabled": Restricted tools (read-only, ls, etc.) / 受限工具(只读、ls 等)
|
||||
# - "": Let Cursor CLI decide (may default to sandbox in headless) / 由 CLI 决定(headless 可能默认沙箱)
|
||||
#
|
||||
# Optional: specify a model / 可选:指定模型
|
||||
# model = "claude-sonnet-4-20250514"
|
||||
#
|
||||
|
||||
Reference in new issue
Block a user