cyrenecode 0.1.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/LICENSE +21 -0
- package/README.md +260 -0
- package/SECURITY.md +117 -0
- package/assets/brand/cyrene-logo.svg +11 -0
- package/assets/brand/cyrene-mark.svg +8 -0
- package/bin/cyrene.js +2 -0
- package/dist/cli.js +35308 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cyrene
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/brand/cyrene-logo.svg" alt="Cyrene" width="420" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# Cyrene
|
|
6
|
+
|
|
7
|
+
Terminal-first coding assistant built with Bun, React Ink, and a reviewable query loop.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
### Global CLI
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g cyrenecode
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or run it without a global install:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx cyrenecode
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### From source
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bun install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
> The published npm package ships a prebuilt CLI bundle. If you are developing
|
|
30
|
+
> from source, install Bun first.
|
|
31
|
+
|
|
32
|
+
## Run from source
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
bun dev
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
By default, the CLI runs with a local in-memory core transport, so you can test
|
|
39
|
+
the full query loop without any backend service.
|
|
40
|
+
|
|
41
|
+
## Configure
|
|
42
|
+
|
|
43
|
+
Cyrene now uses a **global user config home** by default:
|
|
44
|
+
|
|
45
|
+
- Windows: `C:\Users\<you>\.cyrene`
|
|
46
|
+
- macOS / Linux: `~/.cyrene`
|
|
47
|
+
|
|
48
|
+
Project-local `.cyrene/` is still read for backward compatibility, but global
|
|
49
|
+
user scope is the primary home for model/provider metadata and session state.
|
|
50
|
+
|
|
51
|
+
### HTTP credentials
|
|
52
|
+
|
|
53
|
+
You can still launch with explicit environment variables:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
CYRENE_BASE_URL=https://your-openai-compatible-host
|
|
57
|
+
CYRENE_API_KEY=your_api_key
|
|
58
|
+
CYRENE_MODEL=gpt-4o-mini
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
When they are present, they remain the **highest-priority source** for that run.
|
|
62
|
+
Cyrene will report them as `process_env` via `/auth` and will not overwrite them
|
|
63
|
+
behind your back.
|
|
64
|
+
|
|
65
|
+
### First-run login onboarding
|
|
66
|
+
|
|
67
|
+
If usable HTTP credentials are missing, Cyrene auto-opens a skippable login
|
|
68
|
+
wizard on the initial idle screen.
|
|
69
|
+
|
|
70
|
+
Wizard flow:
|
|
71
|
+
|
|
72
|
+
1. provider base URL
|
|
73
|
+
2. API key
|
|
74
|
+
3. optional initial model
|
|
75
|
+
4. confirmation + persistence target preview
|
|
76
|
+
|
|
77
|
+
Skip is always allowed. If you skip, Cyrene stays fully usable in `local-core`
|
|
78
|
+
mode and you can reconnect later with `/login`.
|
|
79
|
+
|
|
80
|
+
### What gets persisted where
|
|
81
|
+
|
|
82
|
+
- **Secret only:** `CYRENE_API_KEY`
|
|
83
|
+
- Windows: user-level environment variable
|
|
84
|
+
- macOS/Linux zsh: managed block in `~/.zshrc`
|
|
85
|
+
- macOS/Linux bash: managed block in `~/.bashrc` or `~/.bash_profile`
|
|
86
|
+
- fish: managed file in `~/.config/fish/conf.d/`
|
|
87
|
+
- other POSIX shells: managed block in `~/.profile`
|
|
88
|
+
- **Non-secret provider/model metadata:** global user `.cyrene/model.yaml`
|
|
89
|
+
|
|
90
|
+
Successful `/login` persists the API key at user scope and also updates the
|
|
91
|
+
current CLI process so the transport can switch immediately without restart.
|
|
92
|
+
`/logout` removes only the Cyrene-managed persisted API key. It does **not**
|
|
93
|
+
delete sessions, summaries, or model/provider catalog files.
|
|
94
|
+
|
|
95
|
+
When credentials are missing or incomplete, Cyrene falls back to local-core
|
|
96
|
+
instead of blocking the app.
|
|
97
|
+
|
|
98
|
+
#### Shell-specific persistence behavior
|
|
99
|
+
|
|
100
|
+
- **zsh**: updates one managed block in `~/.zshrc`
|
|
101
|
+
- **bash**: uses `~/.bashrc`, otherwise `~/.bash_profile`, otherwise creates `~/.bashrc`
|
|
102
|
+
- **fish**: writes `~/.config/fish/conf.d/cyrene-auth.fish`
|
|
103
|
+
- **other POSIX shells**: updates one managed block in `~/.profile`
|
|
104
|
+
|
|
105
|
+
Repeated `/login` updates replace the existing Cyrene-managed entry instead of
|
|
106
|
+
duplicating it. `/logout` removes only the Cyrene-managed block or file and
|
|
107
|
+
does not touch unrelated shell configuration.
|
|
108
|
+
|
|
109
|
+
Current request shape:
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"model": "gpt-4o-mini",
|
|
113
|
+
"stream": true,
|
|
114
|
+
"messages": [{ "role": "user", "content": "..." }]
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Model switch:
|
|
119
|
+
- `/model` opens model picker (Up/Down select, Left/Right page, Enter switch).
|
|
120
|
+
- `/model refresh` pulls model list immediately and overwrites `.cyrene/model.yaml`.
|
|
121
|
+
- `/model <name>` switches immediately only if model exists in `.cyrene/model.yaml`; otherwise it fails.
|
|
122
|
+
- `/login` opens the auth wizard on demand.
|
|
123
|
+
- `/logout` removes Cyrene-managed user-scoped API key persistence.
|
|
124
|
+
- `/auth` shows the current mode, credential source, and persistence target.
|
|
125
|
+
|
|
126
|
+
Model source priority:
|
|
127
|
+
1. `.cyrene/model.yaml`
|
|
128
|
+
2. If missing/invalid, fetch from `GET /v1/models`
|
|
129
|
+
3. If fetch fails, model initialization fails (and refresh reports failure)
|
|
130
|
+
|
|
131
|
+
Prompt priority and customization:
|
|
132
|
+
- Priority is fixed as: `system prompt > .cyrene/.cyrene.md > pins`.
|
|
133
|
+
- User-facing config is centralized in `.cyrene/config.yaml`.
|
|
134
|
+
- `system_prompt` can be set in `.cyrene/config.yaml` (or env fallback: `CYRENE_SYSTEM_PROMPT=...`).
|
|
135
|
+
- `auto_summary_refresh` can be set in `.cyrene/config.yaml` to enable/disable the rolling reducer that updates `summary` + `pendingDigest` inside normal user turns. Default: `true`.
|
|
136
|
+
- `request_temperature` can be set in `.cyrene/config.yaml` to control the HTTP main-request sampling temperature. Default: `0.2`.
|
|
137
|
+
- Runtime system prompt commands:
|
|
138
|
+
- `/system` show current system prompt
|
|
139
|
+
- `/system <text>` set current runtime system prompt
|
|
140
|
+
- `/system reset` reset to default
|
|
141
|
+
- `.cyrene/.cyrene.md` is fully user-editable project policy.
|
|
142
|
+
- `/pin <note>` and `/pins` manage human-selected focus.
|
|
143
|
+
- `/unpin <index>` removes one pinned focus item (1-based index).
|
|
144
|
+
|
|
145
|
+
Session and context:
|
|
146
|
+
- Sessions are persisted under `.cyrene/session` as JSON files.
|
|
147
|
+
- `/help` shows the command reference.
|
|
148
|
+
- `/sessions` lists sessions by latest update time.
|
|
149
|
+
- `/resume <session_id>` restores a previous session.
|
|
150
|
+
- `/resume` opens keyboard picker (Left/Right page, Enter resume, Esc cancel).
|
|
151
|
+
- `/new` starts a fresh session.
|
|
152
|
+
- `/pin <note>` stores human-selected key context.
|
|
153
|
+
- `/pins` shows pinned key context.
|
|
154
|
+
- `/unpin <index>` removes a pinned key context item.
|
|
155
|
+
- `/state` shows reducer/session state diagnostics for the current runtime.
|
|
156
|
+
- `/auth` shows whether the runtime is using HTTP or local-core, plus where the
|
|
157
|
+
current credential came from.
|
|
158
|
+
- Pin count comes from `.cyrene/config.yaml` via `pin_max_count`.
|
|
159
|
+
- Older context is tracked through the rolling working-state pair: durable `summary` + lagging `pendingDigest`, while recent turns are kept for prompt context.
|
|
160
|
+
|
|
161
|
+
## Rolling context architecture
|
|
162
|
+
|
|
163
|
+
Cyrene keeps long-running coding context in three layers instead of stuffing the
|
|
164
|
+
entire transcript back into every prompt:
|
|
165
|
+
|
|
166
|
+
1. **`summary`** - a durable, compact working state used as the main context anchor
|
|
167
|
+
2. **`pendingDigest`** - the most recent turn digest that has not been merged yet
|
|
168
|
+
3. **memory index** - richer archived evidence that can be retrieved on demand
|
|
169
|
+
|
|
170
|
+
This keeps prompts smaller while still preserving continuity. The durable summary
|
|
171
|
+
is intentionally structured into sections such as:
|
|
172
|
+
|
|
173
|
+
- `OBJECTIVE`
|
|
174
|
+
- `CONFIRMED FACTS`
|
|
175
|
+
- `CONSTRAINTS`
|
|
176
|
+
- `COMPLETED`
|
|
177
|
+
- `REMAINING`
|
|
178
|
+
- `KNOWN PATHS`
|
|
179
|
+
- `RECENT FAILURES`
|
|
180
|
+
- `NEXT BEST ACTIONS`
|
|
181
|
+
|
|
182
|
+
### High-level memory layout
|
|
183
|
+
|
|
184
|
+
```mermaid
|
|
185
|
+
flowchart TD
|
|
186
|
+
U["User turn"] --> P["Prompt builder"]
|
|
187
|
+
S["Durable summary"] --> P
|
|
188
|
+
D["Pending digest<br/>(last turn, not yet merged)"] --> P
|
|
189
|
+
M["Memory index<br/>(retrieved evidence)"] --> P
|
|
190
|
+
P --> Q["Main model request"]
|
|
191
|
+
Q --> A["Visible assistant answer"]
|
|
192
|
+
Q --> H["Hidden reducer block<br/><cyrene_state_update>..."]
|
|
193
|
+
H --> R["Reducer parser"]
|
|
194
|
+
R --> S
|
|
195
|
+
R --> D
|
|
196
|
+
M -. "search / retrieval guided by summary + digest" .-> P
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### One turn -> summary progression
|
|
200
|
+
|
|
201
|
+
Cyrene does **not** make a second background summary request after the answer.
|
|
202
|
+
Instead, state updates piggyback on the same main response.
|
|
203
|
+
|
|
204
|
+
```mermaid
|
|
205
|
+
sequenceDiagram
|
|
206
|
+
participant U as User
|
|
207
|
+
participant C as Cyrene UI
|
|
208
|
+
participant P as Prompt Builder
|
|
209
|
+
participant L as LLM
|
|
210
|
+
participant R as Reducer Parser
|
|
211
|
+
participant S as Session Store
|
|
212
|
+
|
|
213
|
+
U->>C: Send current request
|
|
214
|
+
C->>S: Load summary + pendingDigest + retrieved memory
|
|
215
|
+
S-->>C: Current session context
|
|
216
|
+
C->>P: Build main prompt
|
|
217
|
+
P->>L: One normal model request
|
|
218
|
+
|
|
219
|
+
L-->>C: Visible answer + hidden state tail
|
|
220
|
+
Note over L,C: <cyrene_state_update>{...}</cyrene_state_update>
|
|
221
|
+
|
|
222
|
+
C->>R: Strip visible answer, parse reducer payload
|
|
223
|
+
R-->>C: Parsed update
|
|
224
|
+
C->>S: Persist visible assistant message
|
|
225
|
+
|
|
226
|
+
alt First reducer-enabled turn
|
|
227
|
+
C->>S: Keep summary as-is
|
|
228
|
+
C->>S: Store new pendingDigest
|
|
229
|
+
else Later turn with valid reducer payload
|
|
230
|
+
C->>S: Merge old pendingDigest into summary
|
|
231
|
+
C->>S: Replace pendingDigest with current-turn digest
|
|
232
|
+
else Missing/invalid reducer tail
|
|
233
|
+
C->>R: Build local fallback digest
|
|
234
|
+
alt Prior pendingDigest exists
|
|
235
|
+
C->>S: Locally advance summary from prior pendingDigest
|
|
236
|
+
C->>S: Store fallback pendingDigest for current turn
|
|
237
|
+
else No prior pendingDigest
|
|
238
|
+
C->>S: Store fallback pendingDigest only
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Why this design exists
|
|
244
|
+
|
|
245
|
+
- avoids a hidden second model call after every answer
|
|
246
|
+
- keeps prompt growth bounded
|
|
247
|
+
- makes task progress explicit for the model
|
|
248
|
+
- lets archive retrieval stay detailed while the working state stays small
|
|
249
|
+
|
|
250
|
+
Use `/state` during a session to inspect reducer mode, `summary` length,
|
|
251
|
+
`pendingDigest` length, and the latest state-update diagnostic.
|
|
252
|
+
|
|
253
|
+
## Security
|
|
254
|
+
|
|
255
|
+
See [SECURITY.md](SECURITY.md) for repository security boundaries, disclosure
|
|
256
|
+
guidelines, and hardening notes.
|
|
257
|
+
|
|
258
|
+
## License
|
|
259
|
+
|
|
260
|
+
[MIT](LICENSE)
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
This repository is under active development. Security fixes are expected to land
|
|
6
|
+
on the latest mainline code first.
|
|
7
|
+
|
|
8
|
+
| Version | Supported |
|
|
9
|
+
| --- | --- |
|
|
10
|
+
| latest `main` / current working tree | Yes |
|
|
11
|
+
| older snapshots / forks / local patches | Best effort only |
|
|
12
|
+
|
|
13
|
+
## Reporting a vulnerability
|
|
14
|
+
|
|
15
|
+
If you believe you found a security issue, please **avoid public disclosure
|
|
16
|
+
first**.
|
|
17
|
+
|
|
18
|
+
Recommended process:
|
|
19
|
+
|
|
20
|
+
1. Share the issue privately with the project maintainers through an existing
|
|
21
|
+
trusted channel.
|
|
22
|
+
2. Include:
|
|
23
|
+
- affected commit / branch
|
|
24
|
+
- reproduction steps
|
|
25
|
+
- impact assessment
|
|
26
|
+
- whether the issue requires local access, workspace access, or network access
|
|
27
|
+
3. Wait for a fix or mitigation plan before publishing details.
|
|
28
|
+
|
|
29
|
+
If this repository is hosted on a platform that supports private security
|
|
30
|
+
reporting, prefer that channel.
|
|
31
|
+
|
|
32
|
+
## Security model
|
|
33
|
+
|
|
34
|
+
Cyrene is a local, terminal-first coding assistant. Its security posture relies
|
|
35
|
+
on a few core boundaries:
|
|
36
|
+
|
|
37
|
+
### 1. Workspace boundary
|
|
38
|
+
|
|
39
|
+
- file tools are intended to stay inside the configured workspace root
|
|
40
|
+
- path-escape checks should reject reads/writes outside the workspace
|
|
41
|
+
- review-gated mutations should show the exact target path before approval
|
|
42
|
+
|
|
43
|
+
### 2. Human review boundary
|
|
44
|
+
|
|
45
|
+
- destructive or higher-risk filesystem actions should require review
|
|
46
|
+
- shell and command execution should be reviewable unless explicitly classified
|
|
47
|
+
as low risk
|
|
48
|
+
- persistent shell sessions should preserve clear status output so users know
|
|
49
|
+
what is running
|
|
50
|
+
|
|
51
|
+
### 3. Prompt/context boundary
|
|
52
|
+
|
|
53
|
+
- long-lived context is compacted into `summary` and `pendingDigest`
|
|
54
|
+
- archive memory is indexed and retrieved selectively instead of replaying
|
|
55
|
+
entire transcripts
|
|
56
|
+
- hidden reducer state should never be shown to users as visible transcript text
|
|
57
|
+
|
|
58
|
+
### 4. Provider boundary
|
|
59
|
+
|
|
60
|
+
- HTTP transport sends prompts to an OpenAI-compatible API when configured
|
|
61
|
+
- `CYRENE_API_KEY` is intentionally excluded from transcript items, session
|
|
62
|
+
JSON, reducer state (`summary` / `pendingDigest`), and memory index storage
|
|
63
|
+
- Cyrene may persist `CYRENE_API_KEY` in **user-scoped environment/profile
|
|
64
|
+
storage** through the login flow:
|
|
65
|
+
- Windows user environment
|
|
66
|
+
- managed shell-profile blocks for zsh / bash / POSIX shells
|
|
67
|
+
- managed fish config file under `~/.config/fish/conf.d/`
|
|
68
|
+
- provider URL and model catalog metadata live in the global user `.cyrene`
|
|
69
|
+
directory and are treated as non-secret runtime metadata
|
|
70
|
+
- model/provider switching should be explicit and visible in the UI
|
|
71
|
+
|
|
72
|
+
## Current hardening expectations
|
|
73
|
+
|
|
74
|
+
When changing code, please preserve or improve these properties:
|
|
75
|
+
|
|
76
|
+
- prevent duplicate request submission and duplicate completion handling
|
|
77
|
+
- avoid command/tool loops that cause accidental repeated execution
|
|
78
|
+
- keep approval flows one-shot and idempotent where possible
|
|
79
|
+
- do not allow hidden reducer metadata to leak into visible assistant output
|
|
80
|
+
- keep large-file and large-output handling bounded to protect terminal stability
|
|
81
|
+
- maintain test coverage for:
|
|
82
|
+
- workspace escape protection
|
|
83
|
+
- review-gated file mutations
|
|
84
|
+
- command/shell risk handling
|
|
85
|
+
- duplicate submit / duplicate finalize guards
|
|
86
|
+
- reducer fallback behavior
|
|
87
|
+
|
|
88
|
+
## Out of scope / non-goals
|
|
89
|
+
|
|
90
|
+
Unless explicitly documented otherwise, this project does **not** currently
|
|
91
|
+
promise:
|
|
92
|
+
|
|
93
|
+
- sandboxing against a malicious local user with full machine access
|
|
94
|
+
- protection against a compromised upstream model or provider
|
|
95
|
+
- protection against unsafe custom plugins, local patches, or user-modified
|
|
96
|
+
prompts/policies
|
|
97
|
+
- backward security support for stale forks or heavily diverged branches
|
|
98
|
+
|
|
99
|
+
## Secure deployment notes
|
|
100
|
+
|
|
101
|
+
If you run Cyrene outside local experimentation:
|
|
102
|
+
|
|
103
|
+
- keep API keys out of the repo and shell history
|
|
104
|
+
- review `.cyrene/` config and session files before sharing them
|
|
105
|
+
- remember that login persistence writes `CYRENE_API_KEY` to user-scoped shell
|
|
106
|
+
or environment storage, not to session JSON
|
|
107
|
+
- treat session logs as potentially sensitive prompt/output data
|
|
108
|
+
- prefer least-privilege execution contexts for shell access
|
|
109
|
+
- verify Docker / CI mounts so the workspace root is exactly what you intend
|
|
110
|
+
- rotate provider credentials if they were ever written to logs or transcripts
|
|
111
|
+
|
|
112
|
+
## Disclosure philosophy
|
|
113
|
+
|
|
114
|
+
Please report vulnerabilities responsibly and give maintainers time to patch
|
|
115
|
+
before publishing exploit details. Public issues are welcome for general
|
|
116
|
+
hardening ideas, but not for live secrets, escape techniques, or reproducible
|
|
117
|
+
unpatched exploit chains.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg width="820" height="200" viewBox="0 0 820 200" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="cyreneLogoTitle cyreneLogoDesc">
|
|
2
|
+
<title id="cyreneLogoTitle">Cyrene Logo</title>
|
|
3
|
+
<desc id="cyreneLogoDesc">Cyrene wordmark paired with a geometric cyan C-shaped signal mark.</desc>
|
|
4
|
+
<g transform="translate(18 20)">
|
|
5
|
+
<path d="M108 44C95.8497 32.2032 77.5944 28.7658 61.9407 35.2795C46.287 41.7932 36 57.07 36 74.0252C36 90.9804 46.287 106.257 61.9407 112.771C77.5944 119.284 95.8497 115.847 108 104.05" stroke="#2FD7FF" stroke-width="18" stroke-linecap="round"/>
|
|
6
|
+
<path d="M77 63L98 80L77 97" stroke="#08131B" stroke-width="14" stroke-linecap="round" stroke-linejoin="round"/>
|
|
7
|
+
<path d="M77 63L98 80L77 97" stroke="#F3FCFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/>
|
|
8
|
+
<circle cx="108" cy="80" r="8" fill="#2FD7FF" stroke="#08131B" stroke-width="4"/>
|
|
9
|
+
</g>
|
|
10
|
+
<text x="178" y="118" fill="#F4FCFF" stroke="#08131B" stroke-width="8" paint-order="stroke fill" font-family="'Segoe UI', 'Helvetica Neue', Arial, sans-serif" font-size="88" font-weight="800" letter-spacing="11">CYRENE</text>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="cyreneMarkTitle cyreneMarkDesc">
|
|
2
|
+
<title id="cyreneMarkTitle">Cyrene Mark</title>
|
|
3
|
+
<desc id="cyreneMarkDesc">A geometric cyan C-shape with a forward signal arrow and locator dot.</desc>
|
|
4
|
+
<path d="M108 44C95.8497 32.2032 77.5944 28.7658 61.9407 35.2795C46.287 41.7932 36 57.07 36 74.0252C36 90.9804 46.287 106.257 61.9407 112.771C77.5944 119.284 95.8497 115.847 108 104.05" stroke="#2FD7FF" stroke-width="18" stroke-linecap="round"/>
|
|
5
|
+
<path d="M77 63L98 80L77 97" stroke="#08131B" stroke-width="14" stroke-linecap="round" stroke-linejoin="round"/>
|
|
6
|
+
<path d="M77 63L98 80L77 97" stroke="#F3FCFF" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/>
|
|
7
|
+
<circle cx="108" cy="80" r="8" fill="#2FD7FF" stroke="#08131B" stroke-width="4"/>
|
|
8
|
+
</svg>
|
package/bin/cyrene.js
ADDED