diff --git a/.agents/types/agent-definition.ts b/.agents/types/agent-definition.ts
index 9dce8fa7c..d89843404 100644
--- a/.agents/types/agent-definition.ts
+++ b/.agents/types/agent-definition.ts
@@ -423,8 +423,7 @@ export type ModelName =
// Other open source models
| 'moonshotai/kimi-k2'
| 'moonshotai/kimi-k2:nitro'
- | 'moonshotai/kimi-k2.5'
- | 'moonshotai/kimi-k2.5:nitro'
+ | 'moonshotai/kimi-k2.6'
| 'z-ai/glm-5'
| 'z-ai/glm-4.6'
| 'z-ai/glm-4.6:nitro'
diff --git a/agents/__tests__/editor.test.ts b/agents/__tests__/editor.test.ts
index 36d6b75c5..31f100078 100644
--- a/agents/__tests__/editor.test.ts
+++ b/agents/__tests__/editor.test.ts
@@ -5,9 +5,7 @@ import editor, { createCodeEditor } from '../editor/editor'
import type { AgentState, ToolCall } from '../types/agent-definition'
describe('editor agent', () => {
- const createMockAgentState = (
- messageHistory: any[] = [],
- ): AgentState => ({
+ const createMockAgentState = (messageHistory: any[] = []): AgentState => ({
agentId: 'editor-test',
runId: 'test-run',
parentId: undefined,
@@ -67,6 +65,11 @@ describe('editor agent', () => {
expect(glmEditor.model).toBe('z-ai/glm-5.1')
})
+ test('creates kimi editor', () => {
+ const kimiEditor = createCodeEditor({ model: 'kimi' })
+ expect(kimiEditor.model).toBe('moonshotai/kimi-k2.6')
+ })
+
test('creates minimax editor', () => {
const minimaxEditor = createCodeEditor({ model: 'minimax' })
expect(minimaxEditor.model).toBe('minimax/minimax-m2.7')
@@ -84,6 +87,12 @@ describe('editor agent', () => {
expect(glmEditor.instructionsPrompt).not.toContain('')
})
+ test('kimi editor does not include think tags in instructions', () => {
+ const kimiEditor = createCodeEditor({ model: 'kimi' })
+ expect(kimiEditor.instructionsPrompt).not.toContain('')
+ expect(kimiEditor.instructionsPrompt).not.toContain('')
+ })
+
test('minimax editor does not include think tags in instructions', () => {
const minimaxEditor = createCodeEditor({ model: 'minimax' })
expect(minimaxEditor.instructionsPrompt).not.toContain('')
@@ -171,10 +180,10 @@ describe('editor agent', () => {
]
const mockAgentState = createMockAgentState(initialMessages)
const mockLogger = {
- debug: () => { },
- info: () => { },
- warn: () => { },
- error: () => { },
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
}
const generator = editor.handleSteps!({
@@ -194,10 +203,10 @@ describe('editor agent', () => {
]
const mockAgentState = createMockAgentState(initialMessages)
const mockLogger = {
- debug: () => { },
- info: () => { },
- warn: () => { },
- error: () => { },
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
}
const generator = editor.handleSteps!({
@@ -238,10 +247,10 @@ describe('editor agent', () => {
]
const mockAgentState = createMockAgentState(initialMessages)
const mockLogger = {
- debug: () => { },
- info: () => { },
- warn: () => { },
- error: () => { },
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
}
const generator = editor.handleSteps!({
@@ -271,7 +280,9 @@ describe('editor agent', () => {
input: { output: { messages: any[] } }
}
expect(toolCall.input.output.messages).toHaveLength(3)
- expect(toolCall.input.output.messages[0].content[0].text).toBe('Message 2')
+ expect(toolCall.input.output.messages[0].content[0].text).toBe(
+ 'Message 2',
+ )
})
test('handleSteps can be serialized for sandbox execution', () => {
@@ -289,10 +300,10 @@ describe('editor agent', () => {
const initialMessages: any[] = []
const mockAgentState = createMockAgentState(initialMessages)
const mockLogger = {
- debug: () => { },
- info: () => { },
- warn: () => { },
- error: () => { },
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
}
const generator = editor.handleSteps!({
@@ -303,7 +314,9 @@ describe('editor agent', () => {
generator.next()
- const newMessages = [{ role: 'assistant', content: [{ type: 'text', text: 'Done' }] }]
+ const newMessages = [
+ { role: 'assistant', content: [{ type: 'text', text: 'Done' }] },
+ ]
const updatedState = createMockAgentState(newMessages)
const result = generator.next({
@@ -316,7 +329,9 @@ describe('editor agent', () => {
toolName: 'set_output',
input: {
output: {
- messages: [{ role: 'assistant', content: [{ type: 'text', text: 'Done' }] }],
+ messages: [
+ { role: 'assistant', content: [{ type: 'text', text: 'Done' }] },
+ ],
},
},
includeToolCall: false,
@@ -326,10 +341,10 @@ describe('editor agent', () => {
test('works with empty initial message history', () => {
const mockAgentState = createMockAgentState([])
const mockLogger = {
- debug: () => { },
- info: () => { },
- warn: () => { },
- error: () => { },
+ debug: () => {},
+ info: () => {},
+ warn: () => {},
+ error: () => {},
}
const generator = editor.handleSteps!({
@@ -341,7 +356,10 @@ describe('editor agent', () => {
generator.next()
const newMessages = [
- { role: 'assistant', content: [{ type: 'text', text: 'First response' }] },
+ {
+ role: 'assistant',
+ content: [{ type: 'text', text: 'First response' }],
+ },
]
const updatedState = createMockAgentState(newMessages)
diff --git a/agents/base2/base2.ts b/agents/base2/base2.ts
index bacc90b48..d398b2a92 100644
--- a/agents/base2/base2.ts
+++ b/agents/base2/base2.ts
@@ -30,7 +30,8 @@ export function createBase2(
const isSonnet = false
const model =
- modelOverride ?? (isFree ? 'z-ai/glm-5.1' : 'anthropic/claude-opus-4.7')
+ modelOverride ??
+ (isFree ? 'moonshotai/kimi-k2.6' : 'anthropic/claude-opus-4.7')
const defaultProviderOptions = isFree
? {
data_collection: 'deny' as const,
@@ -110,11 +111,12 @@ export function createBase2(
- **Spawn mentioned agents:** If the user uses "@AgentName" in their message, you must spawn that agent.
- **Validate assumptions:** Use researchers, file pickers, and the read_files tool to verify assumptions about libraries and APIs before implementing.
- **Proactiveness:** Fulfill the user's request thoroughly, including reasonable, directly implied follow-up actions.
-- **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If asked *how* to do something, explain first, don't just do it.${noAskUser
+- **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If asked *how* to do something, explain first, don't just do it.${
+ noAskUser
? ''
: `
- **Ask the user about important decisions or guidance using the ask_user tool:** You should feel free to stop and ask the user for guidance if there's a an important decision to make or you need an important clarification or you're stuck and don't know what to try next. Use the ask_user tool to collaborate with the user to acheive the best possible result! Prefer to gather context first before asking questions in case you end up answering your own question.`
- }
+ }
- **Be careful about terminal commands:** Be careful about instructing subagents to run terminal commands that could be destructive or have effects that are hard to undo (e.g. git push, git commit, running any scripts -- especially ones that could alter production environments (!), installing packages globally, etc). Don't run any of these effectful commands unless the user explicitly asks you to.
- **Do what the user asks:** If the user asks you to do something, even running a risky terminal command, do it.
- **Don't use set_output:** The set_output tool is for spawned subagents to report results. Don't use it yourself.
@@ -149,22 +151,23 @@ Use the spawn_agents tool to spawn specialized agents to help you complete the u
- **Spawn multiple agents in parallel:** This increases the speed of your response **and** allows you to be more comprehensive by spawning more total agents to synthesize the best response.
- **Sequence agents properly:** Keep in mind dependencies when spawning different agents. Don't spawn agents in parallel that depend on each other.
${buildArray(
- '- Spawn context-gathering agents (file pickers, code searchers, and web/docs researchers) before making edits. Use the list_directory and glob tools directly for searching and exploring the codebase.',
- isFree && 'Do not spawn the thinker-gpt agent, unless the user asks. Not everyone has connected their ChatGPT subscription to Codebuff to allow for it.',
- isDefault &&
- '- Spawn the editor agent to implement the changes after you have gathered all the context you need.',
- (isDefault || isMax) &&
- `- Spawn the ${isDefault ? 'thinker' : 'thinker-best-of-n-opus'} after gathering context to solve complex problems or when the user asks you to think about a problem. (gpt-5-agent is a last resort for complex problems)`,
- isMax &&
- `- IMPORTANT: You must spawn the editor-multi-prompt agent to implement the changes after you have gathered all the context you need. You must spawn this agent for non-trivial changes, since it writes much better code than you would with the str_replace or write_file tools. Don't spawn the editor in parallel with context-gathering agents.`,
- isFree &&
- '- Spawn a code-reviewer-lite to review the changes after you have implemented the changes.',
- '- Spawn bashers sequentially if the second command depends on the the first.',
- isDefault &&
- '- Spawn a code-reviewer to review the changes after you have implemented the changes.',
- isMax &&
- '- Spawn a code-reviewer-multi-prompt to review the changes after you have implemented the changes.',
- ).join('\n ')}
+ '- Spawn context-gathering agents (file pickers, code searchers, and web/docs researchers) before making edits. Use the list_directory and glob tools directly for searching and exploring the codebase.',
+ isFree &&
+ 'Do not spawn the thinker-gpt agent, unless the user asks. Not everyone has connected their ChatGPT subscription to Codebuff to allow for it.',
+ isDefault &&
+ '- Spawn the editor agent to implement the changes after you have gathered all the context you need.',
+ (isDefault || isMax) &&
+ `- Spawn the ${isDefault ? 'thinker' : 'thinker-best-of-n-opus'} after gathering context to solve complex problems or when the user asks you to think about a problem. (gpt-5-agent is a last resort for complex problems)`,
+ isMax &&
+ `- IMPORTANT: You must spawn the editor-multi-prompt agent to implement the changes after you have gathered all the context you need. You must spawn this agent for non-trivial changes, since it writes much better code than you would with the str_replace or write_file tools. Don't spawn the editor in parallel with context-gathering agents.`,
+ isFree &&
+ '- Spawn a code-reviewer-lite to review the changes after you have implemented the changes.',
+ '- Spawn bashers sequentially if the second command depends on the the first.',
+ isDefault &&
+ '- Spawn a code-reviewer to review the changes after you have implemented the changes.',
+ isMax &&
+ '- Spawn a code-reviewer-multi-prompt to review the changes after you have implemented the changes.',
+ ).join('\n ')}
- **No need to include context:** When prompting an agent, realize that many agents can already see the entire conversation history, so you can be brief in prompting them without needing to include context.
- **Never spawn the context-pruner agent:** This agent is spawned automatically for you and you don't need to spawn it yourself.
@@ -183,19 +186,19 @@ For other questions, you can direct them to codebuff.com, or especially codebuff
# Other response guidelines
${buildArray(
- !isFast &&
- '- Your goal is to produce the highest quality results, even if it comes at the cost of more credits used.',
- !isFast && '- Speed is important, but a secondary goal.',
- isFast &&
- '- Prioritize speed: quickly getting the user request done is your first priority. Do not call any unnecessary tools. Spawn more agents in parallel to speed up the process. Be extremely concise in your responses. Use 2 words where you would have used 2 sentences.',
- '- If a tool fails, try again, or try a different tool or approach.',
- (isDefault || isMax) &&
- '- **Use tags for moderate reasoning:** When you need to work through something moderately complex (e.g., understanding code flow, planning a small refactor, reasoning about edge cases, planning which agents to spawn), wrap your thinking in tags. Spawn the thinker agent for anything more complex.',
- '- Context is managed for you. The context-pruner agent will automatically run as needed. Gather as much context as you need without worrying about it.',
- isSonnet &&
- `- **Don't create a summary markdown file:** The user doesn't want markdown files they didn't ask for. Don't create them.`,
- '- **Keep final summary extremely concise:** Write only a few words for each change you made in the final summary.',
- ).join('\n')}
+ !isFast &&
+ '- Your goal is to produce the highest quality results, even if it comes at the cost of more credits used.',
+ !isFast && '- Speed is important, but a secondary goal.',
+ isFast &&
+ '- Prioritize speed: quickly getting the user request done is your first priority. Do not call any unnecessary tools. Spawn more agents in parallel to speed up the process. Be extremely concise in your responses. Use 2 words where you would have used 2 sentences.',
+ '- If a tool fails, try again, or try a different tool or approach.',
+ (isDefault || isMax) &&
+ '- **Use tags for moderate reasoning:** When you need to work through something moderately complex (e.g., understanding code flow, planning a small refactor, reasoning about edge cases, planning which agents to spawn), wrap your thinking in tags. Spawn the thinker agent for anything more complex.',
+ '- Context is managed for you. The context-pruner agent will automatically run as needed. Gather as much context as you need without worrying about it.',
+ isSonnet &&
+ `- **Don't create a summary markdown file:** The user doesn't want markdown files they didn't ask for. Don't create them.`,
+ '- **Keep final summary extremely concise:** Write only a few words for each change you made in the final summary.',
+).join('\n')}
# Response examples
@@ -210,34 +213,38 @@ ${buildArray(
[ You spawn another file-picker and code-searcher to find more relevant files, and use glob tools ]
-[ You read a few other relevant files using the read_files tool ]${!noAskUser
+[ You read a few other relevant files using the read_files tool ]${
+ !noAskUser
? `\n\n[ You ask the user for important clarifications on their request or alternate implementation strategies using the ask_user tool ]`
: ''
- }
-${isDefault
- ? `[ You implement the changes using the editor agent ]`
- : isFast || isFree
- ? '[ You implement the changes using the str_replace or write_file tools ]'
- : '[ You implement the changes using the editor-multi-prompt agent ]'
- }
+ }
+${
+ isDefault
+ ? `[ You implement the changes using the editor agent ]`
+ : isFast || isFree
+ ? '[ You implement the changes using the str_replace or write_file tools ]'
+ : '[ You implement the changes using the editor-multi-prompt agent ]'
+}
-${isDefault
- ? `[ You spawn a code-reviewer, a basher to typecheck the changes, and another basher to run tests, all in parallel ]`
- : isFree
- ? `[ You spawn a code-reviewer-lite to review the changes, a basher to typecheck the local changes, a basher to typecheck the whole project, and another basher to run tests, all in parallel ]`
- : isMax
- ? `[ You spawn a basher to typecheck the changes, and another basher to run tests, in parallel. Then, you spawn a code-reviewer-multi-prompt to review the changes. ]`
- : '[ You spawn a basher to typecheck the changes and another basher to run tests, all in parallel ]'
- }
+${
+ isDefault
+ ? `[ You spawn a code-reviewer, a basher to typecheck the changes, and another basher to run tests, all in parallel ]`
+ : isFree
+ ? `[ You spawn a code-reviewer-lite to review the changes, a basher to typecheck the local changes, a basher to typecheck the whole project, and another basher to run tests, all in parallel ]`
+ : isMax
+ ? `[ You spawn a basher to typecheck the changes, and another basher to run tests, in parallel. Then, you spawn a code-reviewer-multi-prompt to review the changes. ]`
+ : '[ You spawn a basher to typecheck the changes and another basher to run tests, all in parallel ]'
+}
-${isDefault
- ? `[ You fix the issues found by the code-reviewer and type/test errors ]`
- : isFree
- ? `[ You fix the issues found by the code-reviewer-lite and type/test errors ]`
- : isMax
- ? `[ You fix the issues found by the code-reviewer-multi-prompt and type/test errors ]`
- : '[ You fix the issues found by the type/test errors and spawn more bashers to confirm ]'
- }
+${
+ isDefault
+ ? `[ You fix the issues found by the code-reviewer and type/test errors ]`
+ : isFree
+ ? `[ You fix the issues found by the code-reviewer-lite and type/test errors ]`
+ : isMax
+ ? `[ You fix the issues found by the code-reviewer-multi-prompt and type/test errors ]`
+ : '[ You fix the issues found by the type/test errors and spawn more bashers to confirm ]'
+}
[ All tests & typechecks pass -- you write a very short final summary of the changes you made ]
@@ -268,25 +275,25 @@ ${PLACEHOLDER.GIT_CHANGES_PROMPT}
instructionsPrompt: planOnly
? buildPlanOnlyInstructionsPrompt({})
: buildImplementationInstructionsPrompt({
- isSonnet,
- isFast,
- isDefault,
- isMax,
- isFree,
- hasNoValidation,
- noAskUser,
- }),
+ isSonnet,
+ isFast,
+ isDefault,
+ isMax,
+ isFree,
+ hasNoValidation,
+ noAskUser,
+ }),
stepPrompt: planOnly
? buildPlanOnlyStepPrompt({})
: buildImplementationStepPrompt({
- isDefault,
- isFast,
- isMax,
- hasNoValidation,
- isSonnet,
- isFree,
- noAskUser,
- }),
+ isDefault,
+ isFast,
+ isMax,
+ hasNoValidation,
+ isSonnet,
+ isFree,
+ noAskUser,
+ }),
// handleSteps is serialized via .toString() and re-eval'd, so closure
// variables like `isFree` are not in scope at runtime. Pick the right
@@ -351,34 +358,34 @@ function buildImplementationInstructionsPrompt({
The user asks you to implement a new feature. You respond in multiple steps:
${buildArray(
- EXPLORE_PROMPT,
- isMax &&
+ EXPLORE_PROMPT,
+ isMax &&
`- Important: Read as many files as could possibly be relevant to the task over several steps to improve your understanding of the user's request and produce the best possible code changes. Find more examples within the codebase similar to the user's request, dependencies that help with understanding how things work, tests, etc. This is frequently 12-20 files, depending on the task.`,
- !noAskUser &&
+ !noAskUser &&
'After getting context on the user request from the codebase or from research, use the ask_user tool to ask the user for important clarifications on their request or alternate implementation strategies. You should skip this step if the choice is obvious -- only ask the user if you need their help making the best choice.',
- (isDefault || isMax || isFree) &&
+ (isDefault || isMax || isFree) &&
`- For any task requiring 3+ steps, use the write_todos tool to write out your step-by-step implementation plan. Include ALL of the applicable tasks in the list.${isFast ? '' : ' You should include a step to review the changes after you have implemented the changes.'}:${hasNoValidation ? '' : ' You should include at least one step to validate/test your changes: be specific about whether to typecheck, run tests, run lints, etc.'} You may be able to do reviewing and validation in parallel in the same step. Skip write_todos for simple tasks like quick edits or answering questions.`,
- (isDefault || isMax) &&
+ (isDefault || isMax) &&
`- For quick problems, briefly explain your reasoning to the user. If you need to think longer, write your thoughts within the tags. Finally, for complex problems, spawn the thinker agent to help find the best solution. (gpt-5-agent is a last resort for complex problems)`,
- isDefault &&
+ isDefault &&
'- IMPORTANT: You must spawn the editor agent to implement the changes after you have gathered all the context you need. This agent will do the best job of implementing the changes so you must spawn it for all non-trivial changes. Do not pass any prompt or params to the editor agent when spawning it. It will make its own best choices of what to do.',
- isMax &&
+ isMax &&
`- IMPORTANT: You must spawn the editor-multi-prompt agent to implement non-trivial code changes, since it will generate the best code changes from multiple implementation proposals. This is the best way to make high quality code changes -- strongly prefer using this agent over the str_replace or write_file tools, unless the change is very straightforward and obvious. You should also prompt it to implement the full task rather than just a single step.`,
- isFast &&
+ isFast &&
'- Implement the changes using the str_replace or write_file tools. Implement all the changes in one go.',
- isFast &&
+ isFast &&
'- Do a single typecheck targeted for your changes at most (if applicable for the project). Or skip this step if the change was small.',
- !hasNoValidation &&
+ !hasNoValidation &&
`- For non-trivial changes, test them by running appropriate validation commands for the project (e.g. typechecks, tests, lints, etc.). Try to run all appropriate commands in parallel. ${isMax ? ' Typecheck and test the specific area of the project that you are editing *AND* then typecheck and test the entire project if necessary.' : ' If you can, only test the area of the project that you are editing, rather than the entire project.'} You may have to explore the project to find the appropriate commands. Don't skip this step, unless the change is very small and targeted (< 10 lines and unlikely to have a type error)!`,
- (isDefault || isMax) &&
+ (isDefault || isMax) &&
`- Spawn a ${isDefault ? 'code-reviewer' : 'code-reviewer-multi-prompt'} to review the changes after you have implemented changes. (Skip this step only if the change is extremely straightforward and obvious.)`,
- isFree &&
+ isFree &&
`- Spawn a code-reviewer-lite to review the changes after you have implemented changes. (Skip this step only if the change is extremely straightforward and obvious.)`,
- `- Inform the user that you have completed the task in one sentence or a few short bullet points.${isSonnet ? " Don't create any markdown summary files or example documentation files, unless asked by the user." : ''}`,
- !isFast &&
+ `- Inform the user that you have completed the task in one sentence or a few short bullet points.${isSonnet ? " Don't create any markdown summary files or example documentation files, unless asked by the user." : ''}`,
+ !isFast &&
!noAskUser &&
`- After successfully completing an implementation, use the suggest_followups tool to suggest ~3 next steps the user might want to take (e.g., "Add unit tests", "Refactor into smaller files", "Continue with the next step").`,
- ).join('\n')}`
+).join('\n')}`
}
function buildImplementationStepPrompt({
@@ -400,22 +407,22 @@ function buildImplementationStepPrompt({
}) {
return buildArray(
isMax &&
- `Keep working until the user's request is completely satisfied${!hasNoValidation ? ' and validated' : ''}, or until you require more information from the user.`,
+ `Keep working until the user's request is completely satisfied${!hasNoValidation ? ' and validated' : ''}, or until you require more information from the user.`,
'Consider loading relevant skills with the skill tool if they might help with the current task. Do not reload skills that were already loaded earlier in this conversation.',
isMax &&
- `You must spawn the 'editor-multi-prompt' agent to implement code changes rather than using the str_replace or write_file tools, since it will generate the best code changes.`,
+ `You must spawn the 'editor-multi-prompt' agent to implement code changes rather than using the str_replace or write_file tools, since it will generate the best code changes.`,
(isDefault || isMax) &&
- `You must spawn a ${isDefault ? 'code-reviewer' : 'code-reviewer-multi-prompt'} to review the changes after you have implemented the changes and in parallel with typechecking or testing.`,
+ `You must spawn a ${isDefault ? 'code-reviewer' : 'code-reviewer-multi-prompt'} to review the changes after you have implemented the changes and in parallel with typechecking or testing.`,
isFree &&
- `You must spawn a code-reviewer-lite to review the changes after you have implemented the changes and in parallel with typechecking or testing.`,
+ `You must spawn a code-reviewer-lite to review the changes after you have implemented the changes and in parallel with typechecking or testing.`,
`After completing the user request, summarize your changes in a sentence${isFast ? '' : ' or a few short bullet points'}.${isSonnet ? " Don't create any summary markdown files or example documentation files, unless asked by the user." : ''}.`,
!isFast &&
- !noAskUser &&
- `At the end of your turn, you must use the suggest_followups tool to suggest around 3 next steps the user might want to take even if the user just asks a question.`,
+ !noAskUser &&
+ `At the end of your turn, you must use the suggest_followups tool to suggest around 3 next steps the user might want to take even if the user just asks a question.`,
).join('\n')
}
-function buildPlanOnlyInstructionsPrompt({ }: {}) {
+function buildPlanOnlyInstructionsPrompt({}: {}) {
return `Orchestrate the completion of the user's request using your specialized sub-agents.
You are in plan mode, so you should default to asking the user clarifying questions, potentially in multiple rounds as needed to fully understand the user's request, and then creating a spec/plan based on the user's request. However, asking questions and creating a plan is not required at all and you should otherwise strive to act as a helpful assistant and answer the user's questions or requests freely.
@@ -425,8 +432,8 @@ function buildPlanOnlyInstructionsPrompt({ }: {}) {
The user asks you to implement a new feature. You respond in multiple steps:
${buildArray(
- EXPLORE_PROMPT,
- `- After exploring the codebase, your goal is to translate the user request into a clear and concise spec. If the user is just asking a question, you can answer it instead of writing a spec.
+ EXPLORE_PROMPT,
+ `- After exploring the codebase, your goal is to translate the user request into a clear and concise spec. If the user is just asking a question, you can answer it instead of writing a spec.
## Asking questions
@@ -455,10 +462,10 @@ It should not include:
This is more like an extremely short PRD which describes the end result of what the user wants. Think of it like fleshing out the user's prompt to make it more precise, although it should be as short as possible.
`,
- ).join('\n')}`
+).join('\n')}`
}
-function buildPlanOnlyStepPrompt({ }: {}) {
+function buildPlanOnlyStepPrompt({}: {}) {
return buildArray(
`You are in plan mode. Do not make any file changes. Do not call write_file or str_replace. Do not use the write_todos tool.`,
).join('\n')
diff --git a/agents/editor/editor-lite.ts b/agents/editor/editor-lite.ts
index 29225f0c2..6dbb4bb3c 100644
--- a/agents/editor/editor-lite.ts
+++ b/agents/editor/editor-lite.ts
@@ -3,7 +3,7 @@ import { createCodeEditor } from './editor'
import type { AgentDefinition } from '../types/agent-definition'
const definition: AgentDefinition = {
- ...createCodeEditor({ model: 'glm' }),
+ ...createCodeEditor({ model: 'kimi' }),
id: 'editor-lite',
}
export default definition
diff --git a/agents/editor/editor.ts b/agents/editor/editor.ts
index c98544d0f..25d488901 100644
--- a/agents/editor/editor.ts
+++ b/agents/editor/editor.ts
@@ -1,10 +1,9 @@
-
import { publisher } from '../constants'
import type { AgentDefinition } from '../types/agent-definition'
export const createCodeEditor = (options: {
- model: 'gpt-5' | 'opus' | 'glm' | 'minimax'
+ model: 'gpt-5' | 'opus' | 'glm' | 'kimi' | 'minimax'
}): Omit => {
const { model } = options
return {
@@ -14,9 +13,11 @@ export const createCodeEditor = (options: {
? 'openai/gpt-5.1'
: options.model === 'minimax'
? 'minimax/minimax-m2.7'
- : options.model === 'glm'
- ? 'z-ai/glm-5.1'
- : 'anthropic/claude-opus-4.7',
+ : options.model === 'kimi'
+ ? 'moonshotai/kimi-k2.6'
+ : options.model === 'glm'
+ ? 'z-ai/glm-5.1'
+ : 'anthropic/claude-opus-4.7',
...(options.model === 'opus' && {
providerOptions: {
only: ['amazon-bedrock'],
@@ -67,9 +68,13 @@ OR for new files or major rewrites:
}
-${model === 'gpt-5' || model === 'glm' || model === 'minimax'
- ? ''
- : `Before you start writing your implementation, you should use tags to think about the best way to implement the changes.
+${
+ model === 'gpt-5' ||
+ model === 'glm' ||
+ model === 'kimi' ||
+ model === 'minimax'
+ ? ''
+ : `Before you start writing your implementation, you should use tags to think about the best way to implement the changes.
You can also use tags interspersed between tool calls to think about the best way to implement the changes.
@@ -96,7 +101,7 @@ You can also use tags interspersed between tool calls to think about the
`
- }
+}
Your implementation should:
- Be complete and comprehensive
diff --git a/agents/reviewer/code-reviewer-lite.ts b/agents/reviewer/code-reviewer-lite.ts
index feafb87c4..888cadf4f 100644
--- a/agents/reviewer/code-reviewer-lite.ts
+++ b/agents/reviewer/code-reviewer-lite.ts
@@ -5,7 +5,7 @@ import { createReviewer } from './code-reviewer'
const definition: SecretAgentDefinition = {
id: 'code-reviewer-lite',
publisher,
- ...createReviewer('z-ai/glm-5.1'),
+ ...createReviewer('moonshotai/kimi-k2.6'),
}
export default definition
diff --git a/agents/types/agent-definition.ts b/agents/types/agent-definition.ts
index 3608f3631..088dd1dca 100644
--- a/agents/types/agent-definition.ts
+++ b/agents/types/agent-definition.ts
@@ -423,6 +423,7 @@ export type ModelName =
// Other open source models
| 'moonshotai/kimi-k2'
| 'moonshotai/kimi-k2:nitro'
+ | 'moonshotai/kimi-k2.6'
| 'z-ai/glm-5'
| 'z-ai/glm-5.1'
| 'z-ai/glm-4.6'
diff --git a/cli/src/components/freebuff-model-selector.tsx b/cli/src/components/freebuff-model-selector.tsx
index f553ce398..f9376c5db 100644
--- a/cli/src/components/freebuff-model-selector.tsx
+++ b/cli/src/components/freebuff-model-selector.tsx
@@ -6,7 +6,7 @@ import { Button } from './button'
import {
FALLBACK_FREEBUFF_MODEL_ID,
FREEBUFF_GEMINI_PRO_MODEL_ID,
- FREEBUFF_GLM_MODEL_ID,
+ FREEBUFF_KIMI_MODEL_ID,
FREEBUFF_MODELS,
getFreebuffDeploymentAvailabilityLabel,
isFreebuffModelAvailable,
@@ -29,11 +29,11 @@ const FREEBUFF_MODEL_SELECTOR_MODELS = [
...FREEBUFF_MODELS.filter(
(model) => model.id === FREEBUFF_GEMINI_PRO_MODEL_ID,
),
- ...FREEBUFF_MODELS.filter((model) => model.id === FREEBUFF_GLM_MODEL_ID),
+ ...FREEBUFF_MODELS.filter((model) => model.id === FREEBUFF_KIMI_MODEL_ID),
...FREEBUFF_MODELS.filter(
(model) =>
model.id !== FREEBUFF_GEMINI_PRO_MODEL_ID &&
- model.id !== FREEBUFF_GLM_MODEL_ID,
+ model.id !== FREEBUFF_KIMI_MODEL_ID,
),
]
@@ -80,7 +80,7 @@ export const FreebuffModelSelector: React.FC = () => {
// unavailable (e.g. deployment hours close while the picker is open),
// swap to the always-available fallback so Enter doesn't POST a model
// the server will immediately reject. In-memory only — the user's saved
- // preference (e.g. GLM) is preserved for the next launch.
+ // preference (e.g. Kimi) is preserved for the next launch.
if (
(session?.status === 'none' || !session) &&
!isFreebuffModelAvailable(selectedModel, new Date(now))
diff --git a/cli/src/components/waiting-room-screen.tsx b/cli/src/components/waiting-room-screen.tsx
index 9ccba664a..7f83f748d 100644
--- a/cli/src/components/waiting-room-screen.tsx
+++ b/cli/src/components/waiting-room-screen.tsx
@@ -260,7 +260,7 @@ export const WaitingRoomScreen: React.FC = ({
Elapsed
{formatElapsed(elapsedMs)}
- {/* Per-model session quota (e.g. GLM 5.1 caps at 5/12h). Only
+ {/* Per-model session quota (e.g. Kimi K2.6 caps at 5/12h). Only
rendered for rate-limited models so the Minimax queue stays
clutter-free. */}
{session.rateLimit && (
@@ -343,7 +343,7 @@ export const WaitingRoomScreen: React.FC = ({
>
)}
- {/* Per-model session quota exhausted (e.g. 5+ GLM sessions in the
+ {/* Per-model session quota exhausted (e.g. 5+ Kimi sessions in the
last 12h). Terminal for this run — the user can exit and come
back once the oldest session in the window rolls off. */}
{session?.status === 'rate_limited' && (
diff --git a/cli/src/hooks/use-freebuff-session.ts b/cli/src/hooks/use-freebuff-session.ts
index 463a49126..c78d4bbd0 100644
--- a/cli/src/hooks/use-freebuff-session.ts
+++ b/cli/src/hooks/use-freebuff-session.ts
@@ -104,7 +104,7 @@ async function callSession(
return body
}
}
- // 429 from POST is the per-model session-quota reject (e.g. too many GLM
+ // 429 from POST is the per-model session-quota reject (e.g. too many Kimi
// sessions in the last 12h). Terminal for the current poll — the CLI shows
// a screen explaining the limit and when the user can try again. The 429
// status (rather than 200) keeps older CLIs in their error path so they
@@ -442,9 +442,9 @@ export function useFreebuffSession(): UseFreebuffSessionResult {
}
if (next.status === 'model_unavailable') {
// Server says the requested model isn't available right now (e.g.
- // GLM outside deployment hours). Flip to the always-available
+ // Kimi outside deployment hours). Flip to the always-available
// fallback for this run. In-memory only — `setSelectedModel`
- // doesn't persist, so the user's saved preference (e.g. GLM)
+ // doesn't persist, so the user's saved preference (e.g. Kimi)
// is preserved for their next launch during deployment hours.
useFreebuffModelStore
.getState()
diff --git a/common/src/__tests__/freebuff-models.test.ts b/common/src/__tests__/freebuff-models.test.ts
index 664c4c3ef..10709e236 100644
--- a/common/src/__tests__/freebuff-models.test.ts
+++ b/common/src/__tests__/freebuff-models.test.ts
@@ -1,11 +1,17 @@
import { describe, expect, test } from 'bun:test'
import {
+ DEFAULT_FREEBUFF_MODEL_ID,
FREEBUFF_GEMINI_PRO_MODEL_ID,
+ FREEBUFF_GLM_MODEL_ID,
+ FREEBUFF_KIMI_MODEL_ID,
FREEBUFF_MODELS,
+ SUPPORTED_FREEBUFF_MODELS,
getFreebuffDeploymentAvailabilityLabel,
isFreebuffDeploymentHours,
+ isFreebuffModelId,
isFreebuffModelAvailable,
+ isSupportedFreebuffModelId,
} from '../constants/freebuff-models'
describe('freebuff model availability', () => {
@@ -27,6 +33,21 @@ describe('freebuff model availability', () => {
).toBe(true)
})
+ test('defaults to Kimi K2.6', () => {
+ expect(DEFAULT_FREEBUFF_MODEL_ID).toBe(FREEBUFF_KIMI_MODEL_ID)
+ })
+
+ test('supports GLM 5.1 as a legacy server-side model without selecting it for new clients', () => {
+ expect(FREEBUFF_MODELS.map((model) => model.id)).not.toContain(
+ FREEBUFF_GLM_MODEL_ID,
+ )
+ expect(SUPPORTED_FREEBUFF_MODELS.map((model) => model.id)).toContain(
+ FREEBUFF_GLM_MODEL_ID,
+ )
+ expect(isFreebuffModelId(FREEBUFF_GLM_MODEL_ID)).toBe(false)
+ expect(isSupportedFreebuffModelId(FREEBUFF_GLM_MODEL_ID)).toBe(true)
+ })
+
test('formats the close time in the user local timezone while deployment is open', () => {
expect(
getFreebuffDeploymentAvailabilityLabel(new Date('2026-01-05T18:00:00Z'), {
diff --git a/common/src/constants/free-agents.ts b/common/src/constants/free-agents.ts
index 5f020cf8e..6d22152c5 100644
--- a/common/src/constants/free-agents.ts
+++ b/common/src/constants/free-agents.ts
@@ -1,6 +1,6 @@
import { parseAgentId } from '../util/agent-id-parsing'
-import { FREEBUFF_MODELS } from './freebuff-models'
+import { SUPPORTED_FREEBUFF_MODELS } from './freebuff-models'
import type { CostMode } from './model-config'
@@ -20,7 +20,9 @@ export const FREEBUFF_ROOT_AGENT_IDS = ['base2-free'] as const
const FREEBUFF_ROOT_AGENT_ID_SET: ReadonlySet = new Set(
FREEBUFF_ROOT_AGENT_IDS,
)
-const FREEBUFF_SELECTABLE_MODEL_IDS = FREEBUFF_MODELS.map((model) => model.id)
+const FREEBUFF_ALLOWED_MODEL_IDS = SUPPORTED_FREEBUFF_MODELS.map(
+ (model) => model.id,
+)
/**
* Agents that are allowed to run in FREE mode.
@@ -32,7 +34,7 @@ const FREEBUFF_SELECTABLE_MODEL_IDS = FREEBUFF_MODELS.map((model) => model.id)
*/
export const FREE_MODE_AGENT_MODELS: Record> = {
// Root orchestrator
- 'base2-free': new Set(FREEBUFF_SELECTABLE_MODEL_IDS),
+ 'base2-free': new Set(FREEBUFF_ALLOWED_MODEL_IDS),
// File exploration agents
'file-picker': new Set(['google/gemini-2.5-flash-lite']),
@@ -44,13 +46,13 @@ export const FREE_MODE_AGENT_MODELS: Record> = {
'researcher-docs': new Set(['google/gemini-3.1-flash-lite-preview']),
// Command execution
- 'basher': new Set(['google/gemini-3.1-flash-lite-preview']),
+ basher: new Set(['google/gemini-3.1-flash-lite-preview']),
// Editor for free mode
- 'editor-lite': new Set(FREEBUFF_SELECTABLE_MODEL_IDS),
+ 'editor-lite': new Set(FREEBUFF_ALLOWED_MODEL_IDS),
// Code reviewer for free mode
- 'code-reviewer-lite': new Set(FREEBUFF_SELECTABLE_MODEL_IDS),
+ 'code-reviewer-lite': new Set(FREEBUFF_ALLOWED_MODEL_IDS),
}
/**
diff --git a/common/src/constants/freebuff-models.ts b/common/src/constants/freebuff-models.ts
index 2394a03e4..246731a3f 100644
--- a/common/src/constants/freebuff-models.ts
+++ b/common/src/constants/freebuff-models.ts
@@ -23,6 +23,7 @@ export interface FreebuffModelOption {
export const FREEBUFF_DEPLOYMENT_HOURS_LABEL = '9am ET-5pm PT every day'
export const FREEBUFF_GEMINI_PRO_MODEL_ID = 'google/gemini-3.1-pro-preview'
export const FREEBUFF_GLM_MODEL_ID = 'z-ai/glm-5.1'
+export const FREEBUFF_KIMI_MODEL_ID = 'moonshotai/kimi-k2.6'
export const FREEBUFF_MINIMAX_MODEL_ID = 'minimax/minimax-m2.7'
const FREEBUFF_EASTERN_TIMEZONE = 'America/New_York'
const FREEBUFF_PACIFIC_TIMEZONE = 'America/Los_Angeles'
@@ -53,26 +54,42 @@ export const FREEBUFF_MODELS = [
tagline: 'Fastest',
availability: 'always',
},
+ {
+ id: FREEBUFF_KIMI_MODEL_ID,
+ displayName: 'Kimi K2.6',
+ tagline: 'Smartest',
+ availability: 'deployment_hours',
+ },
+] as const satisfies readonly FreebuffModelOption[]
+
+export const LEGACY_FREEBUFF_MODELS = [
{
id: FREEBUFF_GLM_MODEL_ID,
displayName: 'GLM 5.1',
- tagline: 'Smartest',
+ tagline: 'Legacy',
availability: 'deployment_hours',
},
] as const satisfies readonly FreebuffModelOption[]
+export const SUPPORTED_FREEBUFF_MODELS = [
+ ...FREEBUFF_MODELS,
+ ...LEGACY_FREEBUFF_MODELS,
+] as const satisfies readonly FreebuffModelOption[]
+
export type FreebuffModelId = (typeof FREEBUFF_MODELS)[number]['id']
+export type SupportedFreebuffModelId =
+ (typeof SUPPORTED_FREEBUFF_MODELS)[number]['id']
/** What new freebuff users see selected in the picker. May not be currently
- * available (GLM is closed outside deployment hours); callers that need an
+ * available (Kimi is closed outside deployment hours); callers that need an
* always-available id for resolution / auto-fallbacks should use
* FALLBACK_FREEBUFF_MODEL_ID instead. */
-export const DEFAULT_FREEBUFF_MODEL_ID: FreebuffModelId = FREEBUFF_GLM_MODEL_ID
+export const DEFAULT_FREEBUFF_MODEL_ID: FreebuffModelId = FREEBUFF_KIMI_MODEL_ID
/** Always-available fallback used when the requested model can't be served
* right now (unknown id, deployment hours closed, etc.). Kept distinct from
* DEFAULT_FREEBUFF_MODEL_ID so a new user's "preferred default" can be the
- * smartest model without auto-flipping anyone to a closed deployment. */
+ * smartest model without auto-flipping anyone to a closed serverless model. */
export const FALLBACK_FREEBUFF_MODEL_ID: FreebuffModelId =
FREEBUFF_MINIMAX_MODEL_ID
@@ -89,9 +106,22 @@ export function resolveFreebuffModel(
return isFreebuffModelId(id) ? id : FALLBACK_FREEBUFF_MODEL_ID
}
+export function isSupportedFreebuffModelId(
+ id: string | null | undefined,
+): id is SupportedFreebuffModelId {
+ if (!id) return false
+ return SUPPORTED_FREEBUFF_MODELS.some((m) => m.id === id)
+}
+
+export function resolveSupportedFreebuffModel(
+ id: string | null | undefined,
+): SupportedFreebuffModelId {
+ return isSupportedFreebuffModelId(id) ? id : FALLBACK_FREEBUFF_MODEL_ID
+}
+
export function getFreebuffModel(id: string): FreebuffModelOption {
return (
- FREEBUFF_MODELS.find((m) => m.id === id) ??
+ SUPPORTED_FREEBUFF_MODELS.find((m) => m.id === id) ??
FREEBUFF_MODELS.find((m) => m.id === FALLBACK_FREEBUFF_MODEL_ID)!
)
}
@@ -242,7 +272,7 @@ export function isFreebuffModelAvailable(
id: string,
now: Date = new Date(),
): boolean {
- const model = FREEBUFF_MODELS.find((m) => m.id === id)
+ const model = SUPPORTED_FREEBUFF_MODELS.find((m) => m.id === id)
if (!model) return false
return model.availability === 'always' || isFreebuffDeploymentHours(now)
}
diff --git a/common/src/templates/initial-agents-dir/types/agent-definition.ts b/common/src/templates/initial-agents-dir/types/agent-definition.ts
index 3608f3631..088dd1dca 100644
--- a/common/src/templates/initial-agents-dir/types/agent-definition.ts
+++ b/common/src/templates/initial-agents-dir/types/agent-definition.ts
@@ -423,6 +423,7 @@ export type ModelName =
// Other open source models
| 'moonshotai/kimi-k2'
| 'moonshotai/kimi-k2:nitro'
+ | 'moonshotai/kimi-k2.6'
| 'z-ai/glm-5'
| 'z-ai/glm-5.1'
| 'z-ai/glm-4.6'
diff --git a/common/src/types/freebuff-session.ts b/common/src/types/freebuff-session.ts
index f638bb942..9a1b3dad4 100644
--- a/common/src/types/freebuff-session.ts
+++ b/common/src/types/freebuff-session.ts
@@ -130,7 +130,7 @@ export type FreebuffSessionServerResponse =
/** User has an active session bound to a different model. Returned
* from POST /session when they pick a new model without ending their
* current session first. The CLI shows a confirmation prompt: "End
- * your active GLM session to switch?" → on confirm, DELETE then
+ * your active Kimi session to switch?" → on confirm, DELETE then
* re-POST with the new model. */
status: 'model_locked'
currentModel: string
diff --git a/freebuff/README.md b/freebuff/README.md
index 0749fc7c0..cc4037778 100644
--- a/freebuff/README.md
+++ b/freebuff/README.md
@@ -38,23 +38,23 @@ freebuff
## Commands
-| Command | Description |
-|---|---|
-| `/help` | Show keyboard shortcuts and tips |
-| `/new` | Start a new conversation |
-| `/history` | Browse past conversations |
-| `/bash` | Enter bash mode |
-| `/init` | Create a starter knowledge.md |
-| `/feedback` | Share feedback |
-| `/theme:toggle` | Toggle light/dark mode |
-| `/logout` | Sign out |
-| `/exit` | Quit |
+| Command | Description |
+| --------------- | -------------------------------- |
+| `/help` | Show keyboard shortcuts and tips |
+| `/new` | Start a new conversation |
+| `/history` | Browse past conversations |
+| `/bash` | Enter bash mode |
+| `/init` | Create a starter knowledge.md |
+| `/feedback` | Share feedback |
+| `/theme:toggle` | Toggle light/dark mode |
+| `/logout` | Sign out |
+| `/exit` | Quit |
## FAQ
**How can it be free?** Freebuff is supported by ads shown in the CLI.
-**What models do you use?** GLM 5.1 as the main coding agent, Gemini 3.1 Flash Lite for finding files and research, and GPT-5.4 for deep thinking if you connect your ChatGPT subscription.
+**What models do you use?** Kimi K2.6 as the main coding agent, Gemini 3.1 Flash Lite for finding files and research, and GPT-5.4 for deep thinking if you connect your ChatGPT subscription.
**Are you training on my data?** No. We only use model providers that do not train on our requests. Your code stays yours.
diff --git a/freebuff/SPEC.md b/freebuff/SPEC.md
index 195081533..92ae93584 100644
--- a/freebuff/SPEC.md
+++ b/freebuff/SPEC.md
@@ -25,17 +25,17 @@ This enables dead-code elimination in production builds — all `if (!IS_FREEBUF
## 2. Branding Changes
-| Area | Codebuff | Freebuff |
-|---|---|---|
-| Terminal title prefix | `Codebuff: ` | `Freebuff: ` |
-| CLI commander name | `codebuff` | `freebuff` |
-| npm package name | `codebuff` | `freebuff` |
-| Binary name | `codebuff` | `freebuff` |
-| App header text | "Codebuff will run commands on your behalf to help you build." | "Freebuff will run commands on your behalf to help you build." |
-| ASCII logo | `CODEBUFF` block letters | `FREEBUFF` block letters (new logo) |
-| Description | "AI coding agent" | "Free AI coding assistant" |
-| Homepage | codebuff.com | codebuff.com/free (or same) |
-| `WEBSITE_URL` usage | Points to codebuff.com | Same (login, feedback, etc. stay on codebuff.com) |
+| Area | Codebuff | Freebuff |
+| --------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- |
+| Terminal title prefix | `Codebuff: ` | `Freebuff: ` |
+| CLI commander name | `codebuff` | `freebuff` |
+| npm package name | `codebuff` | `freebuff` |
+| Binary name | `codebuff` | `freebuff` |
+| App header text | "Codebuff will run commands on your behalf to help you build." | "Freebuff will run commands on your behalf to help you build." |
+| ASCII logo | `CODEBUFF` block letters | `FREEBUFF` block letters (new logo) |
+| Description | "AI coding agent" | "Free AI coding assistant" |
+| Homepage | codebuff.com | codebuff.com/free (or same) |
+| `WEBSITE_URL` usage | Points to codebuff.com | Same (login, feedback, etc. stay on codebuff.com) |
### Files to modify (conditional on `IS_FREEBUFF`)
@@ -72,34 +72,34 @@ Freebuff only supports **FREE mode**. All mode-related features are stripped.
### Commands to REMOVE in Freebuff
-| Command | Reason |
-|---|---|
-| `/subscribe` (+ `/strong`, `/sub`, `/buy-credits`) | No subscription model |
-| `/usage` (+ `/credits`) | No credits display |
-| `/ads:enable` | Ads always on, not toggleable |
-| `/ads:disable` | Ads always on, not toggleable |
-| `/connect:claude` (+ `/claude`) | Claude subscription not available |
-| `/refer-friends` (+ `/referral`, `/redeem`) | Referrals earn credits, not applicable |
-| `/mode:*` (all mode commands) | Only FREE mode |
-| `/agent:gpt-5` | Premium agent, not available in free tier |
-| `/review` | Uses thinker-gpt under the hood |
-| `/publish` | Agent publishing not available in free tier |
-| `/image` (+ `/img`, `/attach`) | Image attachments unavailable with free model (GLM 5.1) |
+| Command | Reason |
+| -------------------------------------------------- | --------------------------------------------------------- |
+| `/subscribe` (+ `/strong`, `/sub`, `/buy-credits`) | No subscription model |
+| `/usage` (+ `/credits`) | No credits display |
+| `/ads:enable` | Ads always on, not toggleable |
+| `/ads:disable` | Ads always on, not toggleable |
+| `/connect:claude` (+ `/claude`) | Claude subscription not available |
+| `/refer-friends` (+ `/referral`, `/redeem`) | Referrals earn credits, not applicable |
+| `/mode:*` (all mode commands) | Only FREE mode |
+| `/agent:gpt-5` | Premium agent, not available in free tier |
+| `/review` | Uses thinker-gpt under the hood |
+| `/publish` | Agent publishing not available in free tier |
+| `/image` (+ `/img`, `/attach`) | Image attachments unavailable with free model (Kimi K2.6) |
### Commands to KEEP
-| Command | Notes |
-|---|---|
-| `/help` | Modified help content (see §6) |
-| `/new` (+ `/clear`, `/reset`, `/n`, `/c`) | Clear conversation |
-| `/history` (+ `/chats`) | Browse past conversations |
-| `/feedback` (+ `/bug`, `/report`) | Share feedback |
-| `/bash` (+ `/!`) | Bash mode |
-| `/theme:toggle` | Light/dark toggle |
-| `/logout` (+ `/signout`) | Sign out |
-| `/exit` (+ `/quit`, `/q`) | Quit |
-| `/login` (+ `/signin`) | Already-logged-in message |
-| Skill commands (`/skill:*`) | Keep if skills are loaded |
+| Command | Notes |
+| ----------------------------------------- | ------------------------------ |
+| `/help` | Modified help content (see §6) |
+| `/new` (+ `/clear`, `/reset`, `/n`, `/c`) | Clear conversation |
+| `/history` (+ `/chats`) | Browse past conversations |
+| `/feedback` (+ `/bug`, `/report`) | Share feedback |
+| `/bash` (+ `/!`) | Bash mode |
+| `/theme:toggle` | Light/dark toggle |
+| `/logout` (+ `/signout`) | Sign out |
+| `/exit` (+ `/quit`, `/q`) | Quit |
+| `/login` (+ `/signin`) | Already-logged-in message |
+| Skill commands (`/skill:*`) | Keep if skills are loaded |
### Implementation
@@ -114,14 +114,14 @@ Freebuff never displays credits, usage, subscription info, or out-of-credits sta
### Components to suppress (render `null` when `IS_FREEBUFF`)
-| Component | File | Behavior |
-|---|---|---|
-| `UsageBanner` | `components/usage-banner.tsx` | Never rendered |
-| `OutOfCreditsBanner` | `components/out-of-credits-banner.tsx` | Never rendered |
-| `SubscriptionLimitBanner` | `components/subscription-limit-banner.tsx` | Never rendered |
-| `BottomStatusLine` | `components/bottom-status-line.tsx` | Never rendered (Claude subscription status) |
-| Credits in `MessageFooter` | `components/message-footer.tsx` | Remove `CreditsOrSubscriptionIndicator` — no credits or "✓ Strong" shown |
-| `ClaudeConnectBanner` | `components/claude-connect-banner.tsx` | Never rendered |
+| Component | File | Behavior |
+| -------------------------- | ------------------------------------------ | ------------------------------------------------------------------------ |
+| `UsageBanner` | `components/usage-banner.tsx` | Never rendered |
+| `OutOfCreditsBanner` | `components/out-of-credits-banner.tsx` | Never rendered |
+| `SubscriptionLimitBanner` | `components/subscription-limit-banner.tsx` | Never rendered |
+| `BottomStatusLine` | `components/bottom-status-line.tsx` | Never rendered (Claude subscription status) |
+| Credits in `MessageFooter` | `components/message-footer.tsx` | Remove `CreditsOrSubscriptionIndicator` — no credits or "✓ Strong" shown |
+| `ClaudeConnectBanner` | `components/claude-connect-banner.tsx` | Never rendered |
### Input modes to disable
@@ -258,7 +258,10 @@ const defineFlags = [
['process.env.NODE_ENV', '"production"'],
['process.env.CODEBUFF_IS_BINARY', '"true"'],
['process.env.CODEBUFF_CLI_VERSION', `"${version}"`],
- ['process.env.CODEBUFF_CLI_TARGET', `"${targetInfo.platform}-${targetInfo.arch}"`],
+ [
+ 'process.env.CODEBUFF_CLI_TARGET',
+ `"${targetInfo.platform}-${targetInfo.arch}"`,
+ ],
// Freebuff mode flag
['process.env.FREEBUFF_MODE', `"${process.env.FREEBUFF_MODE ?? 'false'}"`],
...nextPublicEnvVars,
@@ -336,11 +339,13 @@ No server-side changes are needed for Freebuff, **except** the release download
## 14. Implementation Phases
### Phase 1: Core Flag & Branding
+
1. Add `IS_FREEBUFF` constant
2. Update `build-binary.ts` to pass through `FREEBUFF_MODE`
3. Conditional branding (title, logo, app header, CLI name)
### Phase 2: Feature Stripping
+
4. Filter slash commands and command registry
5. Hide agent mode toggle
6. Suppress credits/subscription UI components
@@ -348,16 +353,19 @@ No server-side changes are needed for Freebuff, **except** the release download
8. Simplify help banner
### Phase 3: Ads & Cleanup
+
9. Always-on ads behavior
10. Disable unreachable input modes
11. Hide `BuildModeButtons` and `ModeDivider` components
### Phase 4: Build & Release Infrastructure
+
11. Create `freebuff/cli/release/` package files
12. Create `freebuff/cli/build.ts` script
13. Create `.github/workflows/freebuff-release.yml`
### Phase 5: Testing
+
14. Add unit tests for IS_FREEBUFF guards
15. Add integration/E2E tests
16. Manual QA of built binary
diff --git a/freebuff/web/src/app/home-client.tsx b/freebuff/web/src/app/home-client.tsx
index 3cff424a3..8e82e9add 100644
--- a/freebuff/web/src/app/home-client.tsx
+++ b/freebuff/web/src/app/home-client.tsx
@@ -2,11 +2,7 @@
import { AnalyticsEvent } from '@codebuff/common/constants/analytics-events'
import { AnimatePresence, motion } from 'framer-motion'
-import {
- Check,
- ChevronDown,
- Copy,
-} from 'lucide-react'
+import { Check, ChevronDown, Copy } from 'lucide-react'
import Image from 'next/image'
import Link from 'next/link'
import posthog from 'posthog-js'
@@ -20,18 +16,17 @@ import { cn } from '@/lib/utils'
const INSTALL_COMMAND = 'npm install -g freebuff'
-const headlineWords = ["The", "free", "coding", "agent"]
+const headlineWords = ['The', 'free', 'coding', 'agent']
const faqs = [
{
question: 'How can it be free?',
- answer:
- 'Freebuff is supported by text ads shown in the CLI.',
+ answer: 'Freebuff is supported by text ads shown in the CLI.',
},
{
question: 'What models do you use?',
answer:
- 'GLM 5.1 as the main coding agent. Gemini 3.1 Flash Lite for finding files and research.\n\nConnect your ChatGPT subscription to unlock GPT-5.4 for deep thinking.',
+ 'Kimi K2.6 as the main coding agent. Gemini 3.1 Flash Lite for finding files and research.\n\nConnect your ChatGPT subscription to unlock GPT-5.4 for deep thinking.',
},
{
question: 'Which countries is Freebuff available in?',
@@ -41,7 +36,7 @@ const faqs = [
{
question: 'Are you training on my data?',
answer:
- 'No. We do not share your data with third parties that would train on it or use it for another purpose.\n\nIn the future, we may use request data to train custom models to improve Freebuff — this will be opt-out, so you\'ll always have control.',
+ "No. We do not share your data with third parties that would train on it or use it for another purpose.\n\nIn the future, we may use request data to train custom models to improve Freebuff — this will be opt-out, so you'll always have control.",
},
{
question: 'What data do you store?',
@@ -50,8 +45,7 @@ const faqs = [
},
{
question: 'What else is cool in Freebuff?',
- answer:
- `Freebuff comes with 9 specialized subagents:
+ answer: `Freebuff comes with 9 specialized subagents:
- file-picker finds relevant files across your codebase
- code-reviewer gives critical feedback on your changes
- browser-use lets the AI control a real browser to test your app
@@ -67,7 +61,8 @@ For big tasks, try the commands /interview → /plan → (implement) → /review
const setupSteps = [
{
label: 'Open your terminal',
- description: 'Use any terminal — within VS Code, plain terminal, PowerShell, etc.',
+ description:
+ 'Use any terminal — within VS Code, plain terminal, PowerShell, etc.',
},
{
label: 'Navigate to your project',
@@ -91,9 +86,7 @@ function SetupGuide() {