@first-tree-ai/context-tree 0.1.5 → 0.1.7-alpha.202609010710

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.
Files changed (35) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +7 -3
  3. package/.codex-plugin/plugin.json +16 -9
  4. package/README.md +150 -117
  5. package/dist/cli/index.mjs +955 -573
  6. package/dist/index.d.mts +64 -15
  7. package/dist/index.mjs +833 -471
  8. package/dist/{schemas-C4bs-FkC.d.mts → schemas-C_7izpsa.d.mts} +130 -134
  9. package/dist/{schemas-BWM6Q6iz.mjs → schemas-DKHE1sWt.mjs} +62 -51
  10. package/dist/schemas.d.mts +2 -2
  11. package/dist/schemas.mjs +2 -2
  12. package/docs/specification.md +158 -144
  13. package/hooks/session-start.mjs +5 -14
  14. package/package.json +1 -1
  15. package/policy/context-tree-policy.md +10 -12
  16. package/skills/context-tree-connect/SKILL.md +34 -0
  17. package/skills/context-tree-connect/agents/openai.yaml +4 -0
  18. package/skills/context-tree-create/SKILL.md +32 -0
  19. package/skills/context-tree-create/agents/openai.yaml +4 -0
  20. package/skills/context-tree-publish/SKILL.md +26 -0
  21. package/skills/context-tree-publish/agents/openai.yaml +4 -0
  22. package/skills/context-tree-publish/scripts/context-tree.mjs +41 -0
  23. package/skills/context-tree-read/SKILL.md +20 -43
  24. package/skills/context-tree-read/agents/openai.yaml +2 -2
  25. package/skills/context-tree-setup/SKILL.md +33 -0
  26. package/skills/context-tree-setup/agents/openai.yaml +4 -0
  27. package/skills/context-tree-setup/scripts/context-tree.mjs +41 -0
  28. package/skills/context-tree-write/SKILL.md +29 -125
  29. package/skills/context-tree-write/agents/openai.yaml +2 -2
  30. package/skills/context-tree-init/SKILL.md +0 -51
  31. package/skills/context-tree-init/agents/openai.yaml +0 -4
  32. package/skills/context-tree-link/SKILL.md +0 -45
  33. package/skills/context-tree-link/agents/openai.yaml +0 -4
  34. /package/skills/{context-tree-init → context-tree-connect}/scripts/context-tree.mjs +0 -0
  35. /package/skills/{context-tree-link → context-tree-create}/scripts/context-tree.mjs +0 -0
@@ -1,146 +1,160 @@
1
- # Context Tree Format Specification
2
-
3
- ## Repository and root
4
-
5
- A shared Context Tree lives in a `github.com` repository identified as
6
- `OWNER/REPO`. GitHub commit SHAs identify exact shared snapshots. The package
7
- still operates on local clones and worktrees because validation and editing are
8
- filesystem operations.
9
-
10
- The tree root is a real directory containing a regular, non-symlink `NODE.md`.
11
- That root node is both the tree manifest and the repository-wide context node.
12
- It must contain non-empty prose and schema-version-1 frontmatter:
13
-
14
- ```yaml
15
- ---
16
- schemaVersion: 1
17
- title: "Service Context"
18
- description: "Durable decisions shared across service domains."
19
- ---
1
+ # Context Tree lifecycle specification
2
+
3
+ ## Scope
4
+
5
+ The package exposes setup as an orchestration skill over five concrete user
6
+ intentions: create, connect, read, write, and publish. Supporting commands
7
+ (`resolve`, `sync`, `list`, `prepare-write`, `finish-write`, `verify`, and
8
+ `policy`) are plugin and integration plumbing. Every JSON contract is strict
9
+ and uses `schemaVersion: 1`.
10
+
11
+ ## Shared invariants
12
+
13
+ - Every core Git and GitHub subprocess uses one injectable runner. Errors redact
14
+ credential-bearing URLs, authorization values, and common GitHub token forms.
15
+ - Repository arguments are validated `OWNER/REPO` identities. Credential-bearing
16
+ repository URLs are rejected and never logged.
17
+ - A Git project canonicalizes to the exact current checkout root. Separate
18
+ clones and worktrees remain separate projects.
19
+ - A non-Git project connection matches only its exact canonical directory.
20
+ - Tree validation rejects symlink components, requires an exact clean Git root,
21
+ parses the root node, and requires full tree verification to succeed. An
22
+ unclean checkout is `DIRTY_TREE` and failed verification is `INVALID_TREE`;
23
+ neither is reported as a stale connection.
24
+ - Stored `local` or `github` state remains that kind after connection; every
25
+ selected managed checkout is classified from a safe origin before storage.
26
+ - Duplicate records for one project produce `CORRUPT_CONNECTION`.
27
+ - Connections are persisted by an atomic replacement with mode `0600`. No
28
+ locking or schema migration is provided.
29
+
30
+ ## Result contracts
31
+
32
+ ```ts
33
+ type Create = {
34
+ created: boolean; title: string; treePath: string; branch: string;
35
+ commitSha: string; schemaVersion: 1;
36
+ };
37
+
38
+ type Tree =
39
+ | { kind: "local"; path: string }
40
+ | { kind: "github"; path: string; repository: string };
41
+
42
+ type Connection = { tree: Tree; schemaVersion: 1 };
43
+ type ManagedTreeListing = {
44
+ schemaVersion: 1;
45
+ trees: Array<{ name: string; tree: Tree }>;
46
+ };
47
+ type Sync = { tree: Tree; branch: string; sha: string; schemaVersion: 1 };
48
+ type Prepare = { worktreePath: string; schemaVersion: 1 };
49
+ type Finish = { branch: string; sha: string; schemaVersion: 1 };
50
+ type Publish = {
51
+ repository: string; url: string; branch: string; sha: string;
52
+ schemaVersion: 1;
53
+ };
20
54
  ```
21
55
 
22
- Root-only `schemaVersion` is required and is not valid on domain nodes or
23
- Markdown leaves. A legacy `SCOPE.md` has no special meaning and is validated as
24
- an ordinary leaf.
25
-
26
- ## Nodes and content classes
27
-
28
- The root requires the manifest fields above in `NODE.md`. Every semantic
29
- directory contains `NODE.md`, including `members/` and each member directory.
30
- Nodes and leaves require a non-empty `title`. Optional
31
- `description` is non-empty prose, and optional `soft_links` contains
32
- tree-root-relative Markdown files or node directories.
33
-
34
- - `normal`: root and durable domain decisions.
35
- - `member`: member-oriented context beneath `members/`.
36
- - `repo-infra`: dot paths, generated output, root `scripts/`, instructions, build, and CI files.
37
-
38
- `raw-context/` has no reserved meaning and follows ordinary node rules.
39
- Symlinks fail closed: they may not escape the tree, cross content-class
40
- boundaries, or stand in for domain directories. Repository infrastructure is
41
- excluded from semantic validation and reads.
42
-
43
- ## Memory model
44
-
45
- The Context Tree itself is shared memory. Repository-wide memory belongs in the
46
- root `NODE.md`; domain memory belongs in the corresponding domain node or leaf.
47
- There is no reserved shared-memory directory or second store alongside the
48
- canonical domain tree. Add and split shared memory with the ordinary node
49
- policy.
50
-
51
- An agent's optional private memory lives at `members/<agent_slug>/memory.md`.
52
- The `members/` directory, agent directory, and memory file are all optional;
53
- when present, each directory requires its ordinary `NODE.md` index. Skills use
54
- `agent_slug` to avoid unrelated member content by default. Scaffolding does not
55
- create empty private memory files.
56
-
57
- Domain scope controls read relevance, not authorization. Shared tree memory is
58
- commonly readable but writes still require authorization from the user or host
59
- and follow the GitHub workflow. Member boundaries are relevance guidance only:
60
- the library and CLI apply no member-level access restriction, and the format
61
- claims no directory-level confidentiality.
62
-
63
- ## Public contracts
64
-
65
- CLI JSON uses `schemaVersion: 1`. Version 1 was redefined before deployment;
66
- owner-bearing contracts have no compatibility layer. Exported strict Zod
67
- schemas are the source of truth for library and CLI wire contracts. Unknown
68
- output properties are rejected. Successful command results and runtime or
69
- argument failures emit one JSON object on stdout; help and version output remain
70
- plain text. An invalid `verify` report is still emitted and the command exits
71
- with status 1.
72
-
73
- `policy` returns `content` and `schemaVersion`. `read` returns the root, target,
74
- schema version, a selected node with its complete parsed frontmatter and body,
75
- and sorted immediate child summaries. `verify` returns
76
- the root, schema version, validity, findings, and content-class counts. None
77
- includes a tree digest or per-entry digest. The Git commit SHA is recorded by
78
- the surrounding host Git workflow rather than computed by the core.
79
-
80
- `link` and `resolve` return a strict link result containing the
81
- project identity and tree `OWNER/REPO` plus a canonical absolute, single-line
82
- checkout path. Link
83
- failures distinguish `NO_LINK`, `AMBIGUOUS_LINK`,
84
- `CORRUPT_LINK`, and `STALE_LINK` from other CLI failures.
85
-
86
- ## Lifecycle
87
-
88
- Scaffolding creates exactly four files: root `NODE.md`, root `AGENTS.md`, root
89
- `CLAUDE.md`, and `.github/workflows/validate-context-tree.yml`. `AGENTS.md`
90
- explains the tree's purpose, structure, authority, and write discipline to
91
- agents entering the repository. `CLAUDE.md` is a relative symlink to `AGENTS.md`
92
- so both instruction filenames expose the same packaged guidance. The workflow
93
- is pinned to the package version that generated it. Init takes canonical `OWNER/REPO` and an
94
- optional absent or empty destination. It requires Git, runs ordinary `git init`, and uses the
95
- unborn branch selected by Git's effective `init.defaultBranch` configuration or
96
- compiled fallback. The generated workflow filters pushes to that exact branch.
97
- The local tree title and default destination name come from `REPO`. Init
98
- configures a credential-free `https://github.com/OWNER/REPO.git` origin. Init
99
- records an unambiguous current project link only in the machine-local links
100
- file and never embeds the source-project association in the tree.
101
- The core and CLI perform no authenticated GitHub operations.
102
-
103
- Internal links live at `~/.context-tree/connections.json`. A link
104
- maps a normalized Git project origin or a real non-Git directory to canonical
105
- tree `OWNER/REPO` and checkout path. Git lookup also confirms that the project
106
- origin matches the local record; non-Git lookup includes descendants.
107
- Zero or multiple matches fail, and a project cannot link to different tree
108
- repositories. Explicit linking requires a clean exact Git root, safe GitHub
109
- origin, and complete tree verification. Init may
110
- automatically link only its exact new uncommitted scaffold. Resolve rejects symlinked,
111
- dirty, moved, mismatched-origin, and invalid-root candidates, but parses only
112
- root `NODE.md` rather than scanning all semantic content. Full verification is
113
- the responsibility of read and write after refresh.
114
-
115
- A moved checkout produces `STALE_LINK`; explicit linking may replace its
116
- path only after verifying the same stored tree repository and proving the prior
117
- path absent, no longer an exact checkout, or occupied by another repository. A
118
- second live checkout cannot replace the stored path, even when the stored
119
- checkout is dirty. Relinking the same canonical path is idempotent.
120
-
121
- Link setup selects or clones a verified checkout and writes only the local link
122
- record. It never mutates or publishes the Context Tree repository.
123
-
124
- Reads and writes take only `agent_slug`, sourced from authoritative task role
125
- instructions. They resolve the current project, then discover the live default
126
- branch using `git ls-remote --symref origin HEAD`; branches are never configured
127
- or cached. The exact clean, non-symlink Git root and its credential-free GitHub
128
- `origin` remain the authorization boundary. Resolution selects a candidate and
129
- does not replace full semantic verification. Reads refresh fast-forward-only,
130
- validate, and report the commit SHA; authorized stale reads stay read-only.
131
-
132
- The package root exports `linkProject`, `resolveLink`,
133
- `readContextTreePolicy`, `readTree`, `scaffoldTree`, and `verifyTree`.
134
- Project identification, URL normalization, and the links-file storage
135
- schema are internal. Public strict CLI result schemas remain available from
136
- the schemas entrypoint.
137
-
138
- Writes fetch the discovered default branch through that checkout and edit an
139
- isolated worktree. One source comes from task context, not an invocation
140
- argument, and scopes one write and commit. The base and result must validate;
141
- publication first uses a non-force direct push to the discovered default branch.
142
- Concurrent updates are rebased, resolved from authorized evidence, and verified
143
- again with bounded retries. Explicit direct-push denial or exhausted retries
144
- uses a latest-base, conflict-free task-branch PR fallback that remains open.
145
- Invalid bases permit only explicitly requested validator-scoped repair, and the
146
- workflow never merges.
56
+ Errors use `{ ok: false, error: { code, message }, schemaVersion: 1 }`.
57
+ Lifecycle-specific codes are `NO_CONNECTION`, `CORRUPT_CONNECTION`,
58
+ `STALE_CONNECTION`, `DIRTY_TREE`, `INVALID_TREE`, `WRITE_OUTDATED`,
59
+ `GITHUB_AUTH`, `REPOSITORY_EXISTS`, and `PUBLISH_INCOMPLETE`. Other failures
60
+ use `CONTEXT_TREE_FAILED`.
61
+
62
+ ## Creation and connection
63
+
64
+ `create` derives `<normalized-project-directory>-context-tree` from the
65
+ canonical project root. It scaffolds and commits the tree in the flat managed
66
+ namespace before atomically connecting it. Repetition is idempotent only when
67
+ the project is still connected to that tree. An occupied name otherwise fails
68
+ with guidance to use `connect <name>`, and a project already connected to a
69
+ different tree fails rather than being silently repointed. Files created by a
70
+ failed create are removed; a destination that existed before the invocation is
71
+ never removed.
72
+
73
+ `connect <name>` performs an exact managed-directory lookup. `connect
74
+ OWNER/REPO` reuses a matching checkout or clones it under the lowercased
75
+ repository name. Every selection is validated and safely classified as local
76
+ or GitHub state. Local-tree, repository, and unsafe-origin name collisions fail
77
+ before the project connection changes. Explicit connection switches are
78
+ automatic. Only a directory created by a failed clone is removed.
79
+
80
+ `connect --tree-path <path>` attaches an exact, clean, fully valid Git root
81
+ with no symlink components in place and never copies, moves, or deletes it.
82
+ Trees without an origin classify as local state; credential-free GitHub
83
+ origins classify as GitHub state; all other origins are rejected. Stored-
84
+ connection validation accepts verified external paths while name-based
85
+ discovery remains restricted to the managed namespace. `list` reports valid,
86
+ clean managed trees as `{ schemaVersion: 1, trees: [{ name, tree }] }`; a
87
+ missing managed directory is an empty list and is never created by listing.
88
+
89
+ ## Synchronization and reading
90
+
91
+ Local synchronization makes no network call and reports the checked-out branch
92
+ and exact `HEAD`. GitHub synchronization performs exactly one
93
+ `git pull --ff-only origin <checked-out-branch>`, revalidates, then reports its
94
+ exact SHA. It does not discover or enforce the remote default branch and does
95
+ not report an `updated` flag.
96
+
97
+ `read` returns a selected node and only its immediate indexed children. Callers
98
+ navigate narrowly from indexes rather than scanning the semantic tree.
99
+
100
+ ## Writing
101
+
102
+ `prepare-write` synchronizes and creates a random `context-tree/write/*` branch
103
+ in an isolated worktree at the synchronized SHA. It returns only the worktree
104
+ path and schema version; no token, registry, manifest, lock, or preparation
105
+ record exists.
106
+
107
+ `finish-write` requires that the supplied path is a real non-symlink directory,
108
+ belongs to the connected tree's Git common directory, uses the reserved branch
109
+ prefix, contains pending changes, and verifies as a complete Context Tree.
110
+ Calling it authorizes all pending changes. It stages everything and creates one
111
+ commit with `commit.gpgsign=false` while retaining the host Git identity.
112
+
113
+ For local state it attempts one fast-forward merge into the connected checkout's
114
+ current branch. For GitHub state it attempts one non-force push to that branch.
115
+ Success removes the worktree and task branch. A non-fast-forward failure emits
116
+ `WRITE_OUTDATED` and preserves both. There is no rebase, race loop, semantic
117
+ conflict result, pull-request fallback, or abandoned-worktree cleanup.
118
+
119
+ The write skill may prepare fresh and reapply the intended semantic change
120
+ once after `WRITE_OUTDATED`. A second outdated result is reported to the user.
121
+
122
+ ## Publication
123
+
124
+ `publish` requires stored local state, a clean valid tree, and no existing
125
+ `origin`. By default it combines the authenticated GitHub login with the
126
+ managed tree name; an explicit validated `OWNER/REPO` may override it.
127
+ It runs one `gh repo create --private --source <tree> --remote origin --push`.
128
+
129
+ After success, the connection is atomically updated to GitHub state. Clear
130
+ authentication failures produce `GITHUB_AUTH`; clear name collisions produce
131
+ `REPOSITORY_EXISTS`; uncertain or partial outcomes produce
132
+ `PUBLISH_INCOMPLETE`. Publication does not inspect, adopt, repair, retry, or
133
+ delete partial GitHub state. The GitHub operation and local connection update are not
134
+ atomic.
135
+
136
+ ## Setup orchestration
137
+
138
+ `context-tree-setup` is an orchestration skill over the five concrete
139
+ workflows. It stops when the project is already connected; otherwise it asks
140
+ whether to create a new tree or connect an existing one and delegates to the
141
+ chosen workflow. Connect targets include listed managed names when any exist,
142
+ plus GitHub `OWNER/REPO` and exact disk paths; without managed trees only
143
+ GitHub and disk-path targets are offered. It never publishes without explicit
144
+ user confirmation. `context-tree-read` and `context-tree-write` invoke setup
145
+ when they receive `NO_CONNECTION`, then retry the operation once.
146
+
147
+ ## Hook and skills
148
+
149
+ The session hook resolves the host-supplied `cwd` rather than its own process
150
+ directory, and is silent without a valid connection, including unconnected
151
+ sessions and payloads with no `cwd`; setup routing happens in the read and
152
+ write skills, never in the hook. With a connection, it reports only
153
+ `Context Tree connected at <path>`.
154
+
155
+ Skills invoke the packaged CLI directly as
156
+ `node "<skill-directory>/scripts/context-tree.mjs"` after checking `--version`.
157
+ They rely on the packaged CLI and do not prescribe raw Git/GitHub operations.
158
+
159
+ The skill inventory is setup, create, connect, read, write, and publish;
160
+ setup orchestrates the five concrete workflows.
@@ -28,37 +28,28 @@ if (input.hook_event_name !== "SessionStart" && input.hook_event_name !== "Subag
28
28
  const pluginRoot = process.env.PLUGIN_ROOT ?? process.env.CLAUDE_PLUGIN_ROOT;
29
29
  const packagedCli = pluginRoot === undefined ? undefined : join(pluginRoot, "dist", "cli", "index.mjs");
30
30
  if (packagedCli === undefined || !existsSync(packagedCli)) {
31
- process.stdout.write(JSON.stringify({ systemMessage: "Context Tree setup warning: packaged CLI is unavailable." }));
32
31
  process.exit(0);
33
32
  }
34
33
  const resolved = spawnSync(process.execPath, [packagedCli, "resolve", "--project-path", input.cwd], {
35
34
  encoding: "utf8",
36
35
  stdio: ["ignore", "pipe", "ignore"],
37
36
  });
37
+ if (resolved.status !== 0) process.exit(0);
38
+
38
39
  let payload;
39
40
  try {
40
41
  payload = JSON.parse(resolved.stdout);
41
42
  } catch {
42
- process.stdout.write(JSON.stringify({ systemMessage: "Context Tree setup warning: packaged CLI is unavailable." }));
43
- process.exit(0);
44
- }
45
-
46
- if (resolved.status !== 0) {
47
- const code = payload?.error?.code;
48
- if (code === "NO_LINK") process.exit(0);
49
- if (["AMBIGUOUS_LINK", "CORRUPT_LINK", "STALE_LINK"].includes(code)) {
50
- process.stdout.write(JSON.stringify({ systemMessage: `Context Tree setup warning: ${payload.error.message}` }));
51
- }
52
43
  process.exit(0);
53
44
  }
54
45
 
55
- const tree = payload?.link?.tree;
56
- if (typeof tree?.path !== "string" || typeof tree?.repository !== "string") process.exit(0);
46
+ const tree = payload?.tree;
47
+ if (typeof tree?.path !== "string") process.exit(0);
57
48
  process.stdout.write(
58
49
  JSON.stringify({
59
50
  hookSpecificOutput: {
51
+ additionalContext: `Context Tree connected at ${tree.path}`,
60
52
  hookEventName: input.hook_event_name,
61
- additionalContext: `Context Tree ${tree.repository} is linked at ${tree.path}. Use the Context Tree skills for task-relevant durable context.`,
62
53
  },
63
54
  }),
64
55
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@first-tree-ai/context-tree",
3
- "version": "0.1.5",
3
+ "version": "0.1.7-alpha.202609010710",
4
4
  "description": "Context Tree plugin for Codex and Claude Code, with a CLI for shell automation.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -144,15 +144,13 @@ decision, not normal tree content. Keep tree prose current-state: no timeline,
144
144
  provenance, PR references, or implementation detail. `context-tree verify` must
145
145
  pass before any tree commit.
146
146
 
147
- Authorization comes from the user or host and is enforced through the GitHub
148
- workflow. Every write uses a freshly fetched exact supplied default branch in
149
- an isolated clean worktree and changes only necessary non-symlink Markdown.
150
- After verification and repository checks, publish the commit directly to that
151
- branch with a non-force push. Resolve concurrent updates by rebasing unpublished
152
- work onto the latest default branch, resolving evidence-determined conflicts,
153
- and verifying the complete result again. If direct publication is denied or
154
- bounded race retries are exhausted, open a conflict-free, non-force fallback PR
155
- against the supplied default branch and leave it open. Keep each source-backed
156
- write and commit scoped to one source artifact. An invalid base blocks semantic
157
- changes; only an explicit repair request may produce a repair-only write and
158
- commit limited to validator findings.
147
+ Authorization comes from the user or host. Every write synchronizes the connected
148
+ tree's checked-out branch and uses an isolated clean worktree at that exact
149
+ commit. Invocation of the finishing operation authorizes all pending changes in
150
+ that worktree. The lifecycle verifies, commits, and attempts one fast-forward
151
+ merge or one non-force push. If the destination advanced, preserve the outdated
152
+ worktree, prepare from current state, and reapply the intended semantic change
153
+ once. Do not rebase, loop, push manually, or open a fallback pull request. Keep
154
+ each source-backed write and commit scoped to one source artifact. An invalid
155
+ base blocks semantic changes; only an explicit repair request may produce a
156
+ repair-only write and commit limited to validator findings.
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: context-tree-connect
3
+ description: Connect the current project to an existing Context Tree by managed name, GitHub OWNER/REPO, or exact disk path. Use when the tree already exists; context-tree-setup delegates here once the user has chosen a target.
4
+ license: Apache-2.0
5
+ compatibility: Requires Node.js 22.13+ and the context-tree CLI JSON schema version 1.
6
+ metadata:
7
+ author: first-tree-ai
8
+ version: "0.1.7-alpha.202609010710"
9
+ ---
10
+
11
+ # Context Tree Connect
12
+
13
+ Resolve `<skill-directory>` to this skill's directory and run
14
+ `node "<skill-directory>/scripts/context-tree.mjs" --version` once per session.
15
+ If the packaged CLI is unavailable, stop and ask the user to reinstall or
16
+ update the plugin.
17
+
18
+ Connect exactly one target supplied by the user:
19
+
20
+ - A managed tree name or GitHub `OWNER/REPO`:
21
+ `node "<skill-directory>/scripts/context-tree.mjs" connect "<name-or-OWNER/REPO>"`.
22
+ - An exact path to an existing Context Tree checkout:
23
+ `node "<skill-directory>/scripts/context-tree.mjs" connect --tree-path "<path>"`.
24
+ That checkout is attached where it already lives and is never copied, moved,
25
+ or deleted.
26
+
27
+ Never accept a repository URL, and never infer, guess, or search the filesystem
28
+ for a target yourself; pass through only what the user typed or confirmed. An
29
+ explicit connect switches the project's connection. Report whether the
30
+ connected tree is local or GitHub-backed, with its canonical path.
31
+
32
+ If connection reports `INVALID_TREE` or `DIRTY_TREE`, report the failure and
33
+ stop. The tree must be repaired or committed at its own location before it can
34
+ be connected.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Context Tree Connect"
3
+ short_description: "Connect a project to an existing tree"
4
+ default_prompt: "Use $context-tree-connect with a managed name, OWNER/REPO, or exact disk path."
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: context-tree-create
3
+ description: Create and connect a new managed local Context Tree for the current project. Use when the user wants a brand-new tree; context-tree-setup delegates here after confirming the project has none.
4
+ license: Apache-2.0
5
+ compatibility: Requires Node.js 22.13+ and the context-tree CLI JSON schema version 1.
6
+ metadata:
7
+ author: first-tree-ai
8
+ version: "0.1.7-alpha.202609010710"
9
+ ---
10
+
11
+ # Context Tree Create
12
+
13
+ Resolve `<skill-directory>` to this skill's directory and run
14
+ `node "<skill-directory>/scripts/context-tree.mjs" --version` once per session.
15
+ If the packaged CLI is unavailable, stop and ask the user to reinstall or
16
+ update the plugin.
17
+
18
+ Run `node "<skill-directory>/scripts/context-tree.mjs" create`. Report whether
19
+ the managed tree was created or already existed, together with its name, path,
20
+ and exact commit SHA.
21
+
22
+ The managed name is derived from the project directory's name. If that name is
23
+ already taken, or the project is already connected to a different tree, report
24
+ the `connect` command the error supplies and stop. Do not replace or remove the
25
+ existing managed tree or connection.
26
+
27
+ After the tree is created or reused, run
28
+ `node "<skill-directory>/scripts/context-tree.mjs" resolve`. When the tree is
29
+ local, ask the user whether to publish it as a private GitHub repository. An
30
+ explicit prior request to publish counts as confirmation; otherwise a "no"
31
+ leaves the tree local, and a "yes" delegates to `$context-tree-publish`. Never
32
+ publish without that confirmation.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Context Tree Create"
3
+ short_description: "Create managed durable project context"
4
+ default_prompt: "Use $context-tree-create to start a new tree for this project."
@@ -0,0 +1,26 @@
1
+ ---
2
+ name: context-tree-publish
3
+ description: Publish the current project's local Context Tree as a new private GitHub repository. Use only when the user explicitly asks to publish or share the tree.
4
+ license: Apache-2.0
5
+ compatibility: Requires Node.js 22.13+ and the context-tree CLI JSON schema version 1.
6
+ metadata:
7
+ author: first-tree-ai
8
+ version: "0.1.7-alpha.202609010710"
9
+ ---
10
+
11
+ # Context Tree Publish
12
+
13
+ Resolve `<skill-directory>` to this skill's directory and run
14
+ `node "<skill-directory>/scripts/context-tree.mjs" --version` once per session.
15
+ If the packaged CLI is unavailable, stop and ask the user to reinstall or
16
+ update the plugin.
17
+
18
+ Run `node "<skill-directory>/scripts/context-tree.mjs" publish`. When the user
19
+ explicitly supplies an alternative, append the validated `OWNER/REPO` argument.
20
+ Never accept a repository URL.
21
+
22
+ Publication creates one new private repository, and the local connection update
23
+ that follows is not part of the same atomic step. If it reports
24
+ `PUBLISH_INCOMPLETE`, do not inspect, adopt, repair, retry, or delete partial
25
+ state; report the uncertain outcome. If it reports `INVALID_TREE`, run `verify`
26
+ and report its findings.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Context Tree Publish"
3
+ short_description: "Publish durable context privately"
4
+ default_prompt: "Use $context-tree-publish to share this project's tree privately."
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { spawnSync } from "node:child_process";
4
+ import { lstatSync, readFileSync, realpathSync } from "node:fs";
5
+ import { dirname, isAbsolute, relative, resolve } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const PACKAGE_NAME = "@first-tree-ai/context-tree";
9
+ const REINSTALL_MESSAGE = "Context Tree packaged CLI is unavailable. Reinstall or update the Context Tree plugin.";
10
+
11
+ function packagedCli() {
12
+ try {
13
+ const packageRoot = realpathSync(resolve(dirname(fileURLToPath(import.meta.url)), "../../.."));
14
+ const packageJson = resolve(packageRoot, "package.json");
15
+ const cli = resolve(packageRoot, "dist/cli/index.mjs");
16
+ if (lstatSync(packageJson).isSymbolicLink() || !lstatSync(packageJson).isFile()) return undefined;
17
+ if (JSON.parse(readFileSync(packageJson, "utf8")).name !== PACKAGE_NAME) return undefined;
18
+ if (lstatSync(cli).isSymbolicLink() || !lstatSync(cli).isFile()) return undefined;
19
+ const realCli = realpathSync(cli);
20
+ const containedPath = relative(packageRoot, realCli);
21
+ return containedPath !== "" && !containedPath.startsWith("..") && !isAbsolute(containedPath) ? realCli : undefined;
22
+ } catch {
23
+ return undefined;
24
+ }
25
+ }
26
+
27
+ function forward(result) {
28
+ if (result.error !== undefined) {
29
+ process.stderr.write(`${REINSTALL_MESSAGE}\n`);
30
+ process.exit(1);
31
+ }
32
+ if (result.signal !== null) process.kill(process.pid, result.signal);
33
+ process.exit(result.status ?? 1);
34
+ }
35
+
36
+ const cli = packagedCli();
37
+ if (cli === undefined) {
38
+ process.stderr.write(`${REINSTALL_MESSAGE}\n`);
39
+ process.exit(1);
40
+ }
41
+ forward(spawnSync(process.execPath, [cli, ...process.argv.slice(2)], { stdio: "inherit" }));