docs(readme): drop em-dashes, Cursor→Codex, rename agent section (#274)

* docs(readme): drop em-dashes, Cursor→Codex, rename agent section

- Replace all 20 em-dashes with context-appropriate punctuation (colons,
  semicolons, parens, commas) — removes the AI-slop tell.
- Cursor → Codex (the agent-host examples and the MCP host list).
- "Drive it with an AI agent" → "Set it up with an AI agent".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(readme): wordmark header + simplify query examples

- Add the compact wordmark header (light/dark SVG, subtitle, nav row, restyled
  badges) from the header-redesign work; bring the wordmark assets with it.
- Rewrite the Query and mutate examples to lead with the short, config-default
  form (no repeated --server/--graph) and aliases — showing how simple it is,
  not crazy-long lines. The verbose --server/--graph/--store form is demoted to
  a one-line "ad-hoc target" note.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Andrew Altshuler 2026-06-17 02:36:14 +03:00 committed by GitHub
parent b55ca02131
commit b6131393b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 363 additions and 44 deletions

103
README.md
View file

@ -1,11 +1,29 @@
# Omnigraph
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="assets/omnigraph-wordmark-dark.svg">
<img alt="OMNIGRAPH" src="assets/omnigraph-wordmark.svg" width="420">
</picture>
</p>
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Rust](https://img.shields.io/badge/rust-stable-orange.svg)](rust-toolchain.toml)
[![Crates.io](https://img.shields.io/crates/v/omnigraph-cli.svg)](https://crates.io/crates/omnigraph-cli)
<p align="center">
<strong>Lakehouse graph database for context assembly &amp; multi-agent coordination</strong><br>
<sub>Multimodal retrieval · Git-style branching · object-storage native</sub>
</p>
**Lakehouse graph db for context assembly & multi-agent coordination**\
Multimodal retrieval, Git-style branching, object storage-native
<p align="center">
<a href="docs/user/quickstart.md">Quickstart</a> &nbsp;·&nbsp;
<a href="docs/user/clusters/index.md">Docs</a> &nbsp;·&nbsp;
<a href="https://github.com/ModernRelay/omnigraph-cookbooks">Cookbooks</a> &nbsp;·&nbsp;
<a href="docs/user/cli/reference.md">CLI</a>
</p>
<p align="center">
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-1b1b1f?style=flat-square&labelColor=1b1b1f"></a>
<a href="https://crates.io/crates/omnigraph-cli"><img alt="crates.io" src="https://img.shields.io/crates/v/omnigraph-cli?style=flat-square&color=d71921&labelColor=1b1b1f"></a>
<a href="rust-toolchain.toml"><img alt="Rust" src="https://img.shields.io/badge/rust-stable-1b1b1f?style=flat-square&labelColor=1b1b1f"></a>
</p>
<hr>
Omnigraph is the operational state and coordination layer for fleets of agents.\
Run it as a server, declared as code; hundreds of agents operate and enrich the graph on parallel isolated branches, and every change is reviewed and merged safely.
@ -18,7 +36,7 @@ Run it as a server, declared as code; hundreds of agents operate and enrich the
| **Built for fleets of agents** | Hundreds of agents enrich the graph on **parallel isolated branches**; changes are reviewed and merged safely, Git-style, across the whole graph. |
| **Multimodal retrieval** | Graph traversal + vector ANN + full-text + Reciprocal Rank Fusion in **one** query runtime, for context assembly. |
| **Security as code** | Cedar policy enforced **server-side on every mutation**, per-graph and server-wide; bearer auth; actor/audit tracking. |
| **Runs on your infrastructure** | Any S3-compatible object store **on-prem via RustFS / MinIO**, or AWS S3 / R2 / GCS. VPC, on-prem, hybrid; your data never leaves your store. |
| **Runs on your infrastructure** | Any S3-compatible object store: **on-prem via RustFS / MinIO**, or AWS S3 / R2 / GCS. VPC, on-prem, hybrid; your data never leaves your store. |
| **Open, versioned storage** | [`Lance`](https://github.com/lance-format/lance) columnar format: branchable, time-travelable, with native blob-as-data (docs, images, video). |
## What you can build
@ -26,7 +44,7 @@ Run it as a server, declared as code; hundreds of agents operate and enrich the
| Use case | What it's for |
|---|---|
| **Company brain** | Org knowledge unified into one graph every agent can query |
| **Agentic memory** | Durable, versioned memory a branch per agent or per task, merged on review |
| **Agentic memory** | Durable, versioned memory: a branch per agent or per task, merged on review |
| **Context graph** | Decision traces and codified tribal knowledge for retrieval |
| **Dev graph** | Issues & dependency model that coding agents read and write |
| **R&D / ML data layer** | Experiments and trials written into branches, versioned for training & eval |
@ -45,26 +63,26 @@ brew tap ModernRelay/tap
brew install ModernRelay/tap/omnigraph
```
## Drive it with an AI agent
## Set it up with an AI agent
Omnigraph is built to be run by coding agents — two ways in.
Omnigraph is built to be run by coding agents. Two ways in:
**Teach your agent the playbook.** This repo ships the
[**`omnigraph` agent skill**](skills/omnigraph): the operational playbook
cluster mode, the two config surfaces, schema evolution, query linting, data
writes, branches, Cedar policy, and the common gotchas.
[**`omnigraph` agent skill**](skills/omnigraph): the operational playbook
covering cluster mode, the two config surfaces, schema evolution, query linting,
data writes, branches, Cedar policy, and the common gotchas.
```bash
npx skills add ModernRelay/omnigraph@omnigraph
```
**Or have an agent set it up from scratch.** Paste this into Claude Code,
Cursor, or any agent that can read a URL and run a shell command:
Codex, or any agent that can read a URL and run a shell command:
```text
Help me set up Omnigraph
1. Read the docs at https://github.com/ModernRelay/omnigraph — start with
1. Read the docs at https://github.com/ModernRelay/omnigraph, starting with
docs/user/clusters/index.md, then docs/user/deployment.md.
2. Skim the starter graphs and seed data in the cookbooks:
https://github.com/ModernRelay/omnigraph-cookbooks
@ -80,7 +98,7 @@ is the fastest way to see Omnigraph shaped to a real domain.
## Deploy
A deployment is a **cluster** a **multigraph** config directory that declares
A deployment is a **cluster**: a **multigraph** config directory that declares
its graphs, schemas, stored queries, and policies as code. You manage it
**Terraform-style**: `cluster plan` previews the diff, `cluster apply` converges
it. `omnigraph-server` then boots from the cluster and brings every graph online
@ -92,7 +110,7 @@ at `/graphs/{id}/…`, each behind its own policy.
company-brain/
├── cluster.yaml
├── people.pg # schema for the "knowledge" graph
├── queries/ # stored queries the .gq files ARE the declaration
├── queries/ # stored queries: the .gq files ARE the declaration
│ └── people.gq
└── base.policy.yaml # a Cedar policy bundle
```
@ -113,20 +131,20 @@ policies:
applies_to: [knowledge] # graph-bound; use [cluster] for server-level
```
**2. Stand up your object store.** On-prem, run RustFS (or MinIO) Omnigraph
**2. Stand up your object store.** On-prem, run RustFS (or MinIO); Omnigraph
writes [Lance](https://github.com/lance-format/lance) to it over the standard S3
API. In the cloud, point the same `AWS_*` env at S3 / R2 / GCS instead.
**3. Converge and run.** `apply` creates each graph, applies its schema, and
publishes queries and policies into the content-addressed catalog. It is
idempotent re-running is always safe.
idempotent; re-running is always safe.
```bash
omnigraph cluster validate # parse + typecheck everything
omnigraph cluster plan # preview what apply would do
omnigraph cluster apply # converge
# Boot the server from the cluster dir storage resolves through cluster.yaml
# Boot the server from the cluster dir; storage resolves through cluster.yaml
omnigraph-server --cluster company-brain --bind 0.0.0.0:8080
```
@ -137,33 +155,30 @@ containers, AWS/Railway, auth, and the full `AWS_*` contract.
## Query and mutate
Point the CLI at a running server and a graph. Stored queries and mutations run
**by name** from the catalog; branch and merge run across the whole graph, so a
fleet of agents can write in isolation and have changes reviewed before they
land on `main`.
Set a default server and graph once in `~/.omnigraph/config.yaml`, and the
everyday commands stay short. Stored queries and mutations run **by name**:
```bash
# Stored query / mutation, parameters as JSON
omnigraph query search_docs --server https://graph.internal:8080 --graph knowledge --params '{"q":"AI safety"}'
omnigraph mutate add_person --server https://graph.internal:8080 --graph knowledge --params '{"name":"Mina","team":"Research"}'
omnigraph query search_docs --params '{"q":"AI safety"}'
omnigraph mutate add_person --params '{"name":"Mina"}'
# An agent enriches on its own branch; you review, then merge
omnigraph branch create --from main agent/ingest-42 --server https://graph.internal:8080 --graph knowledge
omnigraph branch merge agent/ingest-42 --into main --server https://graph.internal:8080 --graph knowledge
# Branch, review, merge across the whole graph; agents write in isolation
omnigraph branch create --from main agent/ingest-42
omnigraph branch merge agent/ingest-42 --into main
```
Name the server (and a default graph) once in `~/.omnigraph/config.yaml` — with
operator identity and credentials — and the `--server`/`--graph` flags drop
away: `omnigraph query search_docs --params '{"q":"…"}'`. See the
[CLI reference](docs/user/cli/reference.md).
An **alias** is shorter still: bind a server, graph, and stored query to one
name, then `omnigraph alias triage` runs it. For an ad-hoc target, any command
still takes `--server <name|url> --graph <id>` (or `--store <uri>` for a local
graph). See the [CLI reference](docs/user/cli/reference.md).
## Security & governance
- **Engine-wide enforcement** every write path goes through the same Cedar gate, so the HTTP server, the CLI, and the embedded SDK obey identical rules.
- **Declared in the cluster** a policy bundle is bound to graphs (or the whole server) via `policies:``applies_to`.
- **Scoped** rules apply per graph, per branch, or server-wide.
- **No plaintext tokens** bearer tokens are hashed at startup and compared in constant time.
- **Forge-proof identity** the actor is resolved server-side from the token; clients can't set it.
- **Engine-wide enforcement:** every write path goes through the same Cedar gate, so the HTTP server, the CLI, and the embedded SDK obey identical rules.
- **Declared in the cluster:** a policy bundle is bound to graphs (or the whole server) via `policies:``applies_to`.
- **Scoped:** rules apply per graph, per branch, or server-wide.
- **No plaintext tokens:** bearer tokens are hashed at startup and compared in constant time.
- **Forge-proof identity:** the actor is resolved server-side from the token; clients can't set it.
See the [policy guide](docs/user/operations/policy.md).
@ -172,16 +187,16 @@ See the [policy guide](docs/user/operations/policy.md).
| Client | Use it for | Where |
|---|---|---|
| **TypeScript SDK** | typed access from Node / TS | [`@modernrelay/omnigraph`](https://www.npmjs.com/package/@modernrelay/omnigraph) · [source](https://github.com/ModernRelay/omnigraph-ts) |
| **MCP server** | bridge Omnigraph to LLM hosts (Claude, Cursor, …) | [`@modernrelay/omnigraph-mcp`](https://www.npmjs.com/package/@modernrelay/omnigraph-mcp) |
| **HTTP / OpenAPI** | any language the wire contract | the server's OpenAPI spec |
| **MCP server** | bridge Omnigraph to LLM hosts (Claude, Codex, …) | [`@modernrelay/omnigraph-mcp`](https://www.npmjs.com/package/@modernrelay/omnigraph-mcp) |
| **HTTP / OpenAPI** | any language, the wire contract | the server's OpenAPI spec |
| **Python SDK** | typed access from Python | *coming soon* |
Both npm packages are versioned in lockstep with `omnigraph-server`.
## Local quick test (no server)
1-min setup to try it: an **embedded, local file-backed graph** no server, no
object store. For dev and experiments; production is the deployed cluster above.
1-min setup to try it: an **embedded, local file-backed graph** (no server, no
object store). For dev and experiments; production is the deployed cluster above.
```bash
cat > schema.pg <<'PG'
@ -229,7 +244,7 @@ Notes:
- `crates/omnigraph-policy`: Cedar policy compilation and enforcement
- `crates/omnigraph-api-types`: shared HTTP wire DTOs used by both the server and the CLI
- `crates/omnigraph-cluster`: cluster config validation, planning, and apply (the control plane)
- `crates/omnigraph-server`: Axum HTTP server cluster-first, runs N graphs under `/graphs/{id}/…`
- `crates/omnigraph-server`: Axum HTTP server, cluster-first, runs N graphs under `/graphs/{id}/…`
- `crates/omnigraph-cli`: CLI for graph lifecycle, query/mutate, branch/commit/merge, schema/lint, snapshot/export, cluster control, policy/queries, profiles, and maintenance
## Contributing

View file

@ -0,0 +1,152 @@
<svg xmlns="http://www.w3.org/2000/svg" width="757" height="113" viewBox="0 0 757 113" fill="#f5f5f5" role="img" aria-label="OMNIGRAPH">
<circle cx="28.6" cy="14.6" r="4.6"/>
<circle cx="42.6" cy="14.6" r="4.6"/>
<circle cx="56.6" cy="14.6" r="4.6"/>
<circle cx="14.6" cy="28.6" r="4.6"/>
<circle cx="70.6" cy="28.6" r="4.6"/>
<circle cx="14.6" cy="42.6" r="4.6"/>
<circle cx="70.6" cy="42.6" r="4.6"/>
<circle cx="14.6" cy="56.6" r="4.6"/>
<circle cx="70.6" cy="56.6" r="4.6"/>
<circle cx="14.6" cy="70.6" r="4.6"/>
<circle cx="70.6" cy="70.6" r="4.6"/>
<circle cx="14.6" cy="84.6" r="4.6"/>
<circle cx="70.6" cy="84.6" r="4.6"/>
<circle cx="28.6" cy="98.6" r="4.6"/>
<circle cx="42.6" cy="98.6" r="4.6"/>
<circle cx="56.6" cy="98.6" r="4.6"/>
<circle cx="98.6" cy="14.6" r="4.6"/>
<circle cx="154.6" cy="14.6" r="4.6"/>
<circle cx="98.6" cy="28.6" r="4.6"/>
<circle cx="112.6" cy="28.6" r="4.6"/>
<circle cx="140.6" cy="28.6" r="4.6"/>
<circle cx="154.6" cy="28.6" r="4.6"/>
<circle cx="98.6" cy="42.6" r="4.6"/>
<circle cx="126.6" cy="42.6" r="4.6"/>
<circle cx="154.6" cy="42.6" r="4.6"/>
<circle cx="98.6" cy="56.6" r="4.6"/>
<circle cx="126.6" cy="56.6" r="4.6"/>
<circle cx="154.6" cy="56.6" r="4.6"/>
<circle cx="98.6" cy="70.6" r="4.6"/>
<circle cx="154.6" cy="70.6" r="4.6"/>
<circle cx="98.6" cy="84.6" r="4.6"/>
<circle cx="154.6" cy="84.6" r="4.6"/>
<circle cx="98.6" cy="98.6" r="4.6"/>
<circle cx="154.6" cy="98.6" r="4.6"/>
<circle cx="182.6" cy="14.6" r="4.6"/>
<circle cx="238.6" cy="14.6" r="4.6"/>
<circle cx="182.6" cy="28.6" r="4.6"/>
<circle cx="196.6" cy="28.6" r="4.6"/>
<circle cx="238.6" cy="28.6" r="4.6"/>
<circle cx="182.6" cy="42.6" r="4.6"/>
<circle cx="196.6" cy="42.6" r="4.6"/>
<circle cx="238.6" cy="42.6" r="4.6"/>
<circle cx="182.6" cy="56.6" r="4.6"/>
<circle cx="210.6" cy="56.6" r="4.6"/>
<circle cx="238.6" cy="56.6" r="4.6"/>
<circle cx="182.6" cy="70.6" r="4.6"/>
<circle cx="224.6" cy="70.6" r="4.6"/>
<circle cx="238.6" cy="70.6" r="4.6"/>
<circle cx="182.6" cy="84.6" r="4.6"/>
<circle cx="224.6" cy="84.6" r="4.6"/>
<circle cx="238.6" cy="84.6" r="4.6"/>
<circle cx="182.6" cy="98.6" r="4.6"/>
<circle cx="238.6" cy="98.6" r="4.6"/>
<circle cx="280.6" cy="14.6" r="4.6"/>
<circle cx="294.6" cy="14.6" r="4.6"/>
<circle cx="308.6" cy="14.6" r="4.6"/>
<circle cx="294.6" cy="28.6" r="4.6"/>
<circle cx="294.6" cy="42.6" r="4.6"/>
<circle cx="294.6" cy="56.6" r="4.6"/>
<circle cx="294.6" cy="70.6" r="4.6"/>
<circle cx="294.6" cy="84.6" r="4.6"/>
<circle cx="280.6" cy="98.6" r="4.6"/>
<circle cx="294.6" cy="98.6" r="4.6"/>
<circle cx="308.6" cy="98.6" r="4.6"/>
<circle cx="364.6" cy="14.6" r="4.6"/>
<circle cx="378.6" cy="14.6" r="4.6"/>
<circle cx="392.6" cy="14.6" r="4.6"/>
<circle cx="350.6" cy="28.6" r="4.6"/>
<circle cx="406.6" cy="28.6" r="4.6"/>
<circle cx="350.6" cy="42.6" r="4.6"/>
<circle cx="350.6" cy="56.6" r="4.6"/>
<circle cx="378.6" cy="56.6" r="4.6"/>
<circle cx="392.6" cy="56.6" r="4.6"/>
<circle cx="406.6" cy="56.6" r="4.6"/>
<circle cx="350.6" cy="70.6" r="4.6"/>
<circle cx="406.6" cy="70.6" r="4.6"/>
<circle cx="350.6" cy="84.6" r="4.6"/>
<circle cx="406.6" cy="84.6" r="4.6"/>
<circle cx="364.6" cy="98.6" r="4.6"/>
<circle cx="378.6" cy="98.6" r="4.6"/>
<circle cx="392.6" cy="98.6" r="4.6"/>
<circle cx="406.6" cy="98.6" r="4.6"/>
<circle cx="434.6" cy="14.6" r="4.6"/>
<circle cx="448.6" cy="14.6" r="4.6"/>
<circle cx="462.6" cy="14.6" r="4.6"/>
<circle cx="476.6" cy="14.6" r="4.6"/>
<circle cx="434.6" cy="28.6" r="4.6"/>
<circle cx="490.6" cy="28.6" r="4.6"/>
<circle cx="434.6" cy="42.6" r="4.6"/>
<circle cx="490.6" cy="42.6" r="4.6"/>
<circle cx="434.6" cy="56.6" r="4.6"/>
<circle cx="448.6" cy="56.6" r="4.6"/>
<circle cx="462.6" cy="56.6" r="4.6"/>
<circle cx="476.6" cy="56.6" r="4.6"/>
<circle cx="434.6" cy="70.6" r="4.6"/>
<circle cx="462.6" cy="70.6" r="4.6"/>
<circle cx="434.6" cy="84.6" r="4.6"/>
<circle cx="476.6" cy="84.6" r="4.6"/>
<circle cx="434.6" cy="98.6" r="4.6"/>
<circle cx="490.6" cy="98.6" r="4.6"/>
<circle cx="532.6" cy="14.6" r="4.6"/>
<circle cx="546.6" cy="14.6" r="4.6"/>
<circle cx="560.6" cy="14.6" r="4.6"/>
<circle cx="518.6" cy="28.6" r="4.6"/>
<circle cx="574.6" cy="28.6" r="4.6"/>
<circle cx="518.6" cy="42.6" r="4.6"/>
<circle cx="574.6" cy="42.6" r="4.6"/>
<circle cx="518.6" cy="56.6" r="4.6"/>
<circle cx="532.6" cy="56.6" r="4.6"/>
<circle cx="546.6" cy="56.6" r="4.6"/>
<circle cx="560.6" cy="56.6" r="4.6"/>
<circle cx="574.6" cy="56.6" r="4.6"/>
<circle cx="518.6" cy="70.6" r="4.6"/>
<circle cx="574.6" cy="70.6" r="4.6"/>
<circle cx="518.6" cy="84.6" r="4.6"/>
<circle cx="574.6" cy="84.6" r="4.6"/>
<circle cx="518.6" cy="98.6" r="4.6"/>
<circle cx="574.6" cy="98.6" r="4.6"/>
<circle cx="602.6" cy="14.6" r="4.6"/>
<circle cx="616.6" cy="14.6" r="4.6"/>
<circle cx="630.6" cy="14.6" r="4.6"/>
<circle cx="644.6" cy="14.6" r="4.6"/>
<circle cx="602.6" cy="28.6" r="4.6"/>
<circle cx="658.6" cy="28.6" r="4.6"/>
<circle cx="602.6" cy="42.6" r="4.6"/>
<circle cx="658.6" cy="42.6" r="4.6"/>
<circle cx="602.6" cy="56.6" r="4.6"/>
<circle cx="616.6" cy="56.6" r="4.6"/>
<circle cx="630.6" cy="56.6" r="4.6"/>
<circle cx="644.6" cy="56.6" r="4.6"/>
<circle cx="602.6" cy="70.6" r="4.6"/>
<circle cx="602.6" cy="84.6" r="4.6"/>
<circle cx="602.6" cy="98.6" r="4.6"/>
<circle cx="686.6" cy="14.6" r="4.6"/>
<circle cx="742.6" cy="14.6" r="4.6"/>
<circle cx="686.6" cy="28.6" r="4.6"/>
<circle cx="742.6" cy="28.6" r="4.6"/>
<circle cx="686.6" cy="42.6" r="4.6"/>
<circle cx="742.6" cy="42.6" r="4.6"/>
<circle cx="686.6" cy="56.6" r="4.6"/>
<circle cx="700.6" cy="56.6" r="4.6"/>
<circle cx="714.6" cy="56.6" r="4.6"/>
<circle cx="728.6" cy="56.6" r="4.6"/>
<circle cx="742.6" cy="56.6" r="4.6"/>
<circle cx="686.6" cy="70.6" r="4.6"/>
<circle cx="742.6" cy="70.6" r="4.6"/>
<circle cx="686.6" cy="84.6" r="4.6"/>
<circle cx="742.6" cy="84.6" r="4.6"/>
<circle cx="686.6" cy="98.6" r="4.6"/>
<circle cx="742.6" cy="98.6" r="4.6"/>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

View file

@ -0,0 +1,152 @@
<svg xmlns="http://www.w3.org/2000/svg" width="757" height="113" viewBox="0 0 757 113" fill="#1b1b1f" role="img" aria-label="OMNIGRAPH">
<circle cx="28.6" cy="14.6" r="4.6"/>
<circle cx="42.6" cy="14.6" r="4.6"/>
<circle cx="56.6" cy="14.6" r="4.6"/>
<circle cx="14.6" cy="28.6" r="4.6"/>
<circle cx="70.6" cy="28.6" r="4.6"/>
<circle cx="14.6" cy="42.6" r="4.6"/>
<circle cx="70.6" cy="42.6" r="4.6"/>
<circle cx="14.6" cy="56.6" r="4.6"/>
<circle cx="70.6" cy="56.6" r="4.6"/>
<circle cx="14.6" cy="70.6" r="4.6"/>
<circle cx="70.6" cy="70.6" r="4.6"/>
<circle cx="14.6" cy="84.6" r="4.6"/>
<circle cx="70.6" cy="84.6" r="4.6"/>
<circle cx="28.6" cy="98.6" r="4.6"/>
<circle cx="42.6" cy="98.6" r="4.6"/>
<circle cx="56.6" cy="98.6" r="4.6"/>
<circle cx="98.6" cy="14.6" r="4.6"/>
<circle cx="154.6" cy="14.6" r="4.6"/>
<circle cx="98.6" cy="28.6" r="4.6"/>
<circle cx="112.6" cy="28.6" r="4.6"/>
<circle cx="140.6" cy="28.6" r="4.6"/>
<circle cx="154.6" cy="28.6" r="4.6"/>
<circle cx="98.6" cy="42.6" r="4.6"/>
<circle cx="126.6" cy="42.6" r="4.6"/>
<circle cx="154.6" cy="42.6" r="4.6"/>
<circle cx="98.6" cy="56.6" r="4.6"/>
<circle cx="126.6" cy="56.6" r="4.6"/>
<circle cx="154.6" cy="56.6" r="4.6"/>
<circle cx="98.6" cy="70.6" r="4.6"/>
<circle cx="154.6" cy="70.6" r="4.6"/>
<circle cx="98.6" cy="84.6" r="4.6"/>
<circle cx="154.6" cy="84.6" r="4.6"/>
<circle cx="98.6" cy="98.6" r="4.6"/>
<circle cx="154.6" cy="98.6" r="4.6"/>
<circle cx="182.6" cy="14.6" r="4.6"/>
<circle cx="238.6" cy="14.6" r="4.6"/>
<circle cx="182.6" cy="28.6" r="4.6"/>
<circle cx="196.6" cy="28.6" r="4.6"/>
<circle cx="238.6" cy="28.6" r="4.6"/>
<circle cx="182.6" cy="42.6" r="4.6"/>
<circle cx="196.6" cy="42.6" r="4.6"/>
<circle cx="238.6" cy="42.6" r="4.6"/>
<circle cx="182.6" cy="56.6" r="4.6"/>
<circle cx="210.6" cy="56.6" r="4.6"/>
<circle cx="238.6" cy="56.6" r="4.6"/>
<circle cx="182.6" cy="70.6" r="4.6"/>
<circle cx="224.6" cy="70.6" r="4.6"/>
<circle cx="238.6" cy="70.6" r="4.6"/>
<circle cx="182.6" cy="84.6" r="4.6"/>
<circle cx="224.6" cy="84.6" r="4.6"/>
<circle cx="238.6" cy="84.6" r="4.6"/>
<circle cx="182.6" cy="98.6" r="4.6"/>
<circle cx="238.6" cy="98.6" r="4.6"/>
<circle cx="280.6" cy="14.6" r="4.6"/>
<circle cx="294.6" cy="14.6" r="4.6"/>
<circle cx="308.6" cy="14.6" r="4.6"/>
<circle cx="294.6" cy="28.6" r="4.6"/>
<circle cx="294.6" cy="42.6" r="4.6"/>
<circle cx="294.6" cy="56.6" r="4.6"/>
<circle cx="294.6" cy="70.6" r="4.6"/>
<circle cx="294.6" cy="84.6" r="4.6"/>
<circle cx="280.6" cy="98.6" r="4.6"/>
<circle cx="294.6" cy="98.6" r="4.6"/>
<circle cx="308.6" cy="98.6" r="4.6"/>
<circle cx="364.6" cy="14.6" r="4.6"/>
<circle cx="378.6" cy="14.6" r="4.6"/>
<circle cx="392.6" cy="14.6" r="4.6"/>
<circle cx="350.6" cy="28.6" r="4.6"/>
<circle cx="406.6" cy="28.6" r="4.6"/>
<circle cx="350.6" cy="42.6" r="4.6"/>
<circle cx="350.6" cy="56.6" r="4.6"/>
<circle cx="378.6" cy="56.6" r="4.6"/>
<circle cx="392.6" cy="56.6" r="4.6"/>
<circle cx="406.6" cy="56.6" r="4.6"/>
<circle cx="350.6" cy="70.6" r="4.6"/>
<circle cx="406.6" cy="70.6" r="4.6"/>
<circle cx="350.6" cy="84.6" r="4.6"/>
<circle cx="406.6" cy="84.6" r="4.6"/>
<circle cx="364.6" cy="98.6" r="4.6"/>
<circle cx="378.6" cy="98.6" r="4.6"/>
<circle cx="392.6" cy="98.6" r="4.6"/>
<circle cx="406.6" cy="98.6" r="4.6"/>
<circle cx="434.6" cy="14.6" r="4.6"/>
<circle cx="448.6" cy="14.6" r="4.6"/>
<circle cx="462.6" cy="14.6" r="4.6"/>
<circle cx="476.6" cy="14.6" r="4.6"/>
<circle cx="434.6" cy="28.6" r="4.6"/>
<circle cx="490.6" cy="28.6" r="4.6"/>
<circle cx="434.6" cy="42.6" r="4.6"/>
<circle cx="490.6" cy="42.6" r="4.6"/>
<circle cx="434.6" cy="56.6" r="4.6"/>
<circle cx="448.6" cy="56.6" r="4.6"/>
<circle cx="462.6" cy="56.6" r="4.6"/>
<circle cx="476.6" cy="56.6" r="4.6"/>
<circle cx="434.6" cy="70.6" r="4.6"/>
<circle cx="462.6" cy="70.6" r="4.6"/>
<circle cx="434.6" cy="84.6" r="4.6"/>
<circle cx="476.6" cy="84.6" r="4.6"/>
<circle cx="434.6" cy="98.6" r="4.6"/>
<circle cx="490.6" cy="98.6" r="4.6"/>
<circle cx="532.6" cy="14.6" r="4.6"/>
<circle cx="546.6" cy="14.6" r="4.6"/>
<circle cx="560.6" cy="14.6" r="4.6"/>
<circle cx="518.6" cy="28.6" r="4.6"/>
<circle cx="574.6" cy="28.6" r="4.6"/>
<circle cx="518.6" cy="42.6" r="4.6"/>
<circle cx="574.6" cy="42.6" r="4.6"/>
<circle cx="518.6" cy="56.6" r="4.6"/>
<circle cx="532.6" cy="56.6" r="4.6"/>
<circle cx="546.6" cy="56.6" r="4.6"/>
<circle cx="560.6" cy="56.6" r="4.6"/>
<circle cx="574.6" cy="56.6" r="4.6"/>
<circle cx="518.6" cy="70.6" r="4.6"/>
<circle cx="574.6" cy="70.6" r="4.6"/>
<circle cx="518.6" cy="84.6" r="4.6"/>
<circle cx="574.6" cy="84.6" r="4.6"/>
<circle cx="518.6" cy="98.6" r="4.6"/>
<circle cx="574.6" cy="98.6" r="4.6"/>
<circle cx="602.6" cy="14.6" r="4.6"/>
<circle cx="616.6" cy="14.6" r="4.6"/>
<circle cx="630.6" cy="14.6" r="4.6"/>
<circle cx="644.6" cy="14.6" r="4.6"/>
<circle cx="602.6" cy="28.6" r="4.6"/>
<circle cx="658.6" cy="28.6" r="4.6"/>
<circle cx="602.6" cy="42.6" r="4.6"/>
<circle cx="658.6" cy="42.6" r="4.6"/>
<circle cx="602.6" cy="56.6" r="4.6"/>
<circle cx="616.6" cy="56.6" r="4.6"/>
<circle cx="630.6" cy="56.6" r="4.6"/>
<circle cx="644.6" cy="56.6" r="4.6"/>
<circle cx="602.6" cy="70.6" r="4.6"/>
<circle cx="602.6" cy="84.6" r="4.6"/>
<circle cx="602.6" cy="98.6" r="4.6"/>
<circle cx="686.6" cy="14.6" r="4.6"/>
<circle cx="742.6" cy="14.6" r="4.6"/>
<circle cx="686.6" cy="28.6" r="4.6"/>
<circle cx="742.6" cy="28.6" r="4.6"/>
<circle cx="686.6" cy="42.6" r="4.6"/>
<circle cx="742.6" cy="42.6" r="4.6"/>
<circle cx="686.6" cy="56.6" r="4.6"/>
<circle cx="700.6" cy="56.6" r="4.6"/>
<circle cx="714.6" cy="56.6" r="4.6"/>
<circle cx="728.6" cy="56.6" r="4.6"/>
<circle cx="742.6" cy="56.6" r="4.6"/>
<circle cx="686.6" cy="70.6" r="4.6"/>
<circle cx="742.6" cy="70.6" r="4.6"/>
<circle cx="686.6" cy="84.6" r="4.6"/>
<circle cx="742.6" cy="84.6" r="4.6"/>
<circle cx="686.6" cy="98.6" r="4.6"/>
<circle cx="742.6" cy="98.6" r="4.6"/>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB