djournal 0.1.0 → 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.
package/README.md CHANGED
@@ -1,26 +1,67 @@
1
1
  # djournal
2
2
 
3
- Durable project memory for coding agents, readable by humans.
3
+ Portable project memory for coding agents, readable by humans.
4
4
 
5
- djournal records the path of the workplans, research, decisions, changes, and
6
- next steps—as linked Markdown inside your project. Codex and Claude Code can use
7
- that memory automatically across sessions without a database, account, or
8
- proprietary service.
5
+ djournal records the reasoning path of the work: plans, research, decisions,
6
+ changes, validation, and next steps. It lets you start in Codex, continue in
7
+ Claude Code, switch models, survive context compaction, and still reload the
8
+ same project state from plain Markdown.
9
+
10
+ Code preserves what exists. djournal preserves why it exists.
9
11
 
10
12
  > **Files are memory. Indexes are projections.**
11
13
 
12
14
  ## Why djournal exists
13
15
 
14
- Code preserves what a system does. It rarely preserves why it became that way,
15
- what was tried, which evidence mattered, or what should happen next.
16
+ djournal is built for product and engineering work that moves across sessions,
17
+ models, people, and tools.
18
+
19
+ ### Continue across tools
20
+
21
+ Long coding sessions do not survive tool boundaries well when the only handoff
22
+ format is a transcript. A useful session may start in Codex, continue in Claude
23
+ Code, and later resume somewhere else. The journal is the portable handoff
24
+ layer: each agent can read the same Markdown spine, follow the same decisions
25
+ and research links, and close its work in the same structure.
26
+
27
+ The memory belongs to the project, not to a chat session, model, harness,
28
+ database, or proprietary service.
29
+
30
+ ### Preserve the reasoning code cannot show
31
+
32
+ Code shows what a system does. It rarely shows why it became that way, what was
33
+ tried, which constraints mattered, which options were rejected, or what should
34
+ happen next.
35
+
36
+ Chat history preserves too much, with weak structure and poor portability.
37
+ Conventional documentation usually captures polished outcomes after the fact.
38
+ Static analysis can inspect the code as it is, but it cannot reliably recover
39
+ the historical decisions that shaped it.
40
+
41
+ djournal records that missing layer while the work happens.
42
+
43
+ ### Share institutional knowledge
44
+
45
+ In AI-accelerated teams, traditional documentation can become stale almost as
46
+ soon as it is written. Product specs, implementation notes, and architectural
47
+ rationale need to be produced as a by-product of product and engineering work,
48
+ not as a separate ritual.
49
+
50
+ djournal gives that by-product a durable shape. The same entries that let an
51
+ agent resume work also become institutional knowledge: reviewable by humans,
52
+ searchable with ordinary tools, versioned through Git, and recallable by
53
+ whichever model or harness the team uses next.
54
+
55
+ ### Let memory compound
16
56
 
17
- Chat transcripts preserve too much. Conventional documentation is usually
18
- written too late. Retrieval systems can find fragments, but they cannot recover
19
- reasoning that was never recorded.
57
+ A journal can start from nothing. The first entries are mostly orientation:
58
+ current state, open questions, and next steps. As the work accumulates, resume
59
+ behavior changes. The agent is no longer guessing from a cold codebase or
60
+ wandering through broad exploration. It reloads a shaped history: what mattered
61
+ before, what was decided, what remains unresolved, and where the next useful
62
+ move probably is.
20
63
 
21
- djournal makes project memory part of doing the work. Skills capture durable
22
- context when work becomes meaningful; optional hooks make the workflow
23
- default-on without writing entries behind the agent's back.
64
+ The journal turns past work into focused guidance.
24
65
 
25
66
  ## Manifesto
26
67
 
@@ -33,42 +74,10 @@ default-on without writing entries behind the agent's back.
33
74
  4. **Structure should be sufficient, not maximal.** YAML carries stable
34
75
  metadata; Markdown carries meaning; links carry relationships.
35
76
  5. **Tools should remain replaceable.** Memory must survive changes in models,
36
- agent harnesses, databases, and vendors.
77
+ agent harnesses, databases, vendors, and retrieval systems.
37
78
  6. **The workflow should carry the burden.** Maintaining memory should be a
38
79
  consequence of meaningful work, not another ritual to remember.
39
80
 
40
- ## Why plain Markdown
41
-
42
- Markdown is immediately useful. It can be read before an ingestion pipeline
43
- runs, searched with ordinary tools, loaded selectively, reviewed line by line,
44
- and versioned with Git. Frontmatter makes important fields deterministic while
45
- links turn the directory into an explicit graph.
46
-
47
- Google Cloud's draft [Open Knowledge Format](https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/)
48
- formalizes the same broad pattern: knowledge as linked Markdown with YAML
49
- frontmatter, portable through Git and independent of the tools that produce or
50
- consume it. djournal is conceptually aligned with that direction, but uses a
51
- domain-specific schema for project history and is not currently
52
- [OKF v0.1](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)
53
- conformant.
54
-
55
- ## Why not only RAG or a knowledge graph?
56
-
57
- RAG, embeddings, full-text indexes, and graph views are useful retrieval tools.
58
- They are not ideal as the only durable copy of project memory.
59
-
60
- | Layer | What it provides |
61
- | --- | --- |
62
- | djournal Markdown | Canonical meaning, provenance, chronology, and links |
63
- | Git | Review, attribution, history, and team exchange |
64
- | Embeddings / RAG | Semantic retrieval over larger corpora |
65
- | Graph projection | Traversal, visualization, and multi-hop retrieval |
66
-
67
- Vector and graph indexes are derived representations: they require ingestion,
68
- can become stale, and may change with the model or extraction pipeline. djournal
69
- keeps the authored source inspectable and lets those indexes be rebuilt when
70
- needed. It complements retrieval infrastructure rather than replacing it.
71
-
72
81
  ## What djournal records
73
82
 
74
83
  ```text
@@ -85,6 +94,8 @@ needed. It complements retrieval infrastructure rather than replacing it.
85
94
  Entries carry structured frontmatter, stable identities, summaries, timestamps,
86
95
  and typed links. Markdown remains the source of truth.
87
96
 
97
+ See [spec.md](spec.md) for the complete data model and workflow contracts.
98
+
88
99
  ## How it works
89
100
 
90
101
  ```mermaid
@@ -105,48 +116,124 @@ flowchart LR
105
116
  - Hooks never create or modify semantic journal entries.
106
117
  - Read-only and trivial requests do not generate unnecessary ceremony.
107
118
 
119
+ ## Why plain Markdown and Git
120
+
121
+ Markdown is immediately useful. It can be read before an ingestion pipeline
122
+ runs, searched with ordinary tools, loaded selectively, reviewed line by line,
123
+ and versioned with Git. Frontmatter makes important fields deterministic while
124
+ links turn the directory into an explicit graph.
125
+
126
+ Git already distributes code history. djournal lets teams preserve reasoning
127
+ history in the same reviewable medium: who changed the memory, when it changed,
128
+ what it referenced, and how it evolved. That makes institutional knowledge easy
129
+ for people to inspect and easy for agents to recall.
130
+
131
+ Google Cloud's draft [Open Knowledge Format](https://cloud.google.com/blog/products/data-analytics/how-the-open-knowledge-format-can-improve-data-sharing/)
132
+ formalizes the same broad pattern: knowledge as linked Markdown with YAML
133
+ frontmatter, portable through Git and independent of the tools that produce or
134
+ consume it. djournal is conceptually aligned with that direction, but uses a
135
+ domain-specific schema for project history and is not currently
136
+ [OKF v0.1](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)
137
+ conformant.
138
+
139
+ ## Why not only RAG or a knowledge graph?
140
+
141
+ RAG, embeddings, full-text indexes, and graph views are useful retrieval tools.
142
+ They are not ideal as the only durable copy of project memory.
143
+
144
+ | Layer | What it provides |
145
+ | --- | --- |
146
+ | djournal Markdown | Canonical meaning, provenance, chronology, and links |
147
+ | Git | Review, attribution, history, and team exchange |
148
+ | Embeddings / RAG | Semantic retrieval over larger corpora |
149
+ | Graph projection | Traversal, visualization, and multi-hop retrieval |
150
+
151
+ Vector and graph indexes are derived representations: they require ingestion,
152
+ can become stale, and may change with the model or extraction pipeline. djournal
153
+ keeps the authored source inspectable and lets those indexes be rebuilt when
154
+ needed. It complements retrieval infrastructure rather than replacing it.
155
+
156
+ Large context windows help, but they do not replace authored memory. A million
157
+ tokens can hold more text; the agent still needs to know what matters.
158
+
108
159
  ## Install
109
160
 
110
161
  Requires Node.js 18 or newer. Run this from the project you want to equip:
111
162
 
112
163
  ```bash
113
- npx djournal install
164
+ npm install -g djournal
165
+ djournal install
114
166
  ```
115
167
 
116
- The installer targets the current directory and detects Codex or Claude Code.
117
- Select explicitly when needed:
168
+ The global install gives you the `djournal` and `journal` commands. The
169
+ installer targets the current directory and detects Codex or Claude Code. Select
170
+ explicitly when needed:
118
171
 
119
172
  ```bash
120
- npx djournal install --harness codex
121
- npx djournal install --harness claude-code
122
- npx djournal install --all
173
+ djournal install --harness codex
174
+ djournal install --harness claude-code
175
+ djournal install --all
176
+ ```
177
+
178
+ If you do not want a global install, use `npx`:
179
+
180
+ ```bash
181
+ npx djournal install
123
182
  ```
124
183
 
125
184
  Then use your coding agent normally.
126
185
 
186
+ Install creates a local project marker (`.djournal.json`) and a canonical
187
+ per-project store under `~/.djournal/projects/<project-key>/`:
188
+
189
+ ```text
190
+ ~/.djournal/projects/<project-key>/
191
+ config.json
192
+ .journal/
193
+ ```
194
+
195
+ The project store is the private write target. A repository `.journal/` or
196
+ standalone journal repo is a projection that receives shared work only after
197
+ you opt in.
198
+
199
+ For Claude Code, install also grants the project access to that exact global
200
+ store path in `.claude/settings.json`, plus the safe `journal`/`djournal`
201
+ commands used by the workflow. Codex uses runtime sandbox configuration for
202
+ filesystem access, so sandboxed Codex sessions must include the generated store
203
+ path when they need canonical journal memory.
204
+
127
205
  ## Lifecycle
128
206
 
129
207
  ```bash
130
- npx djournal status
131
- npx djournal doctor
132
- npx djournal upgrade
133
- npx djournal uninstall
208
+ djournal status
209
+ djournal doctor
210
+ djournal config sync.enabled true
211
+ djournal share
212
+ djournal sync
213
+ djournal upgrade
214
+ djournal uninstall
134
215
  ```
135
216
 
136
217
  Installation preserves existing agent configuration. Uninstallation removes
137
- djournal's tooling while retaining `.journal/` so the project memory can be
138
- revived later.
218
+ djournal's tooling while retaining durable project memory and the project
219
+ marker so the journal can be revived later.
139
220
 
140
221
  Existing `AGENTS.md` and `CLAUDE.md` files are never replaced. djournal adds an
141
222
  owned block, updates only that block, and removes only that block during
142
223
  uninstall; surrounding project instructions remain untouched.
143
224
 
144
- See [spec.md](spec.md) for the complete data model and workflow contracts.
225
+ `share` marks the active work item in the global sharing index. `sync` is
226
+ opt-in; in colocated mode it projects shared work into the product repository
227
+ for normal commits, and in standalone mode it projects shared work into a
228
+ dedicated journal repository.
145
229
 
146
230
  ## Status
147
231
 
148
232
  Codex and Claude Code are supported. OpenCode, Pi, and Zed adapters are planned.
149
233
 
234
+ Git-backed sharing and automatic sync are opt-in so local-only work remains
235
+ private by default.
236
+
150
237
  ## Contributing and releases
151
238
 
152
239
  Pull request titles use Conventional Commit form, such as
@@ -156,3 +243,12 @@ Pull request titles use Conventional Commit form, such as
156
243
  increment the major version.
157
244
 
158
245
  djournal is licensed under the [Apache License 2.0](LICENSE).
246
+
247
+ ## Documentation
248
+
249
+ - [Installation and repository layouts](docs/installation.md)
250
+ - [Remote Git sync setup](docs/remote-sync.md)
251
+ - [Architecture and data model](docs/architecture.md)
252
+ - [Visibility and sharing](docs/visibility-and-sharing.md)
253
+ - [Djournal in practice](docs/djournal-in-practice.md)
254
+ - [Uninstalling and reinstalling](docs/uninstalling.md)
package/bin/journal.js CHANGED
@@ -5,8 +5,11 @@
5
5
  const path = require("node:path");
6
6
  const {
7
7
  InstallerError,
8
+ configure,
8
9
  doctor,
9
10
  install,
11
+ share,
12
+ sync,
10
13
  status,
11
14
  uninstall,
12
15
  upgrade,
@@ -21,11 +24,15 @@ function usage() {
21
24
  journal uninstall [--target DIR] [--harness LIST | --all]
22
25
  journal status [--target DIR] [--json]
23
26
  journal doctor [--target DIR] [--json]
27
+ journal config [--target DIR] [KEY [VALUE]] [--dry-run] [--json]
28
+ journal share [--target DIR] [--work SLUG] [--dry-run] [--json]
29
+ journal sync [--target DIR] [--work SLUG] [--dry-run] [--json]
24
30
 
25
31
  Options:
26
32
  --dry-run Show the planned operation without writing
27
33
  --yes Disable interactive harness selection
28
34
  --json Emit JSON
35
+ --work SLUG Select a journal work item instead of active state
29
36
  --harness LIST Comma-separated codex,claude-code selection
30
37
  --all Select or remove every supported harness
31
38
  --instructions-only Install core instructions without harness hooks
@@ -35,7 +42,7 @@ Options:
35
42
  function parseArgs(argv) {
36
43
  const args = [...argv];
37
44
  const command = args.shift();
38
- if (!command || !["install", "upgrade", "uninstall", "status", "doctor"].includes(command)) {
45
+ if (!command || !["install", "upgrade", "uninstall", "status", "doctor", "config", "share", "sync"].includes(command)) {
39
46
  throw new InstallerError(usage(), "USAGE");
40
47
  }
41
48
  const options = { command, harnesses: [] };
@@ -45,6 +52,10 @@ function parseArgs(argv) {
45
52
  if (!args.length) throw new InstallerError("--target requires a value", "USAGE");
46
53
  options.target = args.shift();
47
54
  } else if (arg.startsWith("--target=")) options.target = arg.slice(9);
55
+ else if (arg === "--work") {
56
+ if (!args.length) throw new InstallerError("--work requires a value", "USAGE");
57
+ options.work = args.shift();
58
+ } else if (arg.startsWith("--work=")) options.work = arg.slice(7);
48
59
  else if (arg === "--harness") {
49
60
  if (!args.length) throw new InstallerError("--harness requires a value", "USAGE");
50
61
  options.harnesses.push(...args.shift().split(",").filter(Boolean));
@@ -52,9 +63,12 @@ function parseArgs(argv) {
52
63
  else if (arg === "--all") options.all = true;
53
64
  else if (arg === "--instructions-only") options.instructionsOnly = true;
54
65
  else if (arg === "--dry-run") options.dryRun = true;
66
+ else if (arg === "--auto") options.auto = true;
55
67
  else if (arg === "--yes") options.yes = true;
56
68
  else if (arg === "--json") options.json = true;
57
69
  else if (arg === "--help" || arg === "-h") throw new InstallerError(usage(), "HELP");
70
+ else if (command === "config" && !options.key) options.key = arg;
71
+ else if (command === "config" && typeof options.value === "undefined") options.value = arg;
58
72
  else throw new InstallerError(`unknown option: ${arg}`, "USAGE");
59
73
  }
60
74
  if (options.all && options.harnesses.length) throw new InstallerError("use either --all or --harness", "USAGE");
@@ -76,6 +90,8 @@ function print(value, json) {
76
90
  else if (typeof value.installed === "boolean") process.stdout.write(value.installed ? `installed: ${value.target}\n` : `not installed: ${value.target}\n`);
77
91
  else process.stdout.write(`${value.ok ? "ok" : "failed"}: ${value.target}\n`);
78
92
  if (value.harnesses) process.stdout.write(`harnesses: ${value.harnesses.join(", ") || "instructions-only"}\n`);
93
+ if (value.key) process.stdout.write(`${value.key}: ${JSON.stringify(value.value)}\n`);
94
+ else if (value.config) process.stdout.write(`${JSON.stringify(value.config, null, 2)}\n`);
79
95
  if (value.conflicts?.length) process.stdout.write(`conflicts: ${value.conflicts.join(", ")}\n`);
80
96
  if (value.files) {
81
97
  for (const file of value.files) process.stdout.write(`${file.status.padEnd(8)} ${file.path}\n`);
@@ -101,6 +117,9 @@ async function main() {
101
117
  else if (options.command === "upgrade") result = await upgrade(options);
102
118
  else if (options.command === "uninstall") result = uninstall(options);
103
119
  else if (options.command === "status") result = status(options);
120
+ else if (options.command === "config") result = configure(options);
121
+ else if (options.command === "share") result = share(options);
122
+ else if (options.command === "sync") result = sync(options);
104
123
  else result = doctor(options);
105
124
  print(result, options.json);
106
125
  if (result.ok === false || result.installed === false || result.clean === false || result.conflicts?.length) process.exitCode = 2;
@@ -0,0 +1,175 @@
1
+ # Architecture and Data Model
2
+
3
+ djournal is a filesystem journal. Markdown is the source of truth; indexes,
4
+ RAG systems, graph views, and model context are projections over that source.
5
+
6
+ ## Directory layout
7
+
8
+ The canonical journal lives in the user's djournal home, keyed by project:
9
+
10
+ ```text
11
+ ~/.djournal/projects/<project-key>/
12
+ config.json
13
+ .journal/
14
+ state.json
15
+ work/<work-item>/
16
+ work.md
17
+ journal/
18
+ decisions/
19
+ docs/
20
+ _research/
21
+ ```
22
+
23
+ The installed project contains a marker that points back to that store:
24
+
25
+ ```text
26
+ .djournal.json
27
+ ```
28
+
29
+ When sync is enabled, a repository-local `.journal/` is a projection containing
30
+ the shared work items copied out of the global store.
31
+
32
+ ```text
33
+ <projection-target>/
34
+ .journal/
35
+ work/<shared-work-item>/
36
+ ```
37
+
38
+ ## Work items
39
+
40
+ A work item is a durable unit of product or engineering work. It may span
41
+ repositories, branches, harnesses, and models.
42
+
43
+ Every work item has:
44
+
45
+ ```text
46
+ ~/.djournal/projects/<project-key>/.journal/work/<slug>/work.md
47
+ ```
48
+
49
+ The frontmatter stores stable identity, title, status, visibility, authorship,
50
+ and timestamps.
51
+
52
+ ## Configuration
53
+
54
+ `config.json` is a sibling of the global `.journal/` directory. It stores
55
+ project identity, sync settings, and the sharing index. Sync is disabled unless
56
+ configuration opts in:
57
+
58
+ ```json
59
+ {
60
+ "project": {
61
+ "id": "my-product-a1b2c3d4",
62
+ "name": "my-product",
63
+ "sourcePath": "/workspace/my-product"
64
+ },
65
+ "sync": {
66
+ "enabled": true,
67
+ "mode": "colocated",
68
+ "path": "/workspace/my-product",
69
+ "auto": false
70
+ },
71
+ "sharing": {
72
+ "default": "local_only",
73
+ "sharedWorkItems": {}
74
+ }
75
+ }
76
+ ```
77
+
78
+ Use the CLI to change it:
79
+
80
+ ```bash
81
+ djournal config sync.enabled true
82
+ djournal config sync.mode colocated
83
+ djournal config sync.path /workspace/my-product
84
+ ```
85
+
86
+ Use `mode: "standalone"` for a dedicated journal repository. Use
87
+ `mode: "colocated"` when shared work should be projected into the product
88
+ repository and published by normal product commits.
89
+
90
+ ## Entry types
91
+
92
+ | Directory | Entry types | Role |
93
+ | --- | --- | --- |
94
+ | `journal/` | `plan`, `implementation`, `status`, `manual` | Spine |
95
+ | `decisions/` | `decision` | Supporting |
96
+ | `docs/` | `doc` | Supporting |
97
+ | `_research/` | `research` | Supporting |
98
+
99
+ The spine is the chronological project timeline. Supporting entries are durable
100
+ evidence and references linked from the spine or from each other.
101
+
102
+ ## Frontmatter
103
+
104
+ Entries use YAML frontmatter for stable metadata:
105
+
106
+ ```yaml
107
+ ---
108
+ id: ent_...
109
+ workItemId: wi_...
110
+ entryType: implementation
111
+ entryNumber: 7
112
+ title: Implement README overhaul
113
+ summary: Rewrote README.md around portable project memory.
114
+ createdBy: person@example.com
115
+ createdAt: "2026-07-07T20:03:30.906Z"
116
+ updatedAt: "2026-07-07T20:03:30.906Z"
117
+ source: manual
118
+ ---
119
+ ```
120
+
121
+ The Markdown body carries the human-readable meaning. Frontmatter keeps lookup,
122
+ sorting, identity, and link resolution deterministic.
123
+
124
+ ## Links
125
+
126
+ Links are typed objects in frontmatter:
127
+
128
+ ```yaml
129
+ links:
130
+ - id: lnk_...
131
+ fromEntryId: ent_...
132
+ toEntryId: ent_...
133
+ relation: references
134
+ createdAt: "2026-07-08T08:00:00.000Z"
135
+ targetPath: ../docs/example.md
136
+ ```
137
+
138
+ Supported relations:
139
+
140
+ - `references`: source uses target as evidence or context
141
+ - `relates_to`: source is loosely connected to target
142
+ - `supersedes`: newer entry replaces or rolls back an older entry
143
+
144
+ ## Decisions, docs, and research
145
+
146
+ Decision entries record accepted choices, rationale, consequences, and
147
+ supersession.
148
+
149
+ Doc entries synthesize durable reference material such as architecture notes,
150
+ how-tos, and product explanations.
151
+
152
+ Research entries capture codebase or web findings with sources and open
153
+ questions.
154
+
155
+ ## Hooks and skills
156
+
157
+ `AGENTS.md` gives agents portable instructions. Skills perform journal-aware
158
+ work such as resume, planning, research, decision capture, documentation,
159
+ audit, reconciliation, and closure.
160
+
161
+ Hooks remind agents about the workflow and validate final status markers. Hooks
162
+ do not create semantic journal entries. When `.djournal.json` exists, hooks read
163
+ active work and sync config from the global project store.
164
+
165
+ For Claude Code, install also injects a narrow permission grant into
166
+ `.claude/settings.json` for the exact global project store path and safe
167
+ `journal`/`djournal` commands. Codex filesystem access is governed by the Codex
168
+ runtime sandbox, so Codex sessions must be launched with the global store path
169
+ available when sandboxing would otherwise hide `~/.djournal`.
170
+
171
+ ## Related docs
172
+
173
+ - [Djournal in practice](djournal-in-practice.md)
174
+ - [Visibility and sharing](visibility-and-sharing.md)
175
+ - [spec.md](../spec.md)