ccdeck 3.22.15 → 3.23.1

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.
Files changed (51) hide show
  1. package/README.md +53 -10
  2. package/THIRD_PARTY_NOTICES.md +123 -15
  3. package/bin/deck.js +264 -21
  4. package/dist/web/assets/BrowserWatchModal-B00oF8_I.js +1 -0
  5. package/dist/web/assets/UsageHistoryModal-IkFiv0Vg.js +1 -0
  6. package/dist/web/assets/index-DgrvXP9K.css +1 -0
  7. package/dist/web/assets/index-Q2E4ePHr.js +296 -0
  8. package/dist/web/index.html +9 -5
  9. package/hook/hook.js +631 -99
  10. package/package.json +1 -1
  11. package/release-notes.json +62 -1
  12. package/src/server/activity.mjs +42 -4
  13. package/src/server/args.mjs +30 -4
  14. package/src/server/browser-history.mjs +164 -38
  15. package/src/server/browser-presence.mjs +60 -0
  16. package/src/server/browser-react.mjs +160 -7
  17. package/src/server/browser-watch-store.mjs +319 -17
  18. package/src/server/browser-watch.mjs +304 -60
  19. package/src/server/ccusage.mjs +20 -4
  20. package/src/server/claude-accounts.mjs +79 -34
  21. package/src/server/claude-identity.mjs +121 -0
  22. package/src/server/cswap-admin.mjs +160 -133
  23. package/src/server/cswap-auto.mjs +86 -7
  24. package/src/server/cswap-install.mjs +280 -43
  25. package/src/server/deck-home.mjs +1 -1
  26. package/src/server/deck-prefs.mjs +244 -36
  27. package/src/server/deck-probe.mjs +1 -1
  28. package/src/server/exec.mjs +84 -3
  29. package/src/server/global-install.mjs +13 -0
  30. package/src/server/index.mjs +1454 -184
  31. package/src/server/installer.mjs +136 -8
  32. package/src/server/lan-about.mjs +8 -3
  33. package/src/server/lan-engine.mjs +335 -47
  34. package/src/server/lan-socket.mjs +384 -57
  35. package/src/server/lan-sync.mjs +472 -22
  36. package/src/server/log-writer.mjs +575 -2
  37. package/src/server/login-service.mjs +31 -4
  38. package/src/server/open-url.mjs +22 -2
  39. package/src/server/output-watch.mjs +59 -8
  40. package/src/server/purge-key.mjs +135 -0
  41. package/src/server/quota.mjs +112 -7
  42. package/src/server/running-deck.mjs +15 -1
  43. package/src/server/self-update.mjs +98 -4
  44. package/src/server/session-recap.mjs +89 -0
  45. package/src/server/static-cache.mjs +67 -0
  46. package/src/server/stop-deck.mjs +2 -2
  47. package/src/server/store-lock.mjs +51 -0
  48. package/src/server/supervisor.mjs +1 -1
  49. package/src/server/system-metrics.mjs +143 -17
  50. package/dist/web/assets/index-BYqkKWPC.js +0 -274
  51. package/dist/web/assets/index-s_dF8YYA.css +0 -1
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  **ccdeck keeps them in one queue** — every session stopped on a human, longest wait first, and the count in the topbar is one click to the oldest. That queue is Claude Code's, because the deck reads Codex from its rollout log and a rollout carries no such signal; the canvas under it is both, with every Claude Code subagent on a node of its own.
8
8
 
9
9
  [![npm](https://img.shields.io/npm/v/ccdeck?color=cb3837&logo=npm&logoColor=white)](https://www.npmjs.com/package/ccdeck)
10
- [![agents-deck downloads](https://img.shields.io/npm/dm/agents-deck?color=blue&label=agents-deck%20downloads)](https://www.npmjs.com/package/agents-deck)
10
+ [![npm downloads](https://img.shields.io/npm/dm/ccdeck?color=blue)](https://www.npmjs.com/package/ccdeck)
11
11
  [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE)
12
12
  [![Node.js >=18](https://img.shields.io/badge/node-%3E%3D18-brightgreen?logo=node.js&logoColor=white)](https://nodejs.org)
13
13
  [![macOS · Linux · Windows](https://img.shields.io/badge/macOS%20·%20Linux%20·%20Windows-supported-6aa9f7)](#requirements)
@@ -87,7 +87,7 @@ The deck opens on these eight pictures the first time it runs — they are the w
87
87
  | **Both providers, one canvas** | Claude Code through hooks, Codex through its rollout log. The model chip (`Opus 5`, `GPT-5.5`) tells them apart. |
88
88
  | **Cost and quota, live** | Spend per model and per session, plus Claude and Codex quota windows as they refill. |
89
89
  | **Click to inspect** | Any node opens its prompt, tool calls, token usage and timing. |
90
- | **Survives restarts** | Events are appended to `~/.claude/agent-dag/events.jsonl` and replayed on open. |
90
+ | **Survives restarts** | Events are appended to this platform's log directory (see `--history` below) and replayed on open. |
91
91
  | **Accounts without a terminal** | Sign a new Claude account in, move one or your whole set to another machine, rename, reorder, remove — from the panel. |
92
92
  | **Logins that repair each other** | A Claude login that expires on one of your machines is copied back from another machine on the same network that still has it — see [Local network](#local-network). |
93
93
  | **Knows when it is stale** | Node caches modules at startup, so an upgraded-while-running deck keeps executing old code. This one says so, and can restart itself when nothing is running. |
@@ -188,6 +188,8 @@ Only visits **after this deck started** are ever considered. Your existing histo
188
188
 
189
189
  The Accounts panel reads the store [claude-swap](https://pypi.org/project/claude-swap/) keeps, and can drive it.
190
190
 
191
+ The deck installs that package itself, so it installs it **bounded**: `claude-swap~=0.26`, which is `>= 0.26, == 0.*`, and when PyPI can be reached the exact version it resolved rather than the range. What `cswap --version` reports afterwards has to be that version, or the deck says so and leaves the panel dark rather than driving a copy it cannot account for — this is the tool that holds your Claude logins. The daily upgrade is bounded by the same specifier, and what it left behind is written to `~/.agents-deck/cswap-upgrade.json`.
192
+
191
193
  **`+` → Sign in** runs `claude auth login`, shows you the link, takes the code your browser gives back, and hands the result to `cswap add`. The account you were using **stays active** — signing in replaces the live credentials, so the previous one is switched back the moment the new one is recorded. The code goes straight into the CLI's stdin on this machine; it is never stored, logged, or sent anywhere else.
192
194
 
193
195
  **`share`** on an account produces a `ccdeck2:…` blob to paste into another deck's **`+` → Paste a share**.
@@ -249,19 +251,26 @@ ccdeck [options]
249
251
  have shown it
250
252
  --workspace <path> Only capture sessions whose cwd is inside <path>
251
253
  --scope Restrict to the current working directory
252
- --all Capture every session on this machine (default)
253
- (beside --stop: every deck, not every session)
254
+ --all Capture every session on this machine (default;
255
+ accepted and ignored — it is what a bare run does)
254
256
  --history <path> Override the events log file
255
257
  (default: this platform's log directory —
256
258
  ~/Library/Logs/ccdeck on macOS, %LOCALAPPDATA%\ccdeck\Log
257
259
  on Windows, $XDG_STATE_HOME/ccdeck on Linux)
258
260
  --no-persist RAM-only mode — don't write or replay the log
261
+ --install Put the deck on your PATH and start it at login —
262
+ what an `npx` run needs to survive a reboot
263
+ --install-service Start the deck when you log in. Set up on first run;
264
+ this is only for putting it back
265
+ --uninstall-service Stop starting at login (`--uninstall` does this too)
259
266
  --codex Force Codex capture even if ~/.codex/ is missing
260
267
  --no-codex Skip Codex capture (Claude only)
261
268
  --claude Force Claude capture even if Claude Code wasn't found
262
269
  --no-claude Skip Claude entirely — no hooks, no claude-swap,
263
270
  no Accounts panel (Codex only)
264
- --uninstall Remove ccdeck's hooks from settings files
271
+ --uninstall Remove ccdeck's hooks from settings files, and name
272
+ the files that still hold this deck's private key
273
+ --purge With --uninstall: delete those files too
265
274
  -h, --help Show this help
266
275
  -v, --version Print the version and exit
267
276
  ```
@@ -354,6 +363,7 @@ Environment:
354
363
  | `AGENTS_DECK_CLAUDE` | Full path to the `claude` CLI |
355
364
  | `AGENTS_DECK_CCUSAGE` | Full path to your own `ccusage`, used ahead of everything else |
356
365
  | `CLAUDE_SWAP_BACKUP` | Override the claude-swap store root the Accounts panel reads |
366
+ | `CCDECK_HOME` | Put everything the deck writes — its state and its log — under this directory instead of the platform default. Wins over every rule below it |
357
367
  | `CLAUDE_CONFIG_DIR` | Override `~/.claude` — the hook entry, the event log and everything else the deck writes move with it |
358
368
  | `AGENTS_DECK_LHM_PORT` | Port of a running LibreHardwareMonitor web server, when it is not 8085 (Windows temperatures) |
359
369
 
@@ -371,11 +381,44 @@ Removes every hook entry ccdeck injected from `~/.claude/settings.json`, and `~/
371
381
 
372
382
  It removes the hook entries and nothing else. The forwarder script
373
383
  (`~/.claude/agent-dag/hook.js`), the discovery directory around it, the events
374
- log, and the tools ccdeck installed for you — claude-swap, ccusage, and a `uv`
375
- binary if it had to fetch one — are all left in place, and each has its own
376
- uninstaller. Deleting `~/.claude/agent-dag/` and `~/.agents-deck/` clears
377
- ccdeck's own files; `uv tool uninstall claude-swap` (or `pipx uninstall
378
- claude-swap`) removes the account switcher.
384
+ log, the deck's own state, and the tools ccdeck installed for you — claude-swap,
385
+ ccusage, and a `uv` binary if it had to fetch one — are all left in place, and
386
+ each has its own uninstaller.
387
+
388
+ Three directories hold ccdeck's own files, and the second one matters most:
389
+ `~/.claude/agent-dag/` (the forwarder and the discovery directory), the
390
+ platform's **data** directory, and the platform's **log** directory.
391
+
392
+ | | macOS | Windows | Linux |
393
+ |---|---|---|---|
394
+ | data — `prefs.json` | `~/Library/Application Support/ccdeck` | `%LOCALAPPDATA%\ccdeck\Data` | `$XDG_DATA_HOME/ccdeck` |
395
+ | log — `events.jsonl` | `~/Library/Logs/ccdeck` | `%LOCALAPPDATA%\ccdeck\Log` | `$XDG_STATE_HOME/ccdeck` |
396
+
397
+ `prefs.json` is the one to delete deliberately: it holds this deck's **Local
398
+ network private key**, the one every deck you paired with has pinned. Leaving it
399
+ behind leaves that identity on the machine. (`~/.agents-deck/` holds the managed
400
+ tools rather than the deck's own state, and goes when you remove them.)
401
+
402
+ `uv tool uninstall claude-swap` (or `pipx uninstall claude-swap`) removes the
403
+ account switcher.
404
+
405
+ ### Deleting the key
406
+
407
+ You do not have to work the table above out for yourself, and on an upgraded
408
+ machine it is not the whole answer: `prefs.json` moved to the data directory by
409
+ being **copied**, so a second copy is still in `~/.claude/agent-dag/` and
410
+ deleting one of the two is not deleting the key.
411
+
412
+ `--uninstall` prints every path that still holds one, resolved for your machine.
413
+ Adding `--purge` deletes them:
414
+
415
+ ```bash
416
+ npx ccdeck --uninstall --purge
417
+ ```
418
+
419
+ That takes your ccdeck settings — pairings, aliases, which accounts this deck
420
+ offered — with the key, which is the point: after an uninstall there is nothing
421
+ left for them to configure.
379
422
 
380
423
  ## Updating
381
424
 
@@ -18,12 +18,22 @@ merely courteous.
18
18
 
19
19
  Two things are deliberately **not** listed:
20
20
 
21
- - **Build and test tooling** (`vite`, `vitest`, `typescript`, `@vitejs/plugin-react`)
22
- and **type-only packages** (`@types/*`). These are devDependencies that never
23
- reach the published bundle — `@types/*` erase at compile time.
21
+ - **Test and type tooling** (`vitest`, `typescript`, `@vitejs/plugin-react`) and
22
+ **type-only packages** (`@types/*`). These are devDependencies that never reach
23
+ the published bundle — `@types/*` erase at compile time.
24
24
  - **The server, launcher and hook** (`src/server`, `bin`, `hook`). They import
25
25
  nothing but Node built-ins, so they carry no third-party code at all.
26
26
 
27
+ `vite` used to be named in that first bullet and is not any more, because it is
28
+ the exception the bullet cannot hold: it is a build tool that also **writes code
29
+ of its own into the output**. `dist/web/assets/index-*.js` OPENS with Vite's
30
+ `modulePreloadPolyfill` — the `link[rel="modulepreload"]` feature test and the
31
+ `MutationObserver` that watches for late ones — and its bundled CommonJS interop
32
+ helpers follow it. None of that comes from `src/web`; all of it is in the npm
33
+ tarball, because `dist/web` is in `package.json` `files`. So `vite` is in the
34
+ table below like any other bundled package (#962). The entry does not stop it
35
+ being a devDependency; it records that some of its code ships.
36
+
27
37
  `package-lock.json` records the licences of the full dependency graph as npm
28
38
  resolved it. Apart from the root `packages[""]` entry — which describes ccdeck
29
39
  itself and now reads `AGPL-3.0-only` to match `package.json` — every licence
@@ -31,16 +41,27 @@ field in it belongs to a dependency and is left exactly as npm wrote it.
31
41
 
32
42
  ### Software ccdeck fetches but does not distribute
33
43
 
34
- Three third-party tools are downloaded onto the user's own machine at runtime,
35
- on demand, and are **not** in the npm tarball: `macmon`
36
- (github.com/vladkens/macmon), `uv` (github.com/astral-sh/uv) and `ccusage`
37
- (installed from npm). ccdeck runs them as separate processes and reads their
38
- output; it does not link them, bundle them or redistribute them, so their
39
- licences are not reproduced here — each arrives with its own licence beside
40
- it. They are named for completeness, so that "what ccdeck ships" and "what
41
- ccdeck can run" are not confused.
44
+ Four third-party tools are downloaded onto the user's own machine at runtime, on
45
+ demand, and are **not** in the npm tarball:
46
+
47
+ - `macmon` — github.com/vladkens/macmon, fetched as a release binary.
48
+ - `uv` — github.com/astral-sh/uv, fetched by `src/server/uv-bootstrap.mjs` when
49
+ the machine has no way to install a Python application.
50
+ - `ccusage` — installed from npm, into a private prefix under `~/.agents-deck`.
51
+ - `claude-swap` — installed from PyPI by `src/server/cswap-install.mjs`, with
52
+ `uv tool install` or a `pipx` fallback, and upgraded against
53
+ `https://pypi.org/pypi/claude-swap/json`. Unlike the three above it lands in
54
+ the user's **global** tool path and it handles Claude credentials, which is
55
+ why the deck prints what the install did rather than doing it quietly.
42
56
 
43
- ## Bundled packages (27)
57
+ This list said "three" and named the first three until #962. ccdeck runs all of
58
+ them as separate processes and reads their output; it does not link them, bundle
59
+ them or redistribute them, so their licences are not reproduced here — each
60
+ arrives with its own licence beside it. They are named for completeness, so that
61
+ "what ccdeck ships" and "what ccdeck can run" are not confused. Every one of them
62
+ is off under `AGENTS_DECK_NO_INSTALL=1`.
63
+
64
+ ## Bundled packages (25)
44
65
 
45
66
  | Package | Version | Licence | Copyright |
46
67
  | --- | --- | --- | --- |
@@ -49,7 +70,6 @@ ccdeck can run" are not confused.
49
70
  | `@reactflow/core` | 11.11.4 | MIT | Copyright (c) 2019-2023 webkid GmbH |
50
71
  | `@reactflow/minimap` | 11.7.14 | MIT | Copyright (c) 2019-2023 webkid GmbH |
51
72
  | `@reactflow/node-resizer` | 2.2.14 | MIT | Copyright (c) 2019-2023 webkid GmbH |
52
- | `@reactflow/node-toolbar` | 1.3.14 | MIT | Copyright (c) 2019-2023 webkid GmbH |
53
73
  | `classcat` | 5.0.5 | MIT | Copyright © Jorge Bucaran <<https://jorgebucaran.com>> |
54
74
  | `d3-color` | 3.1.0 | ISC | Copyright 2010-2022 Mike Bostock |
55
75
  | `d3-dispatch` | 3.0.1 | ISC | Copyright 2010-2021 Mike Bostock |
@@ -62,14 +82,13 @@ ccdeck can run" are not confused.
62
82
  | `d3-zoom` | 3.0.0 | ISC | Copyright 2010-2021 Mike Bostock |
63
83
  | `dagre` | 0.8.5 | MIT | Copyright (c) 2012-2014 Chris Pettitt |
64
84
  | `graphlib` | 2.1.8 | MIT | Copyright (c) 2012-2014 Chris Pettitt |
65
- | `js-tokens` | 4.0.0 | MIT | Copyright (c) 2014, 2015, 2016, 2017, 2018 Simon Lydell |
66
85
  | `lodash` | 4.18.1 | MIT | Copyright OpenJS Foundation and other contributors <https://openjsf.org/> |
67
- | `loose-envify` | 1.4.0 | MIT | Copyright (c) 2015 Andres Suarez <zertosh@gmail.com> |
68
86
  | `react` | 18.3.1 | MIT | Copyright (c) Facebook, Inc. and its affiliates. |
69
87
  | `react-dom` | 18.3.1 | MIT | Copyright (c) Facebook, Inc. and its affiliates. |
70
88
  | `reactflow` | 11.11.4 | MIT | Copyright (c) 2019-2023 webkid GmbH |
71
89
  | `scheduler` | 0.23.2 | MIT | Copyright (c) Facebook, Inc. and its affiliates. |
72
90
  | `use-sync-external-store` | 1.6.0 | MIT | Copyright (c) Meta Platforms, Inc. and affiliates. |
91
+ | `vite` | 6.4.3 | MIT | Copyright (c) 2019-present, VoidZero Inc. and Vite contributors |
73
92
  | `zustand` | 4.5.7 | MIT | Copyright (c) 2019 Paul Henschel |
74
93
 
75
94
  Every one is a permissive licence (MIT, ISC, BSD-3-Clause). All are
@@ -79,6 +98,33 @@ preserved, which is the purpose of this file. None of these licences is
79
98
  changed by ccdeck's relicensing, and no copyleft obligation flows back to
80
99
  their authors.
81
100
 
101
+ ### Declared but not emitted (3)
102
+
103
+ Three packages resolve into `node_modules` and do **not** survive the build.
104
+ They were in the table above until #962, which is over-attribution rather than
105
+ under-attribution and so harmless legally — but the paragraph at the top of this
106
+ file says everything in the table is *physically present in the published
107
+ tarball*, and that is a factual claim a redistributor is entitled to rely on. So
108
+ they are listed here instead, with what was looked for in the built chunks and
109
+ not found.
110
+
111
+ | Package | Version | Licence | Searched for in `dist/web/assets/*` | Why it is not there |
112
+ | --- | --- | --- | --- | --- |
113
+ | `js-tokens` | 4.0.0 | MIT | `[gmiyus]{1,6}` — a fragment of its one exported regex, which a minifier cannot rename | A browserify transform's dependency, reached only through `loose-envify`. Rollup never invokes it. |
114
+ | `loose-envify` | 1.4.0 | MIT | `[_$a-zA-Z][$\w]+` — the body of its `process.env.` matcher, likewise a regex literal | Same: it is a browserify transform, declared by `react` and never part of a Rollup graph. |
115
+ | `@reactflow/node-toolbar` | 1.3.14 | MIT | `react-flow__node-toolbar` | Tree-shaken. The deck renders no node toolbar, and unlike its siblings this one contributes no stylesheet either. |
116
+
117
+ Their licence texts are still reproduced below — §3, §6 and §7 — because dropping
118
+ a notice is the expensive mistake and keeping one is free.
119
+
120
+ `@reactflow/node-resizer` is deliberately **not** in this list, and it is the one
121
+ entry #962 got wrong. Its JavaScript is tree-shaken exactly as the toolbar's is —
122
+ `react-flow__resize-control` appears nowhere in the JS chunks — but its
123
+ stylesheet is inlined into `reactflow/dist/style.css`, which `src/web/main.tsx`
124
+ imports, and those 27 rules are in `dist/web/assets/index-*.css` and therefore in
125
+ the tarball. A search of the JS alone says it is absent; a search of what
126
+ actually ships says it is not. It stays in the bundled table.
127
+
82
128
  ## Full licence texts
83
129
 
84
130
  ### 1. `react` 18.3.1, `react-dom` 18.3.1, `scheduler` 0.23.2
@@ -393,3 +439,65 @@ maintained libraries used by this software which have their own
393
439
  licenses; we recommend you read them, as their terms may differ from the
394
440
  terms above.
395
441
  ```
442
+
443
+ ### 13. `vite` 6.4.3
444
+
445
+ The code Vite contributes to `dist/web` is its own — the `modulePreloadPolyfill`
446
+ that opens the entry chunk, and the CommonJS interop helpers that follow it. Both
447
+ are emitted from templates inside `vite/dist/node/chunks/`, so what ships is
448
+ covered by Vite's core licence, reproduced verbatim below from
449
+ `node_modules/vite/LICENSE.md`.
450
+
451
+ ```text
452
+ MIT License
453
+
454
+ Copyright (c) 2019-present, VoidZero Inc. and Vite contributors
455
+
456
+ Permission is hereby granted, free of charge, to any person obtaining a copy
457
+ of this software and associated documentation files (the "Software"), to deal
458
+ in the Software without restriction, including without limitation the rights
459
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
460
+ copies of the Software, and to permit persons to whom the Software is
461
+ furnished to do so, subject to the following conditions:
462
+
463
+ The above copyright notice and this permission notice shall be included in all
464
+ copies or substantial portions of the Software.
465
+
466
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
467
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
468
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
469
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
470
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
471
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
472
+ SOFTWARE.
473
+ ```
474
+
475
+ The interop helpers Vite emits originate in `@rollup/plugin-commonjs`, which Vite
476
+ vendors into the chunks named above rather than resolving at build time — it is
477
+ not a package in this tree. Its notice travels inside `vite/LICENSE.md`, under
478
+ "Licenses of bundled dependencies", and is reproduced here too so that a reader
479
+ of this file alone has it:
480
+
481
+ ```text
482
+ The MIT License (MIT)
483
+
484
+ Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors)
485
+
486
+ Permission is hereby granted, free of charge, to any person obtaining a copy
487
+ of this software and associated documentation files (the "Software"), to deal
488
+ in the Software without restriction, including without limitation the rights
489
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
490
+ copies of the Software, and to permit persons to whom the Software is
491
+ furnished to do so, subject to the following conditions:
492
+
493
+ The above copyright notice and this permission notice shall be included in
494
+ all copies or substantial portions of the Software.
495
+
496
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
497
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
498
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
499
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
500
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
501
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
502
+ THE SOFTWARE.
503
+ ```