@yuiseki/gyazocli 0.6.0 → 0.8.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/README.md +25 -2
- package/dist/commands/search.js +6 -1
- package/dist/commands/sync.js +25 -4
- package/dist/index.js +1 -1
- package/docs/ADR/003-cli-structure.md +5 -1
- package/package.json +3 -2
- package/skills/gyazo/SKILL.md +9 -0
package/README.md
CHANGED
|
@@ -203,14 +203,37 @@ commands are, what the search syntax actually accepts, and the judgement calls
|
|
|
203
203
|
that keep a capture from becoming a claim it does not support. It ships in the
|
|
204
204
|
npm package.
|
|
205
205
|
|
|
206
|
-
Install it
|
|
206
|
+
Install it with [skills](https://github.com/vercel-labs/skills), which reads
|
|
207
|
+
`skills/` straight from this repository:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npx skills add yuiseki/gyazocli
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
That writes the skill to `.agents/skills/gyazo/` in the current project, links
|
|
214
|
+
it for whichever agents are present, and records it in `skills-lock.json`.
|
|
215
|
+
`--list` shows what a repository offers without installing, `-g` installs for
|
|
216
|
+
every project, and `-a claude-code` picks an agent explicitly.
|
|
217
|
+
|
|
218
|
+
From an installed npm package instead:
|
|
207
219
|
|
|
208
220
|
```bash
|
|
209
221
|
mkdir -p ~/.claude/skills
|
|
210
222
|
cp -r "$(npm root -g)/@yuiseki/gyazocli/skills/gyazo" ~/.claude/skills/
|
|
211
223
|
```
|
|
212
224
|
|
|
213
|
-
|
|
225
|
+
From a checkout, `npm run skill:install` copies it into `.claude/skills/` here,
|
|
226
|
+
and takes a destination for anywhere else:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
npm run skill:install # this repository
|
|
230
|
+
npm run skill:install ~/.claude/skills # every project
|
|
231
|
+
npm run skill:install ../other/.claude/skills
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
It copies rather than symlinks, so an installed skill survives this repository
|
|
235
|
+
moving or going away. The copy under `.claude/skills/` is committed, and a test
|
|
236
|
+
fails when it drifts from `skills/`.
|
|
214
237
|
|
|
215
238
|
## Development
|
|
216
239
|
|
package/dist/commands/search.js
CHANGED
|
@@ -4,12 +4,15 @@ exports.registerSearchCommand = registerSearchCommand;
|
|
|
4
4
|
const api_1 = require("../api");
|
|
5
5
|
const credentials_1 = require("../credentials");
|
|
6
6
|
const format_1 = require("../format");
|
|
7
|
+
const options_1 = require("../options");
|
|
7
8
|
const memory_1 = require("../services/memory");
|
|
8
9
|
const images_1 = require("../services/images");
|
|
9
10
|
function registerSearchCommand(program) {
|
|
10
11
|
program
|
|
11
12
|
.command('search [query]')
|
|
12
13
|
.description('Search images')
|
|
14
|
+
.option('-p, --page <number>', 'page number', '1')
|
|
15
|
+
.option('-l, --limit <number>', 'items per page', '20')
|
|
13
16
|
.option('-j, --json', 'output as JSON')
|
|
14
17
|
.option('--no-cache', 'force fetch from API')
|
|
15
18
|
.action(async (query, options) => {
|
|
@@ -20,7 +23,9 @@ function registerSearchCommand(program) {
|
|
|
20
23
|
console.error('Hint: Run `gyazo search -h` for usage.');
|
|
21
24
|
process.exit(1);
|
|
22
25
|
}
|
|
23
|
-
const
|
|
26
|
+
const page = (0, options_1.parsePositiveIntegerOption)(options.page, '--page');
|
|
27
|
+
const limit = (0, options_1.parsePositiveIntegerOption)(options.limit, '--limit');
|
|
28
|
+
const images = await (0, api_1.searchImages)(query, page, limit);
|
|
24
29
|
const useCache = options.cache !== false;
|
|
25
30
|
if (options.json) {
|
|
26
31
|
(0, memory_1.cacheSearchResultImages)(images);
|
package/dist/commands/sync.js
CHANGED
|
@@ -13,12 +13,24 @@ function registerSyncCommand(program) {
|
|
|
13
13
|
.option('--days <number>', 'number of days to sync (used when --date is omitted)')
|
|
14
14
|
.option('--date <yyyy|yyyy-mm|yyyy-mm-dd>', 'sync only this date/month/year range')
|
|
15
15
|
.option('--max-pages <number>', 'max pages to fetch', '10')
|
|
16
|
+
.option('--query <query>', 'fill the cache from a search instead of the listing')
|
|
16
17
|
.action(async (options) => {
|
|
17
18
|
await (0, credentials_1.ensureAccessToken)();
|
|
18
19
|
if (options.date && options.days) {
|
|
19
20
|
console.error('Error: --date and --days cannot be used together.');
|
|
20
21
|
process.exit(1);
|
|
21
22
|
}
|
|
23
|
+
if (options.query && (options.date || options.days)) {
|
|
24
|
+
// Search results are not ordered the same way for every query: a plain
|
|
25
|
+
// query comes back newest first, while a `date:` one starts at the
|
|
26
|
+
// beginning of its range. Nothing here can bound a walk by date
|
|
27
|
+
// safely, and the query language can: put the range in the query.
|
|
28
|
+
console.error('Error: --query cannot be used with --date or --days.');
|
|
29
|
+
console.error('Hint: bound the range inside the query, as');
|
|
30
|
+
console.error(' --query "has:exif date:2026-08"');
|
|
31
|
+
console.error(' --query "has:exif since:2026-08-01 until:2026-08-31"');
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
22
34
|
const maxPages = (0, options_1.parsePositiveIntegerOption)(options.maxPages, '--max-pages');
|
|
23
35
|
let startDate;
|
|
24
36
|
let endDate;
|
|
@@ -37,20 +49,29 @@ function registerSyncCommand(program) {
|
|
|
37
49
|
startDate.setDate(startDate.getDate() - days - 1);
|
|
38
50
|
startDate.setHours(0, 0, 0, 0);
|
|
39
51
|
}
|
|
40
|
-
|
|
52
|
+
if (options.query) {
|
|
53
|
+
console.log(`Syncing images matching ${JSON.stringify(options.query)}...`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
console.log(`Syncing images between ${startDate.toISOString()} and ${endDate.toISOString()}...`);
|
|
57
|
+
}
|
|
41
58
|
const hourlyIndices = new Map();
|
|
42
59
|
for (let page = 1; page <= maxPages; page++) {
|
|
43
|
-
const images =
|
|
60
|
+
const images = options.query
|
|
61
|
+
? await (0, api_1.searchImages)(options.query, page, 100)
|
|
62
|
+
: await (0, api_1.listImages)(page, 100);
|
|
44
63
|
if (images.length === 0)
|
|
45
64
|
break;
|
|
46
65
|
let reachedLimit = false;
|
|
47
66
|
for (const img of images) {
|
|
48
67
|
const createdAt = new Date(img.created_at);
|
|
49
|
-
|
|
68
|
+
// A query says for itself what it covers, and the results are not
|
|
69
|
+
// ordered predictably enough to stop early on a date.
|
|
70
|
+
if (!options.query && createdAt > endDate) {
|
|
50
71
|
// Skip images newer than target range.
|
|
51
72
|
continue;
|
|
52
73
|
}
|
|
53
|
-
if (createdAt < startDate) {
|
|
74
|
+
if (!options.query && createdAt < startDate) {
|
|
54
75
|
reachedLimit = true;
|
|
55
76
|
break;
|
|
56
77
|
}
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,7 @@ program
|
|
|
26
26
|
.name('gyazo')
|
|
27
27
|
.description('Gyazo Memory CLI for AI Secretary')
|
|
28
28
|
.option('--mcp-server', 'run as a Model Context Protocol server over stdio')
|
|
29
|
-
.version('0.
|
|
29
|
+
.version('0.8.0');
|
|
30
30
|
(0, config_1.registerConfigCommand)(program);
|
|
31
31
|
(0, list_1.registerListCommand)(program);
|
|
32
32
|
(0, get_1.registerGetCommand)(program);
|
|
@@ -13,7 +13,7 @@ Adopt and document the existing top-level command structure.
|
|
|
13
13
|
|
|
14
14
|
### 1. Program Metadata
|
|
15
15
|
- Binary name: `gyazo`
|
|
16
|
-
- Version: `0.
|
|
16
|
+
- Version: `0.8.0`
|
|
17
17
|
- Description: `Gyazo Memory CLI for AI Secretary`
|
|
18
18
|
|
|
19
19
|
### 2. Commands
|
|
@@ -44,6 +44,8 @@ Adopt and document the existing top-level command structure.
|
|
|
44
44
|
- `--no-cache`
|
|
45
45
|
- `gyazo search [query]`
|
|
46
46
|
- Options:
|
|
47
|
+
- `-p, --page <number>` (default: `1`)
|
|
48
|
+
- `-l, --limit <number>` (default: `20`)
|
|
47
49
|
- `-j, --json`
|
|
48
50
|
- `--no-cache`
|
|
49
51
|
- `gyazo apps`
|
|
@@ -116,6 +118,8 @@ Adopt and document the existing top-level command structure.
|
|
|
116
118
|
- `--days <number>` (default: `1`, used when `--date` is omitted)
|
|
117
119
|
- `--date <yyyy|yyyy-mm|yyyy-mm-dd>`
|
|
118
120
|
- `--max-pages <number>` (default: `10`)
|
|
121
|
+
- `--query <query>` (fill from a search instead of the listing; not with
|
|
122
|
+
`--date` or `--days`, because the range belongs inside the query)
|
|
119
123
|
- `gyazo import <type> <dir>`
|
|
120
124
|
- Supported types: `json`, `hourly`
|
|
121
125
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuiseki/gyazocli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Gyazo Memory CLI for AI Secretary",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"build": "npx tsc",
|
|
28
28
|
"prepack": "npm run build",
|
|
29
29
|
"test": "npm run build && vitest run",
|
|
30
|
-
"test:watch": "vitest"
|
|
30
|
+
"test:watch": "vitest",
|
|
31
|
+
"skill:install": "node scripts/install-skill.mjs"
|
|
31
32
|
},
|
|
32
33
|
"publishConfig": {
|
|
33
34
|
"access": "public"
|
package/skills/gyazo/SKILL.md
CHANGED
|
@@ -48,6 +48,7 @@ gyazo search 'app:"Gyazo Android"' # the application it came from
|
|
|
48
48
|
gyazo search "ocr:Wi-Fi has:exif" # terms are ANDed
|
|
49
49
|
gyazo search "address:広島 OR address:京都" # capital OR
|
|
50
50
|
gyazo search "has:location -app:Chrome" # leading - negates
|
|
51
|
+
gyazo search "has:exif" --page 2 --limit 50 # 20 per page by default
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
Three things worth knowing before composing a query:
|
|
@@ -96,12 +97,20 @@ endpoint returns the first 100 and cannot page.
|
|
|
96
97
|
```bash
|
|
97
98
|
gyazo sync --days 7 # yesterday back through 7 days
|
|
98
99
|
gyazo sync --date 2026-08 # a whole month
|
|
100
|
+
gyazo sync --query "has:exif OR has:location" --max-pages 20
|
|
99
101
|
```
|
|
100
102
|
|
|
101
103
|
`sync` covers yesterday backwards and never today, because today is still
|
|
102
104
|
happening. For anything from today use `ls --today`, `search`, or a ranking
|
|
103
105
|
command with `--today`.
|
|
104
106
|
|
|
107
|
+
`--query` fills the cache from a search instead of the listing, which is how to
|
|
108
|
+
gather one kind of capture without walking past everything else: photographs
|
|
109
|
+
are a small fraction of a day's screenshots. Put any date range inside the
|
|
110
|
+
query (`date:2026-08`, `since:... until:...`) rather than in `--date`, which
|
|
111
|
+
`--query` refuses. Budget about 40 seconds per page of 100 captures that are
|
|
112
|
+
not cached yet.
|
|
113
|
+
|
|
105
114
|
## Answering questions with captures
|
|
106
115
|
|
|
107
116
|
- A day is a local day. `--date 2026-08-30` means that date in this machine's
|