Issho

Issho β€” Collaboration for Phoenix

Issho (δΈ€η·’, "together") is an open-source collaboration toolkit for Phoenix that makes it easier to build applications where people and AI agents work together in real time.

It provides the shared foundations (rooms, participants, presence, authorization, documents, synchronization and agent participation), so that developers can focus on their applications instead of rebuilding collaboration features. Bring your own components, your own agents and your own application logic.

Issho owns collaboration semantics. Applications and component libraries own their behavior and presentation.

Status: early release. Rooms, documents, LiveView sessions, grants, the browser client, the people list and theme, the page's pointers and following, agents however they connect (MCP, your app's own model) and how they move, undo across a page, blocks of other rooms in a page (live embeds), and the bindings of Kotoba, Hakushi and Masu are here. Before 1.0, a minor version may change the API; see the roadmap for what comes next.

Live collaboration in the Hattori libraries is Issho's: Kotoba's shared editing (from 0.6), Masu's grids' people (from 0.4) and Hakushi's canvases. Each library works on its own without it; with it, a page of them has one connection, one list of people, one policy, and agents that work across all of them.

Installation

def deps do
  [
    {:issho, "~> 0.2"}
  ]
end

Issho needs Elixir 1.18 or later, Phoenix 1.7.14 or later and, for Issho.Live, Phoenix LiveView 1.1 or later.

It gives your app:

A sketch

# In your supervision tree, after the PubSub:
{Issho,
 name: MyApp.Issho,
 pubsub: MyApp.PubSub,
 endpoint: MyAppWeb.Endpoint,
 policy: MyApp.Collaboration,
 store: {MyApp.CollabStore, MyApp.Repo}}
defmodule MyApp.Collaboration do
  @behaviour Issho.Policy

  @impl true
  def authorize(who, "board:" <> id, action),
    do: if(MyApp.Boards.allowed?(who.claims["user_id"], id, action), do: :ok, else: {:error, :forbidden})

  @impl true
  def document(_who, "board:" <> id),
    do: {:ok, %{engine: Issho.Engine.Map, initial: MyApp.Boards.content(id)}}
end
# A channel on a socket of your endpoint:
defmodule MyAppWeb.IsshoChannel do
  use Issho.Channel, instance: MyApp.Issho
end

# A LiveView signs the browser's join token:
token = Issho.Token.sign(MyApp.Issho, current_user, "board:42",
  can: :write, claims: %{"user_id" => current_user.id})
<%!-- With `import Issho.Components` in your app's html_helpers: the room's
     people, and everyone's pointer over the page. --%>
<.people id="people" grant={@grant} />
<.pointers id="pointers" grant={@grant} />
# An agent joins the same room:
{:ok, claude} = Issho.join_as(MyApp.Issho, agent, "board:42", on_behalf_of: current_user)
{:ok, _doc} = Issho.Participant.open(claude, "board:42")
{:ok, _receipt} = Issho.Participant.transact(claude, "board:42", ops)

In the browser

import { joinRoom } from "issho"

const room = await joinRoom("board:42", { token, self: "user:ada" })
const doc = await room.open("board:42")

doc.on((event) => event.type === "change" && render(event.state))
doc.change([{ op: "set", path: ["title"], value: "Q3 plan" }])

room.aware({ place: { doc: "board:42", at: { path: ["title"] } } })
room.awareness.on((peers) => drawCursors(peers))
room.presence.on(() => drawPeople(room.presence.others))

Roadmap

Three priorities first, because they prove Issho's promise most directly: components from anyone working together on one page, ordinary Phoenix developers building collaborative features without designing a document engine, and agents as participants everywhere.

1. The component contract, for every author

Kotoba, Masu and Hakushi are built on Issho, but another author should not have to copy their patterns to do the same. The contract between a component and Issho (its engine and places, locate and point, following, motion, agents' tools, releasing a room, a block of another room) becomes the center:

2. Developer experience, and shared state without an engine

An ordinary Phoenix developer should build a collaborative checklist or kanban board in an afternoon, without designing a document engine:

3. Agents through everything

Agents are participants of every room, with presence, places, motion and tools, under the same policy as people. What makes that foundational, before any agent chat interface:

Next, on that foundation

Later, on purpose

Useful, but they do not prove the central promise as directly as components working together do, and they are easy to get wrong early:

What stays Issho's

The server decides every change, and your policy and checks always win. Issho is LiveView's: components, not a hosted SDK. It runs in your app, and your database is the truth. Agents are participants of the room, with presence, motion and tools, as people are.

Development

mix deps.get
npm ci --prefix assets
mix test        # includes the end-to-end test of the client on a real endpoint
mix test.js     # the browser client's unit tests
mix precommit   # compile with warnings as errors, format, credo, test
MIX_ENV=dev mix issho.build   # the bundles, into priv/static

License

MIT. See LICENSE.