---
title: "Write a team profile: Kotharo"
version: v0.8.3
canonical: https://kotharo.com/docs/team-profile/
---

# Write a team profile

A team profile is a plugin named `kotharo-<team>` that holds one team's own settings and rules on top of the Kotharo core. It is the heaviest way to fit Kotharo to a team, so use the lightest one that does the job:

1. Bind a repo's tools with `/kotharo:setup`, which writes the repo's `### Toolchain` section.
2. Set a value for one repo, for you, or for all your repos with [/kotharo:config](https://kotharo.com/docs/config/).
3. Write a team profile, when several repos and several people share the same settings, rules or checks.

Put nothing in a profile that another team could use. That belongs in the core, through a pull request to Kotharo.

## Where it lives

A profile lives in the team's own repo, which is also its marketplace. It never ships in Kotharo's marketplace, since everyone who adds a marketplace sees its whole catalog.

## Layout

| Path | What it holds |
|---|---|
| `skills/team-profile/profile.toml` | Overrides for the core defaults |
| `skills/team-profile/SKILL.md` | Tells the team to load the profile at intake |
| `skills/team-profile/learning/` | Lessons for the team's own domain |
| `rules/00-rules.md` | Rules that add to or tighten the core rules |
| `hooks/hooks.json` | A `SessionStart` hook that loads those rules |
| `hooks/guardrail-rules.mjs` | Commands to refuse or hold for this team |
| `agents/` and `skills/` | Anything only this team needs |

### profile.toml

`profile.toml` overrides the core defaults. It must set `schema_version = 1` and the profile's `name`, and may set only other keys the core defines, with the same types. Arrays replace and tables merge. It covers tool bindings, gate reviewers, risk signals, lane stops, role tiers, limits and the [autonomy level](https://kotharo.com/docs/autonomy-levels/). For example:

```text
schema_version = 1
name = "kotharo-<team>"

[slots]
ticketing = ["jira"]

[roles.dev]
tier = "sonnet"

[autonomy]
level = "guided"
```

A profile can only tighten safety. It can set `guided` and add to `autonomy.ask`, but a looser level, a new `autonomy.allow` or a relaxed safety default such as `deploy.dev_auto_deploy = true` takes effect only from a lead's own `~/.claude/kotharo.toml` or a repo's committed `.claude/kotharo.toml`.

Check the file with the core's checker. Claude Code sets `CLAUDE_PLUGIN_ROOT` for the core's skills and hooks; in a terminal, set it to the folder the core is installed in first:

```
bash "${CLAUDE_PLUGIN_ROOT}/scripts/run-python" "${CLAUDE_PLUGIN_ROOT}/scripts/settings.py" check-profile <path to profile.toml>
```

### SKILL.md

`skills/team-profile/SKILL.md` tells the team to load `profile.toml` when it takes a ticket. Copy it from another team's profile, or write a short one that points at `profile.toml`.

### Rules

`rules/00-rules.md` holds rules that add to or tighten the core rules, such as the team's naming or the column that scopes tenant data. A `SessionStart` hook in `hooks/hooks.json` loads them into every session, so keep them short.

### Lessons

With [teaching mode](https://kotharo.com/docs/teaching-mode/) on, the team teaches from the core's lessons and the profile's own, in `skills/team-profile/learning/`: one TOML file per topic, in the format of the core's `learning/` files. A lesson with a core lesson's id replaces it. Check them with `kotharo teach check --profile <path to profile.toml>`. Lessons teach the craft, never a customer's code or data, so one holding an email address, a link or a secret is refused.

### Guardrails

`hooks/guardrail-rules.mjs` lists commands to refuse or hold for this team's own stacks, accounts and servers. A plugin can't load another plugin's files, so the profile also carries a copy of the core's `hooks/guardrails/` engine and `hooks/learning/guardrail-lesson.mjs`. The fields are listed in the core's `hooks/guardrail-rules.mjs`. Turn each kind on in one plugin only, so a command is never held twice. See [Guardrails](https://kotharo.com/docs/guardrails/).

## Publish and install

Add the team's marketplace once on each machine:

```
claude plugin marketplace add <owner>/<team-repo>
```

Then install the profile at project scope in each repo that uses it, so it is on for everyone who works there:

```
claude plugin install kotharo-<team>@<team marketplace> --scope project
```

`/kotharo:setup` finds the profile once it is enabled, and offers to install it when it finds one that isn't.

So everyone on a repo is offered the marketplace without adding it by hand, declare it in the repo's committed `.claude/settings.json`. `/kotharo:setup` offers to do this when it installs the profile:

```text
{
  "extraKnownMarketplaces": {
    "<team marketplace>": {
      "source": { "source": "github", "repo": "<owner>/<team-repo>" }
    }
  }
}
```

## Turn a profile off in one repo

To turn a profile off in one repo, for example where it was installed in user scope, add this to that repo's `.claude/settings.local.json`:

```text
{
  "enabledPlugins": {
    "kotharo-<team>@<team marketplace>": false
  }
}
```

Next: [FAQ](https://kotharo.com/docs/faq/). [All docs](https://kotharo.com/docs/)

Written for Kotharo v0.8.3.
