Documentation
¶
Index ¶
- Constants
- Variables
- func ContextLimit() int
- func EnsureDefaultSkills() error
- func EstimateTokens(messages []Message) int
- func FormatSkillsSummary(skills []Skill) string
- func FormatTokens(n int) string
- func GenerateUnifiedDiff(oldContent, newContent, filePath string) string
- func ReadSkillContent(appRoot, skillName string) (string, error)
- func ReadSkillSection(appRoot, skillName, query string) (string, error)
- func SaveSession(appRoot string, session *Session) error
- func SaveSetting(appRoot string, scope SettingsScope, key string, value any) error
- func ScanForInjection(text string) (bool, string)
- func SessionListHeader() string
- func SettingsFileList(appRoot string) []string
- type AIClient
- type Agent
- func (a *Agent) ApplySettings(s Settings)
- func (a *Agent) Compact(ctx context.Context) (*CompactResult, error)
- func (a *Agent) ExecuteApprovedPlan(ctx context.Context, plan *PlanSummary) (string, error)
- func (a *Agent) GeneratePlan(ctx context.Context, userPrompt string) (*PlanSummary, error)
- func (a *Agent) RegenerateStep(ctx context.Context, stepIndex int, newDescription string) (*PlanSummary, error)
- func (a *Agent) Run(ctx context.Context, userMessage string) (*RunResult, error)
- func (a *Agent) Settings() Settings
- type AgentCallbacks
- type AgentState
- type Assessment
- type ClarificationQuestion
- type CommandRisk
- type CommandVerdict
- type CompactResult
- type ContentBlock
- type ContextUsage
- type GeneratedImage
- type Message
- type MessageResponse
- type NimbusCloudClient
- func (c *NimbusCloudClient) Chat(ctx context.Context, prompt, model string, projCtx *ProjectContext) (string, error)
- func (c *NimbusCloudClient) GenerateImage(ctx context.Context, prompt, size, model string) (*GeneratedImage, error)
- func (c *NimbusCloudClient) GeneratePlan(ctx context.Context, prompt string, projCtx *ProjectContext, model string) (*PlanSummary, error)
- func (c *NimbusCloudClient) RegenerateStep(ctx context.Context, stepIndex int, newDesc string, currentPlan *PlanSummary, ...) (*PlanSummary, error)
- func (c *NimbusCloudClient) SetRetryHook(fn func(attempt int, reason string))
- func (c *NimbusCloudClient) StreamExecute(ctx context.Context, prompt string, plan *PlanSummary, messages []Message, ...) (*MessageResponse, error)
- func (c *NimbusCloudClient) Turn(ctx context.Context, tr *TurnRequest, onDelta StreamHandler) (*MessageResponse, error)
- type PermissionMode
- type PlanPhase
- type PlanStep
- type PlanSummary
- type ProjectContext
- type RetryReporter
- type RunResult
- type Session
- func (s *Session) AppendAssistant(content []ContentBlock)
- func (s *Session) AppendToolResults(results []ContentBlock)
- func (s *Session) AppendTranscript(e TranscriptEntry)
- func (s *Session) AppendUser(text string)
- func (s *Session) ContextUsage() ContextUsage
- func (s *Session) ConversationSummary() string
- func (s *Session) Describe(now time.Time) string
- func (s *Session) RecordContextTokens(inputTokens int)
- func (s *Session) RecordTurn(prompt, planSummary, outcome string, files []string)
- func (s *Session) SetLimits(limitTokens, compactPercent int)
- type SessionUsage
- type SettingDef
- type SettingKind
- type Settings
- type SettingsScope
- type Skill
- type StreamHandler
- type TokenUsage
- type ToolDefinition
- type ToolExecutor
- func (t *ToolExecutor) AssessToolCall(name string, args map[string]any) Assessment
- func (t *ToolExecutor) Authorize(name string, args map[string]any) error
- func (t *ToolExecutor) Bash(ctx context.Context, commandStr string) (string, error)
- func (t *ToolExecutor) ClearTaint()
- func (t *ToolExecutor) CreateImage(ctx context.Context, prompt, relPath, size string) (string, error)
- func (t *ToolExecutor) DeleteFile(relPath string) (string, string, error)
- func (t *ToolExecutor) EditFile(relPath, target, replacement string) (string, string, error)
- func (t *ToolExecutor) EditFileAll(relPath, target, replacement string, replaceAll bool) (string, string, error)
- func (t *ToolExecutor) ExecuteTool(ctx context.Context, name string, args map[string]any) (output string, diff string, err error)
- func (t *ToolExecutor) FetchURL(ctx context.Context, rawURL, format string) (string, error)
- func (t *ToolExecutor) FindFiles(pattern, relPath string) (string, error)
- func (t *ToolExecutor) GetToolDefinitions() []ToolDefinition
- func (t *ToolExecutor) Grep(pattern, relPath string) (string, error)
- func (t *ToolExecutor) GrepFiltered(pattern, relPath, include string) (string, error)
- func (t *ToolExecutor) ListDir(relPath string) (string, error)
- func (t *ToolExecutor) ListDirDepth(relPath string, depth int) (string, error)
- func (t *ToolExecutor) LoadSkill(skillName string) (string, error)
- func (t *ToolExecutor) PermissionMode() PermissionMode
- func (t *ToolExecutor) QuerySkill(skillName, query string) (string, error)
- func (t *ToolExecutor) ReadFile(relPath string) (string, error)
- func (t *ToolExecutor) ReadFileRange(relPath string, startLine, endLine int) (string, error)
- func (t *ToolExecutor) ReadOnlyToolDefinitions() []ToolDefinition
- func (t *ToolExecutor) ReadSkill(name string) (string, error)
- func (t *ToolExecutor) RunCommand(ctx context.Context, commandStr string) (string, bool)
- func (t *ToolExecutor) SetPermissionMode(mode PermissionMode)
- func (t *ToolExecutor) Tainted() (bool, string, string)
- func (t *ToolExecutor) WriteFile(relPath, newContent string) (string, string, error)
- type TranscriptEntry
- type TurnMode
- type TurnRecord
- type TurnRequest
Constants ¶
const DefaultCompactPercent = 80
DefaultCompactPercent is how full the window gets before the conversation is compacted automatically, when the setting says nothing.
const ExecuteSystemPrompt = `` /* 266-byte string literal not displayed */
ExecuteSystemPrompt documents execution rules (authoritative copy on Nimbus Cloud).
const PlanSystemPrompt = `` /* 569-byte string literal not displayed */
PlanSystemPrompt documents the plan JSON contract the CLI expects. The authoritative prompts live on Nimbus Cloud; this is kept for reference and offline tooling.
Variables ¶
var ErrTurnUnsupported = errors.New("nimbus cloud server does not support agent turns (upgrade the server)")
ErrTurnUnsupported is returned when the cloud server predates the agent turn endpoint; callers fall back to the legacy plan/execute endpoints.
var SettingDefs = []SettingDef{ { Key: "model", Label: "Model", Kind: SettingChoice, Help: "Which model answers. 'optimal' lets the server choose per request.", Choices: []string{"optimal", "fast", "balanced", "deep"}, // contains filtered or unexported fields }, { Key: "auto_compact", Label: "Auto-compact", Kind: SettingBool, Help: "Summarise earlier turns automatically as the window fills, instead of failing the turn.", // contains filtered or unexported fields }, { Key: "context_limit", Label: "Context limit", Kind: SettingInt, Help: "Assumed context window, in tokens. Too high fails requests; too low compacts early.", Min: 16000, Max: 1000000, Step: 16000, Env: contextLimitEnv, // contains filtered or unexported fields }, { Key: "compact_threshold_percent", Label: "Compact at", Kind: SettingInt, Help: "How full the window gets before compaction runs, as a percentage.", Min: 50, Max: 95, Step: 5, // contains filtered or unexported fields }, { Key: "permission_mode", Label: "Permission mode", Kind: SettingChoice, Help: "auto asks about consequential actions · ask confirms every change · allow runs anything not refused.", Choices: []string{string(PermissionAuto), string(PermissionAsk), string(PermissionAllow)}, // contains filtered or unexported fields }, { Key: "verify_builds", Label: "Verify builds", Kind: SettingBool, Help: "Build the project after a turn changes code, and hand failures back to be repaired.", // contains filtered or unexported fields }, { Key: "plan_first", Label: "Plan before executing", Kind: SettingBool, Help: "Route every request through plan → approve → execute, rather than answering directly.", // contains filtered or unexported fields }, { Key: "expand_diffs", Label: "Expand diffs", Kind: SettingBool, Help: "Show full diffs in the transcript instead of a change summary. Ctrl+O toggles it per session.", // contains filtered or unexported fields }, { Key: "show_thinking", Label: "Show thinking", Kind: SettingBool, Help: "Report how long each stretch of thinking took.", // contains filtered or unexported fields }, { Key: "stream_output", Label: "Stream output", Kind: SettingBool, Help: "Print the reply as it arrives rather than when it is complete.", // contains filtered or unexported fields }, { Key: "max_command_output", Label: "Max command output", Kind: SettingInt, Help: "Bytes of a command's output fed back to the model before it is truncated.", Min: 4096, Max: 262144, Step: 4096, // contains filtered or unexported fields }, }
SettingDefs is the catalogue, in the order the screen shows it.
Functions ¶
func ContextLimit ¶ added in v1.6.0
func ContextLimit() int
ContextLimit returns the assumed context window when no session says otherwise. Settings reach a session through Session.SetLimits.
func EnsureDefaultSkills ¶
func EnsureDefaultSkills() error
EnsureDefaultSkills writes embedded default skills to ~/.nimbus/skills/ if not already present. EnsureDefaultSkills is retained as a no-op.
The Nimbus skill library is Nimbus Cloud intellectual property and now lives on the server, which selects the relevant skill for each turn and folds it into the model's instructions. It used to be embedded in this binary and written to ~/.nimbus/skills on every run, which shipped the whole library to every machine that installed the CLI.
Skills the user writes themselves — in the project or in ~/.nimbus/skills — are unaffected: they stay local and are still discovered by LoadSkills and read by the load_skill tool.
func EstimateTokens ¶ added in v1.6.0
EstimateTokens approximates the tokens a conversation occupies.
Four characters per token is the usual rule of thumb for English prose and code; tool results skew longer, which the estimate absorbs by counting every character of them too.
func FormatSkillsSummary ¶
FormatSkillsSummary formats the lightweight skill index as a bullet list for the system prompt.
func FormatTokens ¶ added in v1.6.0
FormatTokens renders a token count compactly (1234 -> "1.2k").
func GenerateUnifiedDiff ¶
GenerateUnifiedDiff builds a simple unified line diff.
func ReadSkillContent ¶
ReadSkillContent reads the full SKILL.md body for a given skill on demand.
func ReadSkillSection ¶ added in v1.5.4
ReadSkillSection reads only the relevant sections matching a query from a skill document.
func SaveSession ¶
SaveSession persists the session JSON under .nimbus/ai-sessions/<id>.json.
func SaveSetting ¶ added in v1.6.0
func SaveSetting(appRoot string, scope SettingsScope, key string, value any) error
SaveSetting writes one key to one scope, leaving the rest of the file alone.
Rewriting the whole file from a resolved Settings would be wrong twice over: it would bake every inherited value into the layer as if it had been set there, and it would drop any key this build does not know about.
func ScanForInjection ¶ added in v1.6.0
ScanForInjection reports whether text appears to be addressing the agent, returning the phrase that tripped it.
func SessionListHeader ¶ added in v1.6.0
func SessionListHeader() string
SessionListHeader is the column header matching Describe.
func SettingsFileList ¶ added in v1.6.0
SettingsFileList reports where each scope's file lives and whether it exists, for the footer of the settings screen.
Types ¶
type AIClient ¶
type AIClient interface {
Chat(ctx context.Context, prompt, model string, projCtx *ProjectContext) (string, error)
GeneratePlan(ctx context.Context, prompt string, projCtx *ProjectContext, model string) (*PlanSummary, error)
RegenerateStep(ctx context.Context, stepIndex int, newDesc string, currentPlan *PlanSummary, projCtx *ProjectContext, model string) (*PlanSummary, error)
StreamExecute(ctx context.Context, prompt string, plan *PlanSummary, messages []Message, tools []ToolDefinition, projCtx *ProjectContext, onDelta StreamHandler) (*MessageResponse, error)
// Turn runs a single agentic model turn. Implementations that cannot
// support it must return ErrTurnUnsupported.
Turn(ctx context.Context, req *TurnRequest, onDelta StreamHandler) (*MessageResponse, error)
}
AIClient is the interface for communicating with Nimbus Cloud AI backend.
func ResolveClient ¶
ResolveClient returns the appropriate AIClient. All intelligence is routed through nimbusgo.space.
type Agent ¶
type Agent struct {
Client AIClient
Tools *ToolExecutor
Context *ProjectContext
Session *Session
Model string
State AgentState
Callbacks AgentCallbacks
// Verifier runs the project's build/tests after execution and returns
// (output, ok). Defaults to a Go build when go.mod is present; tests
// override it. Nil disables verification.
Verifier func(ctx context.Context) (string, bool)
// contains filtered or unexported fields
}
Agent manages the explore → plan → execute → verify flow.
func NewAgent ¶
func NewAgent(client AIClient, tools *ToolExecutor, projCtx *ProjectContext, session *Session) *Agent
NewAgent creates a new Nimbus AI Agent.
func (*Agent) ApplySettings ¶ added in v1.6.0
ApplySettings wires resolved settings into the agent and the pieces it owns.
One place does this so a setting cannot be half-applied — read by the screen that shows it but never reaching the code that acts on it, which is the usual way a configuration screen becomes a lie.
func (*Agent) Compact ¶ added in v1.6.0
func (a *Agent) Compact(ctx context.Context) (*CompactResult, error)
Compact summarises the older part of the conversation in place.
It asks the model for the summary, so it costs one turn; when that fails the conversation is left untouched and the caller decides what to do, rather than silently losing history to a fallback.
func (*Agent) ExecuteApprovedPlan ¶
ExecuteApprovedPlan executes the approved steps using tools, then verifies the result (build) and lets the model repair failures.
func (*Agent) GeneratePlan ¶
GeneratePlan investigates the codebase for the request, then produces a structured plan grounded in what it found. Conversational requests come back as a plan with zero steps whose Summary holds the answer.
func (*Agent) RegenerateStep ¶
func (a *Agent) RegenerateStep(ctx context.Context, stepIndex int, newDescription string) (*PlanSummary, error)
RegenerateStep regenerates a modified step and any downstream steps.
func (*Agent) Run ¶ added in v1.6.0
Run handles one user message in the session's ongoing conversation.
It appends the message to the persistent history, then loops: ask the model, run whatever tools it calls, feed the results back, and repeat until the model answers with no further tool calls. Nothing is gated on a plan, and no clarification round-trip is imposed — if the model needs to ask something it simply says so, and the user's reply is the next message in the same conversation.
type AgentCallbacks ¶
type AgentCallbacks struct {
OnRequestSent func()
OnStreamDelta func(delta string)
OnStatus func(text string)
OnPlanGenerated func(plan *PlanSummary)
OnStepUpdate func(step *PlanStep)
OnDiffGenerated func(filePath, diff string)
OnToolCall func(toolName string, args map[string]any)
OnToolResult func(toolName string, args map[string]any, output string, err error)
OnExecutionCompleted func(summary string)
// OnUsage reports the tokens a turn consumed and the session total.
OnUsage func(turn *TokenUsage, session SessionUsage)
}
AgentCallbacks defines hooks for the TUI to render real-time progress.
type AgentState ¶
type AgentState string
AgentState represents the state of the agent.
const ( StateIdle AgentState = "idle" StateExploring AgentState = "exploring" StatePlanning AgentState = "planning" StateReviewing AgentState = "reviewing" StateExecuting AgentState = "executing" StateVerifying AgentState = "verifying" StateCompleted AgentState = "completed" StateFailed AgentState = "failed" )
type Assessment ¶ added in v1.6.0
type Assessment struct {
Risk CommandRisk
Reason string // shown in the approval prompt or the refusal
Subject string // the command or path the verdict is about
}
Assessment is the verdict on one tool call.
type ClarificationQuestion ¶
type ClarificationQuestion struct {
ID string `json:"id"`
Question string `json:"question"`
Options []string `json:"options,omitempty"`
Default string `json:"default,omitempty"`
Selected string `json:"selected,omitempty"`
}
ClarificationQuestion represents an interactive decision required from the user.
type CommandRisk ¶ added in v1.6.0
type CommandRisk int
CommandRisk is the outcome of classifying a command.
const ( // RiskAllowed is an ordinary workspace command. RiskAllowed CommandRisk = iota // RiskAsk needs the user's approval before running. RiskAsk // RiskBlocked is never run. RiskBlocked )
type CommandVerdict ¶ added in v1.6.0
type CommandVerdict struct {
Risk CommandRisk
Command string // the offending segment
Reason string // human-readable, shown in the approval prompt
}
CommandVerdict explains a classification.
func ClassifyCommand ¶ added in v1.6.0
func ClassifyCommand(command string) CommandVerdict
ClassifyCommand decides whether a command may run unattended.
type CompactResult ¶ added in v1.6.0
type CompactResult struct {
BeforeTokens int
AfterTokens int
Summarised int // messages replaced by the summary
}
CompactResult reports what compaction achieved.
func (CompactResult) Saved ¶ added in v1.6.0
func (r CompactResult) Saved() int
Saved is the estimated tokens reclaimed.
type ContentBlock ¶
type ContentBlock struct {
Type string `json:"type"` // "text" | "tool_use" | "tool_result"
Text string `json:"text,omitempty"`
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Input map[string]any `json:"input,omitempty"`
ToolUseID string `json:"tool_use_id,omitempty"`
Content string `json:"content,omitempty"`
IsError bool `json:"is_error,omitempty"`
}
ContentBlock represents a text or tool block.
type ContextUsage ¶ added in v1.6.0
type ContextUsage struct {
Tokens int
Limit int
// ThresholdPercent is how full the window gets before compaction runs.
// Zero means the default, so a usage built by hand still behaves.
ThresholdPercent int
}
ContextUsage describes how much of the window a conversation occupies.
func (ContextUsage) NeedsCompaction ¶ added in v1.6.0
func (u ContextUsage) NeedsCompaction() bool
NeedsCompaction reports whether the conversation has passed the threshold.
The comparison is in integers scaled by 100 rather than in floats: the threshold is a whole percentage from the settings screen, and this way it means exactly what it says at the boundary.
func (ContextUsage) Percent ¶ added in v1.6.0
func (u ContextUsage) Percent() int
Percent is how full the window is, 0–100.
func (ContextUsage) Remaining ¶ added in v1.6.0
func (u ContextUsage) Remaining() int
Remaining is the estimated room left, never negative.
func (ContextUsage) Threshold ¶ added in v1.6.0
func (u ContextUsage) Threshold() int
Threshold is the configured compaction point, as a percentage.
type GeneratedImage ¶ added in v1.6.0
type GeneratedImage struct {
Data []byte // decoded bytes, ready to write to disk
Model string // the model that drew it
}
GeneratedImage is one image returned by Nimbus Cloud.
type Message ¶
type Message struct {
Role string `json:"role"` // "user" | "assistant" | "system"
Content any `json:"content"` // string or []ContentBlock
}
Message represents a chat message.
type MessageResponse ¶
type MessageResponse struct {
ID string `json:"id"`
Model string `json:"model"`
Role string `json:"role"`
Content []ContentBlock `json:"content"`
StopReason string `json:"stop_reason"`
Usage *TokenUsage `json:"usage,omitempty"`
}
MessageResponse holds the response from the Nimbus Cloud AI.
func (*MessageResponse) TextContent ¶
func (m *MessageResponse) TextContent() string
func (*MessageResponse) ToolUseBlocks ¶
func (m *MessageResponse) ToolUseBlocks() []ContentBlock
type NimbusCloudClient ¶
type NimbusCloudClient struct {
ServerURL string
Token string
HTTPClient *http.Client
// OnRetry is called before each retry so the UI can explain the pause
// instead of appearing to hang. See retry.go.
OnRetry retryNotifier
}
NimbusCloudClient connects the CLI to the intelligence engine hosted at nimbusgo.space.
func NewNimbusCloudClient ¶
func NewNimbusCloudClient(serverURL string) (*NimbusCloudClient, error)
NewNimbusCloudClient initializes client using local authentication credentials.
func (*NimbusCloudClient) Chat ¶
func (c *NimbusCloudClient) Chat(ctx context.Context, prompt, model string, projCtx *ProjectContext) (string, error)
Chat sends a conversational query or question to Nimbus Cloud AI with project context.
func (*NimbusCloudClient) GenerateImage ¶ added in v1.6.0
func (c *NimbusCloudClient) GenerateImage(ctx context.Context, prompt, size, model string) (*GeneratedImage, error)
GenerateImage asks Nimbus Cloud for an image.
The provider keys live on the server, so the CLI never talks to an image provider directly: it posts a prompt and receives bytes. Which model draws the picture is server-side configuration, and changing it does not require a new CLI.
func (*NimbusCloudClient) GeneratePlan ¶
func (c *NimbusCloudClient) GeneratePlan(ctx context.Context, prompt string, projCtx *ProjectContext, model string) (*PlanSummary, error)
GeneratePlan calls POST /api/v1/ai/plan on Nimbus Cloud.
func (*NimbusCloudClient) RegenerateStep ¶
func (c *NimbusCloudClient) RegenerateStep(ctx context.Context, stepIndex int, newDesc string, currentPlan *PlanSummary, projCtx *ProjectContext, model string) (*PlanSummary, error)
RegenerateStep calls POST /api/v1/ai/plan/regenerate on Nimbus Cloud.
func (*NimbusCloudClient) SetRetryHook ¶ added in v1.6.0
func (c *NimbusCloudClient) SetRetryHook(fn func(attempt int, reason string))
SetRetryHook implements RetryReporter.
func (*NimbusCloudClient) StreamExecute ¶
func (c *NimbusCloudClient) StreamExecute(ctx context.Context, prompt string, plan *PlanSummary, messages []Message, tools []ToolDefinition, projCtx *ProjectContext, onDelta StreamHandler) (*MessageResponse, error)
StreamExecute streams step execution and tool guidance from Nimbus Cloud.
func (*NimbusCloudClient) Turn ¶ added in v1.5.4
func (c *NimbusCloudClient) Turn(ctx context.Context, tr *TurnRequest, onDelta StreamHandler) (*MessageResponse, error)
Turn calls POST /api/v1/ai/turn: one agentic model turn with native tools.
type PermissionMode ¶ added in v1.6.0
type PermissionMode string
PermissionMode selects how much is decided without asking.
const ( // PermissionAuto assesses each call and asks only about consequential ones. PermissionAuto PermissionMode = "auto" // PermissionAsk confirms anything that changes the workspace. PermissionAsk PermissionMode = "ask" // PermissionAllow runs whatever the policy does not refuse. PermissionAllow PermissionMode = "allow" )
func ParsePermissionMode ¶ added in v1.6.0
func ParsePermissionMode(s string) PermissionMode
ParsePermissionMode reads a mode name, falling back to auto.
type PlanPhase ¶
type PlanPhase struct {
Name string `json:"name"` // e.g. "Phase 1: Frontend User Interface"
Description string `json:"description"` // e.g. "Implement responsive Todo app view"
Files []string `json:"files"` // e.g. ["resources/views/todo.html"]
}
PlanPhase groups architectural steps into logical stages.
type PlanStep ¶
type PlanStep struct {
ID int `json:"id"`
Phase string `json:"phase,omitempty"` // e.g. "Phase 1: Frontend UI"
Action string `json:"action"` // "create_file" | "edit_file" | "run_command" | "delete_file" | "clarification_needed"
Target string `json:"target"`
Description string `json:"description"`
Content string `json:"content,omitempty"`
Risk string `json:"risk"` // "low" | "medium" | "high"
Approved bool `json:"approved"`
Status string `json:"status,omitempty"` // "pending" | "running" | "applied" | "failed"
Error string `json:"error,omitempty"`
}
PlanStep represents a single reviewable step in the execution plan.
type PlanSummary ¶
type PlanSummary struct {
Summary string `json:"summary"`
Overview string `json:"overview,omitempty"`
NeedsClarification bool `json:"needs_clarification,omitempty"`
Questions []ClarificationQuestion `json:"questions,omitempty"`
Phases []PlanPhase `json:"phases,omitempty"`
Steps []PlanStep `json:"steps"`
Details []string `json:"details,omitempty"`
}
PlanSummary represents the structured plan generated in Plan Mode.
type ProjectContext ¶
type ProjectContext struct {
AppRoot string `json:"app_root"`
ProjectName string `json:"project_name"`
GoModName string `json:"go_mod_name,omitempty"`
GoVersion string `json:"go_version,omitempty"`
NimbusModules []string `json:"nimbus_modules,omitempty"`
NimbusJSON string `json:"nimbus_json,omitempty"`
DirectoryTree string `json:"directory_tree"`
GitBranch string `json:"git_branch,omitempty"`
GitDiffSummary string `json:"git_diff_summary,omitempty"`
RootFiles []string `json:"root_files,omitempty"`
Models []string `json:"models,omitempty"`
Controllers []string `json:"controllers,omitempty"`
Migrations []string `json:"migrations,omitempty"`
RoutesSummary string `json:"routes_summary,omitempty"`
Skills []Skill `json:"skills,omitempty"`
// ActiveSkillFrame holds the most recently loaded skill so the server can
// keep it in the system prompt rather than the message history.
ActiveSkillFrame string `json:"active_skill_frame,omitempty"`
// Instructions holds project-level guidance for the agent, read from
// AGENTS.md / NIMBUS.md / CLAUDE.md / .nimbus/instructions.md. It is the
// project's persistent memory: conventions, do's and don'ts, commands.
Instructions string `json:"instructions,omitempty"`
// InstructionFiles lists which instruction files were found.
InstructionFiles []string `json:"instruction_files,omitempty"`
// Stack summarises non-Go tooling detected (package.json, Vite, Tailwind…).
Stack []string `json:"stack,omitempty"`
// OS is the host operating system, so shell commands can be phrased correctly.
OS string `json:"os,omitempty"`
}
ProjectContext contains scanned information about the current Nimbus project.
func ScanProject ¶
func ScanProject(appRoot string) (*ProjectContext, error)
ScanProject scans the given project directory and constructs a ProjectContext.
func (*ProjectContext) FormatSystemContext ¶
func (p *ProjectContext) FormatSystemContext() string
FormatSystemContext formats the ProjectContext into a rich markdown block for AI system prompts.
func (*ProjectContext) Refresh ¶ added in v1.5.4
func (p *ProjectContext) Refresh()
Refresh re-reads the cheap, fast-changing parts of the context (git state, directory tree, instructions) so later phases see files created earlier.
type RetryReporter ¶ added in v1.6.0
RetryReporter is implemented by clients that can announce transient retries, so the UI can explain a pause instead of looking frozen.
type RunResult ¶ added in v1.6.0
type RunResult struct {
// Text is the assistant's final message.
Text string
// ChangedFiles lists paths written, edited or deleted during the turn.
ChangedFiles []string
// ToolCalls counts tool invocations made during the turn.
ToolCalls int
// Verified reports whether the project build was run and passed.
Verified bool
}
RunResult is the outcome of one conversational turn.
type Session ¶
type Session struct {
ID string `json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
InitialQuery string `json:"initial_query"`
Model string `json:"model"`
Plan *PlanSummary `json:"plan,omitempty"`
ApprovedPlan *PlanSummary `json:"approved_plan,omitempty"`
History []Message `json:"history"`
AppliedSteps []int `json:"applied_steps"`
LoadedSkills map[string]string `json:"loaded_skills,omitempty"`
Status string `json:"status"` // "planning" | "reviewing" | "executing" | "completed"
// Findings is the exploration report produced for the current request.
Findings string `json:"findings,omitempty"`
// Turns is the conversation memory: one record per completed request,
// carried into later prompts so follow-ups build on earlier work.
Turns []TurnRecord `json:"turns,omitempty"`
// Usage totals every model turn in this session, so a resumed session
// keeps reporting what it has cost so far.
Usage SessionUsage `json:"usage"`
// ContextOverhead is the part of a request that Messages does not
// account for — the system prompt, the tool schemas and the project
// context — measured against what the server actually counted. See
// RecordContextTokens.
ContextOverhead int `json:"context_overhead,omitempty"`
// Transcript is what the user saw, kept separately from Messages.
//
// Messages is the model's context: compaction rewrites it and pruning
// drops from it, both of which are right for fitting a context window and
// wrong for a record of the session. The transcript is append-only, so
// reopening a session shows the conversation as it happened — including
// the notices that never went to the model at all.
Transcript []TranscriptEntry `json:"transcript,omitempty"`
// Messages is the live conversation: user turns, assistant replies, tool
// calls and tool results, in order. This is what the model actually sees,
// and what makes "continue" mean something — it is saved with the session
// and restored by --resume.
Messages []Message `json:"messages,omitempty"`
// contains filtered or unexported fields
}
Session represents an AI session stored on disk.
func LatestSession ¶ added in v1.6.0
LatestSession returns the most recently updated session, or nil when the project has none.
func ListSessions ¶
ListSessions returns a list of recent sessions sorted newest first.
func LoadSession ¶
LoadSession reads an existing session from disk.
func NewSession ¶
NewSession creates an empty initialized Session.
func (*Session) AppendAssistant ¶ added in v1.6.0
func (s *Session) AppendAssistant(content []ContentBlock)
AppendAssistant adds the assistant's reply, keeping its content blocks (text and tool_use) intact so the model sees its own tool calls.
func (*Session) AppendToolResults ¶ added in v1.6.0
func (s *Session) AppendToolResults(results []ContentBlock)
AppendToolResults adds the results of the assistant's tool calls. They are sent with the user role, which is how tool results are returned in this protocol.
func (*Session) AppendTranscript ¶ added in v1.6.0
func (s *Session) AppendTranscript(e TranscriptEntry)
AppendTranscript records a line of the session as the user saw it.
func (*Session) AppendUser ¶ added in v1.6.0
AppendUser adds a user message to the conversation.
func (*Session) ContextUsage ¶ added in v1.6.0
func (s *Session) ContextUsage() ContextUsage
ContextUsage estimates how much of the window this session occupies.
func (*Session) ConversationSummary ¶ added in v1.5.4
ConversationSummary renders recent turns for inclusion in prompts, so the model knows what was asked and done earlier in this session.
func (*Session) Describe ¶ added in v1.6.0
Describe renders a session as one line for a picker or a listing: what was asked, how long ago, and how much work is in it.
The prompt is what identifies a session to the person who ran it — an id is only useful once you already know which one you want.
func (*Session) RecordContextTokens ¶ added in v1.6.0
RecordContextTokens calibrates the estimate against what the server counted.
EstimateTokens can only see s.Messages, but a request also carries the system prompt, every tool schema and the project context — none of it visible here, and easily thousands of tokens. The gap between the server's input count and the estimate for the messages that produced it is exactly that overhead, so recording it makes every later reading honest.
Keeping the overhead separate rather than caching the absolute count is what makes the number survive compaction: the message estimate drops immediately, the overhead does not, and the gauge is right before the next turn rather than after it.
func (*Session) RecordTurn ¶ added in v1.5.4
RecordTurn appends a conversation-memory entry for a finished request.
type SessionUsage ¶ added in v1.6.0
type SessionUsage struct {
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
Requests int `json:"requests"`
CostUSD float64 `json:"cost_usd,omitempty"`
}
SessionUsage accumulates token spend across a session.
func (*SessionUsage) Add ¶ added in v1.6.0
func (u *SessionUsage) Add(t *TokenUsage)
Add folds one response's usage into the session total. Responses without usage still count as a request, so the request tally stays honest even against a server that does not report tokens.
func (SessionUsage) Reported ¶ added in v1.6.0
func (u SessionUsage) Reported() bool
Reported reports whether the server ever sent token counts.
func (SessionUsage) Summary ¶ added in v1.6.0
func (u SessionUsage) Summary() string
Summary renders the session's spend for humans, e.g. "18 requests · 42.1k tokens · $0.1240". Returns "" when nothing is known.
func (SessionUsage) Total ¶ added in v1.6.0
func (u SessionUsage) Total() int
Total returns all tokens seen in the session.
type SettingDef ¶ added in v1.6.0
type SettingDef struct {
Key string // the JSON key, and the name used by search
Label string // shown in the list
Help string // one line, shown for the highlighted row
Kind SettingKind
Choices []string // SettingChoice
Min int // SettingInt
Max int // SettingInt
Step int // SettingInt
Env string // the variable that overrides it, if any
// contains filtered or unexported fields
}
SettingDef describes one setting for the /settings screen.
The screen is generated from this list rather than written out row by row, so a setting added here appears in the list, in the search, and in the round-trip to disk without touching the view — the same reason the slash commands live in one registry.
func FindSetting ¶ added in v1.6.0
func FindSetting(key string) (SettingDef, bool)
FindSetting returns the definition for a key.
func (SettingDef) Display ¶ added in v1.6.0
func (d SettingDef) Display(s *Settings) string
Display renders the value the way the screen shows it.
func (SettingDef) Next ¶ added in v1.6.0
func (d SettingDef) Next(s *Settings, delta int)
Next advances the value: bools flip, choices cycle, numbers step. Negative delta goes the other way, which is what ←/→ do on a number.
Cycling rather than opening an editor is deliberate — every setting here has few enough sensible values that a list is faster than typing one, and there is no invalid state to validate.
func (SettingDef) Value ¶ added in v1.6.0
func (d SettingDef) Value(s *Settings) any
Value reads this setting out of a resolved Settings.
type SettingKind ¶ added in v1.6.0
type SettingKind int
SettingKind is how a value is presented and edited.
const ( // SettingBool toggles between true and false. SettingBool SettingKind = iota // SettingChoice cycles through a fixed list. SettingChoice // SettingInt steps between a minimum and a maximum. SettingInt )
type Settings ¶ added in v1.6.0
type Settings struct {
// Model is the default model name, or "optimal" to let the server pick.
Model string `json:"model"`
// AutoCompact summarises the conversation automatically as it fills.
AutoCompact bool `json:"auto_compact"`
// ContextLimit is the assumed context window in tokens.
ContextLimit int `json:"context_limit"`
// CompactThresholdPercent is how full the window gets before compaction.
CompactThresholdPercent int `json:"compact_threshold_percent"`
// PermissionMode decides how much runs without being confirmed.
PermissionMode string `json:"permission_mode"`
// VerifyBuilds runs the project's build after a turn changes code, and
// hands failures back to the model to repair.
VerifyBuilds bool `json:"verify_builds"`
// ExpandDiffs shows full diffs in the transcript rather than a summary.
ExpandDiffs bool `json:"expand_diffs"`
// ShowThinking shows the "Thought for Xs" line between turns.
ShowThinking bool `json:"show_thinking"`
// StreamOutput prints the reply as it arrives rather than when complete.
StreamOutput bool `json:"stream_output"`
// MaxCommandOutput caps the bytes of a command's output fed back.
MaxCommandOutput int `json:"max_command_output"`
// PlanFirst routes every request through plan → approve → execute.
PlanFirst bool `json:"plan_first"`
// MCPServers is carried through untouched for the MCP client to read.
// It is declared here so the raw-JSON round trip keeps it, and is not in
// the registry: a server list is edited as JSON, not toggled in a list.
MCPServers map[string]json.RawMessage `json:"mcp_servers,omitempty"`
}
Settings is the resolved configuration for a run.
Every field is also described in the registry below, which is what /settings renders; a field added here without an entry there is invisible to the user.
func DefaultSettings ¶ added in v1.6.0
func DefaultSettings() Settings
DefaultSettings is the configuration before any file or variable is read.
func LoadSettings ¶ added in v1.6.0
LoadSettings resolves the settings for a project.
Nothing here fails: a malformed or unreadable file is skipped rather than stopping the CLI from starting, because the alternative is a typo in a settings file making the tool unusable.
type SettingsScope ¶ added in v1.6.0
type SettingsScope string
SettingsScope is one layer of the settings stack.
const ( // ScopeUser applies to every project, from ~/.nimbus/settings.json. ScopeUser SettingsScope = "user" // ScopeProject is committed with the repo. ScopeProject SettingsScope = "project" // ScopeLocal is this checkout only, and belongs in .gitignore. ScopeLocal SettingsScope = "local" // ScopeEnv is an environment variable. It cannot be written. ScopeEnv SettingsScope = "env" // ScopeDefault means nothing has set it. ScopeDefault SettingsScope = "default" )
func SettingSource ¶ added in v1.6.0
func SettingSource(appRoot, key string) SettingsScope
SettingSource reports which layer decides a key's value, so the screen can explain why a setting is not what the user thought they set.
This is the question a flat list cannot answer: "I set that to false, why is it true?" is almost always a project file overriding a user file.
type Skill ¶
type Skill struct {
Name string `json:"name"`
Description string `json:"description"`
Path string `json:"path"`
Source string `json:"source"` // "project" | "global" | "embedded"
}
Skill represents a lightweight index entry for an agent skill.
func LoadSkills ¶
LoadSkills discovers and builds a lightweight index of skills (name + description only).
type StreamHandler ¶
type StreamHandler func(delta string)
StreamHandler receives streaming delta chunks.
type TokenUsage ¶ added in v1.6.0
type TokenUsage struct {
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
// CostUSD is what the turn cost, when the server prices it. The CLI does
// not price locally: the server picks the model behind "optimal", so a
// client-side guess would put a wrong number against real money.
CostUSD float64 `json:"cost_usd,omitempty"`
}
TokenUsage reports what a request consumed. It is populated when the server sends a "usage" field (JSON) or a usage SSE event; older servers omit it and the CLI simply reports no usage rather than guessing.
func (*TokenUsage) Total ¶ added in v1.6.0
func (u *TokenUsage) Total() int
Total returns all tokens billed for the request.
type ToolDefinition ¶
type ToolDefinition struct {
Name string `json:"name"`
Description string `json:"description"`
InputSchema map[string]any `json:"input_schema"`
}
ToolDefinition describes a tool schema exposed to the AI agent.
type ToolExecutor ¶
type ToolExecutor struct {
AppRoot string
// CommandTimeout bounds a single bash invocation.
CommandTimeout time.Duration
// ApproveCommand is consulted before running a command the policy flags
// as consequential (see command_policy.go). Returning false refuses the
// command; the model reads the refusal and can choose another route.
//
// Nil means no one can be asked: interactive callers must set it, and
// headless callers set AutoApprove instead. Leaving both unset fails
// closed, so a non-interactive run cannot silently `sudo` its way out of
// a problem.
ApproveCommand func(cmd, reason string) bool
// AutoApprove runs flagged commands without asking (nimbus ai --yes).
AutoApprove bool
// MaxCommandOutput caps the bytes of a command's output handed back to
// the model. Zero means the built-in cap, so a ToolExecutor built without
// settings is still bounded.
MaxCommandOutput int
// GenerateImage draws an image through Nimbus Cloud. The CLI holds no
// provider keys, so this is injected by the command that owns the cloud
// client. Nil means the tool is not offered to the model at all, rather
// than offered and failing when called.
GenerateImage func(ctx context.Context, prompt, size, model string) ([]byte, string, error)
// contains filtered or unexported fields
}
ToolExecutor executes agent tool requests.
func NewToolExecutor ¶
func NewToolExecutor(appRoot string) *ToolExecutor
NewToolExecutor creates a tool executor sandboxed to appRoot.
func (*ToolExecutor) AssessToolCall ¶ added in v1.6.0
func (t *ToolExecutor) AssessToolCall(name string, args map[string]any) Assessment
AssessToolCall judges one tool call before it runs.
func (*ToolExecutor) Authorize ¶ added in v1.6.0
func (t *ToolExecutor) Authorize(name string, args map[string]any) error
Authorize runs the assessment and obtains consent when one is needed.
func (*ToolExecutor) Bash ¶
Bash runs a shell command and returns its combined output. A failing command is not an error at the tool level: the failure text is returned so the model can read and act on it.
func (*ToolExecutor) ClearTaint ¶ added in v1.6.0
func (t *ToolExecutor) ClearTaint()
ClearTaint forgets the warning, once the user has decided about it.
func (*ToolExecutor) CreateImage ¶ added in v1.6.0
func (t *ToolExecutor) CreateImage(ctx context.Context, prompt, relPath, size string) (string, error)
CreateImage draws an image through Nimbus Cloud and writes it into the workspace, returning a one-line report for the model.
The path goes through the same resolution as any write, so a generated image cannot land outside the project.
func (*ToolExecutor) DeleteFile ¶
func (t *ToolExecutor) DeleteFile(relPath string) (string, string, error)
func (*ToolExecutor) EditFile ¶
func (t *ToolExecutor) EditFile(relPath, target, replacement string) (string, string, error)
EditFile replaces a unique target substring.
func (*ToolExecutor) EditFileAll ¶ added in v1.5.4
func (t *ToolExecutor) EditFileAll(relPath, target, replacement string, replaceAll bool) (string, string, error)
EditFileAll replaces the target substring; with replaceAll every occurrence is replaced, otherwise the target must be unique.
func (*ToolExecutor) ExecuteTool ¶
func (*ToolExecutor) FetchURL ¶ added in v1.6.0
FetchURL retrieves a page and returns it as readable text, or as raw markup when format is "html".
func (*ToolExecutor) FindFiles ¶ added in v1.5.4
func (t *ToolExecutor) FindFiles(pattern, relPath string) (string, error)
FindFiles returns workspace-relative paths matching a glob pattern.
func (*ToolExecutor) GetToolDefinitions ¶
func (t *ToolExecutor) GetToolDefinitions() []ToolDefinition
func (*ToolExecutor) Grep ¶
func (t *ToolExecutor) Grep(pattern, relPath string) (string, error)
Grep searches file contents with a regex (no include filter).
func (*ToolExecutor) GrepFiltered ¶ added in v1.5.4
func (t *ToolExecutor) GrepFiltered(pattern, relPath, include string) (string, error)
GrepFiltered searches file contents, optionally restricted to files whose name matches the include glob.
func (*ToolExecutor) ListDir ¶
func (t *ToolExecutor) ListDir(relPath string) (string, error)
ListDir lists a single directory level.
func (*ToolExecutor) ListDirDepth ¶ added in v1.5.4
func (t *ToolExecutor) ListDirDepth(relPath string, depth int) (string, error)
ListDirDepth lists a directory up to depth levels deep (1-3).
func (*ToolExecutor) LoadSkill ¶
func (t *ToolExecutor) LoadSkill(skillName string) (string, error)
LoadSkill loads the full content and documentation of a skill by name on demand.
func (*ToolExecutor) PermissionMode ¶ added in v1.6.0
func (t *ToolExecutor) PermissionMode() PermissionMode
PermissionMode reports the active mode, defaulting to auto.
func (*ToolExecutor) QuerySkill ¶ added in v1.5.4
func (t *ToolExecutor) QuerySkill(skillName, query string) (string, error)
QuerySkill reads specific sections or topics from a skill to keep context lightweight.
func (*ToolExecutor) ReadFile ¶
func (t *ToolExecutor) ReadFile(relPath string) (string, error)
ReadFile reads a whole file (subject to size limits).
A file that has already been read in this conversation, and has not changed since, comes back as a one-line reminder instead of its full contents. An agent investigating a codebase re-reads the same files often — the earlier output is still in the conversation, and sending it again wastes the context it would need to finish the work.
func (*ToolExecutor) ReadFileRange ¶ added in v1.5.4
func (t *ToolExecutor) ReadFileRange(relPath string, startLine, endLine int) (string, error)
ReadFileRange reads a file, optionally restricted to a 1-based inclusive line range. Oversized reads are truncated with a hint to use ranges.
func (*ToolExecutor) ReadOnlyToolDefinitions ¶ added in v1.5.4
func (t *ToolExecutor) ReadOnlyToolDefinitions() []ToolDefinition
ReadOnlyToolDefinitions returns the tools that inspect the workspace without changing files. Used for the exploration and planning phases.
func (*ToolExecutor) ReadSkill ¶
func (t *ToolExecutor) ReadSkill(name string) (string, error)
ReadSkill is an alias for LoadSkill.
func (*ToolExecutor) RunCommand ¶ added in v1.5.4
RunCommand runs a command and reports whether it exited successfully.
func (*ToolExecutor) SetPermissionMode ¶ added in v1.6.0
func (t *ToolExecutor) SetPermissionMode(mode PermissionMode)
ExecuteTool runs the requested tool and returns output string and optional diff string. SetPermissionMode selects how much runs without asking.
type TranscriptEntry ¶ added in v1.6.0
type TranscriptEntry struct {
Role string `json:"role"`
Content string `json:"content,omitempty"`
ToolName string `json:"tool_name,omitempty"`
ToolArgs map[string]string `json:"tool_args,omitempty"`
Detail string `json:"detail,omitempty"`
Diff string `json:"diff,omitempty"`
IsError bool `json:"is_error,omitempty"`
ElapsedMS int64 `json:"elapsed_ms,omitempty"`
At time.Time `json:"at"`
}
TranscriptEntry is one line of the session as it was displayed.
type TurnMode ¶ added in v1.5.4
type TurnMode string
TurnMode selects the server-side system prompt for an agent turn.
const ( // TurnModeAgent is the default: one continuous conversation in which the // model decides whether to answer, investigate, or change code. The other // modes drive the older staged pipeline, still used by --plan-only. TurnModeAgent TurnMode = "agent" TurnModeExplore TurnMode = "explore" TurnModePlan TurnMode = "plan" TurnModeExecute TurnMode = "execute" TurnModeChat TurnMode = "chat" )
type TurnRecord ¶ added in v1.5.4
type TurnRecord struct {
At time.Time `json:"at"`
Prompt string `json:"prompt"`
PlanSummary string `json:"plan_summary,omitempty"`
Outcome string `json:"outcome,omitempty"`
FilesChanged []string `json:"files_changed,omitempty"`
}
TurnRecord summarises one completed request/response cycle.
type TurnRequest ¶ added in v1.5.4
type TurnRequest struct {
Mode TurnMode
Model string
Prompt string // the user's original request
Messages []Message
Tools []ToolDefinition
Plan *PlanSummary
Context *ProjectContext
}
TurnRequest is one model turn of the agent loop: the server composes the system prompt for Mode from the project context and returns text and/or tool calls; the CLI executes tools locally and calls again.