Skip to content

Commit c481b3a

Browse files
idoubiclaude
andcommitted
feat: enhanced system prompt with tool/code/permission guidelines
Added internal/prompt/prompt.go: - Core identity: Codeany as AI terminal agent - Environment context: OS, shell, CWD, git branch/user, date - Tool guidelines: when to use each tool, parallelization hints - Code quality: match style, no unnecessary abstractions, security - Output style: concise by default, extra concise in /brief mode - Permission guidelines: adapts messaging per mode (bypass/plan/auto/default) System prompt is used when user doesn't override via config. Skills and memory context appended separately. 6900+ lines Go, 78 commands Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e933b66 commit c481b3a

2 files changed

Lines changed: 159 additions & 1 deletion

File tree

internal/prompt/prompt.go

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package prompt
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"os/exec"
7+
"path/filepath"
8+
"runtime"
9+
"strings"
10+
"time"
11+
)
12+
13+
// BuildSystemPrompt constructs the full system prompt for codeany
14+
func BuildSystemPrompt(model, cwd, permissionMode string, briefMode bool) string {
15+
var b strings.Builder
16+
17+
b.WriteString(coreIdentity())
18+
b.WriteString("\n\n")
19+
b.WriteString(environmentContext(cwd))
20+
b.WriteString("\n\n")
21+
b.WriteString(toolGuidelines())
22+
b.WriteString("\n\n")
23+
b.WriteString(codeGuidelines())
24+
b.WriteString("\n\n")
25+
b.WriteString(toneAndStyle(briefMode))
26+
b.WriteString("\n\n")
27+
b.WriteString(permissionGuidelines(permissionMode))
28+
29+
return b.String()
30+
}
31+
32+
func coreIdentity() string {
33+
return `You are Codeany, an AI-powered terminal agent for software engineering. You help users with coding tasks by reading files, writing code, running commands, and managing projects.
34+
35+
You have access to tools for file operations (Read, Write, Edit, Glob, Grep), shell execution (Bash), web access (WebFetch, WebSearch), and agent coordination (Agent for subagents).
36+
37+
# Key Principles
38+
- Go straight to the point. Try the simplest approach first.
39+
- Read code before modifying it. Understand existing patterns.
40+
- Don't add features, refactor, or make improvements beyond what was asked.
41+
- Be careful not to introduce security vulnerabilities.
42+
- Only create files when necessary. Prefer editing existing files.
43+
- When referencing code, include file_path:line_number format.`
44+
}
45+
46+
func environmentContext(cwd string) string {
47+
var b strings.Builder
48+
b.WriteString("# Environment\n")
49+
50+
// Platform
51+
b.WriteString(fmt.Sprintf("- Platform: %s/%s\n", runtime.GOOS, runtime.GOARCH))
52+
53+
// Shell
54+
shell := os.Getenv("SHELL")
55+
if shell != "" {
56+
b.WriteString(fmt.Sprintf("- Shell: %s\n", filepath.Base(shell)))
57+
}
58+
59+
// CWD
60+
home, _ := os.UserHomeDir()
61+
cwdDisplay := cwd
62+
if home != "" && strings.HasPrefix(cwd, home) {
63+
cwdDisplay = "~" + cwd[len(home):]
64+
}
65+
b.WriteString(fmt.Sprintf("- Working directory: %s\n", cwdDisplay))
66+
67+
// Git info
68+
if isGit(cwd) {
69+
if branch := gitBranch(cwd); branch != "" {
70+
b.WriteString(fmt.Sprintf("- Git branch: %s\n", branch))
71+
}
72+
if user := gitUser(cwd); user != "" {
73+
b.WriteString(fmt.Sprintf("- Git user: %s\n", user))
74+
}
75+
}
76+
77+
// Date
78+
b.WriteString(fmt.Sprintf("- Date: %s\n", time.Now().Format("2006-01-02")))
79+
80+
return b.String()
81+
}
82+
83+
func toolGuidelines() string {
84+
return `# Using Tools
85+
- Use Read to view files before editing. Never edit blind.
86+
- Use Bash for system commands. Avoid using Bash for tasks that dedicated tools handle (use Read not cat, Edit not sed, Glob not find, Grep not grep).
87+
- Use Glob to find files by pattern. Use Grep to search file contents.
88+
- Use Edit for precise string replacements. The old_string must be unique in the file.
89+
- Use Write only for new files or complete rewrites. Prefer Edit for modifications.
90+
- Use Agent to delegate complex subtasks to specialized subagents.
91+
- When multiple independent operations are needed, describe them clearly so the system can parallelize.`
92+
}
93+
94+
func codeGuidelines() string {
95+
return `# Code Quality
96+
- Match the existing code style and conventions of the project.
97+
- Don't add comments, docstrings, or type annotations to code you didn't change.
98+
- Don't add error handling or validation for scenarios that can't happen.
99+
- Don't create helpers or abstractions for one-time operations.
100+
- Three similar lines of code is better than a premature abstraction.
101+
- When making changes, verify they work (run tests if available).
102+
- For git operations: prefer new commits over amending. Never force push to main/master.`
103+
}
104+
105+
func toneAndStyle(briefMode bool) string {
106+
if briefMode {
107+
return `# Output Style
108+
Be extremely concise. Lead with the answer or action, not reasoning. Skip filler words and preamble. If you can say it in one sentence, don't use three. Only explain when the user explicitly asks for explanation.`
109+
}
110+
return `# Output Style
111+
Keep responses concise and direct. Lead with the answer or action, not the reasoning. Focus on what the user needs. Use markdown for formatting when it improves readability. When referencing files, include the path. When referencing code, include file and line number.`
112+
}
113+
114+
func permissionGuidelines(mode string) string {
115+
switch mode {
116+
case "bypassPermissions":
117+
return "# Permissions\nAll tool operations are auto-approved. Execute tasks efficiently without confirmation."
118+
case "plan":
119+
return "# Permissions\nYou are in PLAN MODE. Analyze and plan only. Do NOT execute any write operations (Edit, Write, Bash). Read-only tools are allowed."
120+
case "acceptEdits":
121+
return "# Permissions\nFile edits and bash commands are auto-approved. Execute tasks efficiently."
122+
default:
123+
return "# Permissions\nWrite operations require user approval. The user will be prompted for permission on Edit, Write, and Bash operations."
124+
}
125+
}
126+
127+
func isGit(cwd string) bool {
128+
cmd := exec.Command("git", "rev-parse", "--is-inside-work-tree")
129+
cmd.Dir = cwd
130+
return cmd.Run() == nil
131+
}
132+
133+
func gitBranch(cwd string) string {
134+
cmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD")
135+
cmd.Dir = cwd
136+
out, err := cmd.Output()
137+
if err != nil {
138+
return ""
139+
}
140+
return strings.TrimSpace(string(out))
141+
}
142+
143+
func gitUser(cwd string) string {
144+
cmd := exec.Command("git", "config", "user.name")
145+
cmd.Dir = cwd
146+
out, err := cmd.Output()
147+
if err != nil {
148+
return ""
149+
}
150+
return strings.TrimSpace(string(out))
151+
}

internal/tui/model.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
"github.com/codeany-ai/codeany/internal/config"
1818
"github.com/codeany-ai/codeany/internal/memory"
19+
"github.com/codeany-ai/codeany/internal/prompt"
1920
"github.com/codeany-ai/codeany/internal/session"
2021
"github.com/codeany-ai/codeany/internal/skills"
2122
"github.com/codeany-ai/codeany/internal/slash"
@@ -205,6 +206,12 @@ func (m *Model) initAgent() tea.Cmd {
205206
return func() tea.Msg {
206207
cwd, _ := os.Getwd()
207208

209+
// Build system prompt: user override OR our enhanced prompt
210+
sysPrompt := m.cfg.SystemPrompt
211+
if sysPrompt == "" {
212+
sysPrompt = prompt.BuildSystemPrompt(m.cfg.Model, cwd, m.cfg.PermissionMode, m.briefMode)
213+
}
214+
208215
// Build extra context from skills and memory
209216
extraContext := buildExtraContext(cwd)
210217
appendPrompt := m.cfg.AppendSystemPrompt
@@ -224,7 +231,7 @@ func (m *Model) initAgent() tea.Cmd {
224231
MaxTurns: m.cfg.MaxTurns,
225232
MaxBudgetUSD: m.cfg.MaxBudgetUSD,
226233
MCPServers: m.cfg.MCPServers,
227-
SystemPrompt: m.cfg.SystemPrompt,
234+
SystemPrompt: sysPrompt,
228235
AppendSystemPrompt: appendPrompt,
229236
CustomHeaders: m.cfg.CustomHeaders,
230237
ProxyURL: m.cfg.ProxyURL,

0 commit comments

Comments
 (0)