Finish setup
Open Kuttle Settings and complete the guided setup. Add a model key, configure an agent, and approve only the folders and integrations you plan to use.
Kuttle product guide
Kuttle is a native Dock for launching apps, asking for outcomes, and supervising work performed by agents, tools, and connected services. This guide explains the product from first launch to advanced setup.
Open Kuttle Settings and complete the guided setup. Add a model key, configure an agent, and approve only the folders and integrations you plan to use.
Click the Kuttle Dock or press ⌘⇧D from another app. The field opens on the display under your pointer.
Ask naturally. Address @kuttle for the main orchestrator or use a configured agent trigger to choose a specialist directly.
Continue working while Kuttle runs. Open Tasks to pause, cancel, retry, approve a protected action, or open a produced file.
Product model
Kuttle separates understanding from execution. Input sources never perform side effects directly; each request is contextualized, planned, validated, and then handed to an approved capability.
Normalizes Dock prompts, shortcuts, agent triggers, and future channels into one task request.
Reads supported desktop metadata and optional screen understanding only when a command runs.
Selects an agent, creates a plan, and coordinates dependent or parallel steps.
Checks available capabilities, allowed folders, risk, exact-action approvals, and resource limits.
Provide controlled access to files, native apps, connected services, tools, MCP servers, and model providers.
Persists status, progress, results, traces, schedules, and artifacts so work remains inspectable.
Requests
A useful request names the outcome, relevant source, destination, timing, and any boundary that matters. Kuttle can ask a follow-up when required information is missing.
@kuttle summarize the PDFs in Documents and create a one-page brief
@kuttle draft a reply to the open email, but show it to me before sending
@research compare these two reports and cite the differences
@kuttle send the invoice summary Friday at 8:00 AM
Supervision
You can send another request while earlier work continues. Kuttle runs tasks up to the concurrency limit, queues additional work, and gives each task independent context, controls, and output.
Pause and cancellation are cooperative. A system call already in progress may finish before a task fully stops. Generated files appear as artifacts that you can open or reveal in Finder.
Settings → General
Controls startup, appearance, Dock behavior, displays, voice input, and optional screen context.
Choose the Dock style, theme colors, app icon size, and chat typography. Changes apply immediately. Keep icon dimensions stable to avoid Dock movement.
Show Kuttle on every connected display or select individual displays. Refresh after connecting or removing a monitor.
Settings → Dock Items
Add applications that remain in the expanded Dock, reorder them, or combine related apps into one group launcher. Running and minimized apps remain separate from pinned configuration.
Reviews when Kuttle opened or restored an application. This activity stays local and supports understanding launcher behavior without exposing app history to a model by default.
Settings → Shortcuts
Enable or disable Kuttle’s global keyboard commands. The default ⌘⇧D opens and focuses the command field on the display under the pointer. Global shortcuts require Accessibility permission and are not installed when that permission is unavailable.
Settings → Agents
Agents define which model handles a request, what specialist knowledge it receives, and when the main @kuttle orchestrator should route work to it. Use @kuttle for a goal that may need planning, tools, or multiple capabilities. Use a named trigger such as @research when you already know which specialist should handle the request.
Create text or image-generation workers, assign a unique trigger, select the provider and model, and edit the three files supplied to that worker.
Store provider credentials in macOS Keychain and enable only the providers Kuttle may call. Model usage is billed by the selected provider.
Open or relocate the editable agent root. The default is ~/kuttle/agents; older data under ~/dile is migrated automatically.
@research. Kuttle adds a missing @, converts the trigger to lowercase, and uses its safe form as the profile and folder identifier.SKILL.md is uploaded, Kuttle appends this purpose to the generated skill.16:9 or 4K, override image defaults.AGENTS.md, SKILL.md, or MEMORY.md. If omitted, Kuttle generates safe starter files; all three remain editable later.Name an agent for the role or outcome it owns, not for the underlying model. Models can change without changing what the agent means to the user.
@researchGood specialistClear responsibility: gather evidence, compare sources, and prepare a cited brief.
@supportGood specialistClear workflow boundary: inspect support context, draft replies, and use approved email or ticket adapters.
@slidesGood specialistClear artifact: structure a presentation and use the PowerPoint adapter when an action is requested.
@helper2AvoidThe role is ambiguous, so users and the orchestrator cannot predict when it should be selected.
@gpt-modelAvoidThis ties identity to a replaceable provider or model instead of a stable capability.
Triggers must be unique. Prefer lowercase words, hyphens, or underscores with no spaces: @invoice-review, @finance, or @product_research. The visible display name can be more natural, such as Invoice Review.
A profile cannot call a remote model until its provider has an enabled credential. Kuttle supports the providers shown in the current build: OpenAI, Anthropic, Gemini, and OpenRouter.
@research summarize why leaves change color in three bullets. If the key is missing or disabled, Kuttle reports which provider must be configured.AGENTS.mdThe startup table of contents: read order, runtime role, and rules for writing durable memory.SKILL.mdThe routing contract: description, capabilities, workflows, constraints, and sequencing.MEMORY.mdDurable facts, decisions, preferences, lessons, constraints, and historical context.Kuttle loads these files at the start of every conversation. Provider and model settings remain controlled by Settings, even if Markdown claims otherwise. Live adapters, permissions, allowed folders, and host policy also take priority over file text.
AGENTS.md: startup and memory policyThis file is read first. Keep it stable and short. It should tell the runtime which files to read, identify the trigger and role, and define what is safe to preserve in memory. It is not the place for API keys, model selection, a long persona, or detailed domain procedures.
# Research Agent Index
This file is the startup table of contents and is read first.
## Read order
1. Read `AGENTS.md` for startup and memory policy.
2. Read `SKILL.md` before planning or accepting routed work.
3. Read relevant `MEMORY.md` entries for durable context.
## Runtime profile
- Trigger: `@research`
- Role: worker
- Agent type: text
- Provider and model are selected in Kuttle Settings.
## Saving memory
Write to `MEMORY.md` only after a successful result reveals durable,
reusable knowledge. Never save credentials, raw conversations, temporary
TODOs, debugging logs, or short-lived task state.
SKILL.md: routing and operating contractThe orchestrator uses this file's description and declared capabilities to decide whether the specialist fits a goal. Be concrete about when to use the agent, its expected inputs and output, its workflow, and its boundaries. A vague skill causes poor routing.
---
name: Research
description: Researches a defined topic, verifies important claims, and
returns a concise source-backed brief with facts separated from inference.
---
# Research Skill
## Use when
- The user asks to compare products, vendors, sources, or claims.
- The result needs evidence, links, or a decision-ready brief.
## Inputs
- A question, topic, or comparison criteria.
- Optional active-browser, selected-file, or user-supplied context.
## Capabilities
- Analyze supplied context and approved source results.
- Organize findings, disagreements, risks, and open questions.
- Produce a brief, comparison table, or source list.
## Workflow
1. Restate the decision or outcome being researched.
2. Use only enabled adapters and approved tools needed for the task.
3. Verify consequential claims with independent evidence when possible.
4. Separate observed facts, source claims, and model inference.
5. Return the requested artifact and identify remaining uncertainty.
## Constraints
- Never invent a source, quote, completed action, or file modification.
- Do not bypass adapter permissions, allowed folders, or approval policy.
- Do not store credentials or user secrets in any agent file.
## Output
- Lead with the answer.
- Cite sources next to supported claims.
- End with material uncertainty or a concrete next action.
MEMORY.md: durable reusable knowledgeMemory is knowledge, not instructions. Save stable preferences, decisions, recurring constraints, historical context, and reusable lessons only when they will improve future work. Explain why each item matters and date decisions that may become stale.
# Research Memory
## User preferences
- The user wants decision briefs to lead with the recommendation and keep
supporting evidence under 600 words. This reduces review time.
## Product decisions
- 2026-07-31: Prefer native macOS integrations over browser automation when
both expose the required capability. Native adapters are easier to audit.
## Known constraints
- Customer documents may be read only from folders approved in Settings.
- Never include credentials, private tokens, or raw email bodies in memory.
## Reusable knowledge
- Distinguish a configured capability from a verified completed action.
Report completion only after the host adapter returns success.
AGENTS.mdDo includeRead order, runtime role, file responsibilities, and memory-writing rules.
SKILL.mdDo includeA discriminating description, use cases, inputs, capabilities, workflow, output contract, constraints, and sequencing.
MEMORY.mdDo includeDurable preferences, dated decisions, stable constraints, lessons, tradeoffs, and historical context with an explanation of why each matters.
NeverAll three filesDo not store API keys, OAuth tokens, passwords, raw conversation transcripts, temporary task status, arbitrary logs, or claims that override Kuttle permissions and policy.
~/kuttle/agents.@research, Kuttle uses a layout like the example below.~/kuttle/agents/
├── agent/
│ ├── AGENTS.md
│ ├── SKILL.md
│ └── MEMORY.md
└── research/
├── AGENTS.md
├── SKILL.md
└── MEMORY.md
@research compare three local-first note apps selects the enabled @research profile directly. Kuttle still enforces adapters, permissions, allowed folders, tools, and risk policy.
@kuttle research three vendors and create a decision brief lets the orchestrator inspect enabled SKILL.md descriptions, choose a specialist, and coordinate approved tools or adapters.
@visual create a 16:9 product illustration at 2K directly uses an image profile; prompt dimensions override the profile's defaults.
Trigger stays plainProfile matchConfirm the trigger exactly matches an enabled profile, including the leading @. Refresh Agent Profiles after changing the storage folder manually.
Missing API keyCredentialsEnable the profile's provider in API Keys, save its credential to Keychain, and confirm the row shows Stored.
Wrong agent routedSkill descriptionMake the first description in SKILL.md specific about when the agent should and should not be used. Remove overlapping promises from other workers.
Edit not appliedConversation contextSave the file, verify it is under the active Agent Storage root, then start a new conversation so Kuttle reloads the full file set.
Action not executedHost authorityAn agent response cannot substitute for an adapter result. Enable the required integration or tool and review the relevant permissions, allowed folders, and risk decision.
Settings → Integrations
Integrations are adapters. Enabling one exposes only its declared capabilities to planning; the planner cannot invent an unconfigured connection.
Connect Drive, Docs, Sheets, Forms, Meet, Gmail, and Calendar through Google OAuth. Review requested scopes in Google’s authorization screen. Tokens remain in Keychain.
Connect Microsoft Graph capabilities such as Outlook, OneDrive, Excel, and Calendar. The sign-in returns through Kuttle’s registered callback.
Enable supported macOS adapters including Calendar, Reminders, Contacts, Mail, Notes, Shortcuts, and Preview. Request access from Settings, not while a task is running.
Pair two Kuttle identities by exchanging a one-time invitation through a channel you already trust. Direct transfers use verified public keys and do not upload the shared file to a central Kuttle server.
The current beta supports peers on the same local network. It does not provide central discovery, STUN, TURN, or relay service.
Settings → Tools
Tools extend what agents can do. Installation and execution remain host-controlled; the model receives tool descriptions and schemas, not unrestricted access to source code or your computer.
Install an approved folder containing tools.json and main.py. Kuttle validates the package, copies it into ~/kuttle/tools, discovers its manifest, and shows the installed metadata.
ZIP installation is currently blocked until archive extraction can be validated inside the sandbox. Unpack the ZIP and choose the tool folder instead.
Choose the Python executable and review isolation, timeout, output, CPU, memory, process, and network limits. Declared capabilities determine what the sandbox grants.
Add local stdio or Streamable HTTP Model Context Protocol servers. Local commands run directly without shell expansion. Remote sessions can use bearer tokens or OAuth with PKCE.
Read-only tools may receive a saved approval. Mutating MCP tools require confirmation for each call. Credentials stay in Keychain and are excluded from configuration and traces.
A tool is one folder with a manifest and one Python entry point. The folder name can be descriptive; the manifest id is the stable identifier Kuttle uses for planning and execution.
my-tool/
├── tools.json
└── main.py
tools.json structure{
"id": "word_count",
"name": "Word Count",
"description": "Counts words and characters in supplied text.",
"author": "Your name",
"version": "1.0.0",
"dependencies": {},
"inputSchema": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "Text to analyze"
}
},
"required": ["text"],
"additionalProperties": true
},
"capabilities": {
"files": [],
"network": {
"enabled": false,
"domains": [],
"methods": [],
"maxResponseBytes": 0
},
"secrets": [],
"subprocesses": false
},
"env": []
}
idString · recommendedThe stable machine identifier used by the planner and runtime. Use a unique value such as word_count or invoice-summary. Kuttle lowercases the value, replaces unsupported characters with hyphens, and accepts only letters, numbers, underscores, and hyphens after normalization.
If omitted, Kuttle falls back to name, then the package folder name. Defining it explicitly prevents the identifier from changing when a folder is renamed.
nameString · recommendedThe human-readable label shown in Settings and supplied to the planner. Use a short noun phrase such as Word Count. If omitted, Kuttle displays the normalized id.
descriptionString · recommendedExplains when the tool should be selected and what result it returns. This is the most important routing field. Describe the capability, expected input, and output without promising permissions the manifest does not declare.
"description": "Counts words and characters in supplied text."
authorString · optionalPublisher or developer displayed with the installed tool. It is metadata only and does not establish trust, signing identity, or sandbox privileges.
versionString · optionalThe package version shown in Settings and planner metadata. Semantic versions such as 1.0.0 are recommended. Kuttle does not currently resolve versions or download updates from this value.
inputSchemaObject · optionalA JSON Schema object describing arguments the planner should place inside payload.input. The alias input_schema is also accepted. An absent or invalid JSON object becomes {}.
Kuttle currently uses this schema as planner metadata; it does not replace runtime validation. Your Python code must still verify types, required values, lengths, paths, and ranges before processing them.
type: normally "object" for the complete input, then "string", "number", "integer", "boolean", "array", or "object" for properties.properties: a map from argument names to their schemas.description: tells the planner what a property means and how to populate it.required: an array of property names that should always be supplied.enum: restricts a value to a documented set, such as ["short", "detailed"].items: describes each element of an array.default: documents a preferred fallback; main.py must apply it.minimum, maximum, minLength, and maxLength: document bounds that Python must enforce.additionalProperties: use false when the tool should receive only documented arguments, or true when Kuttle context fields are acceptable."inputSchema": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "Text to analyze",
"minLength": 1,
"maxLength": 10000
},
"mode": {
"type": "string",
"enum": ["short", "detailed"],
"default": "short"
}
},
"required": ["text"],
"additionalProperties": true
}
dependenciesObject, array, or string · optionalDeclares third-party Python packages. Kuttle accepts a package-to-version object, an array of requirement strings, or one requirement string.
Package map with exact versions:
"dependencies": {
"requests": "2.32.3",
"python-dateutil": "2.9.0"
}
Requirement list with explicit specifiers:
"dependencies": [
"requests==2.32.3",
"python-dateutil>=2.9.0"
]
capabilitiesObject · optionalRequests the minimum sandbox resources the tool needs. Missing keys are denied. Capabilities are requests, not authority: the host validates them against the runner and user policy before every execution.
filesAn array of {"selector", "mode"} objects. Only these two combinations currently run:
{"selector": "user-selected", "mode": "read"}: Kuttle stages read-only copies of current Finder selections or approved Finder context. Original host paths are replaced by sandbox paths.{"selector": "run-output", "mode": "write"}: the tool may write bounded artifacts inside payload.sandbox.outputDirectory; Kuttle copies completed artifacts into managed storage.Other selector/mode combinations are rejected. File actions must also be enabled, and source paths must be within Allowed Folders.
networkMay be false, true, or an object with the following values:
enabled: Boolean requesting network access.domains: array of intended hostnames, such as ["api.example.com"].methods: array of HTTP methods. Kuttle normalizes them to uppercase.maxResponseBytes: integer documenting the maximum expected response body.Current release: only enabled: false is executable. Any enabled network capability fails closed because the host network broker is not implemented.
secretsAn array of secret names the tool would need, for example ["WEATHER_API_KEY"]. Secret values are never included in planner metadata. Current release: any non-empty list blocks execution because Python-tool secret grants are unavailable.
subprocessesA Boolean request to launch child processes. Keep it false. The current runner allows one fixed interpreter process and blocks shells, commands, applications, and child processes.
"capabilities": {
"files": [
{"selector": "user-selected", "mode": "read"},
{"selector": "run-output", "mode": "write"}
],
"network": {
"enabled": false,
"domains": [],
"methods": [],
"maxResponseBytes": 0
},
"secrets": [],
"subprocesses": false
}
envArray or string · optionalLists environment-variable names requested by the tool, not their values. The aliases allowedEnv and allowed_env are accepted for compatibility. Kuttle combines these names with capabilities.secrets.
"env": ["WEATHER_API_KEY"]
Current release: environment and secret injection are unavailable, so any non-empty env value blocks execution. Use "env": []. Never put credentials directly in tools.json or main.py.
permissionsLegacy compatibilityOlder manifests may contain a string list or Boolean map. Legacy readFiles, writeFiles, network, and subprocesses values are translated into the capability model. New tools should use capabilities; a legacy permission never bypasses sandbox enforcement.
main.py contractKuttle runs main.py in its signed sandbox. Read one JSON object from standard input and write the useful result to standard output. The payload has three top-level objects:
{
"input": {
"text": "Count these words",
"prompt": "Use word count for: Count these words",
"activeApp": "Finder"
},
"tool": {
"id": "word_count",
"name": "Word Count"
},
"sandbox": {
"backend": "macos-app-sandbox",
"outputDirectory": "",
"network": "denied",
"subprocesses": "denied"
}
}
The planner supplies fields declared by your schema. Kuttle also adds useful context such as prompt, activeApp, selectedPaths, finderPath, and browser metadata when available. Treat undeclared context as optional.
This zero-input tool uses only the Python standard library and returns JSON as a single stdout result.
import json
import sys
from datetime import datetime
def main():
_payload = json.loads(sys.stdin.read() or "{}")
now = datetime.now().astimezone()
print(json.dumps({
"result": now.strftime("%Y-%m-%d %H:%M:%S %Z"),
"iso": now.isoformat()
}))
if __name__ == "__main__":
main()
Suggested request: @kuttle run the current_date tool.
This example reads the text property declared in the earlier manifest, validates it, and returns a compact structured result.
import json
import sys
def main():
payload = json.loads(sys.stdin.read() or "{}")
tool_input = payload.get("input", {})
text = tool_input.get("text", "")
if not isinstance(text, str) or not text.strip():
raise ValueError("text must be a non-empty string")
result = {
"words": len(text.split()),
"characters": len(text),
"text": text
}
print(json.dumps(result))
if __name__ == "__main__":
main()
Suggested request: @kuttle use the word_count tool to count: One request. Your Mac gets to work.
tools.json and main.py in the same folder.Settings → Files
File actions are constrained by both operation policy and folder scope. A valid plan still fails if its path is outside an allowed root.
Choose which controlled operations are allowed, including read, list, summarize, create, write, append, and delete. Disabled operations are rejected before the file adapter runs.
Add each folder Kuttle may access. Authorize protected macOS folders once to store a security-scoped bookmark that survives relaunch. Remove a folder to revoke Kuttle policy access.
Chooses where video downloads and incoming Peer Sharing files are saved. The selected destination is also added to Allowed Folders so write policy stays enforceable.
Settings → Runtime
Set the maximum number of simultaneous prompts from 1 to 8. Internal agent calls, local processes, extraction, shell commands, and Python tools share this execution budget. Overflow stays in a persistent queue.
Choose how many recent chat messages appear and open the local folders for Kuttle data, agents, tools, conversations, generated media, peer shares, logs, and agent traces.
Inspect app version, Accessibility, Screen Recording, agent count, installed tools, provider keys, context-sharing state, integrations, and Peer Sharing. You can open logs, refresh state, quit, or quit and relaunch.
Control
These are separate decisions. macOS permission lets Kuttle access a system capability. Kuttle policy determines whether that capability is enabled. An approval, when required, applies to one exact action for one task.
Protected actions may include deletion, credential access, broad shell execution, externally visible changes, or actions classified as sensitive. Reading and writing inside an allowed folder may run without another prompt when policy classifies the exact action as low risk.
Local-first
When a task uses a model provider or connected service, the minimum required request data is sent to that provider under its terms. Disable a provider, integration, or context-sharing control to keep it out of future plans.
Support
Open Settings → General → General and enable Launch Kuttle at login. If the status says Review, open macOS System Settings → General → Login Items and allow Kuttle.
Enable it under Settings → Shortcuts → Keyboard Shortcuts. Then check Settings → Runtime → Diagnostics for Accessibility. Kuttle fails closed and does not install the global monitor without permission.
Add the containing folder under Settings → Files → Allowed Folders and choose Authorize. Confirm that the required operation is enabled under Permissions.
Keep the browser as the last active work app before opening Kuttle. Enable the supported browser context setting and verify Automation or Accessibility access when requested. Kuttle should never return a guessed URL.
Confirm the tool is under ~/kuttle/tools and includes tools.json plus main.py. Open Installed Tools and refresh discovery. Review logs if manifest validation fails.
Open the task and review the exact action. Approve and run only when the recipient, path, content, adapter, and operation are correct. Edited material should produce a new approval request.
Run the currently installed, consistently signed build and choose Always Allow only when you trust it. Rebuilding with a different signing identity can cause macOS to treat the binary as a different requester.
Open Settings → Runtime → Storage for every local data location, or Settings → Runtime → Diagnostics → Open Logs.
Still blocked?
Include the Kuttle version from Diagnostics and the relevant log entry. Never send API keys, OAuth tokens, peer private keys, or passwords.
Contact Kuttle support