continuity-note 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,3 @@
1
+ """continuity-note: install the continuity-note agent skill into your AI tools."""
2
+
3
+ __version__ = "0.1.0"
continuity_note/cli.py ADDED
@@ -0,0 +1,221 @@
1
+ """Command-line installer for the continuity-note agent skill.
2
+
3
+ The skill itself is plain Markdown (``SKILL.md``). This CLI copies it into the
4
+ skills directory of whichever AI coding agent you use, so the agent discovers it
5
+ the same way it discovers any other skill. We copy a physical file rather than
6
+ symlinking on purpose: the installed skill must survive ``pip uninstall`` and
7
+ virtualenv changes - it belongs to your agent, not to this Python package.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import argparse
13
+ import os
14
+ import sys
15
+ from importlib import resources
16
+ from pathlib import Path
17
+
18
+ from . import __version__
19
+
20
+ SKILL_NAME = "continuity-note"
21
+
22
+
23
+ def _skill_source() -> str:
24
+ """Return the packaged SKILL.md content."""
25
+ return resources.files("continuity_note").joinpath("data/SKILL.md").read_text(
26
+ encoding="utf-8"
27
+ )
28
+
29
+
30
+ def _codex_skills_dir() -> Path:
31
+ """Codex honors $CODEX_HOME (default ~/.codex)."""
32
+ codex_home = os.environ.get("CODEX_HOME")
33
+ base = Path(codex_home) if codex_home else Path.home() / ".codex"
34
+ return base / "skills"
35
+
36
+
37
+ # name -> (skills directory, human label). Verified against each agent's docs:
38
+ # Claude Code reads ~/.claude/skills; Codex reads $CODEX_HOME/skills; the
39
+ # cross-runtime ~/.agents/skills is shared by Copilot CLI and Gemini CLI.
40
+ def _targets() -> dict[str, tuple[Path, str]]:
41
+ return {
42
+ "claude": (Path.home() / ".claude" / "skills", "Claude Code"),
43
+ "codex": (_codex_skills_dir(), "Codex"),
44
+ "agents": (Path.home() / ".agents" / "skills", "Copilot CLI / Gemini CLI"),
45
+ }
46
+
47
+
48
+ def _detected(targets: dict[str, tuple[Path, str]]) -> list[str]:
49
+ """Targets whose skills directory (or its parent) already exists - i.e. the
50
+ agent looks installed, so we should offer to install there by default."""
51
+ found = []
52
+ for name, (skills_dir, _label) in targets.items():
53
+ if skills_dir.exists() or skills_dir.parent.exists():
54
+ found.append(name)
55
+ return found
56
+
57
+
58
+ def _resolve_target_names(requested: list[str], targets: dict) -> list[str]:
59
+ if "all" in requested:
60
+ return list(targets)
61
+ unknown = [r for r in requested if r not in targets]
62
+ if unknown:
63
+ valid = ", ".join(list(targets) + ["all"])
64
+ raise SystemExit(
65
+ f"Unknown target(s): {', '.join(unknown)}. Valid targets: {valid}."
66
+ )
67
+ return requested
68
+
69
+
70
+ def _install_one(skills_dir: Path, content: str, force: bool) -> str:
71
+ """Install into one skills directory. Returns a one-word status."""
72
+ dest_dir = skills_dir / SKILL_NAME
73
+ dest = dest_dir / "SKILL.md"
74
+ if dest.exists():
75
+ current = dest.read_text(encoding="utf-8")
76
+ if current == content:
77
+ return "up-to-date"
78
+ if not force:
79
+ return "differs" # never clobber local edits silently
80
+ dest_dir.mkdir(parents=True, exist_ok=True)
81
+ dest.write_text(content, encoding="utf-8")
82
+ return "installed"
83
+
84
+
85
+ def cmd_install(args: argparse.Namespace) -> int:
86
+ content = _skill_source()
87
+ targets = _targets()
88
+
89
+ # Custom directory takes precedence and bypasses the known-agent registry.
90
+ if args.target:
91
+ custom = Path(args.target).expanduser().resolve()
92
+ status = _install_one(custom, content, args.force)
93
+ _report(custom / SKILL_NAME, "custom directory", status, args.force)
94
+ return 0
95
+
96
+ if args.targets:
97
+ names = _resolve_target_names(args.targets, targets)
98
+ else:
99
+ names = _detected(targets)
100
+ if not names:
101
+ # Fresh machine with no agent dirs yet: default to Claude Code and
102
+ # create the directory, rather than failing on a clean install.
103
+ names = ["claude"]
104
+ print(
105
+ "No agent skills directory detected; defaulting to Claude Code.\n"
106
+ "Pass target names (claude codex agents all) or --target DIR to choose.\n"
107
+ )
108
+
109
+ any_blocked = False
110
+ for name in names:
111
+ skills_dir, label = targets[name]
112
+ status = _install_one(skills_dir, content, args.force)
113
+ any_blocked |= status == "differs"
114
+ _report(skills_dir / SKILL_NAME, label, status, args.force)
115
+ return 1 if any_blocked else 0
116
+
117
+
118
+ def _report(dest_dir: Path, label: str, status: str, force: bool) -> None:
119
+ dest = dest_dir / "SKILL.md"
120
+ if status == "installed":
121
+ print(f" ok {label}: {dest}")
122
+ elif status == "up-to-date":
123
+ print(f" ok {label}: already up to date ({dest})")
124
+ elif status == "differs":
125
+ print(
126
+ f" skip {label}: {dest} exists and differs from this version.\n"
127
+ f" Re-run with --force to overwrite (this discards local edits)."
128
+ )
129
+
130
+
131
+ def cmd_uninstall(args: argparse.Namespace) -> int:
132
+ targets = _targets()
133
+ if args.target:
134
+ dirs = [(Path(args.target).expanduser().resolve(), "custom directory")]
135
+ else:
136
+ names = _resolve_target_names(args.targets, targets) if args.targets else list(targets)
137
+ dirs = [(targets[n][0], targets[n][1]) for n in names]
138
+
139
+ removed = False
140
+ for skills_dir, label in dirs:
141
+ dest = skills_dir / SKILL_NAME / "SKILL.md"
142
+ skill_dir = skills_dir / SKILL_NAME
143
+ if dest.exists():
144
+ dest.unlink()
145
+ # Remove the skill folder if we left it empty.
146
+ try:
147
+ skill_dir.rmdir()
148
+ except OSError:
149
+ pass
150
+ print(f" removed {label}: {dest}")
151
+ removed = True
152
+ if not removed:
153
+ print("Nothing to remove; continuity-note was not installed in any target.")
154
+ return 0
155
+
156
+
157
+ def cmd_status(args: argparse.Namespace) -> int:
158
+ targets = _targets()
159
+ print(f"continuity-note {__version__}\n")
160
+ for name, (skills_dir, label) in targets.items():
161
+ dest = skills_dir / SKILL_NAME / "SKILL.md"
162
+ if dest.exists():
163
+ same = dest.read_text(encoding="utf-8") == _skill_source()
164
+ state = "installed (current)" if same else "installed (outdated/edited)"
165
+ else:
166
+ state = "not installed"
167
+ print(f" {name:8} {label:28} {state}\n {dest}")
168
+ return 0
169
+
170
+
171
+ def build_parser() -> argparse.ArgumentParser:
172
+ parser = argparse.ArgumentParser(
173
+ prog="continuity-note",
174
+ description="Install the continuity-note agent skill into your AI coding tools.",
175
+ )
176
+ parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
177
+ sub = parser.add_subparsers(dest="command")
178
+
179
+ p_install = sub.add_parser(
180
+ "install",
181
+ help="Copy the skill into agent skills directories (default: detected agents).",
182
+ )
183
+ p_install.add_argument(
184
+ "targets",
185
+ nargs="*",
186
+ help="Which agents: claude, codex, agents, or all. Omit to auto-detect.",
187
+ )
188
+ p_install.add_argument(
189
+ "--target",
190
+ metavar="DIR",
191
+ help="Install into a custom skills directory instead of a known agent.",
192
+ )
193
+ p_install.add_argument(
194
+ "--force",
195
+ action="store_true",
196
+ help="Overwrite an existing SKILL.md even if it was edited locally.",
197
+ )
198
+ p_install.set_defaults(func=cmd_install)
199
+
200
+ p_uninstall = sub.add_parser("uninstall", help="Remove the skill from agent skills directories.")
201
+ p_uninstall.add_argument("targets", nargs="*", help="Which agents (default: all known).")
202
+ p_uninstall.add_argument("--target", metavar="DIR", help="A custom skills directory.")
203
+ p_uninstall.set_defaults(func=cmd_uninstall)
204
+
205
+ p_status = sub.add_parser("status", help="Show where the skill is installed.")
206
+ p_status.set_defaults(func=cmd_status)
207
+
208
+ return parser
209
+
210
+
211
+ def main(argv: list[str] | None = None) -> int:
212
+ parser = build_parser()
213
+ args = parser.parse_args(argv)
214
+ if not getattr(args, "command", None):
215
+ parser.print_help()
216
+ return 0
217
+ return args.func(args)
218
+
219
+
220
+ if __name__ == "__main__":
221
+ sys.exit(main())
@@ -0,0 +1,136 @@
1
+ ---
2
+ name: continuity-note
3
+ description: >-
4
+ Write a self-contained continuity note (a handoff document) so another agent,
5
+ a teammate, or your future self can resume work WITHOUT replaying the
6
+ conversation. Use whenever work is being passed on - the user says "write a
7
+ continuity note", "write a handoff", "hand this off",
8
+ "pass this to another agent/session", "summarize this for the next session",
9
+ "I'm switching to Codex/another tool", "document where we are so I can continue
10
+ tomorrow", "context is running out, save state", or when a long session is
11
+ ending with work still in progress. Trigger even if the user doesn't say the
12
+ word "handoff" - any time the goal is to transfer in-progress work to a fresh
13
+ context, this skill applies. Do NOT use it for normal in-session context
14
+ compaction (the harness already handles that) - handoff is for crossing a
15
+ boundary into a new context that has none of this conversation's history.
16
+ ---
17
+
18
+ # Continuity Note
19
+
20
+ A continuity note (a handoff document) lets a **fresh context** resume your work. The
21
+ reader has none of this conversation: not the goal, not the decisions, not the
22
+ dead ends you already ruled out. They might be a different agent (a new Claude
23
+ session, Codex, DeepSeek, anything), a human teammate, or you tomorrow. The
24
+ whole value is that they can pick up and act *without asking you a single
25
+ question*. Optimize for that.
26
+
27
+ ## When this is the right tool
28
+
29
+ Use it when work crosses a context boundary: ending a session with work unfinished,
30
+ switching to another agent or tool, handing to a colleague, or saving state
31
+ because the context window is about to be lost. The reader starts cold.
32
+
33
+ Do **not** use it for ordinary in-session compaction. The harness already
34
+ summarizes long conversations so the same agent keeps going. Handoff earns its
35
+ cost only when the next reader has zero history.
36
+
37
+ ## What goes in (and what stays out)
38
+
39
+ The reader needs **state and direction**, not a transcript. Two failure modes,
40
+ both fatal:
41
+
42
+ - **Too little**: "continue the refactor." The reader has no idea what refactor,
43
+ why, how far, or what's next. Useless.
44
+ - **Too much**: pasting whole files, full logs, the entire chat. The reader
45
+ drowns and can't find the signal. Also re-pastes data that already lives in
46
+ files - stale the moment you write it.
47
+
48
+ The rule that resolves both: **reference, don't duplicate**. Point to artifacts
49
+ by path or URL (files, PRDs, ADRs, issues, commits, diffs, dashboards). Carry
50
+ across only the things that exist *nowhere but your head*: why you chose A over
51
+ B, the trap that isn't obvious from the code, what to do next.
52
+
53
+ ## Document structure
54
+
55
+ Write the document in this order. Lead with the parts a reader needs in the
56
+ first ten seconds; push detail down. Drop a section if it's genuinely empty -
57
+ don't pad.
58
+
59
+ ```markdown
60
+ # Handoff: <short topic> (<YYYY-MM-DD>)
61
+
62
+ ## Goal
63
+ One or two sentences. What are we ultimately trying to achieve, and why.
64
+
65
+ ## Current state
66
+ Where things stand right now. What works, what's broken, what's half-done.
67
+ Be honest about confidence: mark what you VERIFIED versus what you ASSUME.
68
+ A reader who trusts an assumption as fact will waste hours.
69
+
70
+ ## Done
71
+ - Concrete things already completed, terse bullets.
72
+
73
+ ## Next steps
74
+ The most important section. Ordered, concrete, actionable - each step
75
+ something the reader can just do. Not "improve performance" but "add an index
76
+ on orders.created_at; the slow query is in reports/daily.py:88".
77
+
78
+ ## Key decisions and why
79
+ Choices already made and the reasoning, so the reader doesn't relitigate them
80
+ or accidentally undo them. "Chose Postgres over SQLite because the test suite
81
+ needs concurrent writes."
82
+
83
+ ## Gotchas and constraints
84
+ Traps, surprises, environment quirks. Things that look wrong but are
85
+ intentional. The stuff that would cost the reader an hour of confusion.
86
+
87
+ ## Files and artifacts
88
+ Paths and URLs, each with one line on what it is and why it matters.
89
+ NOT the contents. "src/auth/jwt.py - token logic, the bug is here."
90
+
91
+ ## How to verify
92
+ Commands or checks that confirm the current state, and how the reader will
93
+ know future work succeeded. "Run `pytest tests/auth/`; all green = done."
94
+
95
+ ## Open questions
96
+ Unknowns and decisions that need the user. Be explicit that these are blockers
97
+ versus nice-to-knows.
98
+ ```
99
+
100
+ ## Rules that make a handoff trustworthy
101
+
102
+ **Redact secrets.** Never carry API keys, tokens, passwords, connection strings,
103
+ or personal data into the document. Point to where the credential lives ("token
104
+ in ~/.config/foo/key") - never the value. A handoff often gets pasted into
105
+ another tool or committed to a repo; treat it as if it will be read by someone
106
+ who shouldn't see secrets.
107
+
108
+ **Be portable across agents.** The reader may not share your tooling. Don't
109
+ write "run the /deploy skill" or "use the foo MCP" - the next agent may not have
110
+ either. Describe the *capability* in plain terms ("deploy with the project's
111
+ helm chart under deploy/") so any competent agent or human can act. If you do
112
+ know the next reader is the same setup, naming a specific tool as a shortcut is
113
+ fine - but always also say what it does.
114
+
115
+ **Distinguish verified from assumed.** This is what separates a handoff that
116
+ saves time from one that wastes it. If you ran the tests and they passed, say
117
+ so. If you only *think* the fix works, say "untested - needs verification". The
118
+ reader inherits your uncertainty either way; hiding it just moves the cost
119
+ downstream.
120
+
121
+ **Keep it lean.** Every line should earn its place. If a detail lives in a file
122
+ the reader will open anyway, link the file instead of restating it. Length is
123
+ not thoroughness - precision is.
124
+
125
+ ## Where to save it
126
+
127
+ Default: write the document to the current working directory as
128
+ `handoff-<short-topic>-<YYYY-MM-DD>.md`, then tell the user the exact path so
129
+ they can move, commit, or send it. A handoff buried in an OS temp directory
130
+ tends to vanish before anyone reads it - keep it where it'll be found.
131
+
132
+ If the user names a destination (a docs folder, a ticket, a shared drive), use
133
+ that instead. If they explicitly want it throwaway, a temp path is fine - but
134
+ that's their call, not the default.
135
+
136
+ Adapt the language of the document to the user's working language.
@@ -0,0 +1,99 @@
1
+ Metadata-Version: 2.4
2
+ Name: continuity-note
3
+ Version: 0.1.0
4
+ Summary: Install the continuity-note agent skill: write a self-contained handoff so a fresh context can resume work.
5
+ Project-URL: Homepage, https://github.com/mauriziomocci/continuity-note
6
+ Project-URL: Repository, https://github.com/mauriziomocci/continuity-note
7
+ Project-URL: Changelog, https://github.com/mauriziomocci/continuity-note/blob/main/CHANGELOG.md
8
+ Project-URL: Issues, https://github.com/mauriziomocci/continuity-note/issues
9
+ Author-email: Maurizio Mocci <mauriziomocci64@gmail.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: agent,ai,claude,claude-code,codex,continuity,handoff,llm,skill
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Software Development :: Documentation
25
+ Classifier: Topic :: Utilities
26
+ Requires-Python: >=3.9
27
+ Description-Content-Type: text/markdown
28
+
29
+ # continuity-note
30
+
31
+ *Read this in [Italiano](README.it.md).*
32
+
33
+ Install the **continuity-note** agent skill into your AI coding tools.
34
+
35
+ A continuity note is a self-contained handoff document: it lets a *fresh
36
+ context* — another agent, a teammate, or you tomorrow — resume in-progress work
37
+ **without replaying the conversation**. The skill teaches your agent to write
38
+ one well: a fixed structure (goal, current state, next steps, key decisions,
39
+ gotchas, files, how to verify, open questions), references to artifacts instead
40
+ of pasted copies, redacted secrets, and an honest split between what was
41
+ verified and what was only assumed.
42
+
43
+ This package is a small installer. The skill itself is plain Markdown; the CLI
44
+ copies it into the skills directory your agent already reads.
45
+
46
+ ## Install
47
+
48
+ ```bash
49
+ pip install continuity-note # or: pipx install continuity-note
50
+ continuity-note install # copies the skill into detected agents
51
+ ```
52
+
53
+ `install` with no arguments auto-detects which agents are present and installs
54
+ into each. Choose explicitly with target names:
55
+
56
+ ```bash
57
+ continuity-note install claude # Claude Code (~/.claude/skills)
58
+ continuity-note install codex # Codex ($CODEX_HOME/skills)
59
+ continuity-note install agents # Copilot CLI / Gemini CLI (~/.agents/skills)
60
+ continuity-note install all # all of the above
61
+ continuity-note install --target ~/my/skills # a custom directory
62
+ ```
63
+
64
+ The skill is copied as a physical file (not a symlink), so it keeps working
65
+ after you `pip uninstall continuity-note` or switch virtualenvs.
66
+
67
+ ## Use
68
+
69
+ Once installed, restart your agent so it picks up the new skill, then just ask:
70
+
71
+ > write a continuity note for what we did today
72
+
73
+ or "hand this off", "save state, context is running out", "document where we are
74
+ so I can continue tomorrow". The agent writes the note to your working directory
75
+ as `continuity-note-<topic>-<date>.md` and tells you the path.
76
+
77
+ ## Manage
78
+
79
+ ```bash
80
+ continuity-note status # show where it's installed and whether current
81
+ continuity-note install --force # update after upgrading the package
82
+ continuity-note uninstall # remove from all known agents
83
+ ```
84
+
85
+ ## Supported agents
86
+
87
+ | Target | Agent(s) | Skills directory |
88
+ |----------|---------------------------|-------------------------|
89
+ | `claude` | Claude Code | `~/.claude/skills` |
90
+ | `codex` | Codex | `$CODEX_HOME/skills` (default `~/.codex/skills`) |
91
+ | `agents` | Copilot CLI, Gemini CLI | `~/.agents/skills` |
92
+
93
+ Any other agent that reads a skills directory of `SKILL.md` files works too —
94
+ point `--target` at it.
95
+
96
+ ## License
97
+
98
+ MIT. The skill is derived from the original "handoff" skill by Matt Pocock
99
+ (also MIT); see [LICENSE](LICENSE).
@@ -0,0 +1,8 @@
1
+ continuity_note/__init__.py,sha256=aciDxhS0JrBW1IHXrUrimQQdPlEwbvL2FPYkzS8H8Qw,106
2
+ continuity_note/cli.py,sha256=YUow7rxe_RJyIOQu4EfLIdsIMe5CXumdxVxRMl3xNnE,7915
3
+ continuity_note/data/SKILL.md,sha256=0uj9zlfrL5VaYFeJwHvUu9erPqgDzPuxyJNo4Yl4cog,6195
4
+ continuity_note-0.1.0.dist-info/METADATA,sha256=iDaZDxuKoXZzbhwm6w1rwLSyUGw_eKBuyoo2kG4-7kI,4149
5
+ continuity_note-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
6
+ continuity_note-0.1.0.dist-info/entry_points.txt,sha256=Nn7dwSxSZFWmicORNMQisTjmIu26tB-S-AF04LzhmBw,61
7
+ continuity_note-0.1.0.dist-info/licenses/LICENSE,sha256=MIsovsKjm5cI7eAfTj-a4ReofekqBB1XL5Bm5Fe-jXk,1187
8
+ continuity_note-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ continuity-note = continuity_note.cli:main
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maurizio Mocci
4
+ Portions copyright (c) 2026 Matt Pocock (original "handoff" skill, from which
5
+ the continuity-note skill is derived)
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.