# Basic API







This page introduces katachi's core API.
Once you know these, you should understand the basics of using katachi.

## 1. `architecture { }`

`architecture { }` is the entry point for defining your project's overall architecture.
Inside it, you write the roles of the files that exist in your project.

```kt
architecture {
  "UseCase" { /* ... */ }
  "RepositoryInterface" { /* ... */ }
}
// This project has two roles: `UseCase` and `RepositoryInterface`
```

The elements inside an architecture (Role) are covered in more depth in a later section.

## 2. Testing the architecture with `assert()`

`assert()` is the function that tests the architecture defined with `architecture { }`.

```kt {8}
val projectArchitecture = architecture {
  "UseCase" { /* ... */ }
  "RepositoryInterface" { /* ... */ }
}

@Test
fun `files are placed according to the architecture`() {
  projectArchitecture.assert()
}
```

## 3. Declaring a Role with `"Name" { }`

`"Name" { }` declares the role that a file appearing in the project plays.

```kt {2,4}
architecture {
  "UseCase" { /* ... */ }

  "RepositoryInterface" { /* ... */ }
}
```

Writing `"Name" { }` inside an `architecture { }` block lets you declare the roles of files that appear in the project.

### Example roles

If you're using a well-known architecture, roles typically look something like this.

| Architecture | Role |
|---|---|
| MVC | `Controller` |
| | `View` |
| | `Model` |
| MVVM | `View` |
| | `ViewModel` |
| Clean architecture | `Service` |
| | `UseCase` |
| | `Entity` |
| | `RepositoryInterface`, `RepositoryImplementation` |

### Deny by default

In katachi, **only files with a declared Role are allowed to exist in the project**.

In other words, adopting katachi requires you to enumerate the Roles that match your project's conventions.

### Related documentation

For Role, also see [Role definitions in depth](/katachi/guides/role/).

## 4. Grouping Roles with `"...".group { }`

`"Name".group { }` is a block for grouping Roles together.

For example, in Clean architecture, `UseCase` and `RepositoryInterface` are both **roles in the same domain layer**.

```kt {2}
architecture {
  "domain".group {
    "UseCase" { /* ... */ }
    "RepositoryInterface" { /* ... */ }
  }
}
```

Expressing a group like "the domain layer" in the DSL makes the relationships and hierarchy between roles clear. Grouping Roles at a sensible granularity is important for building an architecture definition that's easy to understand.

### Related documentation

For grouping Roles, also see [Role definitions in depth](/katachi/guides/role/).

## 5. Defining where files may exist with `layout { }`

Declaring a Role with `"..." { }` alone doesn't decide where that Role's files may be placed.

`layout { }` is the block that defines where the files for a Role may be placed.

```kt {3-4}
architecture {
  "UseCase" {
    layout {
      "src/main/kotlin/com/example/useCase" / "*UseCase".ktFile()
    }
  }
}

// A UseCase may be placed at `src/main/kotlin/com/example/useCase/*UseCase.kt`
```

### How it works

Under the Deny by default principle, you can't place a file anywhere that isn't declared in `layout { }`.

Say an AI Agent tries to place a new UseCase file at `src/main/kotlin/com/example/GetItemUseCase.kt` (it should really go inside the useCase package). The moment `assert()` is called, katachi detects that no Role matches this path, and the test fails.

<FileTree>
- src/main/kotlin/com/example/
  - **GetItemUseCase.kt** ❌ a place not declared in `layout { }`
  - useCase/
    - GetUserUseCase.kt ⭐️ where the declaration puts it
</FileTree>

### Related documentation

For `layout { }`, also see [Layout definitions in depth](/katachi/guides/layout/).

## 6. Constraining a file's contents with `"...".konsist { }`

You can set constraints on the files of a declared Role using [Konsist](https://docs.konsist.lemonappdev.com/).

```kt {7}
architecture {
  "UseCase" {
    layout {
      "src/main/kotlin/com/example/useCase" / "*UseCase".ktFile()
    }

    "has exactly one invoke function".konsist {
      classes().must { it.functions().map { f -> f.name } == listOf("invoke") }
    }
  }
}
```

The constraints apply to the files specified in `layout { }`, and the constraints themselves are written with the Konsist API.

To check the constraints, call `assert(FileConstraintCheck())` instead of `assert()` in the test. With `assert()` alone the constraints are not evaluated, and the test fails with `[UncheckedFileConstraint]`.

### Related documentation

For `"...".konsist { }`, also see the [Konsist integration guide](/katachi/guides/konsist-integration/).

## Summary

<table>
  <tr>
    <th>API</th>
    <th style="min-width: 12rem">What it does</th>
    <th>Example</th>
  </tr>

  <tr>
    <td>
      ```kt
      architecture { }
      ```
    </td>
    <td>
      The function that serves as the entry point for defining your project's overall architecture.
    </td>
    <td>
      ```kt nocollapse
      architecture {
        "UseCase" { /* ... */ }
      }
      ```

      - Meaning: this project has a role called `UseCase`
    </td>
  </tr>

  <tr>
    <td>
      ```kt
      assert()
      ```
    </td>
    <td>
      Checks whether files are placed according to the definition. It's a single line called from a test — without it, nothing happens.
    </td>
    <td>
      ```kt nocollapse
      @Test
      fun `placement follows the definition`() {
        projectArchitecture.assert()
      }
      ```

      - Meaning: the test fails if there's a violation. A single run collects every violation and puts them in one message
    </td>
  </tr>

  <tr>
    <td>
      ```kt
      "Name" { }
      ```
    </td>
    <td>
      Declares the role (Role) of a file that appears in the project.
    </td>
    <td>
      ```kt nocollapse
      "UseCase" {
        layout { /* ... */ }
      }
      ```

      - Meaning: there's a role called `UseCase`. Files for undeclared roles can't be placed
    </td>
  </tr>

  <tr>
    <td>
      ```kt
      "Name".group { }
      ```
    </td>
    <td>
      Groups Roles together to build a hierarchy. Optional — Roles work fine without it.
    </td>
    <td>
      ```kt nocollapse
      "domain".group {
        "UseCase" { /* ... */ }
      }
      ```

      - Meaning: `UseCase` is a role in the domain layer. Its qualified name becomes `domain.UseCase`
    </td>
  </tr>

  <tr>
    <td>
      ```kt
      layout { }
      ```
    </td>
    <td>
      Defines where that Role's files may be placed.
    </td>
    <td>
      ```kt nocollapse
      layout {
        "domain/useCase" /
          "*UseCase".ktFile()
      }
      ```

      - Meaning: it can only be placed at `domain/useCase/*UseCase.kt`. Anywhere else is a violation
    </td>
  </tr>

  <tr>
    <td>
      ```kt
      "Name".konsist { }
      ```
    </td>
    <td>
      Constrains the contents of that Role's files. Requires the separate `katachi-konsist` module and `assert(FileConstraintCheck())` in the test.
    </td>
    <td>
      ```kt nocollapse
      "has exactly one invoke".konsist {
        classes().must { /* condition */ }
      }
      ```

      - Meaning: a file that doesn't satisfy this is a violation. **The constraint name appears directly in the violation report**
    </td>
  </tr>
</table>

## Next steps

- [Your first architecture definition](/katachi/get-started/first-architecture/) ... Introduce katachi into your project and actually write these six things.
- [Role](/katachi/guides/role/) ... Learn how to write descriptions for roles, and how to keep the definition from becoming a copy of your directory structure.
- [Layout](/katachi/guides/layout/) ... Learn how to write out placements, and when to reach for the deny-by-default escape hatches `anyFile()` / `ignore()`.