logomarks 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/README.md +10 -2
- package/docs/api.md +9 -2
- package/docs/commands.md +19 -3
- package/docs/data.md +84 -0
- package/docs/mcp.md +3 -3
- package/package.json +9 -9
- package/src/brand/mark.js +2 -2
- package/src/cli/commands/combine.d.ts +2 -0
- package/src/cli/commands/combine.js +3 -0
- package/src/cli/commands/cover.d.ts +2 -0
- package/src/cli/commands/cover.js +3 -0
- package/src/cli/commands/edit.d.ts +2 -0
- package/src/cli/commands/edit.js +3 -0
- package/src/cli/commands/find.d.ts +2 -0
- package/src/cli/commands/find.js +4 -1
- package/src/cli/commands/get.d.ts +2 -0
- package/src/cli/commands/get.js +4 -1
- package/src/cli/commands/glitch.d.ts +2 -0
- package/src/cli/commands/glitch.js +3 -0
- package/src/cli/commands/index.d.ts +5 -3
- package/src/cli/commands/index.js +2 -1
- package/src/cli/commands/kit.d.ts +2 -0
- package/src/cli/commands/kit.js +3 -0
- package/src/cli/commands/mcp.d.ts +3 -2
- package/src/cli/commands/mcp.js +7 -3
- package/src/cli/commands/mockup.d.ts +2 -0
- package/src/cli/commands/mockup.js +3 -0
- package/src/cli/commands/parts.d.ts +2 -0
- package/src/cli/commands/parts.js +3 -0
- package/src/cli/commands/sheet.d.ts +2 -0
- package/src/cli/commands/sheet.js +3 -0
- package/src/cli/commands/similar.d.ts +2 -0
- package/src/cli/commands/similar.js +5 -2
- package/src/cli/commands/social.d.ts +2 -0
- package/src/cli/commands/social.js +3 -0
- package/src/cli/commands/update.d.ts +10 -0
- package/src/cli/commands/update.js +54 -0
- package/src/cli/help.js +1 -0
- package/src/cli/index.d.ts +6 -0
- package/src/cli/index.js +14 -3
- package/src/cli/options.js +3 -0
- package/src/find/index.d.ts +1 -1
- package/src/find/index.js +3 -3
- package/src/index.d.ts +3 -1
- package/src/index.js +4 -1
- package/src/live/build.d.ts +36 -0
- package/src/live/build.js +55 -0
- package/src/live/cache.d.ts +25 -0
- package/src/live/cache.js +75 -0
- package/src/live/current.d.ts +9 -0
- package/src/live/current.js +54 -0
- package/src/live/ensure.d.ts +43 -0
- package/src/live/ensure.js +92 -0
- package/src/live/errors.d.ts +16 -0
- package/src/live/errors.js +19 -0
- package/src/live/format.d.ts +13 -0
- package/src/live/format.js +113 -0
- package/src/live/index.d.ts +7 -0
- package/src/live/index.js +12 -0
- package/src/live/paths.d.ts +17 -0
- package/src/live/paths.js +64 -0
- package/src/live/remote.d.ts +24 -0
- package/src/live/remote.js +109 -0
- package/src/mcp/index.d.ts +5 -3
- package/src/mcp/index.js +26 -13
- package/src/mcp/tools/find.js +2 -2
- package/src/sheet/index.d.ts +1 -1
- package/src/similar/folder.js +2 -2
- package/src/similar/nearest.d.ts +1 -1
- package/src/similar/store.d.ts +9 -6
- package/src/similar/store.js +23 -62
- package/data/index.bin +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,50 @@ All notable changes to `logomarks` are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [2.0.0] — 2026-11-07
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **Breaking: the set is fetched, not bundled.** The package no longer ships the marks (`data/index.bin`, 3 MB). On
|
|
15
|
+
first use the CLI and the MCP server download the set from `https://logomarks.ai/cli/index.bin`, check it against
|
|
16
|
+
the manifest's sha256 (`/cli/index.json`), and cache it in the user cache folder (`$XDG_CACHE_HOME/logomarks`,
|
|
17
|
+
`~/Library/Caches/logomarks` on macOS, `%LOCALAPPDATA%\logomarks\Cache` on Windows, `~/.cache/logomarks`
|
|
18
|
+
elsewhere). The first run needs the network; after that it works offline. A new drop on the site reaches the CLI
|
|
19
|
+
without a new release: the manifest is checked at most once a day. The package is about 470 kB (from 3.5 MB).
|
|
20
|
+
- **Breaking: library use.** Call `await ensureIndex()` before the functions that read the live set (`findMarks`,
|
|
21
|
+
`similar`, `sheet`, `loadMark` by slug …); without it `loadIndex()` reads `LOGOMARKS_INDEX` or the cache, and throws
|
|
22
|
+
an `IndexError` when there's neither. `writeIndex` takes a file (there's no bundled path, `INDEX_FILE`, any more).
|
|
23
|
+
- **Node 22 or later** (global `fetch`).
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- **`logomarks update`** downloads the latest set now.
|
|
28
|
+
- **`--offline`** on every command, and `LOGOMARKS_OFFLINE=1`: the cache alone, never the network. `LOGOMARKS_INDEX`
|
|
29
|
+
uses a local index file; `LOGOMARKS_INDEX_URL` downloads from elsewhere.
|
|
30
|
+
- **A format version** in the index's manifest and header (`INDEX_FORMAT`, 3): a CLI refuses a format it doesn't read
|
|
31
|
+
and says to update, so it never misreads a newer file.
|
|
32
|
+
- **Clear errors** (`IndexError`, with a `code`): no network and nothing cached, offline with nothing cached, a bad
|
|
33
|
+
checksum (nothing is saved), a newer format. With a cached set, a failed check warns and uses the cache.
|
|
34
|
+
- **`buildIndex`**, which builds the index and its manifest (the site serves them), `ensureIndex`, `cacheDir`,
|
|
35
|
+
`encodeIndex` and `decodeIndex`, with TypeScript declarations. Docs: `docs/data.md`.
|
|
36
|
+
|
|
37
|
+
## [1.1.0] — 2026-11-07
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- **Drops 20–25.** The bundled index holds 4,115 marks (from 3,797): font editions, the future-industries round
|
|
42
|
+
(cybersecurity, data centres, smart home, quantum, longevity, hydrogen, carbon removal, circular economy, vertical
|
|
43
|
+
farming, battery storage), wellness and Thailand. `find` reaches the ten new industry pages.
|
|
44
|
+
- **Find by subject.** The bundled index carries each mark's `subject` (what it depicts: letter, animal, food-drink …),
|
|
45
|
+
and `find` matches its label words as the site does ("buildings", "food").
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- **On `@logomarks/core` ^0.1.8:** shape tags (round, square, wide, tall, symmetric, radial, solid, light) are measured
|
|
50
|
+
from each mark's geometry, so `find round` and the shape filters agree with the site.
|
|
51
|
+
|
|
8
52
|
## [1.0.0] — 2026-11-06
|
|
9
53
|
|
|
10
54
|
The first public release (0.2.0 was never published).
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# logomarks
|
|
2
2
|
|
|
3
|
-
Find, check, edit and build on free geometric logomarks from the command line or an AI agent.
|
|
3
|
+
Find, check, edit and build on free geometric logomarks from the command line or an AI agent. It searches the [Logomarks](https://logomarks.ai) set (CC0), checks marks against the set's house rules, edits and glitches them, and builds a brand kit, social pack, mockups and covers. It also runs as an MCP server. Pure JavaScript (resvg in WebAssembly), no native binaries, Node 22 or later.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npx logomarks find coffee
|
|
@@ -19,7 +19,14 @@ npx logomarks kit hex-gem --name "Hexa Labs" --color '#ff5c3a' -o hexa/
|
|
|
19
19
|
npx logomarks mockup hex-gem --name "Hexa Labs" --object card -o card.png
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
Also `specks`, `sheet`, `parts`, `combine`, `social`, `cover` and `
|
|
22
|
+
Also `specks`, `sheet`, `parts`, `combine`, `social`, `cover`, `mcp` and `update`. Run `logomarks --help` for the list and `logomarks <command> --help` for a command's options. A mark is a live slug or name, or the path to your own `.svg`. Every edit comes back fitted to the grid and checked. Every command takes `--json`. Exit codes: 0 ok, 1 a check failed or the command failed, 2 usage.
|
|
23
|
+
|
|
24
|
+
## The set
|
|
25
|
+
|
|
26
|
+
The marks aren't in the package. On first use the CLI downloads the set from logomarks.ai (about 3 MB, checked by
|
|
27
|
+
sha256) and caches it in your user cache folder (`~/.cache/logomarks`, `~/Library/Caches/logomarks` on macOS). It looks
|
|
28
|
+
for a newer set at most once a day; `logomarks update` checks now, and `--offline` (or `LOGOMARKS_OFFLINE=1`) uses the
|
|
29
|
+
cache alone. See [the live set](docs/data.md).
|
|
23
30
|
|
|
24
31
|
## AI agents
|
|
25
32
|
|
|
@@ -49,6 +56,7 @@ codex mcp add logomarks -- npx -y logomarks mcp
|
|
|
49
56
|
- [Editing](docs/editing.md): glitch presets, edit ops and combining.
|
|
50
57
|
- [MCP tools](docs/mcp.md): each tool, its arguments and what it returns.
|
|
51
58
|
- [API](docs/api.md): the functions behind them, for use as a library.
|
|
59
|
+
- [The live set](docs/data.md): where the marks come from, the cache, offline use and the environment variables.
|
|
52
60
|
|
|
53
61
|
Built on [`@logomarks/core`](https://github.com/Logomarks/core), [`@logomarks/editor`](https://github.com/Logomarks/editor), [`@logomarks/brand-kit`](https://github.com/Logomarks/brand-kit), [`@logomarks/mockups`](https://github.com/Logomarks/mockups) and [`@arraypress/covers`](https://github.com/arraypress/covers).
|
|
54
62
|
|
package/docs/api.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# API
|
|
2
2
|
|
|
3
3
|
```js
|
|
4
|
-
import { check, glitchMark, kit } from 'logomarks';
|
|
4
|
+
import { ensureIndex, findMarks, check, glitchMark, kit } from 'logomarks';
|
|
5
5
|
import { createServer, TOOLS } from 'logomarks/mcp';
|
|
6
|
+
|
|
7
|
+
await ensureIndex(); // the live set: cached, or downloaded from logomarks.ai
|
|
6
8
|
```
|
|
7
9
|
|
|
10
|
+
Call `ensureIndex()` once before anything that reads the live set (`findMarks`, `similar`, `sheet`, `loadMark` by slug …).
|
|
11
|
+
|
|
8
12
|
| Export | |
|
|
9
13
|
|---|---|
|
|
10
14
|
| `check(svg, { name, ignore, strict })` | `{ ok, errors, warnings, notes, size, findings }`. |
|
|
@@ -13,6 +17,9 @@ import { createServer, TOOLS } from 'logomarks/mcp';
|
|
|
13
17
|
| `sheet([{ name, svg }])` | `{ png, svg, marks }`. |
|
|
14
18
|
| `findMarks(query, { style, tags, industry, letter, limit })`, `facets()` | `{ total, marks }`; the filters' values. |
|
|
15
19
|
| `fitMark(svg)`, `loadIndex()`, `FINDINGS`, `rules` | The fitter, the live set, every finding id, the house rules. |
|
|
20
|
+
| `ensureIndex({ force, offline, url, dir, maxAge, timeout, warn })` | `{ file, source, checked, manifest }`: the live set, cached or downloaded and verified. Throws an `IndexError` (`code`: `network`, `offline`, `checksum`, `format`, `missing`). |
|
|
21
|
+
| `cacheDir()`, `DEFAULT_INDEX_URL`, `INDEX_FORMAT` | Where it's cached, where it's from, the format this version reads. |
|
|
22
|
+
| `buildIndex({ marks, search })`, `encodeIndex`, `decodeIndex` | `{ bytes, manifest }`: the index as the site builds it; the format both ways. |
|
|
16
23
|
| `loadMark(ref)`, `paint(svg, color)`, `markPng(svg, { size, color })` | A mark by slug, name or file; as a file in a colour; as a PNG. |
|
|
17
24
|
| `glitchMark(svg, { preset, angle, place, slide, gap, cuts, seed })` | `{ svg, checks, glitch }`. |
|
|
18
25
|
| `editMark(svg, ops)`, `markParts(svg)` | `{ svg, checks, parts }`; the parts by index. |
|
|
@@ -28,4 +35,4 @@ import { createServer, TOOLS } from 'logomarks/mcp';
|
|
|
28
35
|
|
|
29
36
|
The palette, lockups and artwork are [`@logomarks/brand-kit`](https://github.com/Logomarks/brand-kit)'s (`palette`, `lockup`, `artwork`), and the edits are [`@logomarks/editor`](https://github.com/Logomarks/editor)'s.
|
|
30
37
|
|
|
31
|
-
The live set
|
|
38
|
+
The live set isn't bundled: logomarks.ai serves it (each mark's SVG, tags, style, mood, subject, description and industries, its signatures and the search), and the CLI caches it ([the live set](data.md)). The marks are CC0. The typefaces (IBM Plex Mono for labels; Inter, Space Grotesk, Instrument Sans, Bricolage Grotesque, Instrument Serif, and for restaurants Fraunces, Cagliostro, Limelight and Shrikhand, for names) are SIL OFL, in `data/fonts/` (`OFL.txt`; `scripts/fonts.js` writes them): latin subsets, except the faces with a Reserved Font Name (Cagliostro, Limelight, IBM Plex Mono), bundled whole and pinned by sha256.
|
package/docs/commands.md
CHANGED
|
@@ -7,12 +7,14 @@ logomarks <command> --help
|
|
|
7
7
|
|
|
8
8
|
A `<mark>` is a live slug or name (`hex-gem`, `"Hex Gem"`) or the path to your own `.svg`, fitted to the grid first. A miss suggests the closest slugs.
|
|
9
9
|
|
|
10
|
-
Every command takes `--json` (machine-readable output on stdout) and `-h, --help`. `logomarks --version` prints the version.
|
|
10
|
+
Every command takes `--json` (machine-readable output on stdout), `--offline` (use the cached set only) and `-h, --help`. `logomarks --version` prints the version.
|
|
11
|
+
|
|
12
|
+
The live set is downloaded from logomarks.ai on first use and cached; a newer one is looked for at most once a day. See [the live set](data.md) for the cache, offline use and the environment variables.
|
|
11
13
|
|
|
12
14
|
| Exit code | Meaning |
|
|
13
15
|
|---|---|
|
|
14
16
|
| 0 | OK: every mark passed, or the file was written. |
|
|
15
|
-
| 1 | A check failed (`check`, `similar`, `specks`, `sheet`, and an edit whose result fails a check), nothing matched (`find`), or the command failed (a file it can't read or write). |
|
|
17
|
+
| 1 | A check failed (`check`, `similar`, `specks`, `sheet`, and an edit whose result fails a check), nothing matched (`find`), or the command failed (a file it can't read or write, or the live set it needs can't be had). |
|
|
16
18
|
| 2 | Usage: an unknown command or option, a missing argument, or a value out of range. |
|
|
17
19
|
|
|
18
20
|
Set `LOGOMARKS_DEBUG=1` to print the stack trace behind an exit 1.
|
|
@@ -22,6 +24,7 @@ Set `LOGOMARKS_DEBUG=1` to print the stack trace behind an exit 1.
|
|
|
22
24
|
- Edit: [`parts`](#parts), [`edit`](#edit), [`glitch`](#glitch), [`combine`](#combine)
|
|
23
25
|
- Build: [`kit`](#kit), [`social`](#social), [`mockup`](#mockup), [`cover`](#cover)
|
|
24
26
|
- Agents: [`mcp`](#mcp)
|
|
27
|
+
- The set: [`update`](#update)
|
|
25
28
|
|
|
26
29
|
## find
|
|
27
30
|
|
|
@@ -127,7 +130,7 @@ Compares outlines, rotations and mirrors included. A score of 0.72 or more is to
|
|
|
127
130
|
|---|---|---|
|
|
128
131
|
| `--top <n>` | 5 | How many matches per mark. |
|
|
129
132
|
| `--letters` | off | Compare a badge's knocked-out letter instead of its outline (0.7 too close, 0.85 a near-copy). |
|
|
130
|
-
| `--against <dir>` | the
|
|
133
|
+
| `--against <dir>` | the live set | Compare with a folder of SVGs instead. |
|
|
131
134
|
| `--each` | off | Compare the candidates with each other too (marked `*`). |
|
|
132
135
|
| `--all <data dir>` | | Write every mark's 8 nearest for a whole set ("More like this"), from its `marks.json`, `descriptions.json` and `svg/`. |
|
|
133
136
|
| `-o, --out <file>` | stdout | Where `--all` writes. |
|
|
@@ -410,3 +413,16 @@ codex mcp add logomarks -- npx -y logomarks mcp
|
|
|
410
413
|
```
|
|
411
414
|
|
|
412
415
|
PNGs are drawn by resvg in WebAssembly, so nothing needs `sharp` or a native build.
|
|
416
|
+
|
|
417
|
+
## update
|
|
418
|
+
|
|
419
|
+
Download the latest set now, rather than waiting for the daily check.
|
|
420
|
+
|
|
421
|
+
```
|
|
422
|
+
logomarks update
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
It asks logomarks.ai for the manifest and downloads the index when its sha256 differs from the cached one, checked
|
|
426
|
+
before it's saved. With `--json`: `{ source, file, format, built, marks, bytes, sha256 }`, where `source` is `download`,
|
|
427
|
+
`cache` (already up to date) or `file` (`LOGOMARKS_INDEX` is set). Exit 1 when the set can't be had, or with
|
|
428
|
+
`--offline`.
|
package/docs/data.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# The live set
|
|
2
|
+
|
|
3
|
+
The Logomarks set isn't in the package. logomarks.ai serves it, as one index of every live mark (its SVG, name, tags,
|
|
4
|
+
style, mood, subject, description, industries, similarity signatures and the site's search), about 3 MB:
|
|
5
|
+
|
|
6
|
+
- `https://logomarks.ai/cli/index.bin`: the index;
|
|
7
|
+
- `https://logomarks.ai/cli/index.json`: its manifest, `{ format, marks, letters, bytes, sha256, built }`.
|
|
8
|
+
|
|
9
|
+
The marks are CC0. The site rebuilds both with every deploy, so a new drop reaches the CLI without a new release.
|
|
10
|
+
|
|
11
|
+
## Download and cache
|
|
12
|
+
|
|
13
|
+
The first command that can use the set (every one but `check`, `specks` and `update`; the MCP server as it starts)
|
|
14
|
+
downloads it, checks its size and sha256 against the manifest, and caches it:
|
|
15
|
+
|
|
16
|
+
| Platform | Cache folder |
|
|
17
|
+
|---|---|
|
|
18
|
+
| Any, with `XDG_CACHE_HOME` set | `$XDG_CACHE_HOME/logomarks` |
|
|
19
|
+
| macOS | `~/Library/Caches/logomarks` |
|
|
20
|
+
| Windows | `%LOCALAPPDATA%\logomarks\Cache` |
|
|
21
|
+
| Linux and the rest | `~/.cache/logomarks` |
|
|
22
|
+
|
|
23
|
+
The folder holds `index.bin` and `index.json` (the manifest it matched, its URL and when it was last checked). Delete
|
|
24
|
+
the folder to start over.
|
|
25
|
+
|
|
26
|
+
After that, every command uses the cache. At most once a day it asks for the manifest again, and downloads the index
|
|
27
|
+
only when its sha256 has changed. `logomarks update` asks now.
|
|
28
|
+
|
|
29
|
+
When the set can't be had, commands that only read your own files (`check`, `specks`, and `parts`, `edit`, `glitch`
|
|
30
|
+
and the rest given an `.svg`) still run. Commands that need a live mark (`find`, `get hex-gem`, `similar`, `sheet` …)
|
|
31
|
+
fail with the reason.
|
|
32
|
+
|
|
33
|
+
## Offline
|
|
34
|
+
|
|
35
|
+
`--offline` (any command) or `LOGOMARKS_OFFLINE=1` uses the cache alone, never the network. With nothing cached, the
|
|
36
|
+
command says so: run `logomarks update` once online.
|
|
37
|
+
|
|
38
|
+
When the site can't be reached, or sends a file that doesn't match its manifest, a command with a cached set warns and
|
|
39
|
+
uses the cache. `logomarks update` fails instead.
|
|
40
|
+
|
|
41
|
+
## Environment
|
|
42
|
+
|
|
43
|
+
| Variable | |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `LOGOMARKS_OFFLINE=1` | Use the cache alone (as `--offline`). |
|
|
46
|
+
| `LOGOMARKS_INDEX=<file>` | Use this index file: no network, no cache (for tests, CI and air-gapped machines). |
|
|
47
|
+
| `LOGOMARKS_INDEX_URL=<url>` | Download the index from here instead; the manifest is `index.json` beside it. |
|
|
48
|
+
| `XDG_CACHE_HOME` | Where the cache folder goes. |
|
|
49
|
+
|
|
50
|
+
## Errors
|
|
51
|
+
|
|
52
|
+
Each comes as one line naming the command, exit 1 (an `IndexError` with a `code`, from the library):
|
|
53
|
+
|
|
54
|
+
| Code | When |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `network` | The site couldn't be reached or answered with an error, and nothing is cached. |
|
|
57
|
+
| `offline` | Offline with nothing cached, or `update` run offline. |
|
|
58
|
+
| `checksum` | The download didn't match the manifest's size or sha256. Nothing was saved. |
|
|
59
|
+
| `format` | The site serves a newer index format than this version reads: update logomarks. |
|
|
60
|
+
| `missing` | `LOGOMARKS_INDEX` names no file, or a library call came before `ensureIndex()`. |
|
|
61
|
+
|
|
62
|
+
## Format
|
|
63
|
+
|
|
64
|
+
The index carries a format version (`INDEX_FORMAT`, now 3), in its manifest and in its own header. A CLI checks both,
|
|
65
|
+
and refuses a format it doesn't read, so an old CLI never misreads a newer file. A change to the layout bumps the
|
|
66
|
+
version. The site must then keep serving the old format where old CLIs look for it, or they keep their cache and warn.
|
|
67
|
+
|
|
68
|
+
## In code
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
import { ensureIndex, findMarks } from 'logomarks';
|
|
72
|
+
|
|
73
|
+
await ensureIndex(); // cached, or downloaded; { file, source, checked, manifest }
|
|
74
|
+
findMarks('coffee'); // and every other function that reads the set
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`ensureIndex({ force, offline, url, dir, maxAge, timeout, warn })` takes the same choices as the CLI. Without it,
|
|
78
|
+
`loadIndex()` reads `LOGOMARKS_INDEX` or the cache, and throws an `IndexError` when neither exists.
|
|
79
|
+
|
|
80
|
+
## Building it
|
|
81
|
+
|
|
82
|
+
`buildIndex({ marks, search })` builds the index and its manifest from the Logomarks data. The site calls it at build
|
|
83
|
+
time; in the Logomarks monorepo, `npm run index` writes `data/index.bin` for the tests, which read it through
|
|
84
|
+
`LOGOMARKS_INDEX`.
|
package/docs/mcp.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MCP tools
|
|
2
2
|
|
|
3
|
-
`logomarks mcp` runs the CLI's functions as MCP tools on stdio, locally: nothing leaves the machine. Relative paths resolve against the server's working folder (the project the agent is in). The renderer, the typefaces and the live set load once and stay warm.
|
|
3
|
+
`logomarks mcp` runs the CLI's functions as MCP tools on stdio, locally: nothing leaves the machine. Relative paths resolve against the server's working folder (the project the agent is in). The renderer, the typefaces and the live set load once and stay warm. The live set is the CLI's: downloaded from logomarks.ai on first use and cached (see [the live set](data.md)); every tool call waits for it, and `logomarks mcp --offline` uses the cache alone.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
claude mcp add logomarks -- npx -y logomarks mcp # Claude Code
|
|
@@ -38,8 +38,8 @@ Every argument is described, with its type, choices and default, in the tool's i
|
|
|
38
38
|
|
|
39
39
|
## Annotations
|
|
40
40
|
|
|
41
|
-
`find_marks`, `similar_marks` and `list_parts` are read-only. `check_mark` (with `fix`), `build_brand_kit` and `build_social_pack` are marked destructive: they rewrite files in place or replace files in a folder. The other tools write only when given `out`, and replace that file. No tool reaches the network (`openWorldHint: false`).
|
|
41
|
+
`find_marks`, `similar_marks` and `list_parts` are read-only. `check_mark` (with `fix`), `build_brand_kit` and `build_social_pack` are marked destructive: they rewrite files in place or replace files in a folder. The other tools write only when given `out`, and replace that file. No tool reaches the network (`openWorldHint: false`); only the server does, to fetch the live set.
|
|
42
42
|
|
|
43
43
|
## Errors
|
|
44
44
|
|
|
45
|
-
A tool that fails returns a tool error (`isError`) with a message to act on: a missing mark comes with the closest slugs, an unknown part with how many the mark has, a missing file with its path.
|
|
45
|
+
A tool that fails returns a tool error (`isError`) with a message to act on: a missing mark comes with the closest slugs, an unknown part with how many the mark has, a missing file with its path, and a live set that can't be had with the reason (no network and nothing cached, a bad checksum, a newer format).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "logomarks",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Find, check, edit and build on free geometric logomarks from the command line or an AI agent: search the CC0 Logomarks set, check marks against its house rules, edit and glitch them, and build a brand kit, social pack, mockups and covers. Includes an MCP server.",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Find, check, edit and build on free geometric logomarks from the command line or an AI agent: search the CC0 Logomarks set (downloaded from logomarks.ai and cached), check marks against its house rules, edit and glitch them, and build a brand kit, social pack, mockups and covers. Includes an MCP server.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"logo",
|
|
7
7
|
"logomark",
|
|
@@ -59,17 +59,17 @@
|
|
|
59
59
|
"files": [
|
|
60
60
|
"bin",
|
|
61
61
|
"src",
|
|
62
|
-
"data",
|
|
62
|
+
"data/fonts",
|
|
63
63
|
"docs",
|
|
64
64
|
"README.md",
|
|
65
65
|
"CHANGELOG.md",
|
|
66
66
|
"LICENSE"
|
|
67
67
|
],
|
|
68
68
|
"engines": {
|
|
69
|
-
"node": ">=
|
|
69
|
+
"node": ">=22.0.0"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
|
-
"test": "node --test tests/*.test.js",
|
|
72
|
+
"test": "node --import ./tests/setup.js --test tests/*.test.js",
|
|
73
73
|
"typecheck": "tsc --noEmit",
|
|
74
74
|
"index": "node scripts/index.js"
|
|
75
75
|
},
|
|
@@ -78,13 +78,13 @@
|
|
|
78
78
|
"registry": "https://registry.npmjs.org/"
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
|
-
"@logomarks/brand-kit": "^0.4.1",
|
|
82
81
|
"@arraypress/color-utils": "^1.5.0",
|
|
83
|
-
"@arraypress/covers": "^1.
|
|
84
|
-
"@logomarks/core": "^0.1.3",
|
|
85
|
-
"@logomarks/mockups": "^0.5.0",
|
|
82
|
+
"@arraypress/covers": "^1.8.0",
|
|
86
83
|
"@arraypress/search": "^0.1.0",
|
|
84
|
+
"@logomarks/brand-kit": "^0.4.1",
|
|
85
|
+
"@logomarks/core": "^0.1.8",
|
|
87
86
|
"@logomarks/editor": "^0.2.4",
|
|
87
|
+
"@logomarks/mockups": "^0.5.0",
|
|
88
88
|
"@modelcontextprotocol/sdk": "1.32.1",
|
|
89
89
|
"@resvg/resvg-wasm": "2.6.2",
|
|
90
90
|
"zod": "4.6.7"
|
package/src/brand/mark.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @module logomarks/brand/mark
|
|
3
3
|
*
|
|
4
4
|
* The mark a brand is built on: a live mark by slug or name (from the
|
|
5
|
-
*
|
|
5
|
+
* live set, ../live), or your own SVG, fitted to the standard. Painted in a
|
|
6
6
|
* colour and drawn at a size.
|
|
7
7
|
*/
|
|
8
8
|
|
|
@@ -50,7 +50,7 @@ export const titleCase = (slug) => slug.split('-').filter(Boolean).map((w) => w[
|
|
|
50
50
|
* A live mark by slug or name, any case.
|
|
51
51
|
*
|
|
52
52
|
* @param {string} ref The slug (`hex-gem`) or name (`Hex Gem`).
|
|
53
|
-
* @param {import('../similar/store.js').MarkIndex} [index] The live set (the
|
|
53
|
+
* @param {import('../similar/store.js').MarkIndex} [index] The live set (the cached index).
|
|
54
54
|
* @returns {import('../similar/store.js').IndexedMark | undefined} The mark.
|
|
55
55
|
*/
|
|
56
56
|
export function findMark(ref, index = loadIndex()) {
|
|
@@ -2,6 +2,8 @@ import type { ArgSpec, Parsed } from '../args.js';
|
|
|
2
2
|
import type { IO } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
|
+
/** It reads the live set: the CLI gets it first. */
|
|
6
|
+
export const live: true;
|
|
5
7
|
/** What `combine` takes. */
|
|
6
8
|
export const spec: ArgSpec;
|
|
7
9
|
/** What `logomarks combine --help` prints. */
|
|
@@ -10,6 +10,9 @@ import { UsageError } from '../args.js';
|
|
|
10
10
|
import { markOf, numArg, asUsage } from '../options.js';
|
|
11
11
|
import { output } from '../edited.js';
|
|
12
12
|
|
|
13
|
+
/** It reads the live set: the CLI gets it first. */
|
|
14
|
+
export const live = true;
|
|
15
|
+
|
|
13
16
|
/** What `combine` takes. */
|
|
14
17
|
export const spec = { flags: ['json'], options: { out: 'o', op: '', scale: '', rotate: '', flip: '', x: '', y: '' } };
|
|
15
18
|
|
|
@@ -2,6 +2,8 @@ import type { ArgSpec, Parsed } from '../args.js';
|
|
|
2
2
|
import type { IO } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
|
+
/** It reads the live set: the CLI gets it first. */
|
|
6
|
+
export const live: true;
|
|
5
7
|
/** What `cover` takes. */
|
|
6
8
|
export const spec: ArgSpec;
|
|
7
9
|
/** What `logomarks cover --help` prints. */
|
|
@@ -10,6 +10,9 @@ import { UsageError } from '../args.js';
|
|
|
10
10
|
import { markArg, colorArg, intArg, writeFile } from '../options.js';
|
|
11
11
|
import { style } from '../style.js';
|
|
12
12
|
|
|
13
|
+
/** It reads the live set: the CLI gets it first. */
|
|
14
|
+
export const live = true;
|
|
15
|
+
|
|
13
16
|
/** What `cover` takes. */
|
|
14
17
|
export const spec = { flags: ['json'], options: { out: 'o', recipe: '', title: '', label: '', color: '', aspect: '', width: '', seed: '' } };
|
|
15
18
|
|
|
@@ -2,6 +2,8 @@ import type { ArgSpec, Parsed } from '../args.js';
|
|
|
2
2
|
import type { IO } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
|
+
/** It reads the live set: the CLI gets it first. */
|
|
6
|
+
export const live: true;
|
|
5
7
|
/** What `edit` takes. */
|
|
6
8
|
export const spec: ArgSpec;
|
|
7
9
|
/** What `logomarks edit --help` prints. */
|
package/src/cli/commands/edit.js
CHANGED
|
@@ -13,6 +13,9 @@ import { output } from '../edited.js';
|
|
|
13
13
|
import { OPS } from '../../edit/ops.js';
|
|
14
14
|
import { wrapList } from '../help.js';
|
|
15
15
|
|
|
16
|
+
/** It reads the live set: the CLI gets it first. */
|
|
17
|
+
export const live = true;
|
|
18
|
+
|
|
16
19
|
/** What `edit` takes. */
|
|
17
20
|
export const spec = { flags: ['json'], options: { out: 'o', ops: '' } };
|
|
18
21
|
|
|
@@ -2,6 +2,8 @@ import type { ArgSpec, Parsed } from '../args.js';
|
|
|
2
2
|
import type { IO } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
|
+
/** It reads the live set: the CLI gets it first. */
|
|
6
|
+
export const live: true;
|
|
5
7
|
/** What `find` takes. */
|
|
6
8
|
export const spec: ArgSpec;
|
|
7
9
|
/** What `logomarks find --help` prints. */
|
package/src/cli/commands/find.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module logomarks/cli/commands/find
|
|
3
3
|
*
|
|
4
|
-
* `logomarks find <words…>`: search the
|
|
4
|
+
* `logomarks find <words…>`: search the live set by words, style,
|
|
5
5
|
* tags, industry or letter. With nothing to search by, the values the
|
|
6
6
|
* filters take.
|
|
7
7
|
*/
|
|
@@ -10,6 +10,9 @@ import { findMarks, facets } from '../../find/index.js';
|
|
|
10
10
|
import { intArg } from '../options.js';
|
|
11
11
|
import { style, pad } from '../style.js';
|
|
12
12
|
|
|
13
|
+
/** It reads the live set: the CLI gets it first. */
|
|
14
|
+
export const live = true;
|
|
15
|
+
|
|
13
16
|
/** What `find` takes. */
|
|
14
17
|
export const spec = { flags: ['json'], options: { style: '', tag: '', industry: '', letter: '', top: '' } };
|
|
15
18
|
|
|
@@ -2,6 +2,8 @@ import type { ArgSpec, Parsed } from '../args.js';
|
|
|
2
2
|
import type { IO } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
|
+
/** It reads the live set: the CLI gets it first. */
|
|
6
|
+
export const live: true;
|
|
5
7
|
/** What `get` takes. */
|
|
6
8
|
export const spec: ArgSpec;
|
|
7
9
|
/** What `logomarks get --help` prints. */
|
package/src/cli/commands/get.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module logomarks/cli/commands/get
|
|
3
3
|
*
|
|
4
|
-
* `logomarks get <slug|name>`: a live mark's SVG (from the
|
|
4
|
+
* `logomarks get <slug|name>`: a live mark's SVG (from the live set) to
|
|
5
5
|
* stdout or a file, in a colour, or a PNG at a size.
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -10,6 +10,9 @@ import { UsageError } from '../args.js';
|
|
|
10
10
|
import { markArg, colorArg, intArg, writeFile } from '../options.js';
|
|
11
11
|
import { style } from '../style.js';
|
|
12
12
|
|
|
13
|
+
/** It reads the live set: the CLI gets it first. */
|
|
14
|
+
export const live = true;
|
|
15
|
+
|
|
13
16
|
/** What `get` takes. */
|
|
14
17
|
export const spec = { flags: ['json'], options: { out: 'o', color: '', size: '', format: '' } };
|
|
15
18
|
|
|
@@ -2,6 +2,8 @@ import type { ArgSpec, Parsed } from '../args.js';
|
|
|
2
2
|
import type { IO } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
|
+
/** It reads the live set: the CLI gets it first. */
|
|
6
|
+
export const live: true;
|
|
5
7
|
/** What `glitch` takes. */
|
|
6
8
|
export const spec: ArgSpec;
|
|
7
9
|
/** What `logomarks glitch --help` prints. */
|
|
@@ -10,6 +10,9 @@ import { UsageError } from '../args.js';
|
|
|
10
10
|
import { markArg, numArg, intArg, asUsage } from '../options.js';
|
|
11
11
|
import { output } from '../edited.js';
|
|
12
12
|
|
|
13
|
+
/** It reads the live set: the CLI gets it first. */
|
|
14
|
+
export const live = true;
|
|
15
|
+
|
|
13
16
|
/** What `glitch` takes. */
|
|
14
17
|
export const spec = { flags: ['json'], options: { out: 'o', preset: '', angle: '', place: '', slide: '', gap: '', cuts: '', seed: '' } };
|
|
15
18
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ArgSpec, Parsed } from '../args.js';
|
|
2
|
-
import type { IO } from '../index.js';
|
|
2
|
+
import type { IO, RunContext } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
5
|
/** A verb: the arguments it takes and how it runs. */
|
|
@@ -7,9 +7,11 @@ export interface Command {
|
|
|
7
7
|
spec: ArgSpec;
|
|
8
8
|
/** What `logomarks <verb> --help` prints. */
|
|
9
9
|
help: CommandHelp;
|
|
10
|
+
/** Whether it may read the live set: the CLI gets the set (cached or downloaded) before running it. */
|
|
11
|
+
live?: boolean;
|
|
10
12
|
/** Runs the verb and resolves to its exit code (0 pass, 1 fail). */
|
|
11
|
-
run(args: Parsed, io: IO): Promise<number>;
|
|
13
|
+
run(args: Parsed, io: IO, ctx?: RunContext): Promise<number>;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
/** Every verb the CLI runs. */
|
|
15
|
-
export const COMMANDS: Readonly<Record<'check' | 'similar' | 'specks' | 'sheet' | 'find' | 'parts' | 'glitch' | 'edit' | 'combine' | 'get' | 'kit' | 'social' | 'mockup' | 'cover' | 'mcp', Command>>;
|
|
17
|
+
export const COMMANDS: Readonly<Record<'check' | 'similar' | 'specks' | 'sheet' | 'find' | 'parts' | 'glitch' | 'edit' | 'combine' | 'get' | 'kit' | 'social' | 'mockup' | 'cover' | 'mcp' | 'update', Command>>;
|
|
@@ -19,6 +19,7 @@ import * as combine from './combine.js';
|
|
|
19
19
|
import * as social from './social.js';
|
|
20
20
|
import * as find from './find.js';
|
|
21
21
|
import * as mcp from './mcp.js';
|
|
22
|
+
import * as update from './update.js';
|
|
22
23
|
|
|
23
24
|
/** Every verb the CLI runs. */
|
|
24
|
-
export const COMMANDS = { check, similar, specks, sheet, find, parts, glitch, edit, combine, get, kit, social, mockup, cover, mcp };
|
|
25
|
+
export const COMMANDS = { check, similar, specks, sheet, find, parts, glitch, edit, combine, get, kit, social, mockup, cover, mcp, update };
|
|
@@ -2,6 +2,8 @@ import type { ArgSpec, Parsed } from '../args.js';
|
|
|
2
2
|
import type { IO } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
|
+
/** It reads the live set: the CLI gets it first. */
|
|
6
|
+
export const live: true;
|
|
5
7
|
/** What `kit` takes. */
|
|
6
8
|
export const spec: ArgSpec;
|
|
7
9
|
/** What `logomarks kit --help` prints. */
|
package/src/cli/commands/kit.js
CHANGED
|
@@ -14,6 +14,9 @@ import { FONTS } from '../../brand/fonts.js';
|
|
|
14
14
|
import { STYLE_IDS, DEFAULT_STYLES } from '@logomarks/brand-kit';
|
|
15
15
|
import { wrapList } from '../help.js';
|
|
16
16
|
|
|
17
|
+
/** It reads the live set: the CLI gets it first. */
|
|
18
|
+
export const live = true;
|
|
19
|
+
|
|
17
20
|
/** What `kit` takes. */
|
|
18
21
|
export const spec = { flags: ['json', 'animated', 'no-social'], options: { out: 'o', name: '', color: '', font: '', tagline: '', url: '', handle: '', styles: '', platforms: '' } };
|
|
19
22
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ArgSpec } from '../args.js';
|
|
1
|
+
import type { ArgSpec, Parsed } from '../args.js';
|
|
2
|
+
import type { IO, RunContext } from '../index.js';
|
|
2
3
|
import type { CommandHelp } from '../help.js';
|
|
3
4
|
|
|
4
5
|
/** What `mcp` takes: nothing. */
|
|
@@ -6,4 +7,4 @@ export const spec: ArgSpec;
|
|
|
6
7
|
/** What `logomarks mcp --help` prints. */
|
|
7
8
|
export const help: CommandHelp;
|
|
8
9
|
/** Starts the MCP server on stdio; resolves to 0 once it is connected. */
|
|
9
|
-
export function run(): Promise<number>;
|
|
10
|
+
export function run(args?: Parsed, io?: IO, ctx?: RunContext): Promise<number>;
|
package/src/cli/commands/mcp.js
CHANGED
|
@@ -14,7 +14,8 @@ export const help = {
|
|
|
14
14
|
summary: 'Run the MCP server on stdio, for Claude Code, Codex, Cursor and other agents.',
|
|
15
15
|
usage: [''],
|
|
16
16
|
about: [
|
|
17
|
-
'Every verb as an MCP tool, run locally; nothing leaves the machine
|
|
17
|
+
'Every verb as an MCP tool, run locally; nothing leaves the machine (the set itself is downloaded',
|
|
18
|
+
'from logomarks.ai on first use and cached). Add it to an agent:',
|
|
18
19
|
' claude mcp add logomarks -- npx -y logomarks mcp',
|
|
19
20
|
' codex mcp add logomarks -- npx -y logomarks mcp',
|
|
20
21
|
'Or install the Claude Code plugin, which adds the skills too:',
|
|
@@ -27,10 +28,13 @@ export const help = {
|
|
|
27
28
|
/**
|
|
28
29
|
* Runs `mcp`: starts the server and returns; the process lives until the client hangs up.
|
|
29
30
|
*
|
|
31
|
+
* @param {import('../args.js').Parsed} [_args] The parsed arguments (none).
|
|
32
|
+
* @param {import('../index.js').IO} [_io] Where output goes (unused: stdout is the protocol's).
|
|
33
|
+
* @param {import('../index.js').RunContext} [ctx] Whether `--offline` was given.
|
|
30
34
|
* @returns {Promise<number>} The exit code: 0.
|
|
31
35
|
*/
|
|
32
|
-
export async function run() {
|
|
36
|
+
export async function run(_args, _io, { offline } = {}) {
|
|
33
37
|
const { serve } = await import('../../mcp/index.js');
|
|
34
|
-
await serve();
|
|
38
|
+
await serve({ offline });
|
|
35
39
|
return 0;
|
|
36
40
|
}
|
|
@@ -2,6 +2,8 @@ import type { ArgSpec, Parsed } from '../args.js';
|
|
|
2
2
|
import type { IO } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
|
+
/** It reads the live set: the CLI gets it first. */
|
|
6
|
+
export const live: true;
|
|
5
7
|
/** What `mockup` takes. */
|
|
6
8
|
export const spec: ArgSpec;
|
|
7
9
|
/** What `logomarks mockup --help` prints. */
|
|
@@ -12,6 +12,9 @@ import { style } from '../style.js';
|
|
|
12
12
|
import { FONTS } from '../../brand/fonts.js';
|
|
13
13
|
import { wrapList } from '../help.js';
|
|
14
14
|
|
|
15
|
+
/** It reads the live set: the CLI gets it first. */
|
|
16
|
+
export const live = true;
|
|
17
|
+
|
|
15
18
|
/** What `mockup` takes. */
|
|
16
19
|
export const spec = { flags: ['json'], options: { out: 'o', object: '', name: '', color: '', font: '', layout: '', surface: '', view: '', base: '', size: '', seed: '' } };
|
|
17
20
|
|
|
@@ -2,6 +2,8 @@ import type { ArgSpec, Parsed } from '../args.js';
|
|
|
2
2
|
import type { IO } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
|
+
/** It reads the live set: the CLI gets it first. */
|
|
6
|
+
export const live: true;
|
|
5
7
|
/** What `parts` takes. */
|
|
6
8
|
export const spec: ArgSpec;
|
|
7
9
|
/** What `logomarks parts --help` prints. */
|
|
@@ -10,6 +10,9 @@ import { partsPreview } from '../../edit/preview.js';
|
|
|
10
10
|
import { markArg, writeFile } from '../options.js';
|
|
11
11
|
import { style, pad } from '../style.js';
|
|
12
12
|
|
|
13
|
+
/** It reads the live set: the CLI gets it first. */
|
|
14
|
+
export const live = true;
|
|
15
|
+
|
|
13
16
|
/** What `parts` takes. */
|
|
14
17
|
export const spec = { flags: ['json'], options: { out: 'o' } };
|
|
15
18
|
|
|
@@ -2,6 +2,8 @@ import type { ArgSpec, Parsed } from '../args.js';
|
|
|
2
2
|
import type { IO } from '../index.js';
|
|
3
3
|
import type { CommandHelp } from '../help.js';
|
|
4
4
|
|
|
5
|
+
/** It reads the live set: the CLI gets it first. */
|
|
6
|
+
export const live: true;
|
|
5
7
|
/** What `sheet` takes. */
|
|
6
8
|
export const spec: ArgSpec;
|
|
7
9
|
/** What `logomarks sheet --help` prints. */
|