Skip to content

Coming from Claude Code

Tatu reads several of Claude Code’s file formats on purpose, so a good part of what you wrote for Claude Code works here. This page says which part, what to change in the rest, and what does not exist.

The short version: Tatu never reads the .claude folders. You copy files into ~/.tatu or .tatu/. After that, CLAUDE.md files and their @path imports work as they are, skills work as they are, hooks work once you move them into Tatu’s settings and change the tool names, and subagents and slash commands need a small edit. A .mcp.json works as it is. Permissions and plugins do not exist.

What you have In Tatu Status
CLAUDE.md in the project read as instructions works as it is
@path imports inside a CLAUDE.md read the same way, relative to the file that holds them, up to four levels works as it is
~/.claude/CLAUDE.md not read; copy it to ~/.tatu/AGENTS.md or ~/.tatu/CLAUDE.md copy
.claude/skills/<name>/SKILL.md .tatu/skills/<name>/SKILL.md works after you copy it
.claude/commands/*.md .tatu/prompts/*.md works after you copy it, if it uses only the fields below
.claude/agents/*.md .tatu/agents/*.md needs tools and model changed
hooks in .claude/settings.json hooks in .tatu/settings.json needs the tool names changed
the rest of settings.json (permissions, env, …) none does not exist; it is an error
.mcp.json in the project read from the project folder; you trust the project once with /mcp trust works as it is
mcpServers of ~/.claude.json ~/.tatu/mcp.json works after you copy it
permissions, plugins none does not exist

Tatu reads AGENTS.md, and in a folder that has none it reads CLAUDE.md. It looks in ~/.tatu, in the folder you start in and in each parent folder, and in a subfolder when the model first reads or changes a file there. See AGENTS.md and /init.

What is different:

  • ~/.claude/CLAUDE.md and .claude/CLAUDE.md are not read. Put the file in the project’s root, or your personal one at ~/.tatu/AGENTS.md.
  • @path imports work as in Claude Code: a relative path is relative to the file that holds the reference, ~ is your home folder, and imports nest up to four levels. A path in backticks is not imported. Each imported file becomes a section of its own right after the file that imports it. See AGENTS.md and /init.
  • If a folder has both files, Tatu uses AGENTS.md and ignores CLAUDE.md, so a CLAUDE.md that only says @AGENTS.md is unnecessary.
  • It does not read CLAUDE.md files in folders below the one you started in.

Tatu uses the same layout: a folder with a SKILL.md. The fields name, description, disable-model-invocation and user-invocable mean the same here as they do in Claude Code. See Skills.

Copy the skills into Tatu’s folders:

Terminal window
mkdir -p ~/.tatu/skills
cp -R ~/.claude/skills/. ~/.tatu/skills/

For a project, copy .claude/skills into .tatu/skills in the same way.

What is different:

  • Every other field in the front matter is ignored without an error: allowed-tools, argument-hint, model, context, hooks and the rest. A skill that Claude Code limits with allowed-tools has no such limit in Tatu, because Tatu has no permissions.
  • The front matter is read by a small parser: key: value lines, quoted text, true and false, and > or | blocks. Indented lines under a key are skipped, so nested values are fine. A list written with - item at the left margin, under a key, makes Tatu ignore the whole skill, with a note at startup (frontmatter: line without a key). Indent the list, or delete the field.
  • Tatu fills in $1, $2, $@, $ARGUMENTS, ${1:-fallback} and ${@:2}. The rest of the body is sent as written, including any command snippets: Tatu does not run anything in a skill itself.
  • A skill without a description is ignored.

Files from .claude/commands/ have the shape of a prompt template: a Markdown file whose name is the command, with description and argument-hint in the front matter. Copy them to ~/.tatu/prompts/ (or .tatu/prompts/ in a project):

Terminal window
mkdir -p ~/.tatu/prompts
cp ~/.claude/commands/*.md ~/.tatu/prompts/

Only files directly in the folder are read, so commands that you grouped in subfolders must be moved up. Other front matter fields (allowed-tools, model) are ignored. Tatu fills in $ARGUMENTS, $1, $2 and the other placeholders listed in the prompt templates page; any other text is sent as written.

The hook format is the same: a hooks object with the event, a matcher, and a list of { "type": "command", "command": "...", "timeout": ... }. The input on standard input and the answers are the same too: session_id, cwd, hook_event_name, tool_name, tool_input, tool_use_id in; exit code 2 to block; hookSpecificOutput with updatedInput, permissionDecision: "deny" and additionalContext, or decision: "block", out. See Hooks.

The proof is the hook of RTK, which was written for Claude Code. Its rtk hook claude command works in Tatu without changes, and a test of Tatu runs it for real against a bash call. So “mostly work as they are” means this: the format and the protocol are the same, and you move the hooks and adjust a few things.

What you must change:

  1. Move the hooks object. Hooks go in ~/.tatu/settings.json or .tatu/settings.json, not in .claude/settings.json. Copy only the hooks object. Tatu stops with an error on any key it does not know, so a whole Claude Code settings file does not load:

    tatu: /home/ana/project/.tatu/settings.json: json: unknown field "permissions"
  2. Write the tool names in lowercase, as Tatu names them. A matcher must match the whole tool name and is case-sensitive, so a matcher "Bash" never matches Tatu’s bash: the hook is loaded and never runs. A script that tests tool_name == "Bash" has the same problem.

    Claude Code Tatu
    Bash bash
    Read read
    Write write
    Edit edit
    Grep grep
    Glob find
    Agent agent
    WebSearch web_search
    WebFetch web_fetch
  3. Check the keys of tool_input. They are Tatu’s own arguments. For read, write and edit the file is path, not file_path, and edit takes a list of edits. For bash the keys are command and timeout, in seconds. See Tools of the model.

  4. Use TATU_PROJECT_DIR. Tatu sets TATU_PROJECT_DIR and TATU_SESSION_ID for a hook. It does not set CLAUDE_PROJECT_DIR. The input also has no transcript_path or permission_mode.

  5. Set a timeout if you care. The default is 60 seconds.

What Tatu rejects, and so stops with an error when it starts:

  • an event other than PreToolUse, PostToolUse, SessionStart, UserPromptSubmit and Stop, for example SubagentStop or Notification:

    tatu: /home/ana/project/.tatu/settings.json: hooks: unknown event "SubagentStop" (use one of: PreToolUse, PostToolUse, SessionStart, UserPromptSubmit, Stop)
  • a hook type other than command, and extra fields on a hook, such as if:

    tatu: /home/ana/project/.tatu/settings.json: json: unknown field "if"
  • a matcher other than empty or * on UserPromptSubmit or Stop.

Remove those entries from the copy. JSON fields in a hook’s answer that Tatu does not know are ignored.

Files from .claude/agents/ have the same shape as custom subagents: description (required), tools, model, and the body as the instructions. Two fields usually need a change:

  • tools uses Tatu’s lowercase names, so Read, Grep, Glob, Bash becomes read, grep, find, bash. Names that Tatu does not know are ignored; if none is known, the subagent does not start.
  • model takes fast, balanced, main, inherit or provider/model. A value such as sonnet or opus makes Tatu skip the file, with a note at startup. Use balanced or anthropic/claude-sonnet-5-5, for example.

Other fields are ignored.

The mcpServers object of a .mcp.json file has the same shape here, so the file works as it is: command, args, env for a local server, type and url and headers for a remote one, and ${VAR} in the values. Tatu reads .mcp.json in the folder you start in (not in parent folders) and ~/.tatu/mcp.json. What is different:

  • Tatu does not ask about each server. The servers of a project’s .mcp.json start only after you trust the project once, with /mcp trust.

  • A server starts when the model first uses one of its tools, not when Tatu starts.

  • A server of "type": "sse" is not supported: use the server’s streamable HTTP address.

  • Tatu uses the tools of a server. It does not use its resources or prompts.

  • The command that adds a server works with tatu in place of claude: claude mcp add --transport http sentry https://mcp.sentry.dev/mcp becomes tatu mcp add --transport http sentry https://mcp.sentry.dev/mcp. The scope user means the same as global here, and local is also global, with a note: Tatu has no scope for one folder. -s project writes .mcp.json. tatu mcp add-json, remove, list and get are there too.

See MCP servers.

The files and the keys are different, and Tatu does not read .claude/settings.json. Unknown keys are an error. See Settings and the settings reference. MCP servers are not a setting: they have files of their own. There is no setting for plugins.