@tanagram/cli 0.4.6 → 0.4.8
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/api/client.go +12 -12
- package/commands/config.go +4 -4
- package/commands/login.go +5 -2
- package/commands/sync.go +14 -14
- package/extractor/extractor.go +0 -2
- package/install.js +46 -2
- package/metrics/metrics.go +0 -2
- package/package.json +1 -1
- package/parser/agents.go +0 -1
- package/snapshot/snapshot.go +2 -2
- package/storage/cache.go +1 -1
- package/tui/puzzle.go +1 -1
package/api/client.go
CHANGED
|
@@ -28,18 +28,18 @@ type Repository struct {
|
|
|
28
28
|
|
|
29
29
|
// Policy represents a Tanagram policy
|
|
30
30
|
type Policy struct {
|
|
31
|
-
ID
|
|
32
|
-
Name
|
|
33
|
-
OrganizationID
|
|
34
|
-
Substrate
|
|
35
|
-
DescriptionFromUser
|
|
36
|
-
DescriptionRewrittenByLLM
|
|
37
|
-
CustomMessage
|
|
38
|
-
EnabledStatus
|
|
39
|
-
CreatedAt
|
|
40
|
-
UpdatedAt
|
|
41
|
-
PolicyRepositories
|
|
42
|
-
ViolationsCount
|
|
31
|
+
ID string `json:"id"`
|
|
32
|
+
Name string `json:"name"`
|
|
33
|
+
OrganizationID string `json:"organization_id"`
|
|
34
|
+
Substrate string `json:"substrate"` // "llm" or "tql"
|
|
35
|
+
DescriptionFromUser string `json:"description_from_user"`
|
|
36
|
+
DescriptionRewrittenByLLM string `json:"description_rewritten_by_llm"`
|
|
37
|
+
CustomMessage string `json:"custom_message"`
|
|
38
|
+
EnabledStatus string `json:"enabled_status"`
|
|
39
|
+
CreatedAt time.Time `json:"created_at"`
|
|
40
|
+
UpdatedAt time.Time `json:"updated_at"`
|
|
41
|
+
PolicyRepositories []Repository `json:"policy_repositories"`
|
|
42
|
+
ViolationsCount int `json:"violations_count"`
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// PolicyListResponse is the response from GET /api/policies/
|
package/commands/config.go
CHANGED
|
@@ -84,7 +84,7 @@ func ConfigClaude(settingsPath string) error {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
if preHookExists && postHookExists {
|
|
87
|
-
fmt.
|
|
87
|
+
fmt.Printf("✓ Tanagram hooks are already configured in %s\n", settingsPath)
|
|
88
88
|
return nil
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -120,7 +120,7 @@ func ConfigClaude(settingsPath string) error {
|
|
|
120
120
|
return fmt.Errorf("failed to save settings: %w", err)
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
fmt.
|
|
123
|
+
fmt.Printf("✓ Tanagram hooks added to %s\n", settingsPath)
|
|
124
124
|
fmt.Println("\nClaude Code will now:")
|
|
125
125
|
fmt.Println(" - Snapshot file state before each Edit/Write (PreToolUse)")
|
|
126
126
|
fmt.Println(" - Check only Claude's changes after Edit/Write (PostToolUse)")
|
|
@@ -191,7 +191,7 @@ func ConfigCursor(hooksPath string) error {
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
if beforeSubmitHookExists && stopHookExists {
|
|
194
|
-
fmt.
|
|
194
|
+
fmt.Printf("✓ Tanagram hooks are already configured in %s\n", hooksPath)
|
|
195
195
|
return nil
|
|
196
196
|
}
|
|
197
197
|
|
|
@@ -215,7 +215,7 @@ func ConfigCursor(hooksPath string) error {
|
|
|
215
215
|
return fmt.Errorf("failed to save hooks: %w", err)
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
fmt.
|
|
218
|
+
fmt.Printf("✓ Tanagram hooks added to %s\n", hooksPath)
|
|
219
219
|
fmt.Println("\nCursor will now:")
|
|
220
220
|
fmt.Println(" - Snapshot file state before each prompt (beforeSubmitPrompt)")
|
|
221
221
|
fmt.Println(" - Check only Cursor's changes after agent completes (stop)")
|
package/commands/login.go
CHANGED
|
@@ -78,11 +78,14 @@ func Login() error {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// Send success message to browser
|
|
81
|
-
w.Header().Set("Content-Type", "text/html")
|
|
81
|
+
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
82
82
|
fmt.Fprintf(w, `
|
|
83
83
|
<!DOCTYPE html>
|
|
84
84
|
<html>
|
|
85
|
-
<head
|
|
85
|
+
<head>
|
|
86
|
+
<meta charset="utf-8">
|
|
87
|
+
<title>Tanagram Login</title>
|
|
88
|
+
</head>
|
|
86
89
|
<body style="font-family: system-ui; text-align: center; padding: 50px;">
|
|
87
90
|
<h1>✓ Login Successful</h1>
|
|
88
91
|
<p>You can close this window and return to your terminal.</p>
|
package/commands/sync.go
CHANGED
|
@@ -191,20 +191,20 @@ func FindInstructionFiles(gitRoot string) ([]string, error) {
|
|
|
191
191
|
|
|
192
192
|
// Directories to skip
|
|
193
193
|
skipDirs := map[string]bool{
|
|
194
|
-
".git":
|
|
195
|
-
"node_modules":
|
|
196
|
-
"vendor":
|
|
197
|
-
".venv":
|
|
198
|
-
"venv":
|
|
199
|
-
"__pycache__":
|
|
200
|
-
".pytest_cache":
|
|
201
|
-
".mypy_cache":
|
|
202
|
-
"dist":
|
|
203
|
-
"build":
|
|
204
|
-
".tanagram":
|
|
205
|
-
".conductor":
|
|
206
|
-
"repos":
|
|
207
|
-
"monorepo_clones":
|
|
194
|
+
".git": true,
|
|
195
|
+
"node_modules": true,
|
|
196
|
+
"vendor": true,
|
|
197
|
+
".venv": true,
|
|
198
|
+
"venv": true,
|
|
199
|
+
"__pycache__": true,
|
|
200
|
+
".pytest_cache": true,
|
|
201
|
+
".mypy_cache": true,
|
|
202
|
+
"dist": true,
|
|
203
|
+
"build": true,
|
|
204
|
+
".tanagram": true,
|
|
205
|
+
".conductor": true, // Skip conductor directories
|
|
206
|
+
"repos": true, // Skip cloned repos
|
|
207
|
+
"monorepo_clones": true, // Skip cloned repos
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
// Search from git root down
|
package/extractor/extractor.go
CHANGED
package/install.js
CHANGED
|
@@ -97,12 +97,53 @@ function buildBinary(goCommand) {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
console.log('✓ Tanagram CLI installed successfully');
|
|
100
|
-
return
|
|
100
|
+
return binaryPath;
|
|
101
101
|
} catch (error) {
|
|
102
102
|
throw new Error(`Build failed: ${error.message}`);
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
function isCIEnvironment() {
|
|
107
|
+
return (
|
|
108
|
+
process.env.CI === 'true' ||
|
|
109
|
+
process.env.GITHUB_ACTIONS === 'true' ||
|
|
110
|
+
process.env.BUILDKITE === 'true' ||
|
|
111
|
+
process.env.GITLAB_CI === 'true' ||
|
|
112
|
+
process.env.TF_BUILD === 'True'
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function shouldConfigureHooks() {
|
|
117
|
+
if (process.env.TANAGRAM_SKIP_HOOKS === '1' || process.env.TANAGRAM_SKIP_HOOKS === 'true') {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (isCIEnvironment()) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function configureEditorHooks(binaryPath) {
|
|
127
|
+
if (!shouldConfigureHooks()) {
|
|
128
|
+
console.log('Skipping Tanagram editor hook setup (CI or TANAGRAM_SKIP_HOOKS set).');
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
console.log('Configuring Tanagram editor hooks (Claude Code, Cursor)...');
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
execSync(`"${binaryPath}" config claude`, { stdio: 'inherit' });
|
|
136
|
+
} catch (err) {
|
|
137
|
+
console.warn('Warning: Failed to configure Claude hooks:', err.message);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
execSync(`"${binaryPath}" config cursor`, { stdio: 'inherit' });
|
|
142
|
+
} catch (err) {
|
|
143
|
+
console.warn('Warning: Failed to configure Cursor hooks:', err.message);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
106
147
|
// Main installation flow
|
|
107
148
|
(async () => {
|
|
108
149
|
try {
|
|
@@ -120,7 +161,10 @@ function buildBinary(goCommand) {
|
|
|
120
161
|
}
|
|
121
162
|
|
|
122
163
|
// 4. Build the binary
|
|
123
|
-
buildBinary(goCommand);
|
|
164
|
+
const binaryPath = buildBinary(goCommand);
|
|
165
|
+
|
|
166
|
+
// 5. Configure hooks
|
|
167
|
+
configureEditorHooks(binaryPath);
|
|
124
168
|
|
|
125
169
|
process.exit(0);
|
|
126
170
|
} catch (error) {
|
package/metrics/metrics.go
CHANGED
package/package.json
CHANGED
package/parser/agents.go
CHANGED
package/snapshot/snapshot.go
CHANGED
|
@@ -23,8 +23,8 @@ type FileState struct {
|
|
|
23
23
|
|
|
24
24
|
// Snapshot represents a snapshot of the working directory
|
|
25
25
|
type Snapshot struct {
|
|
26
|
-
Timestamp time.Time
|
|
27
|
-
Files map[string]*FileState
|
|
26
|
+
Timestamp time.Time `json:"timestamp"`
|
|
27
|
+
Files map[string]*FileState `json:"files"`
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// SnapshotPath returns the path to the snapshot file
|
package/storage/cache.go
CHANGED
|
@@ -28,7 +28,7 @@ type SerializablePolicy struct {
|
|
|
28
28
|
type Cache struct {
|
|
29
29
|
FileMD5s map[string]string // filepath -> MD5 hash
|
|
30
30
|
Policies map[string][]SerializablePolicy // filepath -> policies
|
|
31
|
-
CachePath string
|
|
31
|
+
CachePath string // where the cache file is stored
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// NewCache creates a new empty cache
|