Configuration#
Check all available configs and its default values here.
Ways to configure#
There are multiples ways to configure ECA:
Convenient for users and multiple projects
~/.config/eca/config.json
{
"defaultBehavior": "plan"
}
Convenient for users
.eca/config.json
{
"defaultBehavior": "plan"
}
Convenient for editors
Client editors can pass custom settings when sending the initialize
request via the initializationOptions
object:
"initializationOptions": {
"defaultBehavior": "plan"
}
Via env var during server process spawn:
ECA_CONFIG='{"myConfig": "my_value"}' eca server
Providers / Models#
For providers and models configuration check the dedicated models section.
Tools#
MCP#
For MCP servers configuration, use the mcpServers
config, examples:
~/.config/eca/config.json
{
"mcpServers": {
"memory": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-memory"],
// optional
"env": {"FOO": "bar"}
}
}
}
~/.config/eca/config.json
{
"mcpServers": {
"cool-mcp": {
"url": "https://my-remote-mcp.com/mcp"
}
}
}
Approval / permissions#
By default, ECA ask to call any tool, but that's can easily be configureed in many ways via the toolCall approval
config.
You can configure the default behavior via byDefault
and/or configure a tool in ask
, allow
or deny
configs.
Check some examples:
{
"toolCall": {
"approval": {
"byDefault": "allow"
}
}
}
{
"toolCall": {
"approval": {
"byDefault": "allow",
"ask": {
"eca_editfile": {},
"my-mcp__my_tool": {}
}
}
}
}
{
"toolCall": {
"approval": {
// "byDefault": "ask", not needed as it's eca default
"allow": {
"eca": {},
"my-mcp": {}
}
}
}
}
argsMatchers
is a map of argument name by list of java regex.
{
"toolCall": {
"approval": {
"byDefault": "allow",
"allow": {
"eca_shell_command": {"argsMatchers": {"command": [".*rm.*",
".*mv.*"]}}
}
}
}
}
{
"toolCall": {
"approval": {
"byDefault": "allow",
"deny": {
"eca_shell_command": {"argsMatchers": {"command": [".*rm.*",
".*mv.*"]}}
}
}
}
}
Also check the plan
behavior which is safer.
The manualApproval
setting was deprecated and replaced by the approval
one without breaking changes
File Reading#
You can configure the maximum number of lines returned by the eca_read_file
tool:
{
"toolCall": {
"readFile": {
"maxLines": 1000
}
}
}
Default: 2000
lines
Custom Tools#
You can define your own command-line tools that the LLM can use. These are configured via the customTools
key in your config.json
.
The customTools
value is an object where each key is the name of your tool. Each tool definition has the following properties:
description
: A clear description of what the tool does. This is crucial for the LLM to decide when to use it.command
: An string representing the command and its static arguments.schema
: An object that defines the parameters the LLM can provide.properties
: An object where each key is an argument name.required
: An array of required argument names.
Placeholders in the format {{argument_name}}
within the command
string will be replaced by the values provided by the LLM.
~/.config/eca/config.json
{
"customTools": {
"web-search": {
"description": "Fetches the content of a URL and returns it in Markdown format.",
"command": "trafilatura --output-format=markdown -u {{url}}",
"schema": {
"properties": {
"url": {
"type": "string",
"description": "The URL to fetch content from."
}
},
"required": ["url"]
}
}
}
}
~/.config/eca/config.json
{
"customTools": {
"file-search": {
"description": "Finds files within a directory that match a specific name pattern.",
"command": "find {{directory}} -name {{pattern}}",
"schema": {
"properties": {
"directory": {
"type": "string",
"description": "The directory to start the search from."
},
"pattern": {
"type": "string",
"description": "The search pattern for the filename (e.g., '*.clj')."
}
},
"required": ["directory", "pattern"]
}
}
}
}
Custom command prompts#
You can configure custom command prompts for project, global or via commands
config pointing to the path of the commands.
Prompts can use variables like $ARGS
, $ARG1
, ARG2
, to replace in the prompt during command call.
A .eca/commands
folder from the workspace root containing .md
files with the custom prompt.
.eca/commands/check-performance.md
Check for performance issues in $ARG1 and optimize if needed.
A $XDG_CONFIG_HOME/eca/commands
or ~/.config/eca/commands
folder containing .md
files with the custom command prompt.
~/.config/eca/commands/check-performance.md
Check for performance issues in $ARG1 and optimize if needed.
Just add to your config the commands
pointing to .md
files that will be searched from the workspace root if not an absolute path:
{
"commands": [{"path": "my-custom-prompt.md"}]
}
Rules#
Rules are contexts that are passed to the LLM during a prompt and are useful to tune prompts or LLM behavior.
Rules are text files (typically .md
, but any format works) with the following
optional metadata:
description
: a description used by LLM to decide whether to include this rule in context, absent means always include this rule.globs
: list of globs separated by,
. When present the rule will be applied only when files mentioned matches those globs.
There are 3 possible ways to configure rules following this order of priority:
A .eca/rules
folder from the workspace root containing .md
files with the rules.
.eca/rules/talk_funny.md
---
description: Use when responding anything
---
- Talk funny like Mickey!
A $XDG_CONFIG_HOME/eca/rules
or ~/.config/eca/rules
folder containing .md
files with the rules.
~/.config/eca/rules/talk_funny.md
---
description: Use when responding anything
---
- Talk funny like Mickey!
Just add toyour config the :rules
pointing to .md
files that will be searched from the workspace root if not an absolute path:
{
"rules": [{"path": "my-rule.md"}]
}
Behaviors / prompts#
ECA allows to totally customize the prompt sent to LLM via the behavior
config, allowing to have multiple behaviors for different tasks or workflows.
{
"behavior": {
"my-behavior": {
"systemPromptFile": "/path/to/my-behavior-prompt.md"
}
}
}
All configs#
interface Config {
providers?: {[key: string]: {
api?: 'openai-responses' | 'openai-chat' | 'anthropic';
url?: string;
urlEnv?: string;
key?: string; // when provider supports api key.
keyEnv?: string;
completionUrlRelativePath?: string;
models: {[key: string]: {
extraPayload?: {[key: string]: any}
}};
}};
defaultModel?: string;
rules?: [{path: string;}];
commands?: [{path: string;}];
behavior?: {[key: string]: {
systemPromptFile?: string;
defaultModel?: string;
disabledTools?: string[];
toolCall?: {
approval?: {
byDefault?: 'ask' | 'allow' | 'deny';
allow?: {[key: string]: {argsMatchers?: {[key: string]: string[]}}};
ask?: {[key: string]: {argsMatchers?: {[key: string]: string[]}}};
deny?: {[key: string]: {argsMatchers?: {[key: string]: string[]}}};
};
};
}};
customTools?: {[key: string]: {
description: string;
command: string;
schema: {
properties: {[key: string]: {
type: string;
description: string;
}};
required: string[];
};
}};
disabledTools?: string[],
toolCall?: {
approval?: {
byDefault: 'ask' | 'allow';
allow?: {{key: string}: {argsMatchers?: {{[key]: string}: string[]}}},
ask?: {{key: string}: {argsMatchers?: {{[key]: string}: string[]}}},
deny?: {{key: string}: {argsMatchers?: {{[key]: string}: string[]}}},
};
readFile?: {
maxLines?: number;
};
};
mcpTimeoutSeconds?: number;
lspTimeoutSeconds?: number;
mcpServers?: {[key: string]: {
url?: string; // for remote http-stremable servers
command?: string; // for stdio servers
args?: string[];
disabled?: boolean;
}};
defaultBehavior?: string;
welcomeMessage?: string;
compactPromptFile?: string;
index?: {
ignoreFiles: [{
type: string;
}];
repoMap?: {
maxTotalEntries?: number;
maxEntriesPerDir?: number;
};
};
}
{
"providers": {
"openai": {"key": null,
"url": "https://api.openai.com"},
"anthropic": {"key": null,
"url": "https://api.anthropic.com"},
"github-copilot": {"url": "https://api.githubcopilot.com"},
"ollama": {"url": "http://localhost:11434"}
},
"defaultModel": null, // let ECA decides the default model.
"rules" : [],
"commands" : [],
"disabledTools": [],
"toolCall": {
"approval": {
"byDefault": "ask",
"allow": {"eca_directory_tree": {},
"eca_read_file": {},
"eca_grep": {},
"eca_preview_file_change": {},
"eca_editor_diagnostics": {}},
"ask": {},
"deny": {}
},
"readFile": {
"maxLines": 2000
}
},
"mcpTimeoutSeconds" : 60,
"lspTimeoutSeconds" : 30,
"mcpServers" : {},
"behavior" {
"agent": {"systemPromptFile": "prompts/agent_behavior.md",
"disabledTools": ["eca_preview_file_change"]},
"plan": {"systemPromptFile": "prompts/plan_behavior.md",
"disabledTools": ["eca_edit_file", "eca_write_file", "eca_move_file"],
"toolCall": {"approval": {"deny": {"eca_shell_command":
{"argsMatchers": {"command" [".*>.*",
".*\\|\\s*(tee|dd|xargs).*",
".*\\b(sed|awk|perl)\\s+.*-i.*",
".*\\b(rm|mv|cp|touch|mkdir)\\b.*",
".*git\\s+(add|commit|push).*",
".*npm\\s+install.*",
".*-c\\s+[\"'].*open.*[\"']w[\"'].*",
".*bash.*-c.*>.*"]}}}}}}
}
"defaultBehavior": "agent",
"welcomeMessage" : "Welcome to ECA!\n\nType '/' for commands\n\n",
"compactPromptFile": "prompts/compact.md",
"index" : {
"ignoreFiles" : [ {
"type" : "gitignore"
} ],
"repoMap": {
"maxTotalEntries": 800,
"maxEntriesPerDir": 50
}
}
}