Skip to content

Commit 5724953

Browse files
FeilixXclaude
andcommitted
v0.5.1: TSA on by default, install UX improvements, setup enhancements
- TSA anchoring enabled by default (free DigiCert service, rate-limited) - README: add "Why I built this" section with ICP positioning - README: simplify Quick Start to two commands, Windows in collapsible - install.sh: platform-aware install dir (~/.punkgo/bin/ on Windows) - install.sh: PATH detection + guidance after install - install.sh: skip chmod +x on Windows, mkdir -p before install - setup: print survey link (punkgo.ai/why) after successful setup - setup: check kernel version compatibility, warn if outdated - cargo fmt across touched files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1bbf8cf commit 5724953

9 files changed

Lines changed: 208 additions & 57 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "punkgo-jack"
3-
version = "0.5.0"
3+
version = "0.5.1"
44
edition = "2021"
55
description = "AI tool hook adapter for punkgo-kernel — every tool call gets a cryptographic receipt with Ed25519 signing and RFC 3161 TSA anchoring"
66
license = "MIT"

README.md

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,46 @@ Your AI agent just deleted your production database. Your `.env`. It happens eve
1212

1313
---
1414

15-
**Contents:** [Quick Start](#quick-start) · [How It Works](#how-it-works) · [Verify](#verify) · [Trust Layers](#trust-layers) · [CLI](#cli) · [Config](#config) · [Supported Tools](#supported-tools) · [Evolution](#evolution)
15+
**Contents:** [Why](#why-i-built-this) · [Quick Start](#quick-start) · [How It Works](#how-it-works) · [Verify](#verify) · [Trust Layers](#trust-layers) · [CLI](#cli) · [Config](#config) · [Supported Tools](#supported-tools) · [Evolution](#evolution)
16+
17+
---
18+
19+
## Why I built this
20+
21+
I've been using Claude Code daily since January 2025. After 25,000+ AI actions, I realized I had zero proof of what actually happened. The AI's own logs? It can edit those. Git history? Doesn't capture the thinking process. I wanted something that works like a dashcam — always recording, can't be tampered with, and there when you need it.
22+
23+
PunkGo Jack is that dashcam. Not a log file you can delete. Not a summary the AI writes about itself. A cryptographic receipt — append-only, Ed25519-signed, RFC 3161 timestamped. You can't backdate it, you can't delete it, you can't forge it.
24+
25+
**Who is this for?** If you use Claude Code or Cursor for client work, team projects, or anything where you need to show what your AI actually did — this is for you.
1626

1727
---
1828

1929
## Quick Start
2030

2131
```bash
22-
# Install
2332
curl -fsSL https://raw.githubusercontent.com/PunkGo/punkgo-jack/main/install.sh | bash
24-
# or: cargo install punkgo-jack && cargo install punkgo-kernel
33+
punkgo-jack setup claude-code # or: punkgo-jack setup cursor
34+
```
2535

26-
# Setup (pick your tool)
27-
punkgo-jack setup claude-code
28-
punkgo-jack setup cursor
36+
That's it — two commands. Your next AI session is recorded with Ed25519 signatures and RFC 3161 timestamps. Verify anytime:
37+
38+
```bash
39+
punkgo-jack receipt # session summary + anchor time
40+
punkgo-jack verify <ID> # cryptographic proof
41+
```
2942

30-
# Optional: enable RFC 3161 TSA time anchoring
31-
echo -e '[tsa]\nenabled = true' >> ~/.punkgo/config.toml
43+
Upgrade: `punkgo-jack upgrade`. Uninstall: `punkgo-jack unsetup claude-code`.
44+
45+
<details>
46+
<summary>Windows / manual install</summary>
47+
48+
```powershell
49+
cargo install punkgo-jack && cargo install punkgo-kernel
50+
punkgo-jack setup claude-code
3251
```
3352

34-
That's it. Your next session is already being recorded. Upgrade anytime: `punkgo-jack upgrade`.
53+
Requires [Rust toolchain](https://rustup.rs). The install script also works in Git Bash on Windows.
54+
</details>
3555

3656
## How It Works
3757

@@ -86,17 +106,17 @@ A root operator with the signing key could rebuild the tree — this is the sing
86106

87107
## Config
88108

89-
TSA anchoring is opt-in. Create `~/.punkgo/config.toml`:
109+
TSA anchoring is **on by default** (free DigiCert public service, rate-limited to once per 5 minutes). To customize, create `~/.punkgo/config.toml`:
90110

91111
```toml
92112
[tsa]
93-
enabled = true
94-
# url = "http://timestamp.digicert.com" # default
113+
# enabled = true # default: true
114+
# url = "http://timestamp.digicert.com" # default
95115
# timeout_secs = 10 # default
96116
# min_interval_secs = 300 # 0 for CI burst mode
97117
```
98118

99-
Env var overrides: `PUNKGO_TSA_ENABLED`, `PUNKGO_TSA_URL`, `PUNKGO_TSA_MIN_INTERVAL_SECS`.
119+
Disable TSA: set `enabled = false` or `PUNKGO_TSA_ENABLED=false`. Other env vars: `PUNKGO_TSA_URL`, `PUNKGO_TSA_MIN_INTERVAL_SECS`.
100120

101121
## Supported Tools
102122

@@ -111,7 +131,8 @@ Env var overrides: `PUNKGO_TSA_ENABLED`, `PUNKGO_TSA_URL`, `PUNKGO_TSA_MIN_INTER
111131

112132
| Version | What changed |
113133
|---------|-------------|
114-
| **v0.5.0** | RFC 3161 TSA anchoring, verify-tsr, config system |
134+
| **v0.5.1** | TSA on by default, Windows install fix, kernel version check, setup survey |
135+
| v0.5.0 | RFC 3161 TSA anchoring, verify-tsr, config system |
115136
| v0.4.2 | Multi-agent default (--actor shows all) |
116137
| v0.4.1 | Cursor IDE support, dual-tool coexistence |
117138
| v0.4.0 | Verify, export, presence heatmap, MCP server |

install.sh

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,20 @@ set -euo pipefail
55

66
JACK_REPO="PunkGo/punkgo-jack"
77
KERNEL_REPO="PunkGo/punkgo-kernel"
8-
INSTALL_DIR="${PUNKGO_INSTALL_DIR:-/usr/local/bin}"
8+
9+
# Default install directory: platform-aware.
10+
if [ -z "${PUNKGO_INSTALL_DIR:-}" ]; then
11+
case "$(uname -s)" in
12+
MINGW*|MSYS*|CYGWIN*)
13+
# Windows: install to ~/.punkgo/bin/ (always writable, no sudo).
14+
# Use $HOME (POSIX path, consistent with Git Bash $PATH format).
15+
INSTALL_DIR="$HOME/.punkgo/bin" ;;
16+
*)
17+
INSTALL_DIR="/usr/local/bin" ;;
18+
esac
19+
else
20+
INSTALL_DIR="$PUNKGO_INSTALL_DIR"
21+
fi
922

1023
# Colors
1124
RED='\033[0;31m'
@@ -91,14 +104,15 @@ install_binary() {
91104
return 1
92105
fi
93106

94-
# Install
107+
# Install — ensure target dir exists.
108+
mkdir -p "$INSTALL_DIR"
95109
if [ -w "$INSTALL_DIR" ]; then
96110
mv "${tmpdir}/${bin_name}" "${INSTALL_DIR}/${bin_name}"
97111
else
98112
info "Need sudo to install to ${INSTALL_DIR}"
99113
sudo mv "${tmpdir}/${bin_name}" "${INSTALL_DIR}/${bin_name}"
100114
fi
101-
chmod +x "${INSTALL_DIR}/${bin_name}"
115+
[ "$OS" != "windows" ] && chmod +x "${INSTALL_DIR}/${bin_name}"
102116

103117
rm -rf "$tmpdir"
104118
info "Installed ${bin_name}${INSTALL_DIR}/${bin_name}"
@@ -130,6 +144,21 @@ main() {
130144
if [ "$failed" -eq 0 ]; then
131145
info "Installation complete!"
132146
echo ""
147+
# Check if INSTALL_DIR is in PATH.
148+
case ":$PATH:" in
149+
*":${INSTALL_DIR}:"*) ;;
150+
*)
151+
warn "${INSTALL_DIR} is not in your PATH."
152+
if [ "$OS" = "windows" ]; then
153+
dim "Add it: setx PATH \"%PATH%;$(cygpath -w "$INSTALL_DIR" 2>/dev/null || echo "$INSTALL_DIR")\""
154+
dim "Then restart your terminal."
155+
else
156+
dim "Add it: export PATH=\"${INSTALL_DIR}:\$PATH\""
157+
dim "Or add that line to your ~/.bashrc / ~/.zshrc"
158+
fi
159+
echo ""
160+
;;
161+
esac
133162
dim "Next step:"
134163
echo " punkgo-jack setup claude-code"
135164
echo ""

src/anchor.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,14 @@ pub fn do_anchor(config: &Config) -> Result<Option<AnchorReceipt>> {
100100
let client = IpcClient::from_env(None);
101101
let (tree_size, root_hash) = fetch_checkpoint(&client)?;
102102

103-
let tsr_path = config::tsr_path(tree_size)
104-
.context("failed to determine TSR storage path")?;
103+
let tsr_path = config::tsr_path(tree_size).context("failed to determine TSR storage path")?;
105104
if tsr_path.exists() {
106105
debug!(tree_size, "already anchored");
107106
return Ok(None);
108107
}
109108

110-
let hash_bytes = tsa_verify::hex_to_32bytes(&root_hash)
111-
.context("invalid root_hash hex from checkpoint")?;
109+
let hash_bytes =
110+
tsa_verify::hex_to_32bytes(&root_hash).context("invalid root_hash hex from checkpoint")?;
112111
let tsq = build_timestamp_req(&hash_bytes)?;
113112

114113
info!(url = %config.tsa.url, tree_size, "submitting to TSA");
@@ -145,8 +144,7 @@ fn needs_anchor() -> Result<bool> {
145144
Ok(v) => v,
146145
Err(_) => return Ok(false),
147146
};
148-
let tsr_path = config::tsr_path(tree_size)
149-
.context("failed to determine TSR path")?;
147+
let tsr_path = config::tsr_path(tree_size).context("failed to determine TSR path")?;
150148
Ok(!tsr_path.exists())
151149
}
152150

@@ -162,10 +160,14 @@ fn fetch_checkpoint(client: &IpcClient) -> Result<(i64, String)> {
162160
if resp.status != "ok" {
163161
anyhow::bail!("kernel returned error: {}", resp.payload);
164162
}
165-
let tree_size = resp.payload.get("tree_size")
163+
let tree_size = resp
164+
.payload
165+
.get("tree_size")
166166
.and_then(|v| v.as_i64())
167167
.context("missing tree_size in checkpoint response")?;
168-
let root_hash = resp.payload.get("root_hash")
168+
let root_hash = resp
169+
.payload
170+
.get("root_hash")
169171
.and_then(|v| v.as_str())
170172
.context("missing root_hash in checkpoint response")?
171173
.to_string();

src/config.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ pub struct Config {
2020
/// TSA anchoring configuration.
2121
#[derive(Debug, Deserialize, PartialEq)]
2222
pub struct TsaConfig {
23-
/// Master switch. Default: false (opt-in).
24-
#[serde(default)]
23+
/// Master switch. Default: true (opt-out).
24+
/// TSA uses the free DigiCert public service with rate limiting,
25+
/// so it is safe to enable by default.
26+
#[serde(default = "default_tsa_enabled")]
2527
pub enabled: bool,
2628

2729
/// Primary TSA endpoint URL. RFC 3161 over HTTP(S).
@@ -41,10 +43,14 @@ pub struct TsaConfig {
4143
pub min_interval_secs: u64,
4244
}
4345

46+
fn default_tsa_enabled() -> bool {
47+
true
48+
}
49+
4450
impl Default for TsaConfig {
4551
fn default() -> Self {
4652
Self {
47-
enabled: false,
53+
enabled: true,
4854
url: default_tsa_url(),
4955
timeout_secs: default_timeout(),
5056
min_interval_secs: default_min_interval(),
@@ -127,7 +133,7 @@ mod tests {
127133
#[test]
128134
fn default_config_values() {
129135
let config = Config::default();
130-
assert!(!config.tsa.enabled);
136+
assert!(config.tsa.enabled);
131137
assert_eq!(config.tsa.url, "http://timestamp.digicert.com");
132138
assert_eq!(config.tsa.timeout_secs, 10);
133139
assert_eq!(config.tsa.min_interval_secs, 300);
@@ -168,12 +174,12 @@ min_interval_secs = 0
168174
#[test]
169175
fn env_override_enabled() {
170176
let mut config = Config::default();
171-
assert!(!config.tsa.enabled);
177+
assert!(config.tsa.enabled); // default is now true
172178

173-
// Simulate env var
174-
std::env::set_var("PUNKGO_TSA_ENABLED", "true");
179+
// Simulate env var to disable
180+
std::env::set_var("PUNKGO_TSA_ENABLED", "false");
175181
apply_env_overrides(&mut config);
176-
assert!(config.tsa.enabled);
182+
assert!(!config.tsa.enabled);
177183

178184
// Cleanup
179185
std::env::remove_var("PUNKGO_TSA_ENABLED");

src/history.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,7 @@ fn print_receipt_tsa_status(tree_size: u64) {
556556
let name_str = name.to_string_lossy();
557557
if let Some(stem) = name_str.strip_suffix(".tsr") {
558558
if let Ok(ts) = stem.parse::<i64>() {
559-
if ts >= tree_size as i64
560-
&& best.as_ref().is_none_or(|(b, _)| ts < *b)
561-
{
559+
if ts >= tree_size as i64 && best.as_ref().is_none_or(|(b, _)| ts < *b) {
562560
best = Some((ts, entry.path()));
563561
}
564562
}

0 commit comments

Comments
 (0)