desktop

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: MIT Imports: 27 Imported by: 0

README

Desktop Version

The desktop version of AgentCTL provides a modern GUI interface while maintaining 100% compatibility with the CLI version.

Installation

macOS
# Download and install the .dmg or .pkg from releases
# Or via Homebrew (coming soon):
brew install --cask agentctl
Linux
# Download .deb, .rpm, or .AppImage from releases
# Debian/Ubuntu:
sudo dpkg -i m-desktop_0.0.36_amd64.deb

# Fedora/RHEL:
sudo rpm -i m-desktop-0.0.36.x86_64.rpm

# AppImage (universal):
chmod +x m-desktop-0.0.36.AppImage
./m-desktop-0.0.36.AppImage
Windows
# Download and run the .msi installer from releases
# Or use the standalone .exe

Usage

The desktop version includes both GUI and CLI in a single binary:

GUI Mode
# Launch GUI explicitly:
m --gui
m gui

# On macOS/Windows: Double-click the app icon
# On Linux: Launch from applications menu or desktop
CLI Mode (Same as Always)
# All existing CLI commands work unchanged:
m chat
m run agent.md "task"
m pipe "explain this"
cat error.log | m pipe

Features

GUI Features
  • Visual Chat Interface: Rich markdown rendering with syntax highlighting
  • Agent Manager: Browse and select from built-in and custom agents
  • Tool Execution Visualization: See tool calls in real-time
  • Settings Panel: Configure providers and API keys visually
  • File References: Drag & drop agent files
  • Session History: Persistent chat sessions
Shared Features (GUI & CLI)
  • Same configuration files (~/.agentctl/config.yaml)
  • Same agent definitions (Markdown files)
  • Same session history
  • Same cost tracking
  • Same MCP server support

Development

Prerequisites
# Install Wails CLI
go install github.com/wailsapp/wails/v2/cmd/wails@latest

# Install frontend dependencies
cd frontend && npm install
Build & Run
# Development mode (hot reload)
make desktop-dev

# Build for current platform
make desktop-build

# Build for all platforms
make desktop-build-all
Project Structure
desktop/          # Desktop app bridge
  ├── app.go      # App logic (session management, config)
  └── main.go     # Wails entry point

frontend/         # Svelte UI
  ├── src/
  │   ├── App.svelte           # Main app
  │   └── components/
  │       ├── Chat.svelte      # Chat interface
  │       ├── Sidebar.svelte   # Agent browser
  │       └── Settings.svelte  # Settings panel
  └── package.json

cmd/m/
  ├── main.go         # Entry point with dual-mode detection
  ├── gui_launch.go   # GUI launcher (build tag: gui)
  └── gui_stub.go     # GUI stub (build tag: !gui)

Build Tags

The project uses Go build tags to conditionally compile GUI support:

  • Default (headless): go build → CLI only (~8 MB)
  • With GUI: go build -tags gui → CLI + GUI (~18 MB)
  • Docker: Always headless (uses -tags headless explicitly)

Platform-Specific Notes

macOS
  • Uses native WebKit (WKWebView)
  • Supports Touch Bar (future)
  • Menu bar integration
  • App signing for Gatekeeper
Linux
  • Uses WebKitGTK
  • Desktop entry for application menus
  • AppImage for universal compatibility
  • Wayland and X11 support
Windows
  • Uses WebView2 (Edge)
  • MSI installer with auto-update support
  • System tray integration (future)

FAQ

Q: Can I use both GUI and CLI at the same time?
A: Yes! They share the same configuration and session history.

Q: Does GUI require internet for the UI?
A: No, the UI is bundled. Only LLM API calls require internet.

Q: Can I run CLI commands from the GUI?
A: Not yet, but this is planned. For now, use your terminal.

Q: Does the Docker version include GUI?
A: No, Docker builds are headless-only for minimal size.

Q: Can I build desktop version without Wails?
A: No, Wails is required for desktop builds. CLI builds don't need it.

Contributing

Desktop-specific contributions welcome! See CONTRIBUTING.md.

License

Same as main project - see LICENSE.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Run

func Run(version string) error

Run starts the Wails desktop application. Called from cmd/m/gui_launch.go when GUI mode is selected. Note: For standalone desktop builds, use the root main.go instead.

Types

type AgentInfo

type AgentInfo struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Model       string `json:"model"`
	Path        string `json:"path"`
	Builtin     bool   `json:"builtin"`
	Category    string `json:"category"` // "hub", "spoke", "standalone"
}

AgentInfo describes an available agent.

type App

type App struct {
	// contains filtered or unexported fields
}

App manages the desktop application state.

func NewApp

func NewApp() *App

func (*App) CloseSession

func (a *App) CloseSession(sessionID string)

func (*App) CreateSession

func (a *App) CreateSession(agentName string) (*SessionInfo, error)

func (*App) DeleteMCP added in v0.2.0

func (a *App) DeleteMCP(name string) error

DeleteMCP removes an MCP server MD file by name.

func (*App) DeleteSkill added in v0.2.0

func (a *App) DeleteSkill(name string) error

DeleteSkill removes a user-authored skill MD file by name.

func (*App) DeleteTool added in v0.2.0

func (a *App) DeleteTool(name string) error

DeleteTool removes a user-authored tool MD file by name.

func (*App) GetConfig

func (a *App) GetConfig() *userconfig.Config

func (*App) GetCost

func (a *App) GetCost(sessionID string) *CostInfo

func (*App) GetMCPStatus

func (a *App) GetMCPStatus() []MCPStatus

func (*App) GetPersona added in v0.2.0

func (a *App) GetPersona(agent string) Persona

GetPersona returns the stored persona for an agent (zero value if unset).

func (*App) GetSessions

func (a *App) GetSessions() []SessionInfo

func (*App) GetThemes

func (a *App) GetThemes() []ThemeInfo

func (*App) KMGraph added in v0.2.0

func (a *App) KMGraph() (*KMGraphData, error)

KMGraph returns the graph nodes and links for visualization.

func (*App) KMHealth added in v0.2.0

func (a *App) KMHealth() KMHealth

KMHealth pings the status endpoint with a short timeout.

func (*App) KMIndex added in v0.2.0

func (a *App) KMIndex(path, typ string) error

KMIndex kicks off indexing of path in the background. type is "auto" (repo if a .git exists, else docs), "repo", or "docs". Progress is reported to the frontend via events: "kmIndexProgress" {current,total,file}, "kmIndexDone" {message}, and "kmIndexError" {error}.

func (*App) KMPickDirectory added in v0.2.0

func (a *App) KMPickDirectory() (string, error)

KMPickDirectory opens a native folder picker for choosing what to index.

func (*App) KMStatus added in v0.2.0

func (a *App) KMStatus() (*KMStats, error)

KMStatus returns knowledge base stats (chunks/documents/repos).

func (*App) ListAgents

func (a *App) ListAgents() []AgentInfo

func (*App) ListMCP added in v0.2.0

func (a *App) ListMCP() []MCPDoc

ListMCP returns all MCP server MD files in ~/.config/m/mcp.

func (*App) ListSkills added in v0.2.0

func (a *App) ListSkills() []SkillDoc

ListSkills returns all user-authored skill MD files in ~/.config/m/skills.

func (*App) ListTools added in v0.2.0

func (a *App) ListTools() []ToolDoc

ListTools returns all user-authored tool MD files in ~/.config/m/tools.

func (*App) NewMCPTemplate added in v0.2.0

func (a *App) NewMCPTemplate() string

NewMCPTemplate returns starter MD for a new MCP server.

func (*App) NewSkillTemplate added in v0.2.0

func (a *App) NewSkillTemplate() string

NewSkillTemplate returns starter MD for a new skill.

func (*App) NewToolTemplate added in v0.2.0

func (a *App) NewToolTemplate() string

NewToolTemplate returns starter MD for a new shell tool.

func (*App) OpenFile

func (a *App) OpenFile() (*FileResult, error)

OpenFile opens a native file picker and returns the file path and content.

func (*App) RespondToolApproval added in v0.2.0

func (a *App) RespondToolApproval(requestID string, approved bool)

RespondToolApproval is called from the frontend to answer a pending tool-approval request. Unknown or already-answered ids are ignored.

func (*App) SaveAPIKey

func (a *App) SaveAPIKey(provider, key string) error

func (*App) SaveConfig

func (a *App) SaveConfig(provider, model, baseURL string) error

func (*App) SaveMCP added in v0.2.0

func (a *App) SaveMCP(oldName, content string) error

SaveMCP validates and writes an MCP server MD file. oldName is the file's previous name (empty for new servers); a rename removes the old file.

func (*App) SavePersona added in v0.2.0

func (a *App) SavePersona(agent string, p Persona) error

SavePersona persists the persona for an agent. An empty persona deletes the stored file so the agent reverts to its default behaviour.

func (*App) SaveSkill added in v0.2.0

func (a *App) SaveSkill(oldName, content string) error

SaveSkill validates and writes a skill MD file. oldName is the file's previous name (empty for new skills); a rename removes the old file.

func (*App) SaveTool added in v0.2.0

func (a *App) SaveTool(oldName, content string) error

SaveTool validates and writes a tool MD file. oldName is the file's previous name (empty for new tools); if the tool was renamed, the old file is removed. Returns a descriptive error when the content doesn't parse or validate.

func (*App) SendMessage

func (a *App) SendMessage(sessionID, message string) error

func (*App) Startup

func (a *App) Startup(ctx context.Context)

func (*App) StopGeneration

func (a *App) StopGeneration(sessionID string)

func (*App) SwitchAgent

func (a *App) SwitchAgent(sessionID, agentName string) error

type CostInfo

type CostInfo struct {
	InputTokens  int     `json:"inputTokens"`
	OutputTokens int     `json:"outputTokens"`
	Cost         float64 `json:"cost"`
	Model        string  `json:"model"`
}

CostInfo shows token usage and cost.

type FileResult

type FileResult struct {
	Path    string `json:"path"`
	Name    string `json:"name"`
	Content string `json:"content"`
}

FileResult is returned by OpenFile.

type KMGraphData added in v0.2.0

type KMGraphData struct {
	Nodes []KMNode `json:"nodes"`
	Links []KMLink `json:"links"`
}

KMGraphData is the node/edge payload from GET /api/graph.

type KMHealth added in v0.2.0

type KMHealth struct {
	Available bool   `json:"available"`
	BaseURL   string `json:"baseUrl"`
	Error     string `json:"error,omitempty"`
}

KMHealth reports whether the knowledge-master HTTP server is reachable.

type KMLink struct {
	Source string `json:"source"`
	Target string `json:"target"`
	Type   string `json:"type"`
}

KMLink is one graph edge from GET /api/graph.

type KMNode added in v0.2.0

type KMNode struct {
	ID       string `json:"id"`
	Type     string `json:"type"`
	Label    string `json:"label"`
	Category string `json:"category,omitempty"`
	Source   string `json:"source,omitempty"`
}

KMNode is one graph vertex from GET /api/graph.

type KMStats added in v0.2.0

type KMStats struct {
	Chunks    int `json:"chunks"`
	Documents int `json:"documents"`
	Repos     int `json:"repos"`
}

KMStats mirrors GET /api/v1/status.

type MCPDoc added in v0.2.0

type MCPDoc struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Transport   string `json:"transport"`
	Path        string `json:"path"`
	Content     string `json:"content"`
	Error       string `json:"error,omitempty"`
}

MCPDoc is a user-authored MCP server MD file surfaced to the MCP tab.

type MCPStatus

type MCPStatus struct {
	Name      string `json:"name"`
	Transport string `json:"transport"`
	Installed bool   `json:"installed"`
}

MCPStatus describes an MCP server's state.

type Message

type Message struct {
	ID        string     `json:"id"`
	Role      string     `json:"role"`
	Content   string     `json:"content"`
	Timestamp int64      `json:"timestamp"`
	ToolCalls []ToolCall `json:"toolCalls,omitempty"`
}

Message represents a chat message for the frontend.

type Persona added in v0.2.0

type Persona struct {
	Instructions string   `json:"instructions"`          // free-form custom guidance
	Tone         string   `json:"tone"`                  // "", concise, friendly, formal, playful, direct
	Verbosity    string   `json:"verbosity"`             // "", terse, balanced, detailed
	Temperature  *float64 `json:"temperature,omitempty"` // nil = use the agent's default
}

Persona is a per-agent behaviour overlay. It is stored in user config keyed by agent name and composed into the system prompt at session start, so users can tweak how any agent behaves — including bundled ones like "m" — without editing the agent's MD file.

func (Persona) IsEmpty added in v0.2.0

func (p Persona) IsEmpty() bool

IsEmpty reports whether the persona has no effect on a session.

type Session

type Session struct {
	ID        string    `json:"id"`
	Agent     string    `json:"agent"`
	Model     string    `json:"model"`
	CreatedAt int64     `json:"createdAt"`
	Messages  []Message `json:"messages"`
	// contains filtered or unexported fields
}

Session wraps an engine.Session with desktop-specific state.

type SessionInfo

type SessionInfo struct {
	ID        string `json:"id"`
	Agent     string `json:"agent"`
	Model     string `json:"model"`
	Messages  int    `json:"messages"`
	CreatedAt int64  `json:"createdAt"`
	Preview   string `json:"preview"` // first user message
}

SessionInfo is a summary for the session list.

type SkillDoc added in v0.2.0

type SkillDoc struct {
	Name        string   `json:"name"`
	Description string   `json:"description"`
	Tools       []string `json:"tools"`
	Path        string   `json:"path"`
	Content     string   `json:"content"`
	Error       string   `json:"error,omitempty"`
}

SkillDoc is a user-authored skill MD file surfaced to the Skills tab.

type ThemeInfo

type ThemeInfo struct {
	Name      string `json:"name"`
	BG        string `json:"bg"`
	BGPanel   string `json:"bgPanel"`
	BGInput   string `json:"bgInput"`
	Border    string `json:"border"`
	User      string `json:"user"`
	Assistant string `json:"assistant"`
	Tool      string `json:"tool"`
	Error     string `json:"error"`
	Accent    string `json:"accent"`
	Text      string `json:"text"`
	Muted     string `json:"muted"`
}

ThemeInfo describes a desktop theme.

type ToolCall

type ToolCall struct {
	ID       string `json:"id"`
	Name     string `json:"name"`
	Input    string `json:"input"`
	Output   string `json:"output,omitempty"`
	Error    string `json:"error,omitempty"`
	Duration int64  `json:"duration"` // milliseconds
	Status   string `json:"status"`   // "running", "done", "error", "declined"
}

ToolCall represents a tool execution.

type ToolDoc added in v0.2.0

type ToolDoc struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Runtime     string `json:"runtime"`
	Path        string `json:"path"`
	Content     string `json:"content"`
	Error       string `json:"error,omitempty"` // parse error, if any
}

ToolDoc is a user-authored tool MD file surfaced to the Tools tab.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL