Repository navigation
Commit 2d59604
feat: model-free
* feat: experiment: model-free `tool` CLI and MCP server on one adapter
Do not merge: experiment for evaluating direct altimate-code tools in Claude Code.
- Bring in `altimate-code mcp serve` and the workspace tools from the MCP draft branches
- `tool list|schema|run|context|daemon`: run the same adapter as `mcp serve` without a model
- `mcp serve` default set adds impact, lineage, PII, data-diff, equivalence and translation tools; `--all-tools` exposes the full allow-list
- Long-running per-project process keeps connections warm and releases DuckDB/SQLite file locks between calls
- `--connections` / `ALTIMATE_TOOL_CONNECTIONS`, `--args -` from stdin, `tool schema` for one tool
- DROP DATABASE, DROP SCHEMA and TRUNCATE stay blocked even with `--allow-write`
- `link --claude-md` writes CLI routing guidance for clients without MCP
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: experiment: workspace tools on by default for linked projects
Do not merge: experiment.
- `tool list|schema|run|context|daemon` enable workspace tools automatically when the project is linked; `--no-workspace-tools` disables them
- `tool context` lists the linked workspace, its skills and how to use the workspace tools
- Daemon identity and spawn arguments follow the effective workspace-tools value
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* feat: experiment: mirror workspace skills into Claude Code project skills
Do not merge: experiment.
- Every workspace skill sync also writes the skills into `<project>/.claude/skills/`, so linking or refreshing a project puts them on disk before a Claude Code session starts
- Copies follow the Claude Code plugin's rules: frontmatter reduced to `name` and `description`, command blocks neutralised, hook and plugin component paths skipped, user-written skills never touched, each copy marked and git-ignored
- Unlink and the feature-off path remove the copies; projects without `.claude` are left alone; `ALTIMATE_CLAUDE_SKILL_SYNC=0` disables it
- A mirror failure never changes the sync result
- Tests: `claude-skill-mirror.test.ts`, mirror wiring in `skill-sync.test.ts`
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: harden tool daemon startup, lock release, MCP write gate and skill mirror
- daemon: release file locks when the last request finishes; serialize bind and
stale-socket recovery with a lock; clients never unlink sockets; refuse a
symlinked or foreign-owned socket directory
- mcp: warehouse_remove and driver installs need --allow-write over MCP too
- analyst effort: a per-model effort or thinking option wins over the default
- adapter: bound the answer_commit history kept across turns
- tool CLI: keep spilled results under the state directory, not /tmp
- skill mirror: skip a symlinked .claude or .claude/skills; swap copies without
deleting the old one first
- docs: callers in one directory share the daemon
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: restore shared dispatcher handlers and MCP SDK modules after mocking files
Files that reset the native dispatcher or mock the MCP SDK client modules now
restore them, so tests that run later in the same process see the real ones.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: share the Claude Code plugin's skill-copy safeguards in the workspace skill mirror
Copies carry a marker naming the skill, so a renamed copy is the user's; nested
CLAUDE.md files are not copied; staging uses an .altimate-staging- infix, gets
its .gitignore first and is swept when abandoned; an unreadable snapshot, or one
missing while it is swapped, leaves the copies alone; and the mirror and the
plugin's sync take turns under one mkdir lock in .claude/skills.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: reload daemon connections on edit, release locks in mcp serve, guard read-only warehouse_add
- daemon: reload connections when a connections file changes, only when no other
call is in flight, with calls arriving during a reload waiting for it; key the
socket on the caller's ALTIMATE_CODE_CONN_* environment; resolve --connections
once
- registry: validate a connections file before closing anything; never release
in-memory DuckDB/SQLite connections
- mcp serve: release file database locks when no call is in flight
- warehouse_add: a read-only session cannot replace a connection named in the
active registry, the global or project file, or the credential store
- adapter: bound the answer_commit history on every call, not only on commit
- skill mirror: keep copies when the snapshot or a skill cannot be read; let
withdrawal run with ALTIMATE_CLAUDE_SKILL_SYNC=0
- tool CLI: decide the workspace tools default from the saved link, without a
network call
- workspace-client: telemetry name and disabled-workspace stub
- docs and help text for the daemon, workspace tools and --all-tools
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: keep the workspace skill mirror in step with the plugin's sync under concurrent and partial reads
The mkdir lock shared with the plugin is renewed by its holder, taken over from
a dead one by rename, released only by the holder (an empty token directory),
and never waited on past its deadline; a holder that lost it stops before the
next swap. The manifest is read without following symlinks and re-read before
the removal pass; a listed skill directory that is gone, or credentials that
exist but cannot be read, change nothing. One skill's failed swap no longer
stops the others; tree comparison streams one file pair at a time; frontmatter
whitespace matches Python's; readManifest rejects a skills array.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: publish skill copies only for an unchanged, still-owned snapshot, and withdraw them on sign-out
Each copy is swapped in only while the lock is held and the snapshot is the one
read and still the signed-in account's, so a mid-copy swap, takeover or sign-out
publishes nothing. Swap detection uses the staging directory's mtime, which a
rename updates on every platform. A SKILL.md that is not a regular file skips
that skill instead of freezing every sync; markers decode strictly with their BOM
kept, as the plugin's Python reads them. The sync waits at most 2 s for the lock.
Signing out withdraws the project's copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: keep workspace skill copies when a SKILL.md disappears between its check and its read
The plugin's copy treats that as a snapshot changing underneath and changes nothing;
the mirror dropped the skill instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: a SKILL.md that disappears between its check and its read keeps every copy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: address review findings in the tool CLI, MCP server and workspace tools
- `daemon`: requests wait for an in-progress file release, `stop` replies
before shutting down, and the daemon key includes
`ALTIMATE_DISABLE_SCHEMA_VALUES`, `ALTIMATE_INTEGRATIONS` and
`ALTIMATE_DISABLE_WORKSPACE`.
- `permissions`: the blocked-statement check runs before the read-permission
shortcut.
- `claude-md`: a symlinked `CLAUDE.md` is left untouched.
- `workspace-tools`: workspace-authored names and descriptions render as one
inert line, skills are read through `WorkspaceClient.readSkill`, and the
workspace is labelled with `workspaceLabel`.
- MCP workspace adapter: an adapter is closed only after the operations
using it finish; `serverInstructions` releases file connections it opened.
- `outputLimits` reads organisation-managed config and preferences.
- `schema-list`: MySQL and Redshift (whose drivers ignore binds) get an
escaped schema literal; schema names are sorted before the limit.
- `registry.releaseFileConnections` keeps remote and in-memory URI stores.
- `sql_execute` batches: `truncated` reports row-limited or clipped items,
references resolve against the default warehouse, duplicate labels are
rejected, backslashes are escaped for BigQuery, Snowflake, Databricks and
ClickHouse, and an unmaterialized spill returns no table.
- `answer_commit`: integers keep every digit; coverage and number checks
stand down when the run budget is ending (one shared `budgetEnding`).
- `warehouse_add` resolves relative store paths against the project root;
`warehouse_list` skips only workspace-routed connections in discovery.
- `analyst-effort` honours SAP `modelParams` and the configured
`model.variants`.
- Workspace client: `readSkill` opens with `O_NOFOLLOW`; context lists only
skills with a regular `SKILL.md`. `releaseLocalSession` clears every
per-session map; skill withdrawal runs in `finally` on purge.
- MongoDB `listTables` checks that an empty database exists.
- Docs and `--allow-write` help match the actual policies.
- Tests for each behaviour change; new suites restore their spies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: never send a doubled quote to BigQuery or Databricks in batch references
BigQuery and Spark/Databricks have no `''` escape inside a string literal
(Databricks reads `'it''s'` as two adjacent literals, `its`). Batch
references now escape the quote with a backslash for those two dialects
and keep `''` for the rest. The read-only check does not lex their
backslash escape, so such a step is refused instead of running with a
wrong value.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: keep data_diff and the tool daemon within read-only and release rules; address review findings
- data_diff refuses any source, target or where_clause that is not one complete read-only
query (classifier read, single statement, balanced parentheses, no side-effect or dynamic
query() calls) before connecting, checks every statement it runs, and opens every
connector read-only. sql_check keeps its stricter rules (shared read-only-sql helper).
- isBlockedStatement classifies the whole pattern, so leading comments and multi-statement
patterns stay hard-blocked.
- Redshift values in batch references get their backslashes escaped.
- Tool daemon: the idle timer waits for a pending file release; only a request that ran a
tool leads to a release, and a stop is answered without waiting for one; the socket is
owner-only.
- Workspace: refresh clears the active adapter before closing it; a snapshot removed
mid-read lists no skills; copies into .claude/skills are opt-in with
ALTIMATE_CLAUDE_SKILL_SYNC=1 (the Claude Code plugin sets it).
- Analyst effort ignores non-object model params and output_config without effort; managed
output preferences resolve files against their own directory; warehouse_add shares the
registry's project root; mcp --allow-write help names the hard blocks.
- Docs for warehouse_add's local writes, Claude Code skill copies, analyst effort and
answer_commit; tests for each change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: dialect-aware hard blocks, failed data_diff reported as an error, daemon shutdown and row-bound fixes
- isBlockedStatement classifies with the warehouse's dialect and, without one, checks only
the leading statement, so dollar-quoted or backticked text is never hard-denied.
- A failed or refused data_diff carries its error, so tool run and MCP report it as one.
- Daemon: a run that finishes after stop neither releases files nor re-arms the idle
timer; a chmod failure after listen leaves no server or socket behind.
- {{label.column}} refuses a step with more than the row bound even when not truncated.
- Managed output preferences strip the mobileconfig: prefix before resolving {file:...}.
- readSql reuses the masked SQL; tests for each change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: hard blocks classify with each warehouse's dialect; daemon listen cleanup; test fixes
- The sql_execute write ask and data_diff's ask now carry their warehouse, one ask per side
when source and target differ, so the unoverridable hard-block check classifies each
statement in its own dialect (comments, nested comments, dollar quotes). isBlockedStatement
is the classifier; without a warehouse it uses the classifier's generic lexing.
- A chmod failure after listen destroys accepted sockets and waits for the server to close
before removing the socket and rejecting.
- Tests: batch limit at the top level, a tick before the after-stop release check, and a
managed-preferences fixture shaped like real plist JSON.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: data_diff checks an omitted source in the default warehouse's dialect
The diff engine runs an omitted source_warehouse on the registry's first warehouse; the
permission check now resolves it the same way, so one warehouse gets one check in its own
dialect.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: data_diff treats an empty warehouse name as the default, as the diff engine does
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: read sql_execute SQL in every dialect an omitted warehouse can reach; fail closed where quoting is uncertain
- With no warehouse, sql_execute classifies the SQL under the generic lexing, the registry
default's dialect and the dbt manifest's adapter type: a write if any reads it as one,
blocked if any blocks it. The dialects are found without starting dbt or loading the
handlers (new side-effect-free dbt-adapter-type helper); the write ask names the registry
warehouse when no dbt project can take the call.
- Lexing: BigQuery '...'/"..." (not raw r'...') and Redshift '...' take backslash escapes;
Databricks/Spark/Hive backslashes inside literals are uncertain; with no dialect, a quote
after an odd run of backslashes, or a #, is uncertain.
- Whenever the SQL cannot be read with certainty, DROP DATABASE, DROP SCHEMA or TRUNCATE
anywhere in it (block comments removed) is hard-blocked.
- Tests for both reported payloads (BigQuery default, MySQL default with --allow-write), a
comment holding ; on Databricks, and the lexer rules; BigQuery batch values with a quote now
run escaped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: uncertain SQL is hard-blocked on the words alone; dbt adapter type read without subprocesses
- When the tokenizer cannot read the SQL with certainty, DROP followed anywhere by DATABASE or
SCHEMA, or TRUNCATE not followed by "(", blocks it: quotes and comments are ignored, so no
placement of them can hide the statement. One forward pass.
- The backslash-before-quote and # guards apply to every dialect the lexer does not model
("generic", "unknown", oracle, trino ...), not only an omitted one.
- dbt adapter type: no Python discovery; the manifest under the project's target-path
(DBT_TARGET_PATH), parsed only when it changes; a missing or unreadable manifest, or a
malformed saved config, still counts as a dbt project. The registry fallback is read before
any await.
- Tests for each.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: Oracle, Trino and Fabric keep their reads; TRUNCATE /* c */ ( is the function
- Oracle, Trino and Fabric are lexed as the supported dialects they are, so backslashes and #
in their reads no longer make the SQL uncertain.
- TRUNCATE followed by a closed block comment and ( counts as the function.
- The dbt adapter-type tests cover the modification-time part of the cache key and the saved
altimate-dbt config.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix: classify SQL as each warehouse reads it, and keep the hard block on every reachable path
- SQL Server/Fabric: no E'' strings; statements without a separator count only in their statement forms
- BigQuery triple-quoted and backslash-escaped strings, Snowflake // comments and $$ quotes, Spark
comment line continuation, MySQL -- before ASCII whitespace, non-ASCII dollar tags
- uncertain comments and backslash runs make SQL uncertain; uncertain SQL is checked word by word
- dynamic SQL literals naming DROP DATABASE/SCHEMA or TRUNCATE are blocked; sequence advances are writes
- an omitted warehouse is classified under each dialect execution can reach, with dbt following its
cached adapter
- data_diff and the write ask check the whole SQL, not a preview
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* test: dbt-adapter-type resets the shared adapter route before each test
Another test file in the same bun process can create a dbt adapter and leave its project recorded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>tool CLI and MCP server for external coding agents (#1609)1 parent bdb7dcc commit 2d59604
119 files changed
Lines changed: 12871 additions & 365 deletions
File tree
- docs
- docs
- configure
- usage
- packages
- drivers
- src
- test
- opencode
- src
- altimate
- api
- mcp-server
- native
- connections
- prompts
- session
- tool-cli
- tools
- workspace
- cli/cmd
- memory
- session
- tool
- test
- altimate
- mcp-server
- native
- tool-cli
- tools
- workspace
- cli
- help
- __snapshots__
- lib
- mcp
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
| 34 | + | |
33 | 35 | | |
34 | 36 | | |
35 | 37 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
9 | 46 | | |
10 | 47 | | |
11 | 48 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
341 | 341 | | |
342 | 342 | | |
343 | 343 | | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
31 | 32 | | |
32 | 33 | | |
33 | 34 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
| 107 | + | |
107 | 108 | | |
108 | 109 | | |
109 | 110 | | |
| |||
186 | 187 | | |
187 | 188 | | |
188 | 189 | | |
| 190 | + | |
189 | 191 | | |
190 | 192 | | |
191 | 193 | | |
| |||
0 commit comments