@globalfishingwatch/skills 0.0.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.
- package/README.md +89 -0
- package/dist/decode-url/SKILL.md +51 -0
- package/dist/decode-url/index.js +20339 -0
- package/dist/decode-url/scripts/decode-url.mjs +18 -0
- package/dist/decode-url/scripts/register-gfw-resolver.mjs +24 -0
- package/dist/encode-url/MAINTENANCE.md +53 -0
- package/dist/encode-url/SKILL.md +135 -0
- package/dist/encode-url/index.js +20211 -0
- package/dist/encode-url/references/areas.json +1401 -0
- package/dist/encode-url/references/examples-conversations.md +113 -0
- package/dist/encode-url/references/examples.md +234 -0
- package/dist/encode-url/references/filters.md +67 -0
- package/dist/encode-url/references/highlighted-workspaces.md +65 -0
- package/dist/encode-url/references/layers.md +96 -0
- package/dist/encode-url/references/ports.json +27507 -0
- package/dist/encode-url/references/query-params.md +114 -0
- package/dist/encode-url/references/routes.md +24 -0
- package/dist/encode-url/scripts/encode-url.mjs +26 -0
- package/dist/encode-url/scripts/register-gfw-resolver.mjs +24 -0
- package/dist/index.js +20514 -0
- package/dist/package.json +35 -0
- package/package.json +35 -0
- package/src/decode-url/SKILL.md +51 -0
- package/src/decode-url/decode.ts +87 -0
- package/src/decode-url/index.ts +4 -0
- package/src/decode-url/scripts/decode-url.mjs +18 -0
- package/src/decode-url/scripts/register-gfw-resolver.mjs +24 -0
- package/src/decode-url/workspaces.ts +34 -0
- package/src/encode-url/MAINTENANCE.md +53 -0
- package/src/encode-url/SKILL.md +135 -0
- package/src/encode-url/config.ts +8 -0
- package/src/encode-url/dictionary.ts +305 -0
- package/src/encode-url/encode.ts +79 -0
- package/src/encode-url/index.ts +4 -0
- package/src/encode-url/references/areas.json +1401 -0
- package/src/encode-url/references/examples-conversations.md +113 -0
- package/src/encode-url/references/examples.md +234 -0
- package/src/encode-url/references/filters.md +67 -0
- package/src/encode-url/references/highlighted-workspaces.md +65 -0
- package/src/encode-url/references/layers.md +96 -0
- package/src/encode-url/references/ports.json +27507 -0
- package/src/encode-url/references/query-params.md +114 -0
- package/src/encode-url/references/routes.md +24 -0
- package/src/encode-url/routes.ts +166 -0
- package/src/encode-url/scripts/encode-url.mjs +26 -0
- package/src/encode-url/scripts/register-gfw-resolver.mjs +24 -0
- package/src/index.ts +6 -0
package/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# @globalfishingwatch/skills
|
|
2
|
+
|
|
3
|
+
Agent skills for GFW applications, shareable across repos. Each skill lives in `src/<skill-name>/`: a `SKILL.md` (instructions for the agent), runnable scripts, reference docs, and its own code — built into its own self-contained bundle so the whole `src/<skill-name>/` (or `dist/<skill-name>/`) folder can be copied anywhere and just works.
|
|
4
|
+
|
|
5
|
+
## Skills
|
|
6
|
+
|
|
7
|
+
- [encode-url](src/encode-url/SKILL.md) — build a fishing-map URL + TanStack Router navigation config from a navigation intent (route, layers, filters, time range, viewport).
|
|
8
|
+
- [decode-url](src/decode-url/SKILL.md) — decode a fishing-map URL into structured context of what the user is seeing.
|
|
9
|
+
|
|
10
|
+
Both use the real `parseWorkspace`/`stringifyWorkspace` from `@globalfishingwatch/dataviews-client`, so URLs match the app byte-for-byte. `encode-url` owns the shared logic (layer dictionary, route matching) and `decode-url` imports it from there.
|
|
11
|
+
|
|
12
|
+
## Programmatic use
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { decodeMapUrl } from '@globalfishingwatch/skills/decode-url'
|
|
16
|
+
import { encodeMapUrl } from '@globalfishingwatch/skills/encode-url'
|
|
17
|
+
|
|
18
|
+
const context = decodeMapUrl(currentUrl)
|
|
19
|
+
const { navigation, path } = encodeMapUrl({ route: { type: 'workspace' }, state: context.raw })
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`@globalfishingwatch/skills` (no subpath) also re-exports both, for convenience.
|
|
23
|
+
|
|
24
|
+
## Development
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm nx dist skills # build (also builds dataviews-client deps)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This produces `libs/skills/dist/`: a combined `index.js`, plus one self-contained folder per skill (`encode-url/`, `decode-url/`) — each with its own `index.js` bundle alongside its `SKILL.md`, `scripts/`, and `references/`.
|
|
31
|
+
|
|
32
|
+
Skill scripts run with plain `node` (>= 23) and import their own skill's bundle as `@globalfishingwatch/skills/<skill-name>`, resolved by `scripts/register-gfw-resolver.mjs` from (in order): a sibling `index.js` (dist output), a `../../dist/<skill-name>/index.js` in this monorepo (unbuilt source layout), or — once installed as an npm package — normal `node_modules` resolution via the package's `exports` map.
|
|
33
|
+
|
|
34
|
+
## Installing a skill into Claude Code (or another agent)
|
|
35
|
+
|
|
36
|
+
Each skill folder is self-contained (own bundle + `SKILL.md` + `scripts/` + `references/`), so installing one is just copying its folder into the target skills directory.
|
|
37
|
+
|
|
38
|
+
### From this monorepo
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pnpm nx dist skills
|
|
42
|
+
|
|
43
|
+
# Claude Code, this project only
|
|
44
|
+
cp -r libs/skills/dist/encode-url .claude/skills/
|
|
45
|
+
|
|
46
|
+
# Claude Code, all your projects
|
|
47
|
+
cp -r libs/skills/dist/decode-url ~/.claude/skills/
|
|
48
|
+
|
|
49
|
+
# any other agent that reads SKILL.md folders — same idea, just point at its skills dir
|
|
50
|
+
cp -r libs/skills/dist/encode-url /path/to/agent/skills/
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Or, for your own `~/.claude/skills/`, one command per skill — builds, wipes the old copy, reinstalls:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pnpm nx run skills:claude:encode-url
|
|
57
|
+
pnpm nx run skills:claude:decode-url
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### From the published npm package
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pnpm add @globalfishingwatch/skills
|
|
64
|
+
cp -r node_modules/@globalfishingwatch/skills/dist/encode-url ~/.claude/skills/
|
|
65
|
+
cp -r node_modules/@globalfishingwatch/skills/dist/decode-url ~/.claude/skills/
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Into [gfw-agent](https://github.com/GlobalFishingWatch/gfw-agent)
|
|
69
|
+
|
|
70
|
+
Its skills live at repo root `skills/<skill-name>/` (not `.claude/skills/`), and each agent profile (`agents/<name>.json`) opts in via a `skills` array:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pnpm add @globalfishingwatch/skills
|
|
74
|
+
cp -r node_modules/@globalfishingwatch/skills/dist/encode-url skills/
|
|
75
|
+
cp -r node_modules/@globalfishingwatch/skills/dist/decode-url skills/
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Then add the skill name(s) to the profile, e.g. `agents/default.json`:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
"skills": ["encode-url", "decode-url"]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Adding a new skill
|
|
85
|
+
|
|
86
|
+
Create `libs/skills/src/<skill-name>/` with `SKILL.md` (+ optional `scripts/`, `references/`, and code). If it needs logic another skill already has (e.g. the layer dictionary or route matching in `encode-url/`), import it from there rather than duplicating it. Export the skill's public API from an `index.ts`, add its path to `src/index.ts`, and:
|
|
87
|
+
|
|
88
|
+
- add it as an `additionalEntryPoints` entry + `exports["./<skill-name>"]` in `package.json`, so it gets its own bundle
|
|
89
|
+
- add its `assets` globs (`SKILL.md`, `scripts/**/*`, `references/**/*`, …) to the `dist` target in `project.json`
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: decode-url
|
|
3
|
+
description: Decode a GFW map URL into structured context of what the user is currently seeing — route (map/report/vessel/search), visible layers with filters, time range and viewport. Use whenever you receive the user's current URL and need to understand or describe their view, or to modify it (decode, edit the raw state, re-encode with the encode-url skill).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Decode GFW map URL
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
node scripts/decode-url.mjs '<url or path>'
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Accepts a full URL (`https://globalfishingwatch.org/map/...`) or just the path. Output:
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"route": {
|
|
17
|
+
"type": "report",
|
|
18
|
+
"category": "fishing-activity",
|
|
19
|
+
"workspaceId": "default-public",
|
|
20
|
+
"datasetId": "public-eez-areas",
|
|
21
|
+
"areaId": "5682"
|
|
22
|
+
},
|
|
23
|
+
"workspaceName": "Default public workspace",
|
|
24
|
+
"timeRange": { "start": "2025-08-01T00:00:00.000Z", "end": "2026-08-01T00:00:00.000Z" },
|
|
25
|
+
"viewport": { "latitude": 40.7, "longitude": 12.4, "zoom": 4.7 },
|
|
26
|
+
"timebarVisualisation": "events",
|
|
27
|
+
"layers": [
|
|
28
|
+
{
|
|
29
|
+
"id": "ais",
|
|
30
|
+
"name": "Apparent fishing effort (AIS)",
|
|
31
|
+
"category": "activity",
|
|
32
|
+
"visible": true,
|
|
33
|
+
"filters": { "geartype": ["trawlers"] }
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"report": { "reportBufferValue": 50 },
|
|
37
|
+
"vessel": { "vesselSelfReportedId": "..." },
|
|
38
|
+
"search": { "query": "lake aurora" },
|
|
39
|
+
"raw": {}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
How to narrate it:
|
|
44
|
+
|
|
45
|
+
- `route.type` says where the user is: `workspace` (map browsing), `report` (area report — `areaId` within `datasetId`, e.g. `public-eez-areas`; no `datasetId`/`areaId` = global report), `ports-report`, `vessel` (vessel profile), `vessel-search`, `vessel-group-report`, `user`, `workspaces-list`.
|
|
46
|
+
- `workspaceName` (when present) names a curated workspace: Marine Manager MPAs (`category: "marine-manager"`, e.g. Palau, Galapagos and Hermandad) or global curated reports (`activity-report`, `detections-report`, `events-report`, Deep Sea Mining Watch). Lead with it — "you're looking at the Palau Marine Manager workspace" beats reciting layers.
|
|
47
|
+
- Describe only `visible: true` layers; mention hidden ones only if relevant. Layer `filters` use API values: `flag` is ISO3 (translate to country names), `matched: ["false"]` on detections means dark vessels (no AIS match), `geartype`/`vessel_type` are fleet filters.
|
|
48
|
+
- `timeRange` is the analyzed period; no `timeRange` means the app default (roughly the last year).
|
|
49
|
+
- `raw` is the full parsed workspace state — edit it and feed it back to the encode-url skill (`{"route": <route>, "state": <raw>}`) to produce a modified view that keeps everything else identical.
|
|
50
|
+
|
|
51
|
+
Requires node >= 23 (uses `module.registerHooks`). In the monorepo run `pnpm nx dist skills` once so `dist/` exists.
|