@dotdotgod/claude-code 0.6.2 → 0.6.4
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 +1 -1
- package/commands/dd/plan.md +1 -1
- package/mcp/cli.mjs +5 -15
- package/mcp/server.mjs +31 -52
- package/package.json +2 -2
- package/skills/doc-first-planning/SKILL.md +1 -1
- package/skills/project-initializer/templates/case-and-evidence.json +1 -6
- package/skills/project-initializer/templates/dotdotgod.config.json +1 -6
- package/skills/project-initializer/templates/policy.json +1 -6
- package/skills/project-initializer/templates/portfolio.json +1 -6
- package/skills/project-initializer/templates/publication.json +1 -6
- package/skills/project-initializer/templates/research.json +1 -6
- package/skills/project-initializer/templates/software.json +1 -6
package/README.md
CHANGED
|
@@ -80,7 +80,7 @@ The plugin starts a local stdio MCP server. It exposes `execute` and `execute_fi
|
|
|
80
80
|
|
|
81
81
|
Dotdotgod execution tools share a 10 MiB stdout/stderr capture ceiling per command. Crossing that ceiling terminates the child process and reports `captureLimitExceeded`; direct stdout and stderr excerpts are each capped at 1 MiB. Their child environments preserve compatibility-oriented inheritance after filtering runtime injection variables; this reports filtered names without values but does not isolate ordinary inherited credentials. Large output is indexed before retrieval in the ignored project-local `.dotdotgod/context/context.sqlite` FTS5 store, and searches return bounded excerpts. The store uses WAL, a bounded busy timeout, and transactional source replacement, expiry, and purge. Structural Markdown/JSON chunks, bounded typo-tolerant trigram candidates, reciprocal-rank fusion, and title/path/proximity signals improve retrieval while provenance and `instructionAuthority: "none"` identify retrieved text as non-authoritative data.
|
|
82
82
|
|
|
83
|
-
The MCP `index` tool accepts
|
|
83
|
+
The MCP `index` tool accepts files or explicitly requested bounded directories, including external paths, with deterministic traversal, configurable resource limits, explicit extension/path exclusions, and symlinks skipped by default. These capture and retrieval rules apply when Claude calls the dotdotgod MCP tools; Claude Code's built-in Bash tool keeps its native behavior. URL indexing performs application-level HTTP(S), DNS/address, connected-peer, redirect, and byte-limit validation. Accepted HTML is normalized as bounded untrusted text without browser rendering, JavaScript, subresource loading, or link following by default. The server bundles no browser renderer, so browser opt-in fails unless a host injects that capability. These controls are not a network sandbox or complete prompt-injection prevention. See the [`@dotdotgod/context` npm package](https://www.npmjs.com/package/@dotdotgod/context), its [GitHub README](https://github.com/dotdotgod/dotdotgod-kit/tree/main/packages/context), and the [maintained execution contract](https://github.com/dotdotgod/dotdotgod-kit/blob/main/docs/spec/CONTEXT_EXECUTION.md) for the complete runtime behavior.
|
|
84
84
|
|
|
85
85
|
Bundled hooks mark project load as required at session start, record successful source/config edits, and deny broad verification or handoff commands until matching graph impact succeeds. Denial asks Claude to call the required MCP tool and retry; hooks do not silently change one tool type into another. See [`hooks/README.md`](https://github.com/dotdotgod/dotdotgod-kit/blob/main/packages/claude-code/hooks/README.md) for lifecycle and trust boundaries.
|
|
86
86
|
|
package/commands/dd/plan.md
CHANGED
|
@@ -14,7 +14,7 @@ Task request: `$ARGUMENTS`
|
|
|
14
14
|
|
|
15
15
|
## CLI Context
|
|
16
16
|
|
|
17
|
-
For focused documentation routing, run `dotdotgod query <root> "<focus>" --limit 30 --json`. Run `dotdotgod config <root> --json` when memory-area policy
|
|
17
|
+
For focused documentation routing, run `dotdotgod query <root> "<focus>" --limit 30 --json`. Run `dotdotgod config <root> --json` when memory-area policy or documentation routing/exclusions affect the plan. If the CLI is unavailable, continue from README indexes and focused file reads.
|
|
18
18
|
|
|
19
19
|
## Goal
|
|
20
20
|
|
package/mcp/cli.mjs
CHANGED
|
@@ -938,9 +938,6 @@ var DEFAULT_LOAD_POLICY = {
|
|
|
938
938
|
exclude: ["docs/plan", "docs/archive"]
|
|
939
939
|
}
|
|
940
940
|
};
|
|
941
|
-
var DEFAULT_PLAN_MODE_POLICY = {
|
|
942
|
-
writablePaths: ["docs/plan/**", "docs/archive/**"]
|
|
943
|
-
};
|
|
944
941
|
var DEFAULT_IMPACT_RANKING_POLICY = {
|
|
945
942
|
connectionCap: 80,
|
|
946
943
|
memoryCap: 20,
|
|
@@ -1115,8 +1112,8 @@ function cloneLoadPolicy(policy = DEFAULT_LOAD_POLICY) {
|
|
|
1115
1112
|
}
|
|
1116
1113
|
};
|
|
1117
1114
|
}
|
|
1118
|
-
function clonePlanModePolicy(
|
|
1119
|
-
return {
|
|
1115
|
+
function clonePlanModePolicy() {
|
|
1116
|
+
return {};
|
|
1120
1117
|
}
|
|
1121
1118
|
function normalizeDocumentationRoot(value = DEFAULT_DOCUMENTATION_ROOT) {
|
|
1122
1119
|
return String(value).trim().replaceAll("\\", "/").replace(/^\.\//, "").replace(/\/{2,}/g, "/").replace(/^\/+|\/+$/g, "");
|
|
@@ -1130,7 +1127,7 @@ function isValidDocumentationRoot(value) {
|
|
|
1130
1127
|
}
|
|
1131
1128
|
function defaultMemoryConfig({ documentationRoot = DEFAULT_DOCUMENTATION_ROOT } = {}) {
|
|
1132
1129
|
const root = normalizeDocumentationRoot(documentationRoot);
|
|
1133
|
-
return { source: "default", documentation: { root }, areas: memoryAreasForRoot(root).map(cloneArea), traceability: cloneTraceabilityPolicy({ ...DEFAULT_TRACEABILITY_POLICY, required: [`${root}/spec/**`] }), validation: cloneValidationPolicy(), impactRanking: cloneImpactRankingPolicy(), referenceExpansion: cloneReferenceExpansionPolicy(), load: cloneLoadPolicy({ ...DEFAULT_LOAD_POLICY, documentationSummary: { exclude: [`${root}/plan`, `${root}/archive`] } }), planMode: clonePlanModePolicy(
|
|
1130
|
+
return { source: "default", documentation: { root }, areas: memoryAreasForRoot(root).map(cloneArea), traceability: cloneTraceabilityPolicy({ ...DEFAULT_TRACEABILITY_POLICY, required: [`${root}/spec/**`] }), validation: cloneValidationPolicy(), impactRanking: cloneImpactRankingPolicy(), referenceExpansion: cloneReferenceExpansionPolicy(), load: cloneLoadPolicy({ ...DEFAULT_LOAD_POLICY, documentationSummary: { exclude: [`${root}/plan`, `${root}/archive`] } }), planMode: clonePlanModePolicy() };
|
|
1134
1131
|
}
|
|
1135
1132
|
function normalizePathPattern(value = "") {
|
|
1136
1133
|
return value.replaceAll("\\", "/").replace(/^\.\//, "").replace(/\/+$|^\/+/, "");
|
|
@@ -1191,10 +1188,8 @@ function isSecretLikePathPattern(value = "") {
|
|
|
1191
1188
|
const normalized = normalizePathPattern(value);
|
|
1192
1189
|
return /(^|\/)(\.env|\.npmrc|\.pypirc|id_rsa|id_dsa|id_ed25519|credentials?|secrets?)(\.|\/|$)/i.test(normalized);
|
|
1193
1190
|
}
|
|
1194
|
-
function normalizePlanModePolicy(
|
|
1195
|
-
|
|
1196
|
-
const writablePaths = raw.writablePaths === void 0 ? DEFAULT_PLAN_MODE_POLICY.writablePaths : [...new Set((Array.isArray(raw.writablePaths) ? raw.writablePaths : []).map(normalizePathPattern))];
|
|
1197
|
-
return clonePlanModePolicy({ writablePaths });
|
|
1191
|
+
function normalizePlanModePolicy(_raw) {
|
|
1192
|
+
return clonePlanModePolicy();
|
|
1198
1193
|
}
|
|
1199
1194
|
function normalizeLoadPolicy(raw) {
|
|
1200
1195
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return cloneLoadPolicy();
|
|
@@ -1339,10 +1334,6 @@ Fix: ${fix ?? `update ${field2 ?? "this config"} in ${file} to match the expecte
|
|
|
1339
1334
|
if (planMode !== void 0) {
|
|
1340
1335
|
if (!planMode || typeof planMode !== "object" || Array.isArray(planMode)) {
|
|
1341
1336
|
add("PLAN_MODE_CONFIG_INVALID", "planMode", "Expected an object.");
|
|
1342
|
-
} else if (planMode.writablePaths !== void 0) {
|
|
1343
|
-
const paths = planMode.writablePaths;
|
|
1344
|
-
if (!Array.isArray(paths)) add("PLAN_MODE_CONFIG_INVALID_WRITABLE_PATHS", "planMode.writablePaths", "Expected an array of documentation path strings.");
|
|
1345
|
-
else if (paths.some((value) => !isValidPathPattern(value) || typeof value !== "string" || value.trim().startsWith("/") || !normalizePathPattern(value).startsWith(`${normalizeDocumentationRoot(data.documentation?.root ?? DEFAULT_DOCUMENTATION_ROOT)}/`) || normalizePathPattern(value).startsWith(`${normalizeDocumentationRoot(data.documentation?.root ?? DEFAULT_DOCUMENTATION_ROOT)}/.`) || isSecretLikePathPattern(value))) add("PLAN_MODE_CONFIG_INVALID_WRITABLE_PATHS", "planMode.writablePaths", "Expected safe repository-relative paths under documentation.root using exact paths or /** subtree patterns.");
|
|
1346
1337
|
}
|
|
1347
1338
|
}
|
|
1348
1339
|
const referenceExpansion = data.referenceExpansion;
|
|
@@ -3804,7 +3795,6 @@ function formatConfigOutput(payload) {
|
|
|
3804
3795
|
lines.push(`- load pinned paths: ${(payload.config.load?.pinnedPaths ?? []).join(", ") || "none"}`);
|
|
3805
3796
|
lines.push(`- load pinned bodies: ${(payload.config.load?.pinnedBodies ?? []).join(", ") || "none"}`);
|
|
3806
3797
|
lines.push(`- load documentation summary exclude: ${(payload.config.load?.documentationSummary?.exclude ?? []).join(", ") || "none"}`);
|
|
3807
|
-
lines.push(`- plan mode writable paths: ${(payload.config.planMode?.writablePaths ?? []).join(", ") || "none"}`);
|
|
3808
3798
|
const lowSignal = payload.config.referenceExpansion?.fuzzy?.lowSignal ?? { terms: [], add: [], remove: [] };
|
|
3809
3799
|
lines.push(`- fuzzy low-signal terms: ${(lowSignal.terms ?? []).join(", ") || "none"} (add: ${(lowSignal.add ?? []).join(", ") || "none"}; remove: ${(lowSignal.remove ?? []).join(", ") || "none"})`);
|
|
3810
3800
|
if (errors.length > 0) {
|
package/mcp/server.mjs
CHANGED
|
@@ -3650,49 +3650,49 @@ var require_fast_uri = __commonJS({
|
|
|
3650
3650
|
schemelessOptions.skipEscape = true;
|
|
3651
3651
|
return serialize(resolved, schemelessOptions);
|
|
3652
3652
|
}
|
|
3653
|
-
function resolveComponent(base,
|
|
3653
|
+
function resolveComponent(base, relative3, options, skipNormalization) {
|
|
3654
3654
|
const target = {};
|
|
3655
3655
|
if (!skipNormalization) {
|
|
3656
3656
|
base = parse3(serialize(base, options), options);
|
|
3657
|
-
|
|
3657
|
+
relative3 = parse3(serialize(relative3, options), options);
|
|
3658
3658
|
}
|
|
3659
3659
|
options = options || {};
|
|
3660
|
-
if (!options.tolerant &&
|
|
3661
|
-
target.scheme =
|
|
3662
|
-
target.userinfo =
|
|
3663
|
-
target.host =
|
|
3664
|
-
target.port =
|
|
3665
|
-
target.path = removeDotSegments(
|
|
3666
|
-
target.query =
|
|
3660
|
+
if (!options.tolerant && relative3.scheme) {
|
|
3661
|
+
target.scheme = relative3.scheme;
|
|
3662
|
+
target.userinfo = relative3.userinfo;
|
|
3663
|
+
target.host = relative3.host;
|
|
3664
|
+
target.port = relative3.port;
|
|
3665
|
+
target.path = removeDotSegments(relative3.path || "");
|
|
3666
|
+
target.query = relative3.query;
|
|
3667
3667
|
} else {
|
|
3668
|
-
if (
|
|
3669
|
-
target.userinfo =
|
|
3670
|
-
target.host =
|
|
3671
|
-
target.port =
|
|
3672
|
-
target.path = removeDotSegments(
|
|
3673
|
-
target.query =
|
|
3668
|
+
if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
|
|
3669
|
+
target.userinfo = relative3.userinfo;
|
|
3670
|
+
target.host = relative3.host;
|
|
3671
|
+
target.port = relative3.port;
|
|
3672
|
+
target.path = removeDotSegments(relative3.path || "");
|
|
3673
|
+
target.query = relative3.query;
|
|
3674
3674
|
} else {
|
|
3675
|
-
if (!
|
|
3675
|
+
if (!relative3.path) {
|
|
3676
3676
|
target.path = base.path;
|
|
3677
|
-
if (
|
|
3678
|
-
target.query =
|
|
3677
|
+
if (relative3.query !== void 0) {
|
|
3678
|
+
target.query = relative3.query;
|
|
3679
3679
|
} else {
|
|
3680
3680
|
target.query = base.query;
|
|
3681
3681
|
}
|
|
3682
3682
|
} else {
|
|
3683
|
-
if (
|
|
3684
|
-
target.path = removeDotSegments(
|
|
3683
|
+
if (relative3.path[0] === "/") {
|
|
3684
|
+
target.path = removeDotSegments(relative3.path);
|
|
3685
3685
|
} else {
|
|
3686
3686
|
if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
|
|
3687
|
-
target.path = "/" +
|
|
3687
|
+
target.path = "/" + relative3.path;
|
|
3688
3688
|
} else if (!base.path) {
|
|
3689
|
-
target.path =
|
|
3689
|
+
target.path = relative3.path;
|
|
3690
3690
|
} else {
|
|
3691
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
3691
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
|
|
3692
3692
|
}
|
|
3693
3693
|
target.path = removeDotSegments(target.path);
|
|
3694
3694
|
}
|
|
3695
|
-
target.query =
|
|
3695
|
+
target.query = relative3.query;
|
|
3696
3696
|
}
|
|
3697
3697
|
target.userinfo = base.userinfo;
|
|
3698
3698
|
target.host = base.host;
|
|
@@ -3700,7 +3700,7 @@ var require_fast_uri = __commonJS({
|
|
|
3700
3700
|
}
|
|
3701
3701
|
target.scheme = base.scheme;
|
|
3702
3702
|
}
|
|
3703
|
-
target.fragment =
|
|
3703
|
+
target.fragment = relative3.fragment;
|
|
3704
3704
|
return target;
|
|
3705
3705
|
}
|
|
3706
3706
|
function equal(uriA, uriB, options) {
|
|
@@ -21959,23 +21959,15 @@ import { finished } from "node:stream/promises";
|
|
|
21959
21959
|
|
|
21960
21960
|
// packages/context/src/paths.mjs
|
|
21961
21961
|
import { realpathSync } from "node:fs";
|
|
21962
|
-
import {
|
|
21963
|
-
function assertWithinRoot(base, target, candidate) {
|
|
21964
|
-
const rel = relative(base, target);
|
|
21965
|
-
if (rel === ".." || rel.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute(rel)) {
|
|
21966
|
-
throw new Error(`Path escapes project root: ${candidate}`);
|
|
21967
|
-
}
|
|
21968
|
-
}
|
|
21962
|
+
import { resolve as resolve2 } from "node:path";
|
|
21969
21963
|
function resolveWithinRoot(root2, candidate = ".") {
|
|
21970
21964
|
const base = resolve2(root2 || process.cwd());
|
|
21971
21965
|
const target = resolve2(base, candidate);
|
|
21972
|
-
assertWithinRoot(base, target, candidate);
|
|
21973
21966
|
return target;
|
|
21974
21967
|
}
|
|
21975
21968
|
function resolveExistingWithinRoot(root2, candidate = ".") {
|
|
21976
21969
|
const base = realpathSync(resolve2(root2 || process.cwd()));
|
|
21977
21970
|
const target = realpathSync(resolveWithinRoot(base, candidate));
|
|
21978
|
-
assertWithinRoot(base, target, candidate);
|
|
21979
21971
|
return target;
|
|
21980
21972
|
}
|
|
21981
21973
|
|
|
@@ -22271,7 +22263,7 @@ import { readFileSync as readFileSync3, statSync as statSync4 } from "node:fs";
|
|
|
22271
22263
|
|
|
22272
22264
|
// packages/context/src/directory-ingestion.mjs
|
|
22273
22265
|
import { closeSync, constants, fstatSync, lstatSync, openSync, readFileSync as readFileSync2, readdirSync, realpathSync as realpathSync2, statSync as statSync3 } from "node:fs";
|
|
22274
|
-
import {
|
|
22266
|
+
import { relative, resolve as resolve3, sep } from "node:path";
|
|
22275
22267
|
var DEFAULT_LIMITS = Object.freeze({
|
|
22276
22268
|
maxDepth: 16,
|
|
22277
22269
|
maxVisitedEntries: 1e4,
|
|
@@ -22279,12 +22271,8 @@ var DEFAULT_LIMITS = Object.freeze({
|
|
|
22279
22271
|
maxFileBytes: 25 * 1024 * 1024,
|
|
22280
22272
|
maxAggregateBytes: 100 * 1024 * 1024
|
|
22281
22273
|
});
|
|
22282
|
-
function inside(base, target) {
|
|
22283
|
-
const rel = relative2(base, target);
|
|
22284
|
-
return rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute2(rel);
|
|
22285
|
-
}
|
|
22286
22274
|
function relativePath(base, target) {
|
|
22287
|
-
return
|
|
22275
|
+
return relative(base, target).split(sep).join("/");
|
|
22288
22276
|
}
|
|
22289
22277
|
function boundedInteger(value, fallback, name) {
|
|
22290
22278
|
const selected = value ?? fallback;
|
|
@@ -22335,10 +22323,7 @@ function snapshot(path, target, stat, symlink) {
|
|
|
22335
22323
|
function walkDirectoryManifest(options = {}) {
|
|
22336
22324
|
const root2 = realpathSync2(resolve3(options.root || process.cwd()));
|
|
22337
22325
|
const requested = resolve3(root2, options.path ?? ".");
|
|
22338
|
-
if (!inside(root2, requested)) throw new Error(`Directory escapes project root: ${options.path}`);
|
|
22339
|
-
if (lstatSync(requested).isSymbolicLink()) throw new Error(`Directory symlinks are not followed: ${options.path ?? "."}`);
|
|
22340
22326
|
const directory = realpathSync2(requested);
|
|
22341
|
-
if (!inside(root2, directory)) throw new Error(`Directory escapes project root: ${options.path}`);
|
|
22342
22327
|
if (!statSync3(directory).isDirectory()) throw new Error(`Not a directory: ${options.path ?? "."}`);
|
|
22343
22328
|
const policy = normalizeOptions(options);
|
|
22344
22329
|
const files = [];
|
|
@@ -22395,10 +22380,6 @@ function walkDirectoryManifest(options = {}) {
|
|
|
22395
22380
|
let targetStat;
|
|
22396
22381
|
try {
|
|
22397
22382
|
target = realpathSync2(absolutePath);
|
|
22398
|
-
if (!inside(root2, target)) {
|
|
22399
|
-
skip(path, "symlink-outside-root");
|
|
22400
|
-
continue;
|
|
22401
|
-
}
|
|
22402
22383
|
targetStat = statSync3(target);
|
|
22403
22384
|
} catch {
|
|
22404
22385
|
skip(path, "symlink-unresolvable");
|
|
@@ -22462,9 +22443,7 @@ function matchesIdentity(stat, identity) {
|
|
|
22462
22443
|
return stat.dev === identity.dev && stat.ino === identity.ino && stat.size === identity.size && stat.mtimeMs === identity.mtimeMs;
|
|
22463
22444
|
}
|
|
22464
22445
|
function verifyManifestFile(entry, root2) {
|
|
22465
|
-
const base = realpathSync2(resolve3(root2));
|
|
22466
22446
|
const target = realpathSync2(entry.absolutePath);
|
|
22467
|
-
if (!inside(base, target)) throw new Error(`Manifest file escapes project root: ${entry.path}`);
|
|
22468
22447
|
const stat = statSync3(target);
|
|
22469
22448
|
if (!stat.isFile()) throw new Error(`Manifest entry is not a regular file: ${entry.path}`);
|
|
22470
22449
|
if (!matchesIdentity(stat, entry.identity ?? {})) throw new Error(`Manifest file changed before indexing: ${entry.path}`);
|
|
@@ -23197,7 +23176,7 @@ function runDoctor(options = {}) {
|
|
|
23197
23176
|
// packages/context/src/project.mjs
|
|
23198
23177
|
import { existsSync as existsSync3, readdirSync as readdirSync2 } from "node:fs";
|
|
23199
23178
|
import { fileURLToPath } from "node:url";
|
|
23200
|
-
import { relative as
|
|
23179
|
+
import { relative as relative2, resolve as resolve5 } from "node:path";
|
|
23201
23180
|
import { spawn as spawn2 } from "node:child_process";
|
|
23202
23181
|
var cli = fileURLToPath(new URL("./cli.mjs", import.meta.url));
|
|
23203
23182
|
function markdownTree(root2, maxDepth = 5) {
|
|
@@ -23209,9 +23188,9 @@ function markdownTree(root2, maxDepth = 5) {
|
|
|
23209
23188
|
for (const entry of readdirSync2(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
23210
23189
|
const path = resolve5(dir, entry.name);
|
|
23211
23190
|
if (entry.isDirectory()) {
|
|
23212
|
-
output.push(`${" ".repeat(depth - 1)}- ${
|
|
23191
|
+
output.push(`${" ".repeat(depth - 1)}- ${relative2(root2, path)}/`);
|
|
23213
23192
|
walk(path, depth + 1);
|
|
23214
|
-
} else if (entry.isFile() && entry.name.endsWith(".md")) output.push(`${" ".repeat(depth - 1)}- ${
|
|
23193
|
+
} else if (entry.isFile() && entry.name.endsWith(".md")) output.push(`${" ".repeat(depth - 1)}- ${relative2(root2, path)}`);
|
|
23215
23194
|
}
|
|
23216
23195
|
}
|
|
23217
23196
|
walk(docs, 1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotdotgod/claude-code",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "Claude Code adapter for dotdotgod project memory workflows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Elastic-2.0",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"esbuild": "0.27.3",
|
|
28
|
-
"@dotdotgod/context": "0.6.
|
|
28
|
+
"@dotdotgod/context": "0.6.4"
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
".claude-plugin",
|
|
@@ -10,7 +10,7 @@ version: 1.0.0
|
|
|
10
10
|
|
|
11
11
|
## CLI Context
|
|
12
12
|
|
|
13
|
-
For focused documentation routing, run `dotdotgod query <root> "<focus>" --limit 30 --json`. Run `dotdotgod config <root> --json` when memory-area policy
|
|
13
|
+
For focused documentation routing, run `dotdotgod query <root> "<focus>" --limit 30 --json`. Run `dotdotgod config <root> --json` when memory-area policy or documentation routing/exclusions affect the plan. If the CLI is unavailable, continue from README indexes and focused file reads.
|
|
14
14
|
|
|
15
15
|
## Goal
|
|
16
16
|
|