Install

The extracted release archive is the install and your own git repository; every binary ships prebuilt, no Go or Rust needed.

What the quick start leaves out: components, ports, profiles, unattended installs, skill values, deployment, releases. Every setting: Settings; the installed server: Config server.

macOS and Linux

  1. Download

    Get smine-<version>-darwin-arm64.tar.gz (Apple silicon) or -darwin-amd64 (Intel) from the latest release and extract it to any folder. It unpacks as smine/: the source tree plus every binary prebuilt under bin/ (bin/PAYLOAD carries the version).

    The binaries are unsigned, and macOS marks everything it downloads as quarantined: Gatekeeper kills a quarantined unsigned binary on launch, the installer included. Clear the flag once before the first run; the installer clears it from the rest of the folder itself.

    xattr -dr com.apple.quarantine smine
  2. Run the installer

    Needs git and nothing else. It asks for a preset (Minimal, Full, Custom), the components, the skills (all, none, or a numbered list of the repo's skills to toggle) and whether to keep that skill selection. A kept selection skips the skill question next install; -reset-skills or the Profile page's Installer tick asks again.

    It checks only what the selection needs (a headless token for Routines or the Mining pipeline), shows every step and applies after your yes through bin/configserver -install, which also sets up git: safe.bareRepository explicit, the skillcue merge driver and the pre-commit hook.

    cd smine && ./bin/installer
  3. Keep the access token

    On macOS the server runs as LaunchAgent com.smine.configserver on :6001, logs in ~/Library/Logs/; on Linux the installer prints the start command. The first install prints the access token once, the browser's HTTP Basic password; only its SHA-256 digest is stored.

    To rotate it, run the command below. The running server follows the file; an open page reloads and asks for the new token.

    ./bin/configserver -new-credential
  4. Prepare the nightly (optional)

    Routines and the Mining pipeline need one thing, a token: the installer offers the one from claude setup-token, or add labeled per-account tokens on the Profile page (Account tokens, ~/.config/claude-routine/tokens/<label>) and pick one per routine in the Configure widget's Token setting. Operations manual: Routines.

Change the selection later

The selection lives in ~/.claude/smine/install.json. Change it under Profile → Installation: Preview changes lists the steps, Apply selection stores the selection over the record and runs them.

Apply keeps every setting override and skill row. Unticking a component puts its dependents in suspended until it is ticked again. An unchanged selection re-runs whatever is missing.

Later re-deploys run from the Overview's Sync widget: settings, hooks or skills alone over the stored selection, or all of them (the whole installation apply).

Unattended installs

Command or flagDoes
./bin/installer -components minimal -skills all -yesInstalls without asking.
-previewPrints the steps, writes nothing.
-yes without -componentsKeeps the stored selection; Minimal if none.
-reset-skills -yesOnly clears the kept skill selection.
-addr, -peek-port, -peek-control-port, -heartbeat-portPorts, stored as settings in ~/.claude/smine/install.json (Multiple macOS profiles).

From source (development)

./install.sh is the development path: it needs go (and cargo when agentwt or heartbeat is selected), runs the Go installer with go run and builds every binary from the checkout. The same flags apply. A checkout without bin/PAYLOAD is a development checkout: the apply engine and every later Sync build its binaries with go build there.

./install.sh

Seed from your session history

A one-shot bootstrap mines this machine's past sessions: the Welcome page's Bootstrap button, the /smine-bootstrap skill in a session, or bin/routine bootstrap (installed copy smine-routine bootstrap). Run it from the main checkout on main, with a clean tree and the smine peek entry in ~/.claude.json.

Needs BOOTSTRAP_TOKEN_FILE; optional BOOTSTRAP_SINCE=YYYY-MM-DD or BOOTSTRAP_N. BOOTSTRAP_DRY_RUN=1 prints the stage commands and runs nothing. Four stages:

#Stage
1A headless claude cell runs /smine-style.
2A second cell runs /smine --nightly, mining stages through consolidate.
3A third cell runs /smine-orchestrate bootstrap.
4Context packs deploy to the registered repos.
Your repository

The install dir is not connected to the GitHub repo; to push anywhere, add your own remote: git remote add origin <url>. Updates never run git, so commit local changes before updating.

Windows

  1. Run smine-setup.exe

    Download it from the latest release and run it. The wizard lays the full source tree and prebuilt binaries into the chosen folder (default %USERPROFILE%\smine) and hands the rest to configserver.exe -install.

  2. Get past SmartScreen

    The setup exe is unsigned, so SmartScreen may warn on first run. Choose More info → Run anyway, or unblock it in PowerShell:

    Unblock-File smine-setup.exe
  3. Keep the access token

    The first install shows the config server's access token once in a message box (Ctrl+C copies it); the browser asks for it as the password.

  4. Log off and back on once

    Or restart the config server, so the routine runtime picks up the new PATH entry: %LOCALAPPDATA%\smine\bin with the smine-*.exe binaries, jq.exe, peek-mcp.exe and the claude shim.

A fresh folder becomes a standalone git repository with no remote. An existing install updates in place: commit local changes first, review the update with git status.

Install pathNeedsBundled or handled
smine-setup.exeGit for Windows (the wizard offers winget), a Claude runtime.No Go, no Rust. jq.exe, peek-mcp.exe, every smine binary (agentwt.exe and heartbeat.exe included), the bin\PAYLOAD marker and the repo files ship in the installer.
From source (install.ps1)Git for Windows and Go, installed via winget after a consent prompt; cargo for agentwt and heartbeat.Runs the Go installer (cmd/installer): builds the binaries, asks for the selection, delegates to configserver.exe -install.

From source

Run .\install.bat from the repo root: a thin launcher running install.ps1 under -ExecutionPolicy Bypass, since a PowerShell script cannot lift the default Restricted policy itself. install.ps1 passes every argument unchanged to the Go installer: -components, -skills, -yes, -preview, -addr, -peek-port, -peek-control-port, -heartbeat-port.

.\install.bat

What configserver.exe -install does

The install logic both paths share:

Claude runtime

Claude Desktop or the claude CLI (native installer or npm).

CaseResult
A claude visible from Git BashWins.
None visibleThe installer deploys a shim at %LOCALAPPDATA%\smine\bin\claude that re-resolves Claude Desktop's bundled claude.exe per call; Desktop updates need no re-install.
Neither foundA warning, not an error: the install completes; routines won't run until a runtime appears.
Routine tokeninstall.ps1 offers the routine OAuth token once when Routines or the Mining pipeline is selected; setup.exe prints a note instead. Skipped: routines exit 78 until a token exists.

Shell and logs

Git Bash is the one Git for Windows supplies; no WSL. The server, the routine wrapper and the heartbeat daemon run fully detached (windowsgui subsystem): no console window, no Quick-Edit freezes.

Log in %LOCALAPPDATA%\claude-routine\logs\Holds
configserver.logThe config server.
heartbeat.logThe heartbeat daemon (--log-file).
<routine label>.out.log, <routine label>.err.logOne routine.

Follow a log live with Get-Content <log> -Wait.

Your repository

As on macOS: no connection to the GitHub repo; add your own remote with git remote add origin <url>, and commit local changes before updating.

Multiple macOS profiles on one Mac

All user profiles share the machine's loopback port space, so each install needs its own four ports.

Shared ports

The second profile's config server finds the first's peek on the shared port and refuses it: the log names the foreign homes, and the session column stays disabled rather than show another user's sessions. The second heartbeat cannot bind; its sessions' hooks reach the first profile's daemon, which rejects them as a foreign claude home and marks its own hooks sensor degraded.

Install each profile with explicit ports:

./bin/installer -addr 127.0.0.1:6002 -peek-port 4243 -peek-control-port 42443 -heartbeat-port 6102
SettingDefaultFlagWhat listens
config-server.port6001-addrThe config server.
peek.port4242-peek-portThe central peek MCP server; heartbeat's peek address follows it.
peek.control_port42442-peek-control-portpeek's control dashboard and OTLP telemetry receiver.
heartbeat.port6101-heartbeat-portThe heartbeat daemon.

The ports are install-record settings, so plain re-runs and a Profile apply keep them. peek.control_port also fills {{PEEK_CONTROL_PORT}} in the settings template, so each profile's Claude Code exports telemetry to its own peek. peek.claude_home and peek.codex_home point the spawned peek at non-default agent homes.

The install record

~/.claude/smine/install.json holds only overrides, under settings; every other value is the catalog default. Schema 2: an older schema is refused, never imported.

SettingMeaning
config-server.port, peek.port, peek.control_port, heartbeat.portThis install's ports (-addr, -peek-port, -peek-control-port, -heartbeat-port).
config-server.init_welcome, routines.count_tokensInstaller flags.
peek.claude_home, peek.codex_home, config-server.server_pathOptional; empty takes the default home or the installer's PATH.

Change a setting on the config server's Smine tab or with smine-rules settings set <component>.<key> <value>. Kind, default and help per setting: Settings.

Skill values

The record's skills object holds the skill rows.

RowMapsHolds
skills.variablesSKILL_<SKILL>_<KEY> → valueInstall-wide default of a repo-scoped variable, or pinned value of an install-scoped one (Skill model § Interfaces and environment).
skills.providersPROVIDER_<ID> → programA row per provider whose program this install overrides, e.g. PROVIDER_SMINE_RULES.
skills.defaultsinterface id → valueGlobal default of a repo-scoped kind (Per-repo values).

Install-scoped values

The skills sync fills each install-scoped capability into the skill's deployed copy; the first source with a value wins.

#SourceDetail
1Process environment variable named like the rowOverrides the row for every deploy that process runs; a long-running config server keeps its launch environment.
2The record's SKILL_* rowThat one capability of that one skill.
3PROVIDER_* environment variable or rowMoves every capability of the provider's program at once. A provider implements the capability's interface in skills/interfaces.cue.
4Catalog program of an installed componentsmine-rules, smine-agentwt, smine-heartbeat, smine-routine, toolpolicy: bare names on PATH, copied into the smine bin dir on every platform (~/go/bin, %LOCALAPPDATA%\smine\bin as smine-<name>.exe on Windows). The routine runner and bootstrap prepend that dir to the scheduler's minimal PATH; the container image sets it.

The deploy asks each provider <program> interfaces once per run. A capability stays unset when the answer lacks its interface version, the program does not resolve, a path does not exist or the value breaks the value rules; the deploy log and the skill page name the cause.

The skill page's Environment section edits the defaults and, in its advanced disclosure, the provider and capability overrides; it refuses a bad value. A row no skill or provider declares stays, listed as an orphan with a Forget button; configserver -install prints orphan row kept: <key>.

Repo-scoped defaults

Command and path capabilities, and acdsl, have no provider program and are repo-scoped. Their SKILL_* row is only the default for repos that set nothing on the skill's page. A multi-line command keeps its line breaks in the record.

SKILL_FIMPLEMENT_CHECK="make audit"
SKILL_FIMPLEMENT_BUILD="go build ./..."
SKILL_PACKAGECOMMIT_PROJECT_STRIP="bin/acdsl"

bin/acdsl is each ACDSL (Context Linting) repo's own copy, never a PATH program. A vendoring repo tracks it; a repo holding the acdsl source (cmd/acdsl, this checkout) gets it built by the worktree hook on worktree creation and after a base move.

Per-repo values

A repo-scoped value fills at invocation, never at deploy: the deployed SKILL.md reads SKILL_<SKILL>_<KEY> from the session's environment. An unset required one aborts the invocation with a sentence naming the variable, an example and the fix.

LevelSet onStored in
Repo valueA repo chip in the skill page's Environment section (same widget on the Skills Environment tab), commands one per line.The env map of the repo's row in ~/.claude/smine/repos.json. Nothing goes into the repository; a save needs no deploy.
Skill defaultThe same section's default view.skills.variables
Global defaultThe Environment tab's global defaults card: one value per kind a selected skill reads (test, build, check, lint, the acdsl programs, the plans archive).skills.defaults, keyed by interface id, for every skill on every repo.

Per variable the strongest set value wins: repo value, else skill default, else global default. Example: railroad-review's build and test commands are the repo's SKILL_RAILROADREVIEW_BUILD and _TEST values on its skill page.

The skillenv hook

The skillenv hook belongs to the Skill environment component, its own row under Session hooks; without that component it is off. Two modes:

EventWhat it does
SessionStart, CwdChangedResolves the session's main checkout to its registry row and appends export SKILL_…='…' lines to the harness's CLAUDE_ENV_FILE: the resolved repo-scoped values plus the record's install-scoped SKILL_ rows. An unregistered repo gets the defaults alone.
A typed /<skill> (UserPromptExpansion), the agent's Skill call (PreToolUse)Reads the deployed skill's env.json, the repo values its body reads. An unset required one blocks the command or denies the call, so the body never expands and its guard never runs. The reason names the variable, its purpose, an example, the repo's skill page link, a hint to start a new session after setting it, and the #disable inject:env way out. Otherwise one context line per value.
skillenv: <NAME> = "<value>" (<source>)
skillenv: <NAME> not set — optional, its steps are left out

-repos names the registry, -env-file overrides the target file, -claude-home the Claude home. #disable inject:env turns both modes off for a session. Without the hook (a standalone skill, a bundle user, a session with #disable inject:env) the shell's own exports reach the skill the same way.

Deployment

Deployment runs one way: the repo is the source of truth, nothing is read in place.

SourceTargetWritten by
skills/~/.claude/skills/ and ~/.codex/skills/, one dir per skill and per aliasthe skills sync
skills/**/agents/*.md~/.claude/agents/the skills sync
install.json skills.variablesinstall-scoped values in ~/.claude/skills/the skills sync
settings/claude_code/base.json + components/*.json~/.claude/settings.json and ~/.claude.json (mcpServers)configserver -apply
cmd/<name>/ (14 Go hook binaries)~/.claude/hooks/bin/configserver -apply
cmd/rules, cmd/agentwt, cmd/heartbeat, cmd/routineThe smine bin dir: ~/go/bin/smine-*, %LOCALAPPDATA%\smine\bin\smine-*.exe on Windowsconfigserver -apply, per selected component
settings/codex/config.toml~/.codex/config.tomlconfigserver -apply
context/AGENTS.md and the context dirs of the target project reposconfigserver /context/sync

bin/configserver -apply

Applies the stored selection (~/.claude/smine/install.json) through internal/install, per component: hook binaries, PATH binaries, settings entries, MCP registration, Codex config, LaunchAgents or logon tasks, routines. A release archive (bin/PAYLOAD present) copies the prebuilt binaries; a development checkout builds them with go build.

PartRule
Hook binariestoolpolicy, skillhelp, worktreecreate, sessiontitle, readgate, globalcontext, skillcontext, planmodecontext, acdslhook, skillinvokegate, worktreewriteguard, skillenv, playsound (the sound hook: afplay on macOS, PlaySoundW on Windows), heartbeatfeed (posts SessionStart to the daemon, no curl).
Settings entriesFrom settings/claude_code/base.json plus components/*.json, own entries only; base keys added only where absent.
Hook groupsMatched by smineId; replaced when its semantic smineVersion exceeds the live one (a legacy integer counts as its major release). An unselected component's groups park in hooks.disabled.json with smineReason. Only the repo's retire list (settings/claude_code/retired-hooks.json) removes a group.
Owned files~/.codex/config.toml and every copied file are rewritten only while unchanged since smine wrote them.
TrashEvery overwritten or removed file keeps its previous bytes in ~/.claude/smine/trash/, shown on the config server's Trash page.

configserver -sync-skills

The Go skills sync (internal/skills, also run in process by the config server) writes skills to ~/.claude/skills/ and ~/.codex/skills/, agent definitions to ~/.claude/agents/.

PartRule
SelectionLike the install engine, renders the selected skills for the record's component set and skill rows (skills.variables, skills.providers, skills.defaults). Skipped unavailable: a skill whose requires the set misses. Skipped unconfigured: one with an unset required install-scoped variable.
Repo-scoped variablesIn ~/.claude/skills: invocation placeholders (Per-repo values). In ~/.codex/skills: filled from the deploy environment, the record row, the global default (skills.defaults), then the provider.
Rendered filesSKILL.md, help-test.md, title.json, enforce.json, env.json, answer.md, rendered in process from the model file <leaf>.cue beside the .smine-deployed marker. env.json needs the Skill environment component and a body reading a repo value; ~/.claude/skills only.
Filled variablesInstall-scoped ones, in SKILL.md, every copied sibling text file (workflows/, schemas/, context-map.json) and the agents/ files.
Never shipped<leaf>.cue, payloads/, eval/, smoke/.
PruningSkills gone from the repo are kept and listed. -sync-prune, and every sync the install engine or the config server runs, moves marked dirs outside the selection into the trash.
Foreign dirsAn unmarked or locally modified dir under a deployed name is stashed whole before the write.

The context deploy engine

internal/contextdocs runs from the Context page's sync form and is replayed by routine bootstrap. It builds one overlay per registered repo under ~/.claude/smine/context/<name>/.

FileHolds
context.jsonThe source index cut by each entry's Reach: and its scope's language binding, a deploy record first. The repo's own entries (files under its context folder without the synced header) are merged in.
aspects.jsonThe aspects file, beside it.
overlay.patchAdds both files under the context folder; git apply-able, passed by reviews and evals as overlay-patch:.

Only the form's Write to Repo box writes into the repository's working tree; nothing is ever committed. It writes the two files. "project markdown" adds the expanded AGENTS.md, the actions chapters, the rules guides and the facts files, and removes a leftover CLAUDE.md -> AGENTS.md symlink. "sync acdsl" adds the reach-covered gate slice via acdsl.Dist: rules, registry subset, policy, prebuilt bin/acdsl and verifier binaries.

CaseResult
A repo-owned file under a baseline nameAborts the run.
A repo-owned entry that fails validationAborts the run.
A rewritten baseline filePrevious bytes kept in the trash.
The always packRefreshed by every sync: rewritten only when its content changed, the previous pack stashed. A pack file without the smine header is kept, with an error.

Releases

Tagged releases (v*.*.*) run through GitHub Actions (.github/workflows/ci.yml). Every push runs test, test-windows, audit, darwin-payload, windows-payload and installer; on a tag, publish waits for test, darwin-payload and installer and attaches every asset in one shot.

One payload, built by make payload-bin GOOS=<os> GOARCH=<arch> VERSION=x.y.z for every platform: configserver, routine, acdsl, rules, installer, every verifier binary, the fourteen hook binaries and the bin/PAYLOAD marker holding the version. The marker is what makes an extracted archive take its binaries from bin/ instead of building them.

PlatformRelease assets
darwinsmine-<version>-darwin-arm64.tar.gz and -darwin-amd64.tar.gz: the source tree at the tag as smine/ with the payload plus agentwt and heartbeat (make payload-rust, cargo cross targets) under smine/bin/. A macOS job builds one per arch; make payload GOOS=darwin GOARCH=arm64 VERSION=x.y.z is the same build locally into dist/.
windows

A linux job cross-builds the windows payload (make payload-bin GOOS=windows GOARCH=amd64 PAYLOAD_DIR=dist) and fetches the pinned third-party payloads (jq.exe, peek-mcp.exe).

A windows job then builds agentwt.exe and heartbeat.exe and compiles smine-setup.exe from installer/windows/smine.iss with Inno Setup; the tag's publish job attaches it to the same release.

Every payload job, and go build ./... on a windows runner, runs on every push and pull request (version 0.0.0 off-tag), so a broken archive, installer script or *_windows.go file fails CI before a tag exists. make installer-check is the Inno Setup compile locally, against a dummy payload via a dockerized iscc.