jobhunt-kit 0.2.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.
Files changed (50) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/.claude-plugin/marketplace.json +14 -0
  3. package/AGENTS.md +23 -0
  4. package/CLAUDE.md +5 -0
  5. package/README.md +122 -0
  6. package/bin/jobhunt-kit.mjs +95 -0
  7. package/installer-assets/gitignore.txt +22 -0
  8. package/installer-assets/runtime-lock.json +492 -0
  9. package/installer-assets/workspace-lock.json +495 -0
  10. package/package.json +52 -0
  11. package/plugins/jobhunt-kit/.claude-plugin/plugin.json +9 -0
  12. package/plugins/jobhunt-kit/.codex-plugin/plugin.json +18 -0
  13. package/plugins/jobhunt-kit/THIRD_PARTY.md +18 -0
  14. package/plugins/jobhunt-kit/package-lock.json +492 -0
  15. package/plugins/jobhunt-kit/package.json +14 -0
  16. package/plugins/jobhunt-kit/references/cli.md +125 -0
  17. package/plugins/jobhunt-kit/references/cover-guidance.md +24 -0
  18. package/plugins/jobhunt-kit/references/hirify/LICENSE +202 -0
  19. package/plugins/jobhunt-kit/references/hirify/NOTICE +2 -0
  20. package/plugins/jobhunt-kit/references/hirify/SKILL.md +139 -0
  21. package/plugins/jobhunt-kit/references/hirify/reference.md +286 -0
  22. package/plugins/jobhunt-kit/references/matching.md +28 -0
  23. package/plugins/jobhunt-kit/references/resume-guidance.md +47 -0
  24. package/plugins/jobhunt-kit/references/storage.md +120 -0
  25. package/plugins/jobhunt-kit/references/workflow.md +89 -0
  26. package/plugins/jobhunt-kit/scripts/cli.mjs +9 -0
  27. package/plugins/jobhunt-kit/scripts/commands.mjs +157 -0
  28. package/plugins/jobhunt-kit/scripts/extract-resume.mjs +27 -0
  29. package/plugins/jobhunt-kit/scripts/hirify.mjs +31 -0
  30. package/plugins/jobhunt-kit/scripts/profile.mjs +79 -0
  31. package/plugins/jobhunt-kit/scripts/resume.mjs +92 -0
  32. package/plugins/jobhunt-kit/scripts/send-packet.mjs +36 -0
  33. package/plugins/jobhunt-kit/scripts/setup.mjs +25 -0
  34. package/plugins/jobhunt-kit/scripts/tracker.mjs +332 -0
  35. package/plugins/jobhunt-kit/skills/job-apply/SKILL.md +61 -0
  36. package/plugins/jobhunt-kit/skills/job-profile/SKILL.md +33 -0
  37. package/plugins/jobhunt-kit/skills/job-resume/SKILL.md +29 -0
  38. package/plugins/jobhunt-kit/skills/job-search/SKILL.md +39 -0
  39. package/plugins/jobhunt-kit/skills/job-track/SKILL.md +30 -0
  40. package/plugins/jobhunt-kit/templates/cover-letter.md +17 -0
  41. package/plugins/jobhunt-kit/templates/intake.md +62 -0
  42. package/plugins/jobhunt-kit/templates/policy.json +6 -0
  43. package/plugins/jobhunt-kit/templates/profile.json +29 -0
  44. package/plugins/jobhunt-kit/templates/profile.md +21 -0
  45. package/plugins/jobhunt-kit/templates/resume-review.md +30 -0
  46. package/plugins/jobhunt-kit/templates/scheduled-search.md +21 -0
  47. package/scripts/check-package.mjs +62 -0
  48. package/tests/commands.test.mjs +143 -0
  49. package/tests/installer.test.mjs +52 -0
  50. package/tests/tracker.test.mjs +180 -0
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -0,0 +1,2 @@
1
+ Hirify CLI
2
+ Copyright 2026 Hirify
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: hirify
3
+ description: Job search through Hirify - vacancies from the user's saved feeds, search across the board, reading a vacancy in full, the contact to apply to, applying on Hirify, and saved searches with delivery. Use when the user asks to find jobs, look at their feeds, pick roles that fit their profile, apply, or set up alerts. Triggers - "find jobs", "what is in my feed", "where do I apply", "apply to this", "hirify".
4
+ ---
5
+
6
+ # Hirify job search
7
+
8
+ Use the Hirify job board through the `hirify` CLI. This file gives the working order; `reference.md`
9
+ has every command in full, and `hirify intro` is the server's guide.
10
+
11
+ ## What stays here, and what you fetch
12
+
13
+ This installed file holds only stable rules. Fetch anything Hirify can change:
14
+
15
+ | What you need | Ask for it |
16
+ |---|---|
17
+ | Filter names and their values | `hirify filter guide` |
18
+ | Reveals, vacancy opens and applies left | `hirify account show` |
19
+ | Rate limits, plan, abilities | `hirify account show --json` |
20
+ | The commands that exist | `hirify --help`, `hirify <noun>` |
21
+
22
+ ## Two rules before anything else
23
+
24
+ **Lists are free. Three commands are metered, and they spend different things.**
25
+
26
+ - `vacancy read` spends one of the day's vacancy opens. Re-reading a vacancy the same day is free.
27
+ - `vacancy reveal` spends 1 reveal, and reveals are scarce. When they run out, reading still works.
28
+ - `vacancy apply` counts against a small daily allowance of its own and **cannot be taken back**. It
29
+ sends a real application, with the user's name and profile, to a person who will read it.
30
+
31
+ **`hirify account show` is the only place these numbers are true.** Read it before spending; never
32
+ state what is left from memory or plan a batch on a stale figure.
33
+
34
+ **Ask the user before every apply, and before anything that changes their account.** Reading needs
35
+ no permission. Sending, saving and configuring do.
36
+
37
+ ## Working order
38
+
39
+ ```bash
40
+ hirify account show
41
+ hirify feed list
42
+ hirify feed show <id>
43
+ hirify vacancy search "senior go"
44
+ hirify vacancy read <slug>
45
+ hirify vacancy reveal <slug>
46
+ hirify vacancy apply <slug>
47
+ ```
48
+
49
+ 1. `hirify account show` before revealing anything.
50
+ 2. Feeds first, search second. A feed is a filter the user built, so it already says what they want.
51
+ 3. Shortlist **from the cards**. They carry no contacts, and that is normal.
52
+ 4. `hirify vacancy read` the shortlist. The card is a headline; the text is where fit is decided, and
53
+ reading is cheap. Judging fit without reading is guessing.
54
+ 5. `hirify vacancy reveal` only what still fits after reading. A reveal spent at random is spent.
55
+ 6. Apply only after the user says yes, and read the rules below first.
56
+
57
+ ## Searching
58
+
59
+ `vacancy search` takes a phrase and any criterion the site's filter form can express, passed as an
60
+ option under its own name. `--limit` sets the page size and `--page` moves through pages; those two
61
+ are the CLI's own, not filters.
62
+
63
+ **`hirify filter guide` is the method and vocabulary, and the only source for either.** Do not guess
64
+ criterion names or values. The final search refuses an unknown criterion, while a misspelt value
65
+ can return an empty list that looks like an honest "nothing matches". If a server does not serve
66
+ the guide, it says so; then ask the user what to filter on.
67
+
68
+ 1. Read `hirify filter guide` and build a draft from the user's request or profile.
69
+ 2. Run `hirify api call filters.preview --data '{"filters":{...},"mode":"compact","per_page":20}'`.
70
+ 3. Inspect cards and `meta.total`; refine and preview again if they are empty, broad or irrelevant.
71
+ 4. Run `hirify vacancy search` with the validated criteria.
72
+
73
+ ## Applying
74
+
75
+ Two cases, two commands:
76
+
77
+ - **Hosted on Hirify** -> `hirify vacancy apply <slug>` sends the application through Hirify.
78
+ - **From somewhere else** -> `hirify vacancy reveal <slug>` gives the link or contact, and the
79
+ application goes there rather than through Hirify. `vacancy apply` refuses these and says so.
80
+ What you do with that destination is between you and your user.
81
+
82
+ - **Ask first, every time, and show what you are about to send.** An application cannot be taken
83
+ back. Never apply to a list on a single "yes".
84
+ - **Never invent the cover letter.** Draft it from what the user actually said about themselves and
85
+ show them the draft; if they gave you nothing, ask rather than fill the gap.
86
+ - **Never choose the profile** when the user has several: `hirify profile list` lists them. With
87
+ exactly one profile it is chosen automatically.
88
+ - After a successful apply, say it was sent and stop. Nobody follows up: the recruiter replies where
89
+ they choose to, and Hirify does not track it.
90
+
91
+ ## Saved searches and delivery
92
+
93
+ These change the user's account, so the same rule holds: propose, get a yes, then do it.
94
+
95
+ ```bash
96
+ hirify feed create "<name>" --filters '<json>' # criteria: hirify filter guide
97
+ hirify feed deliver <id> --telegram | --no-telegram | --webhook <id> | --no-webhook
98
+ hirify webhook list
99
+ hirify webhook create "<name>" <url>
100
+ ```
101
+
102
+ `--filters` takes the same criteria as the site's filter form; read `hirify filter guide` first.
103
+ Creating a delivery endpoint returns a **secret shown once**: give it to the user immediately to
104
+ store, because it signs every delivery and cannot be shown again.
105
+
106
+ ## Telling Hirify something is broken
107
+
108
+ `hirify feedback send <bug|feature> "<title>" --body "<text>" [--vacancy <slug>]` sends a report,
109
+ free. Ask first, send the user's words rather than your own, and report that it was passed on: it
110
+ gives a ticket number or says there is none yet, nothing writes back, and no fix or date is promised.
111
+
112
+ ## When something goes wrong
113
+
114
+ **The message you were given is the truth; this is a map of the kinds, not strings to match.** Every
115
+ failure exits non-zero and writes one line to stderr. Read that line and tell the user what it says.
116
+
117
+ - **Not signed in**: ask the user to run `hirify login` (it opens a browser and needs a person -
118
+ never run it yourself). On a server with no browser: `hirify auth <key>`, key from
119
+ hirify.me/account/api-access.
120
+ - **Sign-in no longer good** (401): expired or revoked. Ask the user to run `hirify login` again.
121
+ - **No access** (403): the sign-in is missing an ability, or the plan does not cover agent access.
122
+ Abilities are fixed at sign-in, so a user who signed in before an ability existed signs in again.
123
+ - **A budget or the pace** (429): a metered action is used up - reveals, vacancy opens, or applies -
124
+ or commands came too fast. The message names which; feeds and search keep working. What is left:
125
+ `hirify account show`.
126
+ - **A refusal naming a length or a value** comes from the server: shorten what it named and send
127
+ again, do not argue with it or assume a bound.
128
+ - **`hirify <noun> has no verb "..."`**: the name does not exist and the message lists the verbs that
129
+ noun takes. Read the list rather than guessing again.
130
+
131
+ ## When no command fits
132
+
133
+ `hirify api call <capability-id> --data '<json>'` runs a capability by its id and prints the answer
134
+ as it comes back, so a job with no named command is a detour, not a dead end. `hirify --help` and
135
+ the server's own catalogue name the capabilities.
136
+
137
+ Reach for a named command first where one exists: it says what a call costs and what a refusal means,
138
+ and this one cannot. It will spend a reveal or send a real application just as readily, so the same
139
+ rule holds - ask the user before anything that sends, saves or configures.
@@ -0,0 +1,286 @@
1
+ # hirify CLI reference
2
+
3
+ Written for an agent. Every command, what it costs, what it answers, and how it refuses.
4
+
5
+ Commands are a noun and a verb: the noun is the thing you are working with, the verb is what you do
6
+ to it. `hirify <noun>` on its own lists the verbs that noun takes. `login`, `logout`, `auth` and
7
+ `intro` stay single words: they are not operations on a thing.
8
+
9
+ **This file describes the CLI, not the state of Hirify.** It is installed with the skill and never
10
+ updated afterwards, so it names no filter, no limit and no number that our side can change. Those
11
+ come from commands: `hirify filter guide` for filters, `hirify account show` for what is left,
12
+ `hirify account show --json` for the plan and the limits. Where this file would have quoted one, it
13
+ names the command instead.
14
+
15
+ Add `--json` to any command to get the server's payload verbatim instead of the text below.
16
+ `--fields a,b` narrows a compact answer to the fields you name and never adds one the answer did not
17
+ carry. Parse `--json`; do not parse the text, it is written for a person to read.
18
+
19
+ **Exit codes are stable.** `0` is success, `1` an ordinary error, and `2` means this Hirify speaks a
20
+ newer manifest than your CLI can read - update the CLI. Every failure also writes one line to stderr
21
+ beginning with `hirify: `. Branch on the code rather than on the message text.
22
+
23
+ Set `HIRIFY_DEBUG=1` in front of a command to also get the server's own answer on stderr. Use it
24
+ when you need to report a problem; the normal output never contains raw payloads.
25
+
26
+ ## Cost model
27
+
28
+ | Command | Cost | Reversible |
29
+ |---|---|---|
30
+ | `account show`, `feed list`, `feed show`, `vacancy search`, `profile list`, `webhook list` | free: they spend nothing | reading only |
31
+ | `vacancy read` | 1 vacancy open from a generous daily allowance, repeats the same day are free | reading only |
32
+ | `vacancy reveal` | 1 reveal, repeats on the same vacancy are free | reading only |
33
+ | `vacancy apply` | counts against a daily allowance of its own | **no**: a real application reaches a real person |
34
+ | `feed create`, `feed deliver`, `webhook create` | free | changes the user's account |
35
+ | `feedback send` | free | a ticket is filed |
36
+ | `filter guide` | free: it spends nothing | reading only |
37
+ | `api call` | whatever the capability it calls costs | whatever that capability does |
38
+
39
+ Free is not unlimited: every command is rate-limited, reading more loosely than searching. A burst
40
+ answers `429` and names the seconds to wait. The numbers are the server's and change without this
41
+ file: `hirify account show --json`, block `limits`.
42
+
43
+ Three budgets run out, and they are separate. Vacancy opens are the allowance `vacancy read` draws
44
+ on. Reveals are the scarce one. Applications have a daily allowance of their own - `vacancy apply`
45
+ is not the free step it looks like. All three are in `hirify account show`, and in
46
+ `hirify account show --json` under
47
+ `quota.read`, `quota.reveal` and `quota.apply`.
48
+
49
+ **No number for any of them is written in this file.** Each block carries `limit`, `used` and
50
+ `remaining` as the server currently has them; that is the only place they are true, and this file
51
+ outlives every change to them.
52
+
53
+ ## Signing in
54
+
55
+ `hirify login` opens a browser and needs a person. Never run it yourself: ask the user to run it.
56
+ It stores access in `~/.config/hirify/auth.json` (mode 600) and renews it without asking again.
57
+ `hirify logout` forgets it. On CI or a server: `hirify auth <key>`, or `HIRIFY_KEY` in the
58
+ environment, which wins over a stored sign-in.
59
+
60
+ Permissions are fixed when the user signs in and cannot be added afterwards. A 403 naming a missing
61
+ permission means the user signed in before that permission existed: they have to run `hirify login`
62
+ again.
63
+
64
+ ## Reading
65
+
66
+ ```bash
67
+ hirify account show
68
+ hirify feed list
69
+ hirify feed show <id> [--limit N] [--page N]
70
+ hirify vacancy search "<phrase>" [--<criterion> <value>]... [--limit N] [--page N]
71
+ ```
72
+
73
+ `account show` reports the plan, the reveals left, the vacancy opens left today, the applications
74
+ left today, and reveal usage over 7 and 30 days. Check it before spending any of the three. The
75
+ allowances come as one number each, not as a fraction.
76
+
77
+ `feed list` lists saved searches as `<id> <name>`, with `(off)` for an inactive one. `feed show
78
+ <id>` returns that feed's vacancies, using the criteria saved in the feed.
79
+
80
+ `vacancy search` is a conduit. The words are the phrase; every option is forwarded to the API under
81
+ the name you gave it, so the criteria are the server's and this CLI holds no copy of them to fall
82
+ behind. `--limit` is the page size and arrives as the API's `per_page`; `--json` steers the CLI and
83
+ is never sent. An option repeated is joined with a comma, which is how the site sends a criterion
84
+ with several values.
85
+
86
+ **The criteria and the method come from `hirify filter guide`, and only from there.** Do not guess
87
+ names or values. The final search refuses an unknown criterion, while a misspelt value can return
88
+ an empty list that looks like an honest answer.
89
+
90
+ Both `feed show` and `vacancy search` page with `--page N`. The last line of a list says which page
91
+ you are on and offers the next one when there may be another.
92
+
93
+ Vacancy cards print as:
94
+
95
+ ```
96
+ <slug>
97
+ <title> · <company or "company hidden">
98
+ [<remote> · <format> · <employment> · <english> · <salary> · verified]
99
+ ```
100
+
101
+ Cards never carry contacts. `company hidden` means the name is revealed by `vacancy reveal`, not
102
+ that the field is broken.
103
+
104
+ ## filter guide: what search can filter on
105
+
106
+ ```bash
107
+ hirify filter guide
108
+ ```
109
+
110
+ Prints the filter guide the server writes: which criteria search accepts, what their values are,
111
+ and the method for turning what a person wants into a filter that works. Free, and it needs
112
+ `agent:read` like the other reading commands.
113
+
114
+ The server derives it from the same source the site's own search reads, so it cannot fall behind
115
+ the search. That is the whole point: nothing in this package writes filter names down, because a
116
+ list written here goes stale silently and an agent acts on it without knowing.
117
+
118
+ The guide requires a preview before a filter is used. For the CLI, invoke the preview capability
119
+ through the generic command:
120
+
121
+ ```bash
122
+ hirify api call filters.preview --data '{"filters":{"search":"product manager"},"mode":"compact","per_page":20}'
123
+ ```
124
+
125
+ Inspect the cards and `meta.total`, refine when needed, and only then run `hirify vacancy search`
126
+ with the same criteria. Preview and search use the same search implementation.
127
+
128
+ `--json` gives `{"guide": "<text>"}`. The text is written for a model to read, so pass it through
129
+ rather than summarising it.
130
+
131
+ A server that does not serve the guide yet answers plainly: `this Hirify server does not serve the
132
+ filter guide yet.` Then the criteria have to come from the user, not from a guess.
133
+
134
+ ## vacancy read: one vacancy in full
135
+
136
+ ```bash
137
+ hirify vacancy read <slug>
138
+ ```
139
+
140
+ The card plus everything else the vacancy page shows: area, grade, skills, location, when it was
141
+ posted, the page address, and the description as text. This is the command that decides fit, and it
142
+ is deliberately cheap.
143
+
144
+ It costs one vacancy open from the daily allowance, and the same vacancy read again the same day
145
+ costs nothing. The output states whether an open was used and how many are left.
146
+
147
+ The last line before that says which way to apply:
148
+
149
+ - `Apply on Hirify: hirify vacancy apply <slug>` - the vacancy is hosted here.
150
+ - `Where to apply: hirify vacancy reveal <slug> (uses 1 reveal)` - it came from elsewhere, so the
151
+ application goes to that destination rather than through Hirify. Take this from `vacancy read`
152
+ rather than finding out from a refusal on `vacancy apply`.
153
+
154
+ Contacts, the apply destination and where the vacancy came from are never in this answer. That is
155
+ what `vacancy reveal` is for.
156
+
157
+ With `--json`, `data.description` is HTML (`data.description_format` says so) and the text output is
158
+ the same content flattened for a terminal. `charged` and `quota` sit next to `data`.
159
+
160
+ Refusals: `there is no vacancy with that slug.`, and, when the day's opens are spent, `you have
161
+ opened as many vacancies today as the daily allowance covers.` - feeds and search still work then,
162
+ and so does any vacancy already read today.
163
+
164
+ ## vacancy reveal: where to apply
165
+
166
+ ```bash
167
+ hirify vacancy reveal <slug>
168
+ ```
169
+
170
+ Spends 1 reveal and returns the company, its LinkedIn page when known, and one or more
171
+ contacts: an address, a form URL, or a link. Revealing the same vacancy again returns the same thing
172
+ and spends nothing, so a repeat is safe. The output states whether a reveal was used and how many
173
+ are left.
174
+
175
+ Shortlist with `vacancy read` first. A reveal spent at random is spent.
176
+
177
+ ## vacancy apply: only on Hirify
178
+
179
+ ```bash
180
+ hirify profile list
181
+ hirify vacancy apply <slug> [--profile <id>] [--cover "<text>"]
182
+ ```
183
+
184
+ `profile list` lists what the user can apply with: `<profile_id> <name> [status · incomplete]`.
185
+
186
+ `vacancy apply` sends an application through Hirify. **Ask the user first, every time, and show
187
+ what you are sending.** It cannot be undone, and it counts against a daily allowance of its own:
188
+ `hirify account show` reports what is left, and `hirify account show --json` carries it as
189
+ `quota.apply` with `limit`, `used` and `remaining` as the server currently has them.
190
+
191
+ - `--profile` is required when the user has more than one profile. With exactly one, it is chosen
192
+ automatically. Never guess between several.
193
+ - `--cover` is optional. There is a length ceiling and the server owns it: if the letter is too
194
+ long, the answer says so. Write it from what the user told you and show them the draft first.
195
+
196
+ Answers:
197
+
198
+ - success: `Applied. Application <id>, status <status>.` Nothing follows up: the recruiter replies
199
+ where they choose to.
200
+ - `there is no vacancy with that slug.`
201
+ - a refusal in the server's own words, which covers archived, flagged, someone else's profile, and
202
+ **vacancies not hosted on Hirify**. For those, use `vacancy reveal` and apply at the destination it
203
+ returns.
204
+ - `the application could not be sent right now.` means our side failed, not the user's data.
205
+
206
+ ## Saved searches and delivery
207
+
208
+ ```bash
209
+ hirify feed create "<name>" [--filters '<json>'] [--telegram|--no-telegram] [--webhook <id>]
210
+ hirify feed deliver <id> [--telegram|--no-telegram] [--webhook <id>|--no-webhook]
211
+ hirify webhook list
212
+ hirify webhook create "<name>" <url>
213
+ ```
214
+
215
+ These change the user's account. Propose, get a yes, then run them.
216
+
217
+ `--filters` takes the same criteria the site's filter form produces, as JSON, and the names come
218
+ from `hirify filter guide`. Omitting it saves a feed with no criteria, which means "send me
219
+ everything" and is legal.
220
+
221
+ `webhook create` answers with the endpoint and a **secret shown once**. Hand it to the user
222
+ immediately and tell them to store it: it signs every delivery and cannot be shown again.
223
+
224
+ ## feedback send
225
+
226
+ ```bash
227
+ hirify feedback send <bug|feature> "<title>" --body "<text>" [--vacancy <slug>]
228
+ ```
229
+
230
+ Both a title and a body are required, and the CLI says so before sending anything. Their lengths
231
+ are the server's rule, not the CLI's: too short or too long comes back as the server's own sentence
232
+ naming which. Ask the user before sending and send their words. The answer gives a ticket number,
233
+ or says there is no number yet. There is no page to open, nothing writes back to the user, and no
234
+ reply, fix or date is promised. Report that it was passed on and stop there.
235
+
236
+ Refusals: too many reports in a short time (with the wait in seconds), the channel being off, or the
237
+ report not being accepted.
238
+
239
+ ## api call: any capability by its id
240
+
241
+ ```bash
242
+ hirify api call <capability-id> [--data '<json>'] [--fields a,b] [--json]
243
+ ```
244
+
245
+ Invokes any capability Hirify lists in its manifest, by its id, and prints the answer. It is here so
246
+ that a job this CLI has no named command for is a detour rather than a dead end. The ids are the
247
+ ones the manifest publishes; the named commands above cover the common ones, and this reaches the
248
+ rest.
249
+
250
+ ```bash
251
+ hirify api call account.status
252
+ hirify api call vacancies.search --data '{"search":"go","per_page":5}'
253
+ hirify api call feeds.create --data '{"name":"Senior Go","filters":{}}'
254
+ ```
255
+
256
+ - Inputs go in `--data` as one JSON object. Each value is routed where the manifest places it: into
257
+ the path, the query string, or the body. A `--data` that is not JSON is refused before anything is
258
+ sent, and a capability the manifest does not list is named as unknown without a request being made.
259
+ - The answer is rendered compactly by default, so it reads without a parser: a vacancy card shows the
260
+ same shortlist fields `vacancy search` prints, and any other shape shows the fields the server
261
+ returned, one per line. `--fields a,b` narrows that to the fields you name.
262
+ - `--json` gives the raw canonical answer instead, refusals included, so what you parse is the
263
+ server's own payload rather than a sentence of ours. On a refusal the raw answer is printed and the
264
+ exit code is non-zero.
265
+
266
+ **Prefer a named command where one exists.** This one carries none of what they know: it will not
267
+ tell you that a call costs a reveal, and it will send a real application as readily as
268
+ `vacancy apply` would. The permission rules do not change: ask the user before anything that sends,
269
+ saves or configures.
270
+
271
+ ## Failure modes worth knowing
272
+
273
+ | Message | What it means | What to do |
274
+ |---|---|---|
275
+ | `you are not signed in yet` | no stored access | ask the user to run `hirify login` |
276
+ | `your sign-in is no longer valid` | the session expired past renewal | ask the user to run `hirify login` |
277
+ | `the key was not accepted (401)` | a manual key was revoked or truncated | new key from the account page |
278
+ | `no access (403)` | missing permission, or the plan does not cover agent access | sign in again, or check the plan |
279
+ | `you have no reveals left right now` | the reveal budget is spent | reading still works; `hirify account show` has what is left |
280
+ | `you have sent as many applications today...` | the daily allowance for applying is spent | reading and revealing still work; `hirify account show` has what is left |
281
+ | `you have opened as many vacancies today...` | the day's vacancy opens are spent | feeds, search and anything already read today still work |
282
+ | `too many requests in a short time` | asking faster than the API allows | wait the seconds it names, then carry on |
283
+ | `something went wrong on our side` | our fault, not the request | retry in a minute |
284
+ | an empty list from a filtered search | usually a criterion name or value that does not exist | check the name against what the server accepts, do not keep guessing |
285
+ | `the network seems to be unavailable` | no connection | retry |
286
+ | `hirify <noun> has no verb "..."` | a command name this CLI does not have | the message lists the verbs that noun takes; read it rather than guessing again |
@@ -0,0 +1,28 @@
1
+ # Сопоставление вакансии с профилем
2
+
3
+ Проверять полное описание. Сначала ограничения, затем предпочтения. Оценка — помощь
4
+ в принятии решения, не предсказание ответа работодателя. Не сравнивать кандидатов.
5
+
6
+ Для каждого обязательного условия из профиля и вакансии записать:
7
+ `requirement`, `result` (pass/fail/unknown), `evidence` (цитата/путь к факту и объяснение).
8
+ Обязательно проверить ограничения remote по стране, уровень/обязанности, рабочий
9
+ график, языки, право на работу по словам кандидата, обязательные навыки, исключения
10
+ компаний и компенсацию, если она является жёстким условием.
11
+ Не переводить gross в net или валюты без явных допущений и текущего источника курса.
12
+ Отсутствующий диапазон зарплаты — unknown, пока кандидат не разрешил такие вакансии.
13
+
14
+ - `suitable`: все обязательные условия подтверждены; предпочтения могут совпадать частично.
15
+ - `review`: есть значимый unknown или неоднозначное обязательное требование.
16
+ - `rejected`: явное нарушение обязательного условия или исключение кандидата.
17
+ - `unreviewed`: только карточка; не входит в число найденных подходящих вакансий.
18
+
19
+ В reasons объяснить сильные совпадения, пробелы и компромиссы. Для ранжирования
20
+ подходящих использовать предпочтения кандидата и актуальность, без выдуманного
21
+ универсального процента. Unknown нельзя превратить в pass ради заполнения пятёрки.
22
+
23
+ `target=5` — максимум новых suitable за запуск. Карточки review показывать отдельно;
24
+ старые вакансии и повторные страницы не считать новыми. До поиска снять список
25
+ существующих ID; put возвращает is_new для первой записи, а обновление карточки
26
+ полным текстом уже даёт false. Поэтому вести множество «новые в этом запуске».
27
+ Остановиться при target, конце выдачи, повторении страницы, исчерпании бюджета
28
+ или времени. Если найдено меньше пяти, назвать конкретную причину.