@trailkeep/cli 0.0.0-stage → 0.3.2
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/.claude-plugin/marketplace.json +11 -0
- package/.claude-plugin/plugin.json +8 -0
- package/LICENSE +21 -0
- package/README.md +154 -2
- package/bin/trailkeep +1456 -0
- package/hooks/hooks.json +28 -0
- package/package.json +42 -4
- package/skills/effort/SKILL.md +59 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "trailkeep",
|
|
3
|
+
"owner": { "name": "Mario Širić" },
|
|
4
|
+
"plugins": [
|
|
5
|
+
{
|
|
6
|
+
"name": "trailkeep",
|
|
7
|
+
"source": "./",
|
|
8
|
+
"description": "Injects your private repo notes and the current branch's effort file at session start, plus the effort skill."
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "trailkeep",
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"description": "Injects your private repo notes and the current branch's effort file at session start, plus the effort skill.",
|
|
5
|
+
"author": { "name": "Mario Širić" },
|
|
6
|
+
"repository": "https://github.com/msiric/trailkeep",
|
|
7
|
+
"license": "MIT"
|
|
8
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mario Širić
|
|
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.
|
package/README.md
CHANGED
|
@@ -1,3 +1,155 @@
|
|
|
1
|
-
#
|
|
1
|
+
# trailkeep
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Context for coding agents that works the same in **Claude Code**, **Codex CLI** and **GitHub Copilot CLI**. It keeps three kinds of knowledge apart: what's always true about you, what's always true about a repo, and what matters only for the branch you're on. It also keeps an append-only log of why things were decided.
|
|
4
|
+
|
|
5
|
+
It's a single POSIX shell script that needs only `git`. It never changes your repos' tracked files. In a repo with no notes, effort or log, it adds at most one hint line to a session, and none at all with `TRAILKEEP_HINT=0`.
|
|
6
|
+
|
|
7
|
+
## Install (one command, once per machine)
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install -g @trailkeep/cli && trailkeep install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or without npm, or if your npm goes through a company mirror that doesn't carry the package (a 404 from a feed proxy):
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
git clone https://github.com/msiric/trailkeep ~/.trailkeep && ~/.trailkeep/bin/trailkeep install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`install` copies the tool to `~/.agents/trailkeep/` and points every hook there. After that, the npm package or the clone can move, upgrade or disappear (a Node version switch with nvm or fnm, say) without breaking any hook or Codex's trust in them.
|
|
20
|
+
|
|
21
|
+
That's the whole setup, and it covers every repo on the machine: the hooks are user-level, so there's nothing to do per repo. If you already have instructions in `~/.claude/CLAUDE.md`, install offers to share them with all three agents.
|
|
22
|
+
|
|
23
|
+
Codex needs one manual step, because trusting hooks is a security gate Codex deliberately keeps for you. Open `codex`, run `/hooks` and trust the two trailkeep hooks once. After that, `trailkeep doctor` checks the setup and `trailkeep verify` runs a live test with each agent.
|
|
24
|
+
|
|
25
|
+
Later, `trailkeep update` gets the latest version the same way you installed it (npm or git) and re-applies the setup.
|
|
26
|
+
|
|
27
|
+
## The layers
|
|
28
|
+
|
|
29
|
+
| Layer | File | Who writes it | Loaded |
|
|
30
|
+
|---|---|---|---|
|
|
31
|
+
| **Personal**: you, in every repo | `~/.agents/AGENTS.md` | you | every session, by all three agents |
|
|
32
|
+
| **Repo**: true for every task here | the repo's own `AGENTS.md` (committed) | you and your team | natively by all three agents |
|
|
33
|
+
| **Private repo notes**: things you can't commit | `~/.agents/repos/<repo>/NOTES.md` | you | at session start, by a hook |
|
|
34
|
+
| **Effort**: this branch's goal, plan, progress, decisions | `.trailkeep/<branch>.md` in the worktree, ignored by git | the agent | at session start and after compaction, by a hook |
|
|
35
|
+
| **Decision log**: why things happened, append-only | `~/.agents/repos/<repo>/log/YYYY-MM.tsv` | the session-end hook | never loaded; agents search it |
|
|
36
|
+
|
|
37
|
+
`<repo>` comes from the origin URL, so every clone and worktree of a repo shares the same notes and log.
|
|
38
|
+
|
|
39
|
+
## What happens on its own
|
|
40
|
+
|
|
41
|
+
| When | What happens automatically |
|
|
42
|
+
|---|---|
|
|
43
|
+
| Any session starts in any repo | Notes and the branch's effort file are injected. A one-line pointer mentions the decision log if it has entries. Leftovers from a session that didn't exit cleanly are logged first. |
|
|
44
|
+
| You're on a feature branch with no effort file | One line tells the agent it can run `trailkeep new` for multi-session work. Turn it off with `TRAILKEEP_HINT=0`. |
|
|
45
|
+
| The agent works | It keeps the effort file current: plan ticks, a progress line per session, decisions and dead ends. That's the effort skill's job. |
|
|
46
|
+
| Context gets compacted | The effort file is re-injected fresh. |
|
|
47
|
+
| A session ends | New Decisions and Progress lines from every effort in the worktree go into the decision log, stamped with the commit, the branch's changed files, branch and session id. It takes under 0.1 s, well inside Codex's 3-second limit for this hook. Anything a killed session missed is picked up at the next start, in the background. |
|
|
48
|
+
| A branch is renamed | Its effort file follows the new name. Git's reflog records renames. |
|
|
49
|
+
| A branch is deleted, locally and on the remote | Its last lines are logged, then its effort file is archived and the archive is logged. |
|
|
50
|
+
|
|
51
|
+
The one deliberate manual step is promoting a lasting lesson into a permanent file (`AGENTS.md`, notes, personal). The agent proposes it at close, and you approve. Permanent files that agents edit without review drift and bloat. That's the failure this design exists to avoid.
|
|
52
|
+
|
|
53
|
+
## The decision log
|
|
54
|
+
|
|
55
|
+
Git already records what changed, when and where, and each agent keeps its own transcripts. The log adds the missing part, **why**, with pointers to both. It's write-everything, read-narrowly, because unfiltered history in context hurts more than it helps ([SWE Context Bench](https://arxiv.org/abs/2602.08316)), while a plain chronological log works well ([DreamBench-SWE](https://arxiv.org/abs/2608.20664)).
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
trailkeep log --path src/auth # entries whose changed files include src/auth
|
|
59
|
+
trailkeep log --grep jwt --type dead-end --since 2026-10-01
|
|
60
|
+
trailkeep log show 73a8b76 # one entry in full: commit, files, session, transcript
|
|
61
|
+
git show <commit> # then the actual change
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Results are one short line each, newest first, at most 20 by default. Agents learn this from the effort skill and the one-line pointer, and they never write the log directly. Writes happen in hooks, which run outside the agent's sandbox.
|
|
65
|
+
|
|
66
|
+
The format is one event per line, tab-separated, one file per month: `id time type branch commit paths text session transcript`. It needs no parser or database, `grep` works on it, and appends never rewrite history. In the effort file, start a line with `Dead end:` to log it as a failed approach.
|
|
67
|
+
|
|
68
|
+
## Across repos, sessions and machines
|
|
69
|
+
|
|
70
|
+
- **Repos:** nothing to set up per repo. An agent in a repo you've never touched just gets your personal file plus that repo's `AGENTS.md`.
|
|
71
|
+
- **Sessions and agents:** state lives in files, not chats. End a session in Claude and continue in Codex, and the effort file and log carry over.
|
|
72
|
+
- **Worktrees:** each one has its own `.trailkeep/`, so parallel agents on different branches never share task state. Notes and the log are shared per repo.
|
|
73
|
+
- **Machines:** `~/.agents` is local. To sync it, put it in a private git repo (it's plain text). Effort files travel with the worktree; the log and notes stay with `~/.agents`.
|
|
74
|
+
|
|
75
|
+
## Daily commands
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
trailkeep new # start an effort for this branch (or ask the agent to)
|
|
79
|
+
trailkeep show # exactly what agents get here at session start
|
|
80
|
+
trailkeep list # active efforts across all repos, with their last progress line
|
|
81
|
+
trailkeep close # archive the effort; lists decisions worth promoting
|
|
82
|
+
trailkeep notes # private notes for this repo
|
|
83
|
+
trailkeep log ... # search the decision log
|
|
84
|
+
trailkeep doctor # check setup and this repo's instruction files
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Why it's built this way
|
|
88
|
+
|
|
89
|
+
Every rule below comes from vendor documentation, the CLIs' source code or published evaluations. None of it is taste.
|
|
90
|
+
|
|
91
|
+
- **Global files stay short and hold only what code can't tell an agent.** In a controlled study, context files didn't improve task success but raised cost by over 20% ([ICLR 2026](https://arxiv.org/abs/2602.11988)). Anthropic says to keep CLAUDE.md under 200 lines ([memory](https://code.claude.com/docs/en/memory)), and `doctor` flags files over 200 lines.
|
|
92
|
+
- **Task state lives in a file, not in the chat.** Anthropic's long-running harness and OpenAI's ExecPlans both rebuild state from a file at the start of every session ([Anthropic](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents), [OpenAI](https://developers.openai.com/cookbook/articles/codex_exec_plans)).
|
|
93
|
+
- **Effort files live in the worktree** because that's the only place every agent can write without prompting. Codex also keeps `.git/`, `.agents/` and `.codex/` read-only inside the workspace (codex source, `PROTECTED_METADATA_PATH_NAMES`). `.trailkeep/` ignores itself with a one-line `.gitignore`. `git clean -fdx` deletes it.
|
|
94
|
+
- **Output fits each tool's limits.** Claude caps hook text at 10,000 characters ([hooks](https://code.claude.com/docs/en/hooks)), and Codex spills hook text over about 2,500 tokens to a file. trailkeep stays under 9,000 characters. A file larger than that is replaced with its path, never silently truncated.
|
|
95
|
+
- **AGENTS.md is the one repo file.** Claude Code reads it natively from v2.1.277, but only when no CLAUDE.md exists. `doctor` warns when a CLAUDE.md hides it. Codex stops at 32 KiB of project instructions (`project_doc_max_bytes`), and `doctor` adds up the files for your current directory.
|
|
96
|
+
- **Copilot is handled differently.** It needs JSON from hooks and ignores `~/` imports ([hooks](https://docs.github.com/en/copilot/reference/copilot-cli-reference/cli-hooks-reference), [instructions](https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-custom-instructions)), so it gets a symlink and JSON output.
|
|
97
|
+
- **There's no vector database, MCP server or generated AGENTS.md.** A plain log did about as well as a memory product, MCP tool definitions cost context in every session ([Anthropic](https://www.anthropic.com/engineering/advanced-tool-use)), and LLM-generated context files slightly lowered success.
|
|
98
|
+
|
|
99
|
+
## What `install` changes
|
|
100
|
+
|
|
101
|
+
Files it edits are backed up to `~/.agents/backups/` first.
|
|
102
|
+
|
|
103
|
+
- `~/.claude/CLAUDE.md` gets a 3-line block importing `~/.agents/AGENTS.md`; your own lines stay. HTML comments are stripped by Claude, so the markers cost nothing.
|
|
104
|
+
- `~/.codex/AGENTS.md` and `~/.copilot/copilot-instructions.md` become symlinks to `~/.agents/AGENTS.md`. Existing files with content are left alone, with a warning.
|
|
105
|
+
- Hooks go in through a Claude Code plugin (installed from the clone), `~/.codex/hooks.json` and `~/.copilot/hooks/trailkeep.json`. Hook files it didn't create are never edited; it prints what to add instead.
|
|
106
|
+
- The `effort` skill is linked into `~/.agents/skills/`, which Codex and Copilot read. Claude Code gets it from the plugin, at about 60 always-on tokens.
|
|
107
|
+
- A copy of the tool goes to `~/.agents/trailkeep/`, and `trailkeep` is linked into `~/.local/bin`.
|
|
108
|
+
|
|
109
|
+
`trailkeep uninstall` removes all of that. It leaves each agent a plain copy of your personal instructions, and keeps `~/.agents` and any `.trailkeep/` folders.
|
|
110
|
+
|
|
111
|
+
## What's tested
|
|
112
|
+
|
|
113
|
+
`sh tests/run.sh` runs every test in a throwaway `$HOME`. It covers:
|
|
114
|
+
- install, re-install as a no-op, adopt, dry run, update and uninstall
|
|
115
|
+
- a real `npm pack` and global install, including hooks still working after the npm copy is deleted
|
|
116
|
+
- preservation of your files
|
|
117
|
+
- repo keys and worktrees
|
|
118
|
+
- the effort lifecycle, auto-archive and context output for each agent
|
|
119
|
+
- the decision log: harvesting, dedupe, filters, show, malformed text, and recovery from killed sessions
|
|
120
|
+
- every doctor check, and verify
|
|
121
|
+
|
|
122
|
+
`TRAILKEEP_REAL=1` also checks the real CLIs offline. Codex's own prompt renderer must show the personal and nested files, and must parse the hooks file. Claude Code must validate, install and remove the plugin.
|
|
123
|
+
|
|
124
|
+
CI runs the suite on Linux and macOS, under dash and `bash --posix`. A weekly job runs against the latest CLIs to catch upstream changes.
|
|
125
|
+
|
|
126
|
+
Last verified with Claude Code 2.1.316, Codex CLI 0.166.0 and Copilot CLI 1.0.105.
|
|
127
|
+
|
|
128
|
+
Live-session behavior can't be tested offline: hooks running, the Claude import being followed, Copilot reading the symlink. `trailkeep verify` checks it on your machine. It plants a random marker in each layer and a decision in an effort file, asks each agent what it sees, and checks the decision reached the log. Then it restores everything. If Copilot misses your personal file, set `COPILOT_CUSTOM_INSTRUCTIONS_DIRS=~/.agents`.
|
|
129
|
+
|
|
130
|
+
## Environment
|
|
131
|
+
|
|
132
|
+
- `TRAILKEEP_HOME` (default `~/.agents`)
|
|
133
|
+
- `TRAILKEEP_MAX_CHARS` (default 9000, max 9500)
|
|
134
|
+
- `TRAILKEEP_HINT=0` (no hint on branches without an effort file)
|
|
135
|
+
- `TRAILKEEP_EFFORT` (use a named effort instead of the branch)
|
|
136
|
+
|
|
137
|
+
It also honours `CLAUDE_CONFIG_DIR`, `CODEX_HOME` and `COPILOT_HOME`. It works on Linux and macOS; on Windows, use WSL.
|
|
138
|
+
|
|
139
|
+
## Releasing (maintainers)
|
|
140
|
+
|
|
141
|
+
From anywhere, with nothing installed: on GitHub, open Actions, then **release**, then **Run workflow**, and pick `patch`, `minor`, `major` or an exact `X.Y.Z`. Or from any terminal with `gh`:
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
gh workflow run release.yml -R msiric/trailkeep -f version=patch
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The workflow bumps the version in all three places, runs the tests, and only then pushes the release commit and tag, publishes to npm and creates the GitHub release. If the tests fail, nothing is pushed.
|
|
148
|
+
|
|
149
|
+
From a clone, `sh scripts/release patch` (or `X.Y.Z`) does the bump, tests, commit and tag locally and pushes; the tag starts the same workflow, which checks the versions, tests again and publishes. Either way, no machine but GitHub's talks to npm.
|
|
150
|
+
|
|
151
|
+
npm authentication:
|
|
152
|
+
- **Trusted publishing (preferred):** on npmjs.com, open the package's Settings, then Trusted Publisher, then GitHub Actions. Enter owner `msiric`, repository `trailkeep`, workflow `release.yml`. No secret is needed. npm only offers this for packages that already exist.
|
|
153
|
+
- **An `NPM_TOKEN` repository secret** was used for the very first publish only. The workflow no longer reads it; trusted publishing is set up for `@trailkeep/cli`.
|
|
154
|
+
|
|
155
|
+
If a publish fails after the release commit and tag were pushed, run the workflow again with that exact version (`-f version=X.Y.Z`); it publishes the existing tag without bumping.
|