diff --git a/src/browser/assets/initMessage.txt b/src/browser/assets/initMessage.txt new file mode 100644 index 0000000000..675139f557 --- /dev/null +++ b/src/browser/assets/initMessage.txt @@ -0,0 +1,76 @@ + +Use your tools to write an AGENTS.md file in the root of the workspace which will serve as a contribution guide for AI agents. +Inspect the workspace layout, code, documentation and git history to ensure correctness and accuracy. + +Insert the following preamble at the top of the file before any other sections. Do not include the surrounding code fence backticks; only include the text. +```md +You are an experienced, pragmatic software engineering AI agent. Do not over-engineer a solution when a simple one is possible. Keep edits minimal. If you want an exception to ANY rule, you MUST stop and get permission first. +``` + +Recommended sections: +- Project Overview (mandatory) + - Basic details about the project (e.g., high-level overview and goals). + - Technology choices (e.g., languages, databases, frameworks, libraries, build tools). +- Reference (mandatory) + - List important code files. + - List important directories and basic code structure tips. + - Project architecture. +- Essential commands (mandatory) + - build + - format + - lint + - test + - clean + - development server + - other *important* scripts (use `find -type f -name '*.sh'` or similar) +- Patterns (optional) + - List any important or uncommon patterns (compared to other similar codebases), with examples (e.g., how to authorize an HTTP request). + - List any important workflows and their steps (e.g., how to make a database migration). + - Testing patterns. +- Anti-patterns (optional) + - Search git history and comments to find recurring mistakes or forbidden patterns. + - List each pattern and its reason. +- Code style (optional) + - Style guide to follow (with link). +- Commit and Pull Request Guidelines (mandatory) + - Required steps for validating changes before committing. + - Commit message conventions (read `git log`, or use `type: message` by default). + - Pull request description requirements. + +You can add other sections if they are necessary. +If the information required for mandatory sections isn't available due to the workspace being empty or sparse, add TODO text in its place. +Optional sections should be scrapped if the information is too thin. + +Some investigation tips: + - Read existing lint configs, tsconfig, and CI workflows to find any style or layout rules. + - Search for "TODO", "HACK", "FIXME", "don't", "never", "always" in comments. + - Examine test files for patterns. + - Read PR templates and issue templates if they exist. + - Check for existing CONTRIBUTING.md, CODE_OF_CONDUCT.md, or similar documentation files. + +Some writing tips: +- Each "do X" should have a corresponding "don't Y" where applicable. +- Commands should be easily copy-pastable and tested. +- Terms or phrases specific to this project should be explained on first use. +- Anything that is against the norm should be explicitly highlighted and called out. + +Above all things: +- The document must be clear and concise. Simple projects should need less than 400 words, but larger and more mature codebases will likely need 700+. Prioritize completeness over brevity. +- Don't include useless fluff. +- The document must be in Markdown format and use headings for structure. +- Give examples where necessary or helpful (commands, directory paths, naming patterns). +- Explanations and examples must be correct and specific to this codebase. +- Maintain a professional, instructional tone. + +If the workspace is empty or sparse, ask the user for more information. Avoid hallucinating important decisions. You can provide suggestions to the user for language/technology/tool choices, but always respect the user's decision. +- Project description and goals. +- Language(s). +- Technologies (database?), frameworks, libraries. +- Tools. +- Any other questions as you deem necessary. + +For empty or sparse workspaces ONLY, when finished writing AGENTS.md, ask the user if they would like you to do the following: +- initialize git IF it's not already set up (e.g., `git init`, `git remote add`, etc.) +- write a concise README.md file +- generate the bare minimum project scaffolding (e.g., initializing the package manager, writing a minimal build tool config) + diff --git a/src/browser/components/ChatInput/index.tsx b/src/browser/components/ChatInput/index.tsx index a40cefa230..ca89dc176c 100644 --- a/src/browser/components/ChatInput/index.tsx +++ b/src/browser/components/ChatInput/index.tsx @@ -93,6 +93,7 @@ import { } from "./draftImagesStorage"; import { RecordingOverlay } from "./RecordingOverlay"; import { ReviewBlockFromData } from "../shared/ReviewBlock"; +import initMessage from "@/browser/assets/initMessage.txt?raw"; // localStorage quotas are environment-dependent and relatively small. // Be conservative here so we can warn the user before writes start failing. @@ -855,6 +856,16 @@ const ChatInputInner: React.FC = (props) => { // Route to creation handler for creation variant if (variant === "creation") { + // Handle /init command in creation variant - populate input with init message + if (messageText.startsWith("/")) { + const parsed = parseCommand(messageText); + if (parsed?.type === "init") { + setInput(initMessage); + focusMessageInput(); + return; + } + } + // Creation variant: simple message send + workspace creation const creationImageParts = imageAttachmentsToImageParts(imageAttachments); const ok = await creationState.handleSend( @@ -952,7 +963,12 @@ const ChatInputInner: React.FC = (props) => { return; } - // Handle /vim command + // Handle /init command - populate input with init message + if (parsed.type === "init") { + setInput(initMessage); + focusMessageInput(); + return; + } // Handle other non-API commands (help, invalid args, etc) const commandToast = createCommandToast(parsed); diff --git a/src/browser/utils/slashCommands/parser.test.ts b/src/browser/utils/slashCommands/parser.test.ts index 571a8ac9f0..929291cf7a 100644 --- a/src/browser/utils/slashCommands/parser.test.ts +++ b/src/browser/utils/slashCommands/parser.test.ts @@ -226,3 +226,17 @@ describe("plan commands", () => { }); }); }); + +describe("init command", () => { + it("should parse /init", () => { + expectParse("/init", { type: "init" }); + }); + + it("should reject /init with arguments", () => { + expectParse("/init extra", { + type: "unknown-command", + command: "init", + subcommand: "extra", + }); + }); +}); diff --git a/src/browser/utils/slashCommands/registry.ts b/src/browser/utils/slashCommands/registry.ts index 4a18eb8d67..e405e4c562 100644 --- a/src/browser/utils/slashCommands/registry.ts +++ b/src/browser/utils/slashCommands/registry.ts @@ -456,6 +456,23 @@ const vimCommandDefinition: SlashCommandDefinition = { }, }; +const initCommandDefinition: SlashCommandDefinition = { + key: "init", + description: "Bootstrap an AGENTS.md file in a new or existing project", + appendSpace: false, + handler: ({ cleanRemainingTokens }): ParsedCommand => { + if (cleanRemainingTokens.length > 0) { + return { + type: "unknown-command", + command: "init", + subcommand: cleanRemainingTokens[0], + }; + } + + return { type: "init" }; + }, +}; + const planOpenCommandDefinition: SlashCommandDefinition = { key: "open", description: "Open plan in external editor", @@ -700,6 +717,7 @@ export const SLASH_COMMAND_DEFINITIONS: readonly SlashCommandDefinition[] = [ vimCommandDefinition, mcpCommandDefinition, idleCommandDefinition, + initCommandDefinition, ]; export const SLASH_COMMAND_DEFINITION_MAP = new Map( diff --git a/src/browser/utils/slashCommands/types.ts b/src/browser/utils/slashCommands/types.ts index a8488b319b..26b8680550 100644 --- a/src/browser/utils/slashCommands/types.ts +++ b/src/browser/utils/slashCommands/types.ts @@ -35,6 +35,7 @@ export type ParsedCommand = | { type: "mcp-open" } | { type: "plan-show" } | { type: "plan-open" } + | { type: "init" } | { type: "unknown-command"; command: string; subcommand?: string } | { type: "idle-compaction"; hours: number | null } | null; diff --git a/src/types/txt.d.ts b/src/types/txt.d.ts new file mode 100644 index 0000000000..14ca031449 --- /dev/null +++ b/src/types/txt.d.ts @@ -0,0 +1,4 @@ +declare module "*.txt?raw" { + const content: string; + export default content; +}