The install block was written under the assumption that this project has no
users but its author. It has two, so every claim in it is now load-bearing.
Three corrections, each measured rather than reasoned:
- The guard's host is reachable. `git.fromaitochitta.com` resolves to a public
address, serves a valid certificate and answers `git ls-remote` with no
credentials, no global git config and no terminal prompt; a non-existent
repository on the same host fails, so the query can distinguish. A full
anonymous `pip install` of the pinned `v1.3.0` builds a wheel and imports at
1.3.0. The old text told a third party they probably could not reach it.
- The Claude Code route did not work. `claude plugin install` resolves only
through a marketplace and `jobbsok` is not among the catalog's twelve
plugins, so the documented command failed at its first step. It is marked as
landing with milestone 2 instead of being printed as if it worked.
- Windows is named as unsupported, with the specific reason: the entry points
are shell scripts and `.mcp.json` starts the tool server through `bash`. The
Python underneath is already platform-clean, so the gap is packaging.
Prerequisites are stated up front, with a preflight command that needs nothing
installed, because an adopter should learn about a blocked network before
building a virtualenv rather than after.
Outside Step 16's Files list, and so a separate commit rather than part of the
pinned Cowork-verification commit, following the precedent of 90ef620.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
113 lines
5 KiB
Markdown
113 lines
5 KiB
Markdown
# jobbsok
|
||
Local-first job search workspace: sourcing, scoring, case tracking, applications and interview prep.
|
||
|
||
A read-only job search operating system for one person searching for their own
|
||
job. It reads listings the operator is already looking at, scores them against
|
||
a maintained candidate profile, records every accept/reject decision with a
|
||
reason, keeps each case's full correspondence in one folder, drafts
|
||
applications as files, and flags threads that have gone silent. It never
|
||
submits, never sends, never stores a credential.
|
||
|
||
> **Solo-maintained, fork-and-own.** This plugin is a starting point, not a vendor product. Issues are welcome as signals; pull requests are not accepted.
|
||
|
||
*AI-generated: all code produced by Claude Code through dialog-driven development.*
|
||
|
||

|
||

|
||

|
||
|
||
**Status:** pre-release, milestone 1 of six. The candidate profile, the
|
||
scoring script, two skills and the host tool server are built; case folders,
|
||
ingestion, correspondence, drafting and learning are not. The build brief in
|
||
`docs/build-brief.md` is the contract, and milestones ship in order (M1–M6).
|
||
|
||
## Install
|
||
|
||
**Prerequisites.** Python 3.10 or newer -- the host tool server refuses to start
|
||
below that rather than serving on an interpreter the guard cannot run on --
|
||
`git` on `PATH`, and network access to `git.fromaitochitta.com`, the self-hosted
|
||
Forgejo host the ingestion guard is installed from. That host is public and
|
||
needs no account. One command tells you whether your network agrees, and it
|
||
needs nothing else installed:
|
||
|
||
```bash
|
||
git ls-remote https://git.fromaitochitta.com/open/llm-ingestion-pipeline-security.git v1.3.0
|
||
```
|
||
|
||
A printed hash means the guarded ingestion path will build. An error means it
|
||
will not, and that is not a cosmetic loss: the guard is the boundary every
|
||
untrusted listing and email body passes at the write, so an install without it
|
||
is a reader rather than a workspace.
|
||
|
||
**Platform support.** macOS and Linux work today. **Windows does not yet**, and
|
||
the reason is specific rather than general: this plugin's entry points are shell
|
||
scripts and `.mcp.json` starts the tool server through `bash`, which stock
|
||
Windows does not have. The Python underneath is already platform-clean, so this
|
||
is a packaging gap being closed rather than a rewrite. Until it is closed,
|
||
Windows needs a POSIX shell (WSL or Git Bash) and is not a supported target.
|
||
|
||
The plugin runs on two surfaces, and they install differently.
|
||
|
||
**Claude Cowork** -- the route that works today. There is no marketplace command:
|
||
build the archive from this repository's explicit include list, then upload it
|
||
through *Customize -> Plugins*:
|
||
|
||
```bash
|
||
bash scripts/package_plugin.sh # writes jobbsok.plugin
|
||
```
|
||
|
||
Never build that archive with a recursive zip of the repository root: it would
|
||
ship `.git`, the virtualenv, the local-only `STATE.md` and everything under
|
||
`.claude/`. The script exists so that cannot happen by accident.
|
||
|
||
**Claude Code** -- not available yet. `jobbsok` is deliberately absent from the
|
||
`ktg-plugin-marketplace` catalog while it is pre-release, and `claude plugin
|
||
install` resolves only through a marketplace, so no command here would work
|
||
today. The catalog entry lands with milestone 2, pinned to a release tag.
|
||
Printing an install line that fails at its first step would be worse than
|
||
saying so.
|
||
|
||
**Then, once, on either surface** -- build the Python environment the scripts
|
||
and the host tool server run on. This is also the step that installs the
|
||
ingestion guard, and it prints the version it resolved:
|
||
|
||
```bash
|
||
bash scripts/bootstrap.sh # add --med-xlsx for the spreadsheet export
|
||
```
|
||
|
||
In an installed copy this builds the environment under `$CLAUDE_PLUGIN_DATA`,
|
||
which survives a plugin update; the packaged archive deliberately excludes the
|
||
virtualenv, so the bootstrap is the supported route there. Without it the
|
||
`jobbsok-tools` server has no interpreter to run on and refuses to start
|
||
rather than serving on whatever `python3` the PATH offers. `JOBBSOK_PYTHON`
|
||
overrides the interpreter choice.
|
||
|
||
**Finally, the workspace** -- the plugin never guesses at a location:
|
||
|
||
```bash
|
||
export JOBBSOK_WORKSPACE=~/jobbsok-workspace # or pass --workspace
|
||
```
|
||
|
||
The `kandidatprofil` skill scaffolds the tree on first run. The workspace is
|
||
yours, lives outside this repository, and is never committed.
|
||
|
||
## Non-goals
|
||
|
||
Submitting applications. Sending email. Any write to Finn.no or LinkedIn.
|
||
Credential storage. Background jobs. Multi-user support. Recruiter-side
|
||
features. Bulk listing harvest.
|
||
|
||
## Security
|
||
|
||
The trust model, the boundaries and the risks this design accepts are in
|
||
[SECURITY.md](SECURITY.md). The short version: read-only against external
|
||
sites, no credential handling, all data local, and every listing or email body
|
||
passes the ingestion guard before it becomes a file.
|
||
|
||
## Changelog
|
||
|
||
See [CHANGELOG.md](CHANGELOG.md).
|
||
|
||
## License
|
||
|
||
MIT — see [LICENSE](LICENSE).
|