corkern 2.0.0rc2__tar.gz
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.
- corkern-2.0.0rc2/.gitignore +12 -0
- corkern-2.0.0rc2/LICENSE +21 -0
- corkern-2.0.0rc2/PKG-INFO +110 -0
- corkern-2.0.0rc2/PYPI.md +82 -0
- corkern-2.0.0rc2/pyproject.toml +53 -0
- corkern-2.0.0rc2/src/corkern/__init__.py +1 -0
- corkern-2.0.0rc2/src/corkern/claude_commands/corkern-distill.md +12 -0
- corkern-2.0.0rc2/src/corkern/claude_commands/corkern-harvest.md +13 -0
- corkern-2.0.0rc2/src/corkern/claude_commands/corkern-memory-prune.md +15 -0
- corkern-2.0.0rc2/src/corkern/claude_commands/corkern-status.md +6 -0
- corkern-2.0.0rc2/src/corkern/claude_print.py +30 -0
- corkern-2.0.0rc2/src/corkern/commands/__init__.py +0 -0
- corkern-2.0.0rc2/src/corkern/commands/add_cmd.py +104 -0
- corkern-2.0.0rc2/src/corkern/commands/ai_cmd.py +238 -0
- corkern-2.0.0rc2/src/corkern/commands/crg_cmd.py +60 -0
- corkern-2.0.0rc2/src/corkern/commands/distill_cmd.py +106 -0
- corkern-2.0.0rc2/src/corkern/commands/export_cmd.py +305 -0
- corkern-2.0.0rc2/src/corkern/commands/graphify_cmd.py +128 -0
- corkern-2.0.0rc2/src/corkern/commands/harvest_cmd.py +412 -0
- corkern-2.0.0rc2/src/corkern/commands/init_cmd.py +30 -0
- corkern-2.0.0rc2/src/corkern/commands/init_device_cmd.py +396 -0
- corkern-2.0.0rc2/src/corkern/commands/iwe_cmd.py +122 -0
- corkern-2.0.0rc2/src/corkern/commands/list_cmd.py +105 -0
- corkern-2.0.0rc2/src/corkern/commands/metrics_cmd.py +81 -0
- corkern-2.0.0rc2/src/corkern/commands/migrate_cmd.py +69 -0
- corkern-2.0.0rc2/src/corkern/commands/prune_cmd.py +127 -0
- corkern-2.0.0rc2/src/corkern/commands/reminders.py +145 -0
- corkern-2.0.0rc2/src/corkern/commands/remove_cmd.py +32 -0
- corkern-2.0.0rc2/src/corkern/commands/secrets_cmd.py +177 -0
- corkern-2.0.0rc2/src/corkern/commands/sessions_cmd.py +52 -0
- corkern-2.0.0rc2/src/corkern/commands/setup_cmd.py +92 -0
- corkern-2.0.0rc2/src/corkern/commands/signing_check.py +216 -0
- corkern-2.0.0rc2/src/corkern/commands/signing_cmd.py +275 -0
- corkern-2.0.0rc2/src/corkern/commands/status_cmd.py +421 -0
- corkern-2.0.0rc2/src/corkern/commands/trust_cmd.py +342 -0
- corkern-2.0.0rc2/src/corkern/config.py +352 -0
- corkern-2.0.0rc2/src/corkern/devices.py +74 -0
- corkern-2.0.0rc2/src/corkern/export_format.py +93 -0
- corkern-2.0.0rc2/src/corkern/guard.py +630 -0
- corkern-2.0.0rc2/src/corkern/hooks/corkern-commit-memory.sh +35 -0
- corkern-2.0.0rc2/src/corkern/hooks/corkern-pull.sh +12 -0
- corkern-2.0.0rc2/src/corkern/hooks/corkern-push.sh +20 -0
- corkern-2.0.0rc2/src/corkern/hooks/corkern-session-notify.sh +15 -0
- corkern-2.0.0rc2/src/corkern/hooks/corkern.sh +47 -0
- corkern-2.0.0rc2/src/corkern/hooks/lib.sh +553 -0
- corkern-2.0.0rc2/src/corkern/hooks_install.py +64 -0
- corkern-2.0.0rc2/src/corkern/instance.py +134 -0
- corkern-2.0.0rc2/src/corkern/knowledge_repo.py +246 -0
- corkern-2.0.0rc2/src/corkern/main.py +112 -0
- corkern-2.0.0rc2/src/corkern/memory_index.py +36 -0
- corkern-2.0.0rc2/src/corkern/migrate.py +211 -0
- corkern-2.0.0rc2/src/corkern/secret_scan.py +86 -0
corkern-2.0.0rc2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SCPG
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: corkern
|
|
3
|
+
Version: 2.0.0rc2
|
|
4
|
+
Summary: Collective knowledge for Claude Code: syncs its memory across projects, devices and people through a private git repository
|
|
5
|
+
Author: SCPG
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: ai,claude,claude-code,git,knowledge-base,memory,sync
|
|
9
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: rich<14,>=13
|
|
23
|
+
Requires-Dist: typer<1,>=0.12
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest-cov<6,>=5; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest<10,>=9.0.3; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
> ⚠ **First test release — please do not use it yet.**
|
|
30
|
+
> This is corkern's first upload to PyPI, published only to try the release process. It is
|
|
31
|
+
> not meant for use. A proper version is planned for the coming weeks.
|
|
32
|
+
|
|
33
|
+
# corkern
|
|
34
|
+
|
|
35
|
+
**Collective knowledge for Claude Code — across projects, devices and people.**
|
|
36
|
+
|
|
37
|
+
Claude Code keeps what it learns about you and your work in per-project memory files on one
|
|
38
|
+
machine. corkern turns that into a synced knowledge base: a private git repository that every
|
|
39
|
+
machine you use reads from and writes to, so what was learned in one project, on one laptop, is
|
|
40
|
+
there the next time — anywhere.
|
|
41
|
+
|
|
42
|
+
## Install — once per machine
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
uv tool install corkern # or: pipx install corkern
|
|
46
|
+
corkern setup --clone git@github.com:<you>/<your-private-knowledge-repo>.git
|
|
47
|
+
corkern signing # this machine's signing (+ push) key — asks first
|
|
48
|
+
corkern init-device --apply # wire Claude Code — shows the plan, asks first
|
|
49
|
+
corkern doctor # check the installation
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
First machine without a knowledge repo yet: `corkern setup --create-github <you>/<name>` creates
|
|
53
|
+
it as a **private** GitHub repository (`--new` keeps it local).
|
|
54
|
+
|
|
55
|
+
corkern is meant to be installed exactly once per user, as a tool. A copy inside a project's
|
|
56
|
+
virtual environment refuses to act (only `--version`, `--help`, `doctor` and `status` run) —
|
|
57
|
+
`corkern doctor` shows every copy it finds.
|
|
58
|
+
|
|
59
|
+
## What it does
|
|
60
|
+
|
|
61
|
+
- **Syncs memories** between machines through a private git repository you own: pulled when a
|
|
62
|
+
Claude session starts, committed as memories are written, pushed when Claude finishes a reply.
|
|
63
|
+
- **Brings context into every session**: open reminders, recent session notes and important
|
|
64
|
+
memories are shown to Claude at session start.
|
|
65
|
+
- **Keeps concurrent edits side by side**: when two machines change the same memory, both versions
|
|
66
|
+
are kept (`<name>.conflict-<host>-<time>.md`) and reported. Memory indexes and the project
|
|
67
|
+
registry merge line by line.
|
|
68
|
+
- **Stays out of Claude's way**: the hooks always exit successfully; sync problems are recorded and
|
|
69
|
+
shown by `corkern status`.
|
|
70
|
+
- **One key per machine**: each machine signs its memory commits with its own key and can push
|
|
71
|
+
with a deploy key limited to the knowledge repository.
|
|
72
|
+
- **Accepts only what your devices signed** (opt-in, `corkern trust`): incoming memories signed by
|
|
73
|
+
any other key, or unsigned, are held back until you accept them.
|
|
74
|
+
- **Keeps secrets out of the repository**: before every commit, known token formats, private keys
|
|
75
|
+
and `password = …`-style values are replaced by a marker; the original stays on that machine.
|
|
76
|
+
The scan is pattern-based: a secret in a format it does not know can still get through.
|
|
77
|
+
- **Warns when `MEMORY.md` outgrows what Claude Code loads** (200 lines / 25 KB).
|
|
78
|
+
- **Uses Claude Code's own setting** (`autoMemoryDirectory`) to point each project's memory at the
|
|
79
|
+
knowledge repository.
|
|
80
|
+
|
|
81
|
+
## What corkern writes on your machine
|
|
82
|
+
|
|
83
|
+
| File | What corkern adds |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `~/.config/corkern/machine.conf` | this machine's knowledge repository (machine-local) |
|
|
86
|
+
| `~/.local/share/corkern/hooks/` | its hook scripts, copied from the package |
|
|
87
|
+
| `~/.claude/settings.json` | one hook each for SessionStart, PostToolUse, Stop, SessionEnd — merged, a backup first |
|
|
88
|
+
| `~/.claude/CLAUDE.md` | one line: `@~/.corkern/global/CLAUDE.md` |
|
|
89
|
+
| `~/.claude/commands/corkern-*.md` | four slash commands |
|
|
90
|
+
| `<project>/.claude/settings.local.json` | `autoMemoryDirectory` (kept out of the project's git) |
|
|
91
|
+
|
|
92
|
+
What goes into `~/.claude` is the same on every machine (`$HOME`-relative, a no-op where corkern
|
|
93
|
+
is not installed), so it works with dotfile managers such as yadm, chezmoi or stow. A file that is
|
|
94
|
+
a symlink is never written through.
|
|
95
|
+
|
|
96
|
+
## Status
|
|
97
|
+
|
|
98
|
+
corkern was built by one developer for their own machines. Team use has only been simulated (10
|
|
99
|
+
Docker containers, three teams, one untrusted intruder). Use it at your own risk; when something
|
|
100
|
+
goes wrong, corkern reports it and keeps both versions rather than overwriting.
|
|
101
|
+
|
|
102
|
+
Memories leave the machine only through git, to the knowledge repository you configure — and,
|
|
103
|
+
when you run `corkern distill` or `corkern harvest`, to Claude for the analysis.
|
|
104
|
+
|
|
105
|
+
For Claude Code there is an open request for built-in sync of user config and memory:
|
|
106
|
+
[anthropics/claude-code#87027](https://github.com/anthropics/claude-code/issues/87027).
|
|
107
|
+
|
|
108
|
+
## Licence
|
|
109
|
+
|
|
110
|
+
MIT
|
corkern-2.0.0rc2/PYPI.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
> ⚠ **First test release — please do not use it yet.**
|
|
2
|
+
> This is corkern's first upload to PyPI, published only to try the release process. It is
|
|
3
|
+
> not meant for use. A proper version is planned for the coming weeks.
|
|
4
|
+
|
|
5
|
+
# corkern
|
|
6
|
+
|
|
7
|
+
**Collective knowledge for Claude Code — across projects, devices and people.**
|
|
8
|
+
|
|
9
|
+
Claude Code keeps what it learns about you and your work in per-project memory files on one
|
|
10
|
+
machine. corkern turns that into a synced knowledge base: a private git repository that every
|
|
11
|
+
machine you use reads from and writes to, so what was learned in one project, on one laptop, is
|
|
12
|
+
there the next time — anywhere.
|
|
13
|
+
|
|
14
|
+
## Install — once per machine
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
uv tool install corkern # or: pipx install corkern
|
|
18
|
+
corkern setup --clone git@github.com:<you>/<your-private-knowledge-repo>.git
|
|
19
|
+
corkern signing # this machine's signing (+ push) key — asks first
|
|
20
|
+
corkern init-device --apply # wire Claude Code — shows the plan, asks first
|
|
21
|
+
corkern doctor # check the installation
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
First machine without a knowledge repo yet: `corkern setup --create-github <you>/<name>` creates
|
|
25
|
+
it as a **private** GitHub repository (`--new` keeps it local).
|
|
26
|
+
|
|
27
|
+
corkern is meant to be installed exactly once per user, as a tool. A copy inside a project's
|
|
28
|
+
virtual environment refuses to act (only `--version`, `--help`, `doctor` and `status` run) —
|
|
29
|
+
`corkern doctor` shows every copy it finds.
|
|
30
|
+
|
|
31
|
+
## What it does
|
|
32
|
+
|
|
33
|
+
- **Syncs memories** between machines through a private git repository you own: pulled when a
|
|
34
|
+
Claude session starts, committed as memories are written, pushed when Claude finishes a reply.
|
|
35
|
+
- **Brings context into every session**: open reminders, recent session notes and important
|
|
36
|
+
memories are shown to Claude at session start.
|
|
37
|
+
- **Keeps concurrent edits side by side**: when two machines change the same memory, both versions
|
|
38
|
+
are kept (`<name>.conflict-<host>-<time>.md`) and reported. Memory indexes and the project
|
|
39
|
+
registry merge line by line.
|
|
40
|
+
- **Stays out of Claude's way**: the hooks always exit successfully; sync problems are recorded and
|
|
41
|
+
shown by `corkern status`.
|
|
42
|
+
- **One key per machine**: each machine signs its memory commits with its own key and can push
|
|
43
|
+
with a deploy key limited to the knowledge repository.
|
|
44
|
+
- **Accepts only what your devices signed** (opt-in, `corkern trust`): incoming memories signed by
|
|
45
|
+
any other key, or unsigned, are held back until you accept them.
|
|
46
|
+
- **Keeps secrets out of the repository**: before every commit, known token formats, private keys
|
|
47
|
+
and `password = …`-style values are replaced by a marker; the original stays on that machine.
|
|
48
|
+
The scan is pattern-based: a secret in a format it does not know can still get through.
|
|
49
|
+
- **Warns when `MEMORY.md` outgrows what Claude Code loads** (200 lines / 25 KB).
|
|
50
|
+
- **Uses Claude Code's own setting** (`autoMemoryDirectory`) to point each project's memory at the
|
|
51
|
+
knowledge repository.
|
|
52
|
+
|
|
53
|
+
## What corkern writes on your machine
|
|
54
|
+
|
|
55
|
+
| File | What corkern adds |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `~/.config/corkern/machine.conf` | this machine's knowledge repository (machine-local) |
|
|
58
|
+
| `~/.local/share/corkern/hooks/` | its hook scripts, copied from the package |
|
|
59
|
+
| `~/.claude/settings.json` | one hook each for SessionStart, PostToolUse, Stop, SessionEnd — merged, a backup first |
|
|
60
|
+
| `~/.claude/CLAUDE.md` | one line: `@~/.corkern/global/CLAUDE.md` |
|
|
61
|
+
| `~/.claude/commands/corkern-*.md` | four slash commands |
|
|
62
|
+
| `<project>/.claude/settings.local.json` | `autoMemoryDirectory` (kept out of the project's git) |
|
|
63
|
+
|
|
64
|
+
What goes into `~/.claude` is the same on every machine (`$HOME`-relative, a no-op where corkern
|
|
65
|
+
is not installed), so it works with dotfile managers such as yadm, chezmoi or stow. A file that is
|
|
66
|
+
a symlink is never written through.
|
|
67
|
+
|
|
68
|
+
## Status
|
|
69
|
+
|
|
70
|
+
corkern was built by one developer for their own machines. Team use has only been simulated (10
|
|
71
|
+
Docker containers, three teams, one untrusted intruder). Use it at your own risk; when something
|
|
72
|
+
goes wrong, corkern reports it and keeps both versions rather than overwriting.
|
|
73
|
+
|
|
74
|
+
Memories leave the machine only through git, to the knowledge repository you configure — and,
|
|
75
|
+
when you run `corkern distill` or `corkern harvest`, to Claude for the analysis.
|
|
76
|
+
|
|
77
|
+
For Claude Code there is an open request for built-in sync of user config and memory:
|
|
78
|
+
[anthropics/claude-code#87027](https://github.com/anthropics/claude-code/issues/87027).
|
|
79
|
+
|
|
80
|
+
## Licence
|
|
81
|
+
|
|
82
|
+
MIT
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "corkern"
|
|
7
|
+
version = "2.0.0rc2"
|
|
8
|
+
description = "Collective knowledge for Claude Code: syncs its memory across projects, devices and people through a private git repository"
|
|
9
|
+
readme = "PYPI.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
authors = [{ name = "SCPG" }]
|
|
13
|
+
requires-python = ">=3.10"
|
|
14
|
+
keywords = ["claude", "claude-code", "memory", "sync", "git", "knowledge-base", "ai"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Operating System :: POSIX :: Linux",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: Software Development",
|
|
27
|
+
"Topic :: Utilities",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"typer>=0.12,<1",
|
|
31
|
+
"rich>=13,<14",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"pytest>=9.0.3,<10",
|
|
37
|
+
"pytest-cov>=5,<6",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
corkern = "corkern.main:main"
|
|
42
|
+
|
|
43
|
+
[tool.hatch.build.targets.wheel]
|
|
44
|
+
packages = ["src/corkern"]
|
|
45
|
+
|
|
46
|
+
# The source package holds the code, its licence and the PyPI page, nothing else — never tests, docs, docker, migrate or any
|
|
47
|
+
# untracked folder (reports/, research_notes/, tmp.local/ may hold personal data). Enforced by
|
|
48
|
+
# tests/test_package.py.
|
|
49
|
+
[tool.hatch.build.targets.sdist]
|
|
50
|
+
only-include = ["src/corkern", "pyproject.toml", "PYPI.md", "LICENSE"]
|
|
51
|
+
|
|
52
|
+
[tool.pytest.ini_options]
|
|
53
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.0.0rc2"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Run `corkern distill` to synthesise cross-project insights from all corkern memory files.
|
|
2
|
+
|
|
3
|
+
Steps:
|
|
4
|
+
1. Ask the user whether to run interactively or auto-save:
|
|
5
|
+
- **Auto** (saves to `memory/global/synthesis.md`): run `corkern distill --auto`
|
|
6
|
+
- **Interactive** (review with Claude): run `corkern distill`
|
|
7
|
+
2. Run the chosen command via Bash.
|
|
8
|
+
3. If `--auto` was used, read `memory/global/synthesis.md` in the knowledge repo (`$CORKERN_MEMORY_DIR`) and summarise the findings to the user.
|
|
9
|
+
4. For any **Stale Candidates** identified: offer to add `status: stale` to their frontmatter — one file at a time, with user confirmation for each.
|
|
10
|
+
5. For any **Universal Principles** identified (rules appearing in 2+ projects): offer to add them to `memory/global/principles.md` and remove them from the individual project memory files — with user confirmation.
|
|
11
|
+
|
|
12
|
+
Always confirm with the user before modifying any memory file.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Run `corkern harvest` to extract memories from past Claude conversations for the current project.
|
|
2
|
+
|
|
3
|
+
Steps:
|
|
4
|
+
1. Run `corkern prune` first to show which conversations are new, changed or already harvested.
|
|
5
|
+
2. Run `corkern harvest` (detects the project from the current directory). With several conversations it asks which to process — answer `all` or numbers.
|
|
6
|
+
3. Review the new memory files it lists in `memory/<slug>/` of the knowledge repo; they are already added to `MEMORY.md`. Existing files are never overwritten (a new version gets a `.harvested-<time>` suffix) — merge those with the user.
|
|
7
|
+
4. If it saved a `harvested-<date>.md` bulk file instead, run `corkern refine`.
|
|
8
|
+
|
|
9
|
+
Flags:
|
|
10
|
+
- `corkern harvest --interactive` — opens an interactive Claude session with the conversations as context, so the user can add their own recollections.
|
|
11
|
+
- `corkern harvest --all` — reprocesses already harvested conversations.
|
|
12
|
+
|
|
13
|
+
Secrets in transcripts are replaced by a marker before anything is committed. After harvesting, run `/corkern-distill` to check whether any extracted memories should be promoted to global.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Run `corkern memory-prune` to archive expired or stale memory files for the current project.
|
|
2
|
+
|
|
3
|
+
Steps:
|
|
4
|
+
1. Run `corkern memory-prune --dry-run` to preview candidates without touching anything.
|
|
5
|
+
2. Show the user the list of expired/stale files found.
|
|
6
|
+
3. Explain what each candidate is and why it was flagged (expired date, status: stale marker).
|
|
7
|
+
4. Ask the user to confirm before proceeding.
|
|
8
|
+
5. If confirmed, run `corkern memory-prune` (which asks for confirmation again in the terminal).
|
|
9
|
+
|
|
10
|
+
Notes:
|
|
11
|
+
- Files with `expires: YYYY-MM-DD` in frontmatter are candidates after that date passes.
|
|
12
|
+
- Files with `status: stale` in frontmatter are candidates regardless of date.
|
|
13
|
+
- Archived files go to `memory/<slug>/archive/` — never deleted, always recoverable.
|
|
14
|
+
- To mark a file stale: add `status: stale` inside its frontmatter `metadata:` block.
|
|
15
|
+
- To mark a file with an expiry: add `expires: YYYY-MM-DD` inside `metadata:`.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
Run `corkern status` to check corkern's health.
|
|
2
|
+
|
|
3
|
+
- `corkern status` — summary: sync, signing and trust, secrets removed, memory index sizes, hooks, projects.
|
|
4
|
+
- `corkern status -v` — full diagnostics: every project's wiring, hook scripts, slash commands, Claude Code memory folders not synced into corkern, knowledge graphs per project, IWE.
|
|
5
|
+
|
|
6
|
+
Run this when something seems off with memory sync, or after setting up on a new machine. Report problems (✗) and warnings (!) to the user with the fix each line suggests.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Text-in/text-out `claude -p` calls (distill --auto, harvest, refine).
|
|
2
|
+
|
|
3
|
+
The prompt carries memory text that teammates wrote, so these calls get nothing beyond the
|
|
4
|
+
text: no tools at all (`--tools ""`), only the user's own settings (`--setting-sources user`:
|
|
5
|
+
no project or local settings, so no hooks from a repo), no MCP servers (`--strict-mcp-config`
|
|
6
|
+
without `--mcp-config`), and they start in a fresh private empty folder instead of the
|
|
7
|
+
knowledge repo (guard.capture_tool_isolated). Flags checked against Claude Code 2.1.285 and
|
|
8
|
+
2.1.287 (`claude --help`).
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from corkern import guard
|
|
15
|
+
|
|
16
|
+
ISOLATION = ("--setting-sources", "user", "--strict-mcp-config", "--tools", "")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def ask(claude: str, prompt: str, model: str | None = None) -> "guard.subprocess.CompletedProcess":
|
|
20
|
+
argv = [claude, "-p", *ISOLATION, *(["--model", model] if model else [])]
|
|
21
|
+
return guard.capture_tool_isolated(argv, prompt)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def interactive_cwd(preferred: Path | None = None) -> Path:
|
|
25
|
+
"""Where an interactive claude session starts: `preferred` (default: the current folder)
|
|
26
|
+
unless it is missing or inside the knowledge repo — then $HOME."""
|
|
27
|
+
where = Path(preferred) if preferred is not None else Path.cwd()
|
|
28
|
+
if not where.is_dir() or guard.in_knowledge_repo(where):
|
|
29
|
+
return Path.home()
|
|
30
|
+
return where
|
|
File without changes
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import typer
|
|
4
|
+
from corkern import guard
|
|
5
|
+
from corkern.commands.signing_cmd import _ask
|
|
6
|
+
from corkern.config import (
|
|
7
|
+
UnstorablePath, _parse_conf, check_projects, confirm_projects, conf_entries, load_config,
|
|
8
|
+
resolve_project_path, same_path, store_project_path, valid_slug,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _fail(message: str) -> None:
|
|
13
|
+
typer.echo(message, err=True)
|
|
14
|
+
raise typer.Exit(1)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def add_project(
|
|
18
|
+
slug: str = typer.Argument(None, help="Project slug (default: the folder name, like v1)"),
|
|
19
|
+
path: Path = typer.Argument(None, help="Project path (default: cwd)"),
|
|
20
|
+
confirm_all: bool = typer.Option(False, "--confirm-all",
|
|
21
|
+
help="List every project not confirmed on this machine; confirm them after one question"),
|
|
22
|
+
confirm_listed: bool = typer.Option(False, "--confirm-listed",
|
|
23
|
+
help="Confirm the projects whose path matches the slug:path lines on stdin "
|
|
24
|
+
"(this machine's own v1 registry; used by migrate/3)"),
|
|
25
|
+
) -> None:
|
|
26
|
+
"""Add a project to tracking — or confirm on this machine a project that is already registered.
|
|
27
|
+
|
|
28
|
+
corkern.conf is shared: a project's path is used to read its Claude Code conversations
|
|
29
|
+
(harvest, prune) or to wire its folder (init-device) only once this machine confirmed it.
|
|
30
|
+
"""
|
|
31
|
+
if confirm_all or confirm_listed:
|
|
32
|
+
_confirm_many(confirm_listed)
|
|
33
|
+
return
|
|
34
|
+
if slug is None:
|
|
35
|
+
slug = (path or Path(".")).resolve().name
|
|
36
|
+
if not valid_slug(slug):
|
|
37
|
+
_fail(f"Invalid slug {slug!r}: use letters, digits, '.', '_' or '-', "
|
|
38
|
+
"starting with a letter or digit.")
|
|
39
|
+
resolved = (path or Path(".")).resolve()
|
|
40
|
+
try:
|
|
41
|
+
stored = store_project_path(resolved)
|
|
42
|
+
except UnstorablePath as e:
|
|
43
|
+
_fail(f"Invalid path {str(resolved)!r}: {e}.")
|
|
44
|
+
|
|
45
|
+
repo, projects = load_config()
|
|
46
|
+
# Like v1: any line for the slug counts, including other devices' (e.g. Windows) lines
|
|
47
|
+
if slug in {s for s, _ in conf_entries(guard.read_text(repo.conf_file))}:
|
|
48
|
+
check = check_projects(repo.path).get(slug)
|
|
49
|
+
match = next((p for p in (check.candidates if check else ()) if same_path(p, resolved)), None)
|
|
50
|
+
if match is None:
|
|
51
|
+
_fail(f"Slug '{slug}' already exists. Remove it first.")
|
|
52
|
+
_confirm(repo.path, {slug: match})
|
|
53
|
+
typer.echo(f"Confirmed {slug} → {match} on this machine")
|
|
54
|
+
return
|
|
55
|
+
for other, other_path in projects.items():
|
|
56
|
+
if other_path.resolve() == resolved:
|
|
57
|
+
_fail(f"Path '{resolved}' is already tracked under slug '{other}'.")
|
|
58
|
+
|
|
59
|
+
_confirm(repo.path, {slug: resolve_project_path(stored)})
|
|
60
|
+
guard.append_text(repo.conf_file, f"{slug}:{stored}\n")
|
|
61
|
+
typer.echo(f"Added {slug} → {resolved}")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _confirm(repo: Path, items: dict[str, Path]) -> None:
|
|
65
|
+
try:
|
|
66
|
+
confirm_projects(repo, items)
|
|
67
|
+
except (OSError, guard.V1ProtectedError) as e:
|
|
68
|
+
_fail(f"Could not record the confirmation in {repo}/.git/corkern: {e}")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _confirm_many(listed: bool) -> None:
|
|
72
|
+
repo, _ = load_config()
|
|
73
|
+
open_ = [c for c in check_projects(repo.path).values() if not c.confirmed]
|
|
74
|
+
if listed:
|
|
75
|
+
theirs = _parse_conf(sys.stdin.read(), "stdin")
|
|
76
|
+
found: dict[str, Path] = {}
|
|
77
|
+
for c in open_:
|
|
78
|
+
if c.slug not in theirs:
|
|
79
|
+
continue
|
|
80
|
+
match = next((p for p in c.candidates if same_path(p, theirs[c.slug])), None)
|
|
81
|
+
if match is None:
|
|
82
|
+
typer.echo(f" ! {c.slug}: the registry's path differs from the listed one "
|
|
83
|
+
f"({', '.join(map(str, c.candidates))} ≠ {theirs[c.slug]}) — not confirmed")
|
|
84
|
+
else:
|
|
85
|
+
found[c.slug] = match
|
|
86
|
+
_confirm(repo.path, found)
|
|
87
|
+
for slug, p in sorted(found.items()):
|
|
88
|
+
typer.echo(f" ✓ {slug} → {p} confirmed on this machine")
|
|
89
|
+
return
|
|
90
|
+
single = [c for c in open_ if not c.duplicate]
|
|
91
|
+
if not open_:
|
|
92
|
+
typer.echo("✓ Every project is confirmed on this machine.")
|
|
93
|
+
return
|
|
94
|
+
typer.echo("Not confirmed on this machine (corkern.conf is shared — check each path is yours):")
|
|
95
|
+
for c in single:
|
|
96
|
+
typer.echo(f" {c.slug} → {c.candidates[0]} ({c.lines[0]})")
|
|
97
|
+
for c in open_:
|
|
98
|
+
if c.duplicate:
|
|
99
|
+
typer.echo(f" ! {c.explain()}")
|
|
100
|
+
if single and _ask(f"Confirm these {len(single)} project(s) on this machine? [y/N] ", False):
|
|
101
|
+
_confirm(repo.path, {c.slug: c.candidates[0] for c in single})
|
|
102
|
+
typer.echo(f"✓ {len(single)} project(s) confirmed")
|
|
103
|
+
elif single:
|
|
104
|
+
typer.echo("Nothing confirmed.")
|